From 94abb8ffedef9a2550626b71b11d131ed19dcb6c Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Mon, 9 Dec 2013 04:29:47 +0000 Subject: [PATCH] Avoid adding some decls to DeferredDeclsToEmit. Before this patch GetOrCreateLLVMFunction would add a decl to DeferredDeclsToEmit even when it was being called by the function trying to emit that decl. llvm-svn: 196753 --- clang/lib/CodeGen/CGCXX.cpp | 20 +++-- clang/lib/CodeGen/CGVTables.cpp | 3 +- clang/lib/CodeGen/CodeGenModule.cpp | 119 +++++++++++++++------------- clang/lib/CodeGen/CodeGenModule.h | 23 +++--- 4 files changed, 90 insertions(+), 75 deletions(-) diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index 2ba6edca43b2..a17b5132a862 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -205,8 +205,8 @@ void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *ctor, const CGFunctionInfo &fnInfo = getTypes().arrangeCXXConstructorDeclaration(ctor, ctorType); - llvm::Function *fn = - cast(GetAddrOfCXXConstructor(ctor, ctorType, &fnInfo)); + llvm::Function *fn = cast( + GetAddrOfCXXConstructor(ctor, ctorType, &fnInfo, true)); setFunctionLinkage(GlobalDecl(ctor, ctorType), fn); CodeGenFunction(*this).GenerateCode(GlobalDecl(ctor, ctorType), fn, fnInfo); @@ -218,7 +218,8 @@ void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *ctor, llvm::GlobalValue * CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *ctor, CXXCtorType ctorType, - const CGFunctionInfo *fnInfo) { + const CGFunctionInfo *fnInfo, + bool DontDefer) { GlobalDecl GD(ctor, ctorType); StringRef name = getMangledName(GD); @@ -230,7 +231,8 @@ CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *ctor, llvm::FunctionType *fnType = getTypes().GetFunctionType(*fnInfo); return cast(GetOrCreateLLVMFunction(name, fnType, GD, - /*ForVTable=*/false)); + /*ForVTable=*/false, + DontDefer)); } void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *dtor, @@ -260,8 +262,8 @@ void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *dtor, const CGFunctionInfo &fnInfo = getTypes().arrangeCXXDestructor(dtor, dtorType); - llvm::Function *fn = - cast(GetAddrOfCXXDestructor(dtor, dtorType, &fnInfo)); + llvm::Function *fn = cast( + GetAddrOfCXXDestructor(dtor, dtorType, &fnInfo, 0, true)); setFunctionLinkage(GlobalDecl(dtor, dtorType), fn); CodeGenFunction(*this).GenerateCode(GlobalDecl(dtor, dtorType), fn, fnInfo); @@ -274,7 +276,8 @@ llvm::GlobalValue * CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *dtor, CXXDtorType dtorType, const CGFunctionInfo *fnInfo, - llvm::FunctionType *fnType) { + llvm::FunctionType *fnType, + bool DontDefer) { GlobalDecl GD(dtor, dtorType); StringRef name = getMangledName(GD); @@ -286,7 +289,8 @@ CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *dtor, fnType = getTypes().GetFunctionType(*fnInfo); } return cast(GetOrCreateLLVMFunction(name, fnType, GD, - /*ForVTable=*/false)); + /*ForVTable=*/false, + DontDefer)); } static llvm::Value *BuildAppleKextVirtualCall(CodeGenFunction &CGF, diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 81648cbef837..894e81ca2970 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -54,7 +54,8 @@ llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD, Out.flush(); llvm::Type *Ty = getTypes().GetFunctionTypeForVTable(GD); - return GetOrCreateLLVMFunction(Name, Ty, GD, /*ForVTable=*/true); + return GetOrCreateLLVMFunction(Name, Ty, GD, /*ForVTable=*/true, + /*DontDefer*/ true); } static void setThunkVisibility(CodeGenModule &CGM, const CXXMethodDecl *MD, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 08c0d0de5c68..4f7886b34d1d 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1374,6 +1374,7 @@ llvm::Constant * CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName, llvm::Type *Ty, GlobalDecl GD, bool ForVTable, + bool DontDefer, llvm::AttributeSet ExtraAttrs) { const Decl *D = GD.getDecl(); @@ -1393,14 +1394,6 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName, return llvm::ConstantExpr::getBitCast(Entry, Ty->getPointerTo()); } - // All MSVC dtors other than the base dtor are linkonce_odr and delegate to - // each other bottoming out with the base dtor. Therefore we emit non-base - // dtors on usage, even if there is no dtor definition in the TU. - if (D && isa(D) && - getCXXABI().useThunkForDtorVariant(cast(D), - GD.getDtorType())) - DeferredDeclsToEmit.push_back(GD); - // This function doesn't have a complete type (for example, the return // type is an incomplete struct). Use a fake type instead, and make // sure not to try to set attributes. @@ -1428,50 +1421,64 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName, B)); } - // This is the first use or definition of a mangled name. If there is a - // deferred decl with this name, remember that we need to emit it at the end - // of the file. - llvm::StringMap::iterator DDI = DeferredDecls.find(MangledName); - if (DDI != DeferredDecls.end()) { - // Move the potentially referenced deferred decl to the DeferredDeclsToEmit - // list, and remove it from DeferredDecls (since we don't need it anymore). - DeferredDeclsToEmit.push_back(DDI->second); - DeferredDecls.erase(DDI); + if (!DontDefer) { + // All MSVC dtors other than the base dtor are linkonce_odr and delegate to + // each other bottoming out with the base dtor. Therefore we emit non-base + // dtors on usage, even if there is no dtor definition in the TU. + if (D && isa(D) && + getCXXABI().useThunkForDtorVariant(cast(D), + GD.getDtorType())) + DeferredDeclsToEmit.push_back(GD); - // Otherwise, if this is a sized deallocation function, emit a weak definition - // for it at the end of the translation unit. - } else if (D && cast(D) - ->getCorrespondingUnsizedGlobalDeallocationFunction()) { - DeferredDeclsToEmit.push_back(GD); + // This is the first use or definition of a mangled name. If there is a + // deferred decl with this name, remember that we need to emit it at the end + // of the file. + llvm::StringMap::iterator DDI = DeferredDecls.find(MangledName); + if (DDI != DeferredDecls.end()) { + // Move the potentially referenced deferred decl to the + // DeferredDeclsToEmit list, and remove it from DeferredDecls (since we + // don't need it anymore). + DeferredDeclsToEmit.push_back(DDI->second); + DeferredDecls.erase(DDI); - // Otherwise, there are cases we have to worry about where we're - // using a declaration for which we must emit a definition but where - // we might not find a top-level definition: - // - member functions defined inline in their classes - // - friend functions defined inline in some class - // - special member functions with implicit definitions - // If we ever change our AST traversal to walk into class methods, - // this will be unnecessary. - // - // We also don't emit a definition for a function if it's going to be an entry - // in a vtable, unless it's already marked as used. - } else if (getLangOpts().CPlusPlus && D) { - // Look for a declaration that's lexically in a record. - const FunctionDecl *FD = cast(D); - FD = FD->getMostRecentDecl(); - do { - if (isa(FD->getLexicalDeclContext())) { - if (FD->isImplicit() && !ForVTable) { - assert(FD->isUsed() && "Sema didn't mark implicit function as used!"); - DeferredDeclsToEmit.push_back(GD.getWithDecl(FD)); - break; - } else if (FD->doesThisDeclarationHaveABody()) { - DeferredDeclsToEmit.push_back(GD.getWithDecl(FD)); - break; + // Otherwise, if this is a sized deallocation function, emit a weak + // definition + // for it at the end of the translation unit. + } else if (D && cast(D) + ->getCorrespondingUnsizedGlobalDeallocationFunction()) { + DeferredDeclsToEmit.push_back(GD); + + // Otherwise, there are cases we have to worry about where we're + // using a declaration for which we must emit a definition but where + // we might not find a top-level definition: + // - member functions defined inline in their classes + // - friend functions defined inline in some class + // - special member functions with implicit definitions + // If we ever change our AST traversal to walk into class methods, + // this will be unnecessary. + // + // We also don't emit a definition for a function if it's going to be an + // entry + // in a vtable, unless it's already marked as used. + } else if (getLangOpts().CPlusPlus && D) { + // Look for a declaration that's lexically in a record. + const FunctionDecl *FD = cast(D); + FD = FD->getMostRecentDecl(); + do { + if (isa(FD->getLexicalDeclContext())) { + if (FD->isImplicit() && !ForVTable) { + assert(FD->isUsed() && + "Sema didn't mark implicit function as used!"); + DeferredDeclsToEmit.push_back(GD.getWithDecl(FD)); + break; + } else if (FD->doesThisDeclarationHaveABody()) { + DeferredDeclsToEmit.push_back(GD.getWithDecl(FD)); + break; + } } - } - FD = FD->getPreviousDecl(); - } while (FD); + FD = FD->getPreviousDecl(); + } while (FD); + } } // Make sure the result is of the requested type. @@ -1489,13 +1496,14 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName, /// create it (this occurs when we see a definition of the function). llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty, - bool ForVTable) { + bool ForVTable, + bool DontDefer) { // If there was no specific requested type, just convert it now. if (!Ty) Ty = getTypes().ConvertType(cast(GD.getDecl())->getType()); StringRef MangledName = getMangledName(GD); - return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable); + return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable, DontDefer); } /// CreateRuntimeFunction - Create a new runtime function with the specified @@ -1504,9 +1512,9 @@ llvm::Constant * CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name, llvm::AttributeSet ExtraAttrs) { - llvm::Constant *C - = GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false, - ExtraAttrs); + llvm::Constant *C = + GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false, + /*DontDefer=*/false, ExtraAttrs); if (llvm::Function *F = dyn_cast(C)) if (F->empty()) F->setCallingConv(getRuntimeCC()); @@ -2090,7 +2098,8 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) { llvm::FunctionType *Ty = getTypes().GetFunctionType(FI); // Get or create the prototype for the function. - llvm::Constant *Entry = GetAddrOfFunction(GD, Ty); + llvm::Constant *Entry = + GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer*/ true); // Strip off a bitcast if we got one back. if (llvm::ConstantExpr *CE = dyn_cast(Entry)) { diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index c16122405d43..098aa0355280 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -639,9 +639,9 @@ public: /// GetAddrOfFunction - Return the address of the given function. If Ty is /// non-null, then this function will use the specified type if it has to /// create it. - llvm::Constant *GetAddrOfFunction(GlobalDecl GD, - llvm::Type *Ty = 0, - bool ForVTable = false); + llvm::Constant *GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty = 0, + bool ForVTable = false, + bool DontDefer = false); /// GetAddrOfRTTIDescriptor - Get the address of the RTTI descriptor /// for the given type. @@ -769,14 +769,16 @@ public: /// given type. llvm::GlobalValue *GetAddrOfCXXConstructor(const CXXConstructorDecl *ctor, CXXCtorType ctorType, - const CGFunctionInfo *fnInfo = 0); + const CGFunctionInfo *fnInfo = 0, + bool DontDefer = false); /// GetAddrOfCXXDestructor - Return the address of the constructor of the /// given type. llvm::GlobalValue *GetAddrOfCXXDestructor(const CXXDestructorDecl *dtor, CXXDtorType dtorType, const CGFunctionInfo *fnInfo = 0, - llvm::FunctionType *fnType = 0); + llvm::FunctionType *fnType = 0, + bool DontDefer = false); /// getBuiltinLibFunction - Given a builtin id for a function like /// "__builtin_fabsf", return a Function* for "fabsf". @@ -1009,12 +1011,11 @@ public: private: llvm::GlobalValue *GetGlobalValue(StringRef Ref); - llvm::Constant *GetOrCreateLLVMFunction(StringRef MangledName, - llvm::Type *Ty, - GlobalDecl D, - bool ForVTable, - llvm::AttributeSet ExtraAttrs = - llvm::AttributeSet()); + llvm::Constant * + GetOrCreateLLVMFunction(StringRef MangledName, llvm::Type *Ty, GlobalDecl D, + bool ForVTable, bool DontDefer = false, + llvm::AttributeSet ExtraAttrs = llvm::AttributeSet()); + llvm::Constant *GetOrCreateLLVMGlobal(StringRef MangledName, llvm::PointerType *PTy, const VarDecl *D,