]> granicus.if.org Git - clang/commitdiff
Add simple interface for protecting runtime functions from name
authorDaniel Dunbar <daniel@zuster.org>
Wed, 1 Oct 2008 00:49:24 +0000 (00:49 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Wed, 1 Oct 2008 00:49:24 +0000 (00:49 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@56899 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h

index 6c9999df2427b3a5b008f7708ca6e098cfa34446..a74f0578a5b99fccf9a409eeed544b40997a6e56 100644 (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);
index 0a4a78d33c87d72a88323fb90ca77a59bd570466..6a201be3760865a2412cffce0d6344ccf51fbd68 100644 (file)
@@ -73,6 +73,12 @@ class CodeGenModule {
   llvm::Function *MemMoveFn;
   llvm::Function *MemSetFn;
 
+  /// RuntimeFunctions - List of runtime functions whose names must be
+  /// protected from introducing conflicts. These functions should be
+  /// created unnamed, we will name them and patch up conflicts when
+  /// we release the module.
+  std::vector< std::pair<llvm::Function*, std::string> > RuntimeFunctions;
+
   /// GlobalDeclMap - Mapping of decl names global variables we have
   /// already emitted. Note that the entries in this map are the
   /// actual globals and therefore may not be of the same type as the
@@ -195,6 +201,11 @@ public:
 
   void AddAnnotation(llvm::Constant *C) { Annotations.push_back(C); }
 
+  /// CreateRuntimeFunction - Create a new runtime function whose name
+  /// must be protected from collisions.
+  llvm::Function *CreateRuntimeFunction(const llvm::FunctionType *Ty, 
+                                        const std::string &Name);
+
   void UpdateCompletedType(const TagDecl *D);
   llvm::Constant *EmitConstantExpr(const Expr *E, CodeGenFunction *CGF = 0);
   llvm::Constant *EmitAnnotateAttr(llvm::GlobalValue *GV,
@@ -263,6 +274,8 @@ private:
   void EmitAliases(void);
   void EmitAnnotations(void);
   void EmitStatics(void);
+
+  void BindRuntimeFunctions();
 };
 }  // end namespace CodeGen
 }  // end namespace clang