summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2012-03-30 04:25:14 +0000
committerJohn McCall <rjmccall@apple.com>2012-03-30 04:25:14 +0000
commit947c1830e4a7e620de7991dea033755f0265b15b (patch)
treee0c4bef92b89e654532dde536cf421df20a5e6be /clang/lib
parent8831303e4fb337d8468ec201011e6247d5d6dfc8 (diff)
downloadbcm5719-llvm-947c1830e4a7e620de7991dea033755f0265b15b.tar.gz
bcm5719-llvm-947c1830e4a7e620de7991dea033755f0265b15b.zip
When emitting a static local variable in C++, handle
the case that the variable already exists. Partly this is just protection against people making crazy declarations with custom asm labels or extern "C" names that intentionally collide with the manglings of such variables, but the main reason is that we can actually emit a static local variable twice with the requirement that it match up. There may be other cases with (e.g.) the various nested functions, but the main exemplar is with constructor variants, where we can be forced into double-emitting the function body under certain circumstances like (currently) the presence of virtual bases. llvm-svn: 153723
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp18
-rw-r--r--clang/lib/CodeGen/ItaniumCXXABI.cpp80
2 files changed, 67 insertions, 31 deletions
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 970f0b2389f..d6d66968948 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -184,6 +184,24 @@ CodeGenFunction::CreateStaticVarDecl(const VarDecl &D,
Name = GetStaticDeclName(*this, D, Separator);
llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(Ty);
+
+ // In C++, there are strange possibilities here involving the
+ // double-emission of constructors and destructors.
+ if (CGM.getLangOpts().CPlusPlus) {
+ llvm::GlobalValue *value = CGM.getModule().getNamedValue(Name);
+ if (value && isa<llvm::GlobalVariable>(value) &&
+ value->getType() ==
+ LTy->getPointerTo(CGM.getContext().getTargetAddressSpace(Ty)))
+ return cast<llvm::GlobalVariable>(value);
+
+ if (value) {
+ CGM.Error(D.getLocation(),
+ "problem emitting static variable: already present as "
+ "different kind of symbol");
+ // Fall through and implicitly give it a uniqued name.
+ }
+ }
+
llvm::GlobalVariable *GV =
new llvm::GlobalVariable(CGM.getModule(), LTy,
Ty.isConstant(getContext()), Linkage,
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 6fcf83d5ace..8cce8c90a07 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -1051,7 +1051,7 @@ static llvm::Constant *getGuardAbortFn(CodeGenModule &CGM,
namespace {
struct CallGuardAbort : EHScopeStack::Cleanup {
llvm::GlobalVariable *Guard;
- CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
+ CallGuardAbort(llvm::GlobalVariable *guard) : Guard(guard) {}
void Emit(CodeGenFunction &CGF, Flags flags) {
CGF.Builder.CreateCall(getGuardAbortFn(CGF.CGM, Guard->getType()), Guard)
@@ -1073,35 +1073,54 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
bool threadsafe =
(getContext().getLangOpts().ThreadsafeStatics && D.isLocalVarDecl());
- llvm::IntegerType *GuardTy;
+ llvm::IntegerType *guardTy;
// If we have a global variable with internal linkage and thread-safe statics
// are disabled, we can just let the guard variable be of type i8.
bool useInt8GuardVariable = !threadsafe && GV->hasInternalLinkage();
if (useInt8GuardVariable) {
- GuardTy = CGF.Int8Ty;
+ guardTy = CGF.Int8Ty;
} else {
// Guard variables are 64 bits in the generic ABI and 32 bits on ARM.
- GuardTy = (IsARM ? CGF.Int32Ty : CGF.Int64Ty);
+ guardTy = (IsARM ? CGF.Int32Ty : CGF.Int64Ty);
}
- llvm::PointerType *GuardPtrTy = GuardTy->getPointerTo();
+ llvm::PointerType *guardPtrTy = guardTy->getPointerTo();
// Create the guard variable.
- SmallString<256> GuardVName;
- llvm::raw_svector_ostream Out(GuardVName);
- getMangleContext().mangleItaniumGuardVariable(&D, Out);
- Out.flush();
-
- // Just absorb linkage and visibility from the variable.
- llvm::GlobalVariable *GuardVariable =
- new llvm::GlobalVariable(CGM.getModule(), GuardTy,
- false, GV->getLinkage(),
- llvm::ConstantInt::get(GuardTy, 0),
- GuardVName.str());
- GuardVariable->setVisibility(GV->getVisibility());
+ SmallString<256> guardName;
+ {
+ llvm::raw_svector_ostream out(guardName);
+ getMangleContext().mangleItaniumGuardVariable(&D, out);
+ out.flush();
+ }
+ // There are strange possibilities here involving the
+ // double-emission of constructors and destructors.
+ llvm::GlobalVariable *guard = nullptr;
+ if (llvm::GlobalValue *existingGuard
+ = CGM.getModule().getNamedValue(guardName.str())) {
+ if (isa<llvm::GlobalVariable>(existingGuard) &&
+ existingGuard->getType() == guardPtrTy) {
+ guard = cast<llvm::GlobalVariable>(existingGuard); // okay
+ } else {
+ CGM.Error(D.getLocation(),
+ "problem emitting guard for static variable: "
+ "already present as different kind of symbol");
+ // Fall through and implicitly give it a uniqued name.
+ }
+ }
+
+ if (!guard) {
+ // Just absorb linkage and visibility from the variable.
+ guard = new llvm::GlobalVariable(CGM.getModule(), guardTy,
+ false, GV->getLinkage(),
+ llvm::ConstantInt::get(guardTy, 0),
+ guardName.str());
+ guard->setVisibility(GV->getVisibility());
+ }
+
// Test whether the variable has completed initialization.
- llvm::Value *IsInitialized;
+ llvm::Value *isInitialized;
// ARM C++ ABI 3.2.3.1:
// To support the potential use of initialization guard variables
@@ -1115,9 +1134,9 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
// ...
// }
if (IsARM && !useInt8GuardVariable) {
- llvm::Value *V = Builder.CreateLoad(GuardVariable);
+ llvm::Value *V = Builder.CreateLoad(guard);
V = Builder.CreateAnd(V, Builder.getInt32(1));
- IsInitialized = Builder.CreateIsNull(V, "guard.uninitialized");
+ isInitialized = Builder.CreateIsNull(V, "guard.uninitialized");
// Itanium C++ ABI 3.3.2:
// The following is pseudo-code showing how these functions can be used:
@@ -1135,10 +1154,9 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
// }
} else {
// Load the first byte of the guard variable.
- llvm::Type *PtrTy = Builder.getInt8PtrTy();
- llvm::LoadInst *LI =
- Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy));
- LI->setAlignment(1);
+ llvm::LoadInst *load =
+ Builder.CreateLoad(Builder.CreateBitCast(guard, CGM.Int8PtrTy));
+ load->setAlignment(1);
// Itanium ABI:
// An implementation supporting thread-safety on multiprocessor
@@ -1147,16 +1165,16 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
//
// In LLVM, we do this by marking the load Acquire.
if (threadsafe)
- LI->setAtomic(llvm::Acquire);
+ load->setAtomic(llvm::Acquire);
- IsInitialized = Builder.CreateIsNull(LI, "guard.uninitialized");
+ isInitialized = Builder.CreateIsNull(load, "guard.uninitialized");
}
llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check");
llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
// Check if the first byte of the guard variable is zero.
- Builder.CreateCondBr(IsInitialized, InitCheckBlock, EndBlock);
+ Builder.CreateCondBr(isInitialized, InitCheckBlock, EndBlock);
CGF.EmitBlock(InitCheckBlock);
@@ -1164,7 +1182,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
if (threadsafe) {
// Call __cxa_guard_acquire.
llvm::Value *V
- = Builder.CreateCall(getGuardAcquireFn(CGM, GuardPtrTy), GuardVariable);
+ = Builder.CreateCall(getGuardAcquireFn(CGM, guardPtrTy), guard);
llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init");
@@ -1172,7 +1190,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
InitBlock, EndBlock);
// Call __cxa_guard_abort along the exceptional edge.
- CGF.EHStack.pushCleanup<CallGuardAbort>(EHCleanup, GuardVariable);
+ CGF.EHStack.pushCleanup<CallGuardAbort>(EHCleanup, guard);
CGF.EmitBlock(InitBlock);
}
@@ -1185,9 +1203,9 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
CGF.PopCleanupBlock();
// Call __cxa_guard_release. This cannot throw.
- Builder.CreateCall(getGuardReleaseFn(CGM, GuardPtrTy), GuardVariable);
+ Builder.CreateCall(getGuardReleaseFn(CGM, guardPtrTy), guard);
} else {
- Builder.CreateStore(llvm::ConstantInt::get(GuardTy, 1), GuardVariable);
+ Builder.CreateStore(llvm::ConstantInt::get(guardTy, 1), guard);
}
CGF.EmitBlock(EndBlock);
OpenPOWER on IntegriCloud