diff options
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 50 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 5 | ||||
-rw-r--r-- | clang/test/CodeGen/constructor-attribute.c | 20 |
3 files changed, 58 insertions, 17 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 69af3d265c9..ecfd8c98c32 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -429,7 +429,7 @@ void CodeGenModule::EmitDeferred() { // FIXME: The AST should have some sort of aggregate decls or // global symbol map. // FIXME: This is missing some important cases. For example, we - // need to check for uses in an alias and in a constructor. + // need to check for uses in an alias. if (!GlobalDeclMap.count(getMangledName(D))) { i++; continue; @@ -491,10 +491,31 @@ llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV, return llvm::ConstantStruct::get(Fields, 4, false); } -void CodeGenModule::EmitGlobal(const ValueDecl *Global) { - bool isDef, isStatic; +bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) { + // Never defer when EmitAllDecls is specified. + if (Features.EmitAllDecls) + return false; if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) { + // Constructors and destructors should never be deferred. + if (FD->getAttr<ConstructorAttr>() || FD->getAttr<DestructorAttr>()) + return false; + + if (FD->getStorageClass() != FunctionDecl::Static) + return false; + } else { + const VarDecl *VD = cast<VarDecl>(Global); + assert(VD->isFileVarDecl() && "Invalid decl."); + + if (VD->getStorageClass() != VarDecl::Static) + return false; + } + + return true; +} + +void CodeGenModule::EmitGlobal(const ValueDecl *Global) { + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) { // Aliases are deferred until code for everything else has been // emitted. if (FD->getAttr<AliasAttr>()) { @@ -504,25 +525,22 @@ void CodeGenModule::EmitGlobal(const ValueDecl *Global) { return; } - isDef = FD->isThisDeclarationADefinition(); - isStatic = FD->getStorageClass() == FunctionDecl::Static; + // Forward declarations are emitted lazily on first use. + if (!FD->isThisDeclarationADefinition()) + return; } else { const VarDecl *VD = cast<VarDecl>(Global); assert(VD->isFileVarDecl() && "Cannot emit local var decl as global."); - isDef = !((VD->getStorageClass() == VarDecl::Extern || - VD->getStorageClass() == VarDecl::PrivateExtern) && - VD->getInit() == 0); - isStatic = VD->getStorageClass() == VarDecl::Static; + // Forward declarations are emitted lazily on first use. + if ((VD->getStorageClass() == VarDecl::Extern || + VD->getStorageClass() == VarDecl::PrivateExtern) && + VD->getInit() == 0) + return; } - // Forward declarations are emitted lazily on first use. - if (!isDef) - return; - - // If the global is a static, defer code generation until later so - // we can easily omit unused statics. - if (isStatic && !Features.EmitAllDecls) { + // Defer code generation when possible. + if (MayDeferGeneration(Global)) { DeferredDecls.push_back(Global); return; } diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 1d10f9d1e39..967889a92df 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -324,6 +324,11 @@ private: void EmitLLVMUsed(void); void BindRuntimeFunctions(); + + /// MayDeferGeneration - Determine if the given decl can be emitted + /// lazily; this is only relevant for definitions. The given decl + /// must be either a function or var decl. + bool MayDeferGeneration(const ValueDecl *D); }; } // end namespace CodeGen } // end namespace clang diff --git a/clang/test/CodeGen/constructor-attribute.c b/clang/test/CodeGen/constructor-attribute.c index 0ecc47babfe..f75fa4f7fac 100644 --- a/clang/test/CodeGen/constructor-attribute.c +++ b/clang/test/CodeGen/constructor-attribute.c @@ -1,6 +1,8 @@ // RUN: clang -emit-llvm -o %t %s && // RUN: grep -e "global_ctors.*@A" %t && -// RUN: grep -e "global_dtors.*@B" %t +// RUN: grep -e "global_dtors.*@B" %t && +// RUN: grep -e "global_ctors.*@C" %t && +// RUN: grep -e "global_dtors.*@D" %t #include <stdio.h> @@ -15,6 +17,22 @@ void B() { printf("B\n"); } +static void C() __attribute__((constructor)); + +static void D() __attribute__((destructor)); + +static int foo() { + return 10; +} + +static void C() { + printf("A: %d\n", foo()); +} + +static void D() { + printf("B\n"); +} + int main() { return 0; } |