- Add a "getOrInsertGlobal" method to the Module class. This acts similarly to
"getOrInsertFunction" in that it either adds a new declaration of the global
and returns it, or returns the current one -- optionally casting it to the
correct type.
- Use the new getOrInsertGlobal in the stack protector code.
- Use "splitBasicBlock" in the stack protector code.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@58727 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/llvm/Module.h b/include/llvm/Module.h
index de12157..09eba81 100644
--- a/include/llvm/Module.h
+++ b/include/llvm/Module.h
@@ -229,6 +229,15 @@
return getGlobalVariable(Name, true);
}
+ /// getOrInsertGlobal - Look up the specified global in the module symbol
+ /// table.
+ /// 1. If it does not exist, add a declaration of the global and return it.
+ /// 2. Else, the global exists but has the wrong type: return the function
+ /// with a constantexpr cast to the right type.
+ /// 3. Finally, if the existing global is the correct delclaration, return
+ /// the existing global.
+ Constant *getOrInsertGlobal(const std::string &Name, const Type *Ty);
+
/// @}
/// @name Global Alias Accessors
/// @{
diff --git a/lib/CodeGen/StackProtector.cpp b/lib/CodeGen/StackProtector.cpp
index 4bbb357..30c3db5 100644
--- a/lib/CodeGen/StackProtector.cpp
+++ b/lib/CodeGen/StackProtector.cpp
@@ -52,7 +52,7 @@
AllocaInst *StackProtFrameSlot;
/// StackGuardVar - The global variable for the stack guard.
- GlobalVariable *StackGuardVar;
+ Constant *StackGuardVar;
Function *F;
Module *M;
@@ -115,14 +115,8 @@
BasicBlock &Entry = F->getEntryBlock();
Instruction &InsertPt = Entry.front();
- const char *StackGuardStr = "__stack_chk_guard";
- StackGuardVar = M->getNamedGlobal(StackGuardStr);
-
- if (!StackGuardVar)
- StackGuardVar = new GlobalVariable(PointerType::getUnqual(Type::Int8Ty),
- false, GlobalValue::ExternalLinkage,
- 0, StackGuardStr, M);
-
+ StackGuardVar = M->getOrInsertGlobal("__stack_chk_guard",
+ PointerType::getUnqual(Type::Int8Ty));
StackProtFrameSlot = new AllocaInst(PointerType::getUnqual(Type::Int8Ty),
"StackProt_Frame", &InsertPt);
LoadInst *LI = new LoadInst(StackGuardVar, "StackGuard", false, &InsertPt);
@@ -161,7 +155,7 @@
// %3 = cmp i1 %1, %2
// br i1 %3, label %SPRet, label %CallStackCheckFailBlk
//
- // SPRet:
+ // SP_return:
// ret ...
//
// CallStackCheckFailBlk:
@@ -174,12 +168,15 @@
ReturnInst *RI = cast<ReturnInst>(BB->getTerminator());
Function::iterator InsPt = BB; ++InsPt; // Insertion point for new BB.
- BasicBlock *NewBB = BasicBlock::Create("SPRet", F, InsPt);
+ // Split the basic block before the return instruction.
+ BasicBlock *NewBB = BB->splitBasicBlock(RI, "SP_return");
- // Move the return instruction into the new basic block.
- RI->removeFromParent();
- NewBB->getInstList().insert(NewBB->begin(), RI);
+ // Move the newly created basic block to the point right after the old basic
+ // block.
+ NewBB->removeFromParent();
+ F->getBasicBlockList().insert(InsPt, NewBB);
+ // Generate the stack protector instructions in the old basic block.
LoadInst *LI2 = new LoadInst(StackGuardVar, "", false, BB);
LoadInst *LI1 = new LoadInst(StackProtFrameSlot, "", true, BB);
ICmpInst *Cmp = new ICmpInst(CmpInst::ICMP_EQ, LI1, LI2, "", BB);
diff --git a/lib/VMCore/Module.cpp b/lib/VMCore/Module.cpp
index b95f6e3..d4432c6 100644
--- a/lib/VMCore/Module.cpp
+++ b/lib/VMCore/Module.cpp
@@ -224,6 +224,28 @@
return 0;
}
+Constant *Module::getOrInsertGlobal(const std::string &Name, const Type *Ty) {
+ ValueSymbolTable &SymTab = getValueSymbolTable();
+
+ // See if we have a definition for the specified global already.
+ GlobalVariable *GV = dyn_cast_or_null<GlobalVariable>(SymTab.lookup(Name));
+ if (GV == 0) {
+ // Nope, add it
+ GlobalVariable *New =
+ new GlobalVariable(Ty, false, GlobalVariable::ExternalLinkage, 0, Name);
+ GlobalList.push_back(New);
+ return New; // Return the new declaration.
+ }
+
+ // If the variable exists but has the wrong type, return a bitcast to the
+ // right type.
+ if (GV->getType() != PointerType::getUnqual(Ty))
+ return ConstantExpr::getBitCast(GV, PointerType::getUnqual(Ty));
+
+ // Otherwise, we just found the existing function or a prototype.
+ return GV;
+}
+
//===----------------------------------------------------------------------===//
// Methods for easy access to the global variables in the module.
//