From 355bba72ca52c4a70ca3c3802412c03a6ec31f24 Mon Sep 17 00:00:00 2001 From: John McCall Date: Fri, 30 Mar 2012 21:00:39 +0000 Subject: Make sure we unique static-local decls across multiple emissions of the function body, but do so in a way that doesn't make any assumptions about the static local actually having a proper, unique mangling, since apparently we don't do that correctly at all. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153776 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDecl.cpp | 42 ++++++++++++++---------- lib/CodeGen/CodeGenModule.h | 9 +++++ lib/CodeGen/ItaniumCXXABI.cpp | 76 ++++++++++++++++++++++++------------------- 3 files changed, 76 insertions(+), 51 deletions(-) (limited to 'lib/CodeGen') diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 970f0b2389..8c154f0708 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -273,11 +273,23 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D, llvm::Value *&DMEntry = LocalDeclMap[&D]; assert(DMEntry == 0 && "Decl already exists in localdeclmap!"); - llvm::GlobalVariable *GV = CreateStaticVarDecl(D, ".", Linkage); + // Check to see if we already have a global variable for this + // declaration. This can happen when double-emitting function + // bodies, e.g. with complete and base constructors. + llvm::Constant *addr = + CGM.getStaticLocalDeclAddress(&D); + + llvm::GlobalVariable *var; + if (addr) { + var = cast(addr->stripPointerCasts()); + } else { + addr = var = CreateStaticVarDecl(D, ".", Linkage); + } // Store into LocalDeclMap before generating initializer to handle // circular references. - DMEntry = GV; + DMEntry = addr; + CGM.setStaticLocalDeclAddress(&D, addr); // We can't have a VLA here, but we can have a pointer to a VLA, // even though that doesn't really make any sense. @@ -285,42 +297,38 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D, if (D.getType()->isVariablyModifiedType()) EmitVariablyModifiedType(D.getType()); - // Local static block variables must be treated as globals as they may be - // referenced in their RHS initializer block-literal expresion. - CGM.setStaticLocalDeclAddress(&D, GV); + // Save the type in case adding the initializer forces a type change. + llvm::Type *expectedType = addr->getType(); // If this value has an initializer, emit it. if (D.getInit()) - GV = AddInitializerToStaticVarDecl(D, GV); + var = AddInitializerToStaticVarDecl(D, var); - GV->setAlignment(getContext().getDeclAlign(&D).getQuantity()); + var->setAlignment(getContext().getDeclAlign(&D).getQuantity()); if (D.hasAttr()) - CGM.AddGlobalAnnotations(&D, GV); + CGM.AddGlobalAnnotations(&D, var); if (const SectionAttr *SA = D.getAttr()) - GV->setSection(SA->getName()); + var->setSection(SA->getName()); if (D.hasAttr()) - CGM.AddUsedGlobal(GV); + CGM.AddUsedGlobal(var); // We may have to cast the constant because of the initializer // mismatch above. // // FIXME: It is really dangerous to store this in the map; if anyone // RAUW's the GV uses of this constant will be invalid. - llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(D.getType()); - llvm::Type *LPtrTy = - LTy->getPointerTo(CGM.getContext().getTargetAddressSpace(D.getType())); - llvm::Constant *CastedVal = llvm::ConstantExpr::getBitCast(GV, LPtrTy); - DMEntry = CastedVal; - CGM.setStaticLocalDeclAddress(&D, CastedVal); + llvm::Constant *castedAddr = llvm::ConstantExpr::getBitCast(var, expectedType); + DMEntry = castedAddr; + CGM.setStaticLocalDeclAddress(&D, castedAddr); // Emit global variable debug descriptor for static vars. CGDebugInfo *DI = getDebugInfo(); if (DI) { DI->setLocation(D.getLocation()); - DI->EmitGlobalVariable(static_cast(GV), &D); + DI->EmitGlobalVariable(var, &D); } } diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 5719afb612..38f5008d89 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -280,6 +280,7 @@ class CodeGenModule : public CodeGenTypeCache { llvm::StringMap CFConstantStringMap; llvm::StringMap ConstantStringMap; llvm::DenseMap StaticLocalDeclMap; + llvm::DenseMap StaticLocalDeclGuardMap; llvm::DenseMap AtomicSetterHelperFnMap; llvm::DenseMap AtomicGetterHelperFnMap; @@ -405,6 +406,14 @@ public: StaticLocalDeclMap[D] = C; } + llvm::GlobalVariable *getStaticLocalDeclGuardAddress(const VarDecl *D) { + return StaticLocalDeclGuardMap[D]; + } + void setStaticLocalDeclGuardAddress(const VarDecl *D, + llvm::GlobalVariable *C) { + StaticLocalDeclGuardMap[D] = C; + } + llvm::Constant *getAtomicSetterHelperFnMap(QualType Ty) { return AtomicSetterHelperFnMap[Ty]; } diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 6fcf83d5ac..98f67f34df 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -1064,8 +1064,8 @@ namespace { /// just special-case it at particular places. void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, - llvm::GlobalVariable *GV, - bool PerformInit) { + llvm::GlobalVariable *var, + bool shouldPerformInit) { CGBuilderTy &Builder = CGF.Builder; // We only need to use thread-safe statics for local variables; @@ -1073,35 +1073,44 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, bool threadsafe = (getContext().getLangOpts().ThreadsafeStatics && D.isLocalVarDecl()); - 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(); + bool useInt8GuardVariable = !threadsafe && var->hasInternalLinkage(); + + llvm::IntegerType *guardTy; 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(); + + // Create the guard variable if we don't already have it (as we + // might if we're double-emitting this function body). + llvm::GlobalVariable *guard = CGM.getStaticLocalDeclGuardAddress(&D); + if (!guard) { + // Mangle the name for the guard. + SmallString<256> guardName; + { + llvm::raw_svector_ostream out(guardName); + getMangleContext().mangleItaniumGuardVariable(&D, out); + out.flush(); + } + + // Create the guard variable with a zero-initializer. + // Just absorb linkage and visibility from the guarded variable. + guard = new llvm::GlobalVariable(CGM.getModule(), guardTy, + false, var->getLinkage(), + llvm::ConstantInt::get(guardTy, 0), + guardName.str()); + guard->setVisibility(var->getVisibility()); + + CGM.setStaticLocalDeclGuardAddress(&D, guard); } - 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()); // 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 +1124,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,9 +1144,8 @@ 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)); + Builder.CreateLoad(Builder.CreateBitCast(guard, CGM.Int8PtrTy)); LI->setAlignment(1); // Itanium ABI: @@ -1149,14 +1157,14 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, if (threadsafe) LI->setAtomic(llvm::Acquire); - IsInitialized = Builder.CreateIsNull(LI, "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); @@ -1164,7 +1172,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,22 +1180,22 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, InitBlock, EndBlock); // Call __cxa_guard_abort along the exceptional edge. - CGF.EHStack.pushCleanup(EHCleanup, GuardVariable); + CGF.EHStack.pushCleanup(EHCleanup, guard); CGF.EmitBlock(InitBlock); } // Emit the initializer and add a global destructor if appropriate. - CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit); + CGF.EmitCXXGlobalVarDeclInit(D, var, shouldPerformInit); 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), 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); -- cgit v1.2.3