Add simple interface for protecting runtime functions from name

collisions.
 - Provide CodeGenModule::CreateRuntimeFunction which guarantees that
   the function it creates will have the provided name in the final
   module. This allows the runtime to have its functions protected
   from declarations of the same name in the source code.

 - One could argue that this is a reason to abuse the llvm::Module
   namespace for dealing with function redeclarations. However, that
   approach seems conceptually flawed to me. This one also happens to
   be somewhat more efficient.

No functionality change.

llvm-svn: 56899
This commit is contained in:
Daniel Dunbar
2008-10-01 00:49:24 +00:00
parent 1df16dff64
commit 23fd462f48
2 changed files with 56 additions and 0 deletions

View File

@@ -63,6 +63,7 @@ void CodeGenModule::Release() {
EmitCtorList(GlobalCtors, "llvm.global_ctors");
EmitCtorList(GlobalDtors, "llvm.global_dtors");
EmitAnnotations();
BindRuntimeFunctions();
// Run the verifier to check that the generated code is consistent.
if (verifyModule(TheModule, llvm::PrintMessageAction)) {
TheModule.dump();
@@ -70,6 +71,38 @@ void CodeGenModule::Release() {
}
}
void CodeGenModule::BindRuntimeFunctions() {
// Deal with protecting runtime function names.
for (unsigned i = 0, e = RuntimeFunctions.size(); i < e; ++i) {
llvm::Function *Fn = RuntimeFunctions[i].first;
const std::string &Name = RuntimeFunctions[i].second;
// See if there is a conflict against a function.
llvm::Function *Conflict = TheModule.getFunction(Name);
if (Conflict) {
// Decide which version to take. If the conflict is a definition
// we are forced to take that, otherwise assume the runtime
// knows best.
if (!Conflict->isDeclaration()) {
llvm::Value *Casted =
llvm::ConstantExpr::getBitCast(Conflict, Fn->getType());
Fn->replaceAllUsesWith(Casted);
Fn->eraseFromParent();
} else {
Fn->takeName(Conflict);
llvm::Value *Casted =
llvm::ConstantExpr::getBitCast(Fn, Conflict->getType());
Conflict->replaceAllUsesWith(Casted);
Conflict->eraseFromParent();
}
} else {
// FIXME: There still may be conflicts with aliases and
// variables.
Fn->setName(Name);
}
}
}
/// ErrorUnsupported - Print out an error that codegen doesn't support the
/// specified stmt yet.
void CodeGenModule::ErrorUnsupported(const Stmt *S, const char *Type,
@@ -655,6 +688,16 @@ void CodeGenModule::EmitGlobalFunctionDefinition(const FunctionDecl *D) {
}
}
llvm::Function *
CodeGenModule::CreateRuntimeFunction(const llvm::FunctionType *FTy,
const std::string &Name) {
llvm::Function *Fn = llvm::Function::Create(FTy,
llvm::Function::ExternalLinkage,
"", &TheModule);
RuntimeFunctions.push_back(std::make_pair(Fn, Name));
return Fn;
}
void CodeGenModule::UpdateCompletedType(const TagDecl *TD) {
// Make sure that this type is translated.
Types.UpdateCompletedType(TD);