diff options
author | Chandler Carruth <chandlerc@gmail.com> | 2012-03-30 19:44:53 +0000 |
---|---|---|
committer | Chandler Carruth <chandlerc@gmail.com> | 2012-03-30 19:44:53 +0000 |
commit | 0f30a12ce7b3d4d86c9ca9072f587da77c8eef34 (patch) | |
tree | 7065652fa4ad45d8dce3c6cb377f1c8c0f904cab /lib/CodeGen/ItaniumCXXABI.cpp | |
parent | 40afb7d4f3840e5b9dcdf77086d9e4843fd5463a (diff) |
Revert r153723, and its follow-ups r153728 and r153733.
These patches cause us to miscompile and/or reject code with static
function-local variables in an extern-C context. Previously, we were
papering over this as long as the variables are within the same
translation unit, and had not seen any failures in the wild. We still
need a proper fix, which involves mangling static locals inside of an
extern-C block (as GCC already does), but this patch causes pretty
widespread regressions. Firefox, and many other applications no longer
build.
Lots of test cases have been posted to the list in response to this
commit, so there should be no problem reproducing the issues.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153768 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/ItaniumCXXABI.cpp')
-rw-r--r-- | lib/CodeGen/ItaniumCXXABI.cpp | 94 |
1 files changed, 35 insertions, 59 deletions
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index ce16c86b8d..6fcf83d5ac 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -123,7 +123,7 @@ public: llvm::Value *&AllocPtr, CharUnits &CookieSize); void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, - llvm::Constant *addr, bool PerformInit); + llvm::GlobalVariable *DeclPtr, bool PerformInit); }; class ARMCXXABI : public ItaniumCXXABI { @@ -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) @@ -1064,7 +1064,7 @@ namespace { /// just special-case it at particular places. void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, - llvm::Constant *varAddr, + llvm::GlobalVariable *GV, bool PerformInit) { CGBuilderTy &Builder = CGF.Builder; @@ -1073,60 +1073,35 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, bool threadsafe = (getContext().getLangOpts().ThreadsafeStatics && D.isLocalVarDecl()); - llvm::IntegerType *guardTy; - - // Find the underlying global variable for linkage purposes. - // This may not have the right type for actual evaluation purposes. - llvm::GlobalVariable *var = - cast<llvm::GlobalVariable>(varAddr->stripPointerCasts()); + 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 && var->hasInternalLinkage(); + 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> guardName; - { - llvm::raw_svector_ostream out(guardName); - getMangleContext().mangleItaniumGuardVariable(&D, out); - out.flush(); - } + 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()); - // There are strange possibilities here involving the - // double-emission of constructors and destructors. - llvm::GlobalVariable *guard = 0; - 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 static variable '" - + guardName.str() + - "': 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, var->getLinkage(), - llvm::ConstantInt::get(guardTy, 0), - guardName.str()); - guard->setVisibility(var->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 @@ -1140,9 +1115,9 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, // ... // } if (IsARM && !useInt8GuardVariable) { - llvm::Value *V = Builder.CreateLoad(guard); + llvm::Value *V = Builder.CreateLoad(GuardVariable); 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: @@ -1160,9 +1135,10 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, // } } else { // Load the first byte of the guard variable. - llvm::LoadInst *load = - Builder.CreateLoad(Builder.CreateBitCast(guard, CGM.Int8PtrTy)); - load->setAlignment(1); + llvm::Type *PtrTy = Builder.getInt8PtrTy(); + llvm::LoadInst *LI = + Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy)); + LI->setAlignment(1); // Itanium ABI: // An implementation supporting thread-safety on multiprocessor @@ -1171,16 +1147,16 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, // // In LLVM, we do this by marking the load Acquire. if (threadsafe) - load->setAtomic(llvm::Acquire); + LI->setAtomic(llvm::Acquire); - isInitialized = Builder.CreateIsNull(load, "guard.uninitialized"); + IsInitialized = Builder.CreateIsNull(LI, "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); @@ -1188,7 +1164,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, if (threadsafe) { // Call __cxa_guard_acquire. llvm::Value *V - = Builder.CreateCall(getGuardAcquireFn(CGM, guardPtrTy), guard); + = Builder.CreateCall(getGuardAcquireFn(CGM, GuardPtrTy), GuardVariable); llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init"); @@ -1196,22 +1172,22 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, InitBlock, EndBlock); // Call __cxa_guard_abort along the exceptional edge. - CGF.EHStack.pushCleanup<CallGuardAbort>(EHCleanup, guard); + CGF.EHStack.pushCleanup<CallGuardAbort>(EHCleanup, GuardVariable); CGF.EmitBlock(InitBlock); } // Emit the initializer and add a global destructor if appropriate. - CGF.EmitCXXGlobalVarDeclInit(D, varAddr, PerformInit); + CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit); if (threadsafe) { // Pop the guard-abort cleanup if we pushed one. CGF.PopCleanupBlock(); // Call __cxa_guard_release. This cannot throw. - Builder.CreateCall(getGuardReleaseFn(CGM, guardPtrTy), guard); + Builder.CreateCall(getGuardReleaseFn(CGM, GuardPtrTy), GuardVariable); } else { - Builder.CreateStore(llvm::ConstantInt::get(guardTy, 1), guard); + Builder.CreateStore(llvm::ConstantInt::get(GuardTy, 1), GuardVariable); } CGF.EmitBlock(EndBlock); |