}
void CodeGenModule::Release() {
- EmitStatics();
+ EmitDeferred();
EmitAliases();
if (Runtime)
if (llvm::Function *ObjCInitFunction = Runtime->ModuleInitFunction())
EmitCtorList(GlobalCtors, "llvm.global_ctors");
EmitCtorList(GlobalDtors, "llvm.global_dtors");
EmitAnnotations();
+ EmitLLVMUsed();
BindRuntimeFunctions();
}
}
}
-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<const ValueDecl*>::iterator i = StaticDecls.begin(),
- e = StaticDecls.end(); i != e; ) {
+ for (std::list<const ValueDecl*>::iterator i = DeferredDecls.begin(),
+ e = DeferredDecls.end(); i != e; ) {
const ValueDecl *D = *i;
// Check if we have used a decl with the same name
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;
isDef = FD->isThisDeclarationADefinition();
isStatic = FD->getStorageClass() == FunctionDecl::Static;
- } else if (const VarDecl *VD = cast<VarDecl>(Global)) {
+ } 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;
- } else {
- assert(0 && "Invalid argument to EmitGlobal");
- return;
}
// Forward declarations are emitted lazily on first use.
// 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;
}
/// and may reference forward.
std::vector<const FunctionDecl*> 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<const ValueDecl*> 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<const ValueDecl*> 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<llvm::Constant*> LLVMUsed;
/// GlobalCtors - Store the list of global constructors and their respective
/// priorities to be emitted when the translation unit is complete.
/// 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
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();
};