[cfe-commits] r66408 - in /cfe/trunk/lib/CodeGen: CodeGenModule.cpp CodeGenModule.h

Mike Stump mrs at apple.com
Sun Mar 8 23:40:26 PDT 2009


Author: mrs
Date: Mon Mar  9 01:40:26 2009
New Revision: 66408

URL: http://llvm.org/viewvc/llvm-project?rev=66408&view=rev
Log:
Be sure to never create two functions with the same name, instead arrange to
reuse the prior one.

Modified:
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=66408&r1=66407&r2=66408&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Mon Mar  9 01:40:26 2009
@@ -788,7 +788,8 @@
 
 llvm::GlobalValue *
 CodeGenModule::EmitForwardFunctionDefinition(const FunctionDecl *D,
-                                             const llvm::Type *Ty) {
+                                             const llvm::Type *Ty,
+                                             bool ReplaceExisting) {
   bool DoSetAttributes = true;
   if (!Ty) {
     Ty = getTypes().ConvertType(D->getType());
@@ -801,10 +802,13 @@
       DoSetAttributes = false;
     }
   }
-  llvm::Function *F = llvm::Function::Create(cast<llvm::FunctionType>(Ty), 
-                                             llvm::Function::ExternalLinkage,
-                                             getMangledName(D),
-                                             &getModule());
+  const char *Name = getMangledName(D);
+  llvm::Function *F = getModule().getFunction(Name);
+  if (ReplaceExisting || !F || !F->hasExternalLinkage())
+    F = llvm::Function::Create(cast<llvm::FunctionType>(Ty), 
+                               llvm::Function::ExternalLinkage,
+                               Name,
+                               &getModule());
   if (DoSetAttributes)
     SetFunctionAttributes(D, F);
   return F;
@@ -838,33 +842,33 @@
   llvm::GlobalValue *&Entry = GlobalDeclMap[getMangledName(D)];
   if (!Entry) {
     Entry = EmitForwardFunctionDefinition(D, Ty);
-  } else {
-    // If the types mismatch then we have to rewrite the definition.
-    if (Entry->getType() != llvm::PointerType::getUnqual(Ty)) {
-      // Otherwise, we have a definition after a prototype with the
-      // wrong type.  F is the Function* for the one with the wrong
-      // type, we must make a new Function* and update everything that
-      // used F (a declaration) with the new Function* (which will be
-      // a definition).
-      //
-      // This happens if there is a prototype for a function
-      // (e.g. "int f()") and then a definition of a different type
-      // (e.g. "int f(int x)").  Start by making a new function of the
-      // correct type, RAUW, then steal the name.
-      llvm::GlobalValue *NewFn = EmitForwardFunctionDefinition(D, Ty);
-      NewFn->takeName(Entry);
-      
-      // Replace uses of F with the Function we will endow with a body.
-      llvm::Constant *NewPtrForOldDecl = 
-        llvm::ConstantExpr::getBitCast(NewFn, Entry->getType());
-      Entry->replaceAllUsesWith(NewPtrForOldDecl);
-            
-      // Ok, delete the old function now, which is dead.
-      assert(Entry->isDeclaration() && "Shouldn't replace non-declaration");
-      Entry->eraseFromParent();
-      
-      Entry = NewFn;
-    }
+  }
+
+  // If the types mismatch then we have to rewrite the definition.
+  if (Entry->getType() != llvm::PointerType::getUnqual(Ty)) {
+    // Otherwise, we have a definition after a prototype with the
+    // wrong type.  F is the Function* for the one with the wrong
+    // type, we must make a new Function* and update everything that
+    // used F (a declaration) with the new Function* (which will be
+    // a definition).
+    //
+    // This happens if there is a prototype for a function
+    // (e.g. "int f()") and then a definition of a different type
+    // (e.g. "int f(int x)").  Start by making a new function of the
+    // correct type, RAUW, then steal the name.
+    llvm::GlobalValue *NewFn = EmitForwardFunctionDefinition(D, Ty, true);
+    NewFn->takeName(Entry);
+  
+    // Replace uses of F with the Function we will endow with a body.
+    llvm::Constant *NewPtrForOldDecl = 
+      llvm::ConstantExpr::getBitCast(NewFn, Entry->getType());
+    Entry->replaceAllUsesWith(NewPtrForOldDecl);
+
+    // Ok, delete the old function now, which is dead.
+    assert(Entry->isDeclaration() && "Shouldn't replace non-declaration");
+    Entry->eraseFromParent();
+
+    Entry = NewFn;
   }
 
   llvm::Function *Fn = cast<llvm::Function>(Entry);    

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=66408&r1=66407&r2=66408&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Mon Mar  9 01:40:26 2009
@@ -312,14 +312,17 @@
 
   void EmitGlobalDefinition(const ValueDecl *D);
 
-  /// EmitForwardFunctionDefinition - Create a new function for the
-  /// given decl and set attributes as appropriate.
+  /// EmitForwardFunctionDefinition - Create a new function for the given decl
+  /// and set attributes as appropriate if ReplaceExisting is true, or if the
+  /// same named declaration doesn't already exist in the module table,
+  /// otherwise return the existing function from the module table.
   ///
-  /// \arg Ty - If non-null the LLVM function type to use for the
-  /// decl; it is the callers responsibility to make sure this is
-  /// compatible with the correct type.
+  /// \arg Ty - If non-null the LLVM function type to use for the decl; it is
+  /// the callers responsibility to make sure this is compatible with the
+  /// correct type.
   llvm::GlobalValue *EmitForwardFunctionDefinition(const FunctionDecl *D,
-                                                   const llvm::Type *Ty);
+                                                   const llvm::Type *Ty,
+                                                   bool ReplaceExisting=false);
 
   void EmitGlobalFunctionDefinition(const FunctionDecl *D);
   void EmitGlobalVarDefinition(const VarDecl *D);
@@ -337,19 +340,19 @@
   void EmitAliases(void);
   void EmitAnnotations(void);
 
-  /// EmitDeferred - Emit any needed decls for which code generation
-  /// was deferred.
+  /// 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.
+  /// EmitLLVMUsed - Emit the llvm.used metadata used to force references to
+  /// global which may otherwise be optimized out.
   void EmitLLVMUsed(void);
 
   void BindRuntimeGlobals();
 
-  /// 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.
+  /// 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





More information about the cfe-commits mailing list