diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 091158daba75..69af3d265c9c 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -60,7 +60,7 @@ CodeGenModule::~CodeGenModule() { } void CodeGenModule::Release() { - EmitStatics(); + EmitDeferred(); EmitAliases(); if (Runtime) if (llvm::Function *ObjCInitFunction = Runtime->ModuleInitFunction()) @@ -68,6 +68,7 @@ void CodeGenModule::Release() { EmitCtorList(GlobalCtors, "llvm.global_ctors"); EmitCtorList(GlobalDtors, "llvm.global_dtors"); EmitAnnotations(); + EmitLLVMUsed(); BindRuntimeFunctions(); } @@ -388,16 +389,40 @@ void CodeGenModule::EmitAliases() { } } -void CodeGenModule::EmitStatics() { - // Emit code for each used static decl encountered. Since a previously unused - // static decl may become used during the generation of code for a static - // function, iterate until no changes are made. +void CodeGenModule::AddUsedGlobal(llvm::GlobalValue *GV) { + assert(!GV->isDeclaration() && + "Only globals with definition can force usage."); + llvm::Type *i8PTy = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + LLVMUsed.push_back(llvm::ConstantExpr::getBitCast(GV, i8PTy)); +} + +void CodeGenModule::EmitLLVMUsed() { + // Don't create llvm.used if there is no need. + if (LLVMUsed.empty()) + return; + + llvm::ArrayType *ATy = llvm::ArrayType::get(LLVMUsed[0]->getType(), + LLVMUsed.size()); + llvm::GlobalVariable *GV = + new llvm::GlobalVariable(ATy, false, + llvm::GlobalValue::AppendingLinkage, + llvm::ConstantArray::get(ATy, LLVMUsed), + "llvm.used", &getModule()); + + GV->setSection("llvm.metadata"); +} + +void CodeGenModule::EmitDeferred() { + // Emit code for any deferred decl which was used. Since a + // previously unused static decl may become used during the + // generation of code for a static function, iterate until no + // changes are made. bool Changed; do { Changed = false; - for (std::list::iterator i = StaticDecls.begin(), - e = StaticDecls.end(); i != e; ) { + for (std::list::iterator i = DeferredDecls.begin(), + e = DeferredDecls.end(); i != e; ) { const ValueDecl *D = *i; // Check if we have used a decl with the same name @@ -414,7 +439,7 @@ void CodeGenModule::EmitStatics() { EmitGlobalDefinition(D); // Erase the used decl from the list. - i = StaticDecls.erase(i); + i = DeferredDecls.erase(i); // Remember that we made a change. Changed = true; @@ -481,16 +506,14 @@ void CodeGenModule::EmitGlobal(const ValueDecl *Global) { isDef = FD->isThisDeclarationADefinition(); isStatic = FD->getStorageClass() == FunctionDecl::Static; - } else if (const VarDecl *VD = cast(Global)) { + } else { + const VarDecl *VD = cast(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; - } else { - assert(0 && "Invalid argument to EmitGlobal"); - return; } // Forward declarations are emitted lazily on first use. @@ -500,7 +523,7 @@ void CodeGenModule::EmitGlobal(const ValueDecl *Global) { // If the global is a static, defer code generation until later so // we can easily omit unused statics. if (isStatic && !Features.EmitAllDecls) { - StaticDecls.push_back(Global); + DeferredDecls.push_back(Global); return; } diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index bd5a20c68ce9..1d10f9d1e39f 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -95,12 +95,18 @@ class CodeGenModule { /// and may reference forward. std::vector Aliases; - /// StaticDecls - List of static global for which code generation is - /// delayed. When the translation unit has been fully processed we will lazily - /// emit definitions for only the decls that were actually used. This should - /// contain only Function and Var decls, and only those which actually define - /// something. - std::list StaticDecls; + /// DeferredDecls - List of decls for which code generation has been + /// deferred. When the translation unit has been fully processed we + /// will lazily emit definitions for only the decls that were + /// actually used. This should contain only Function and Var decls, + /// and only those which actually define something. + std::list DeferredDecls; + + /// LLVMUsed - List of global values which are required to be + /// present in the object file; bitcast to i8*. This is used for + /// forcing visibility of symbols which may otherwise be optimized + /// out. + std::vector LLVMUsed; /// GlobalCtors - Store the list of global constructors and their respective /// priorities to be emitted when the translation unit is complete. @@ -228,6 +234,11 @@ public: /// EmitTopLevelDecl - Emit code for a single top level declaration. void EmitTopLevelDecl(Decl *D); + /// AddUsedGlobal - Add a global which should be forced to be + /// present in the object file; these are emitted to the llvm.used + /// metadata global. + void AddUsedGlobal(llvm::GlobalValue *GV); + void AddAnnotation(llvm::Constant *C) { Annotations.push_back(C); } /// CreateRuntimeFunction - Create a new runtime function whose name must be @@ -303,7 +314,14 @@ private: void EmitAliases(void); void EmitAnnotations(void); - void EmitStatics(void); + + /// EmitDeferred - Emit any needed decls for which code generation + /// was deferred. + void EmitDeferred(void); + + /// EmitLLVMUsed - Emit the llvm.used metadata used to force + /// references to global which may otherwise be optimized out. + void EmitLLVMUsed(void); void BindRuntimeFunctions(); };