simplify management of llvm::Function creation to all go through
GetAddrOfFunction.  This is simpler and more efficient.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67444 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index d901651..1dab9da 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -782,50 +782,39 @@
   }
 }
 
-/// CreateFunctionPrototypeIR - Create a new LLVM IR Function for the given
-/// decl and set attributes as appropriate.
-///
-/// \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 *
-CodeGenModule::CreateFunctionPrototypeIR(const FunctionDecl *D,
-                                         const llvm::Type *Ty) {
-  bool ShouldSetAttributes = true;
-  if (!Ty) {
+/// GetAddrOfFunction - Return the address of the given function.  If Ty is
+/// non-null, then this function will use the specified type if it has to
+/// create it (this occurs when we see a definition of the function).
+llvm::Function *CodeGenModule::GetAddrOfFunction(const FunctionDecl *D,
+                                                 const llvm::Type *Ty) {
+  // Lookup the entry, lazily creating it if necessary.
+  const char *MangledName = getMangledName(D);
+  llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName];
+  if (Entry)
+    return cast<llvm::Function>(Entry);
+
+  // If there was no specific requested type, just convert it now.
+  if (!Ty)
     Ty = getTypes().ConvertType(D->getType());
-    if (!isa<llvm::FunctionType>(Ty)) {
-      // This function doesn't have a complete type (for example, the return
-      // type is an incomplete struct). Use a fake type instead, and make
-      // sure not to try to set attributes.
-      Ty = llvm::FunctionType::get(llvm::Type::VoidTy,
-                                   std::vector<const llvm::Type*>(), false);
-      ShouldSetAttributes = false;
-    }
+  
+  // This function doesn't have a complete type (for example, the return
+  // type is an incomplete struct). Use a fake type instead, and make
+  // sure not to try to set attributes.
+  bool ShouldSetAttributes = true;
+  if (!isa<llvm::FunctionType>(Ty)) {
+    Ty = llvm::FunctionType::get(llvm::Type::VoidTy,
+                                 std::vector<const llvm::Type*>(), false);
+    ShouldSetAttributes = false;
   }
   llvm::Function *F = llvm::Function::Create(cast<llvm::FunctionType>(Ty), 
                                              llvm::Function::ExternalLinkage,
-                                             getMangledName(D),
-                                             &getModule());
+                                             MangledName, &getModule());
   if (ShouldSetAttributes)
     SetFunctionAttributes(D, F);
+  Entry = F;
   return F;
 }
 
-llvm::Constant *CodeGenModule::GetAddrOfFunction(const FunctionDecl *D) {
-  // Lookup the entry, lazily creating it if necessary.
-  llvm::GlobalValue *&Entry = GlobalDeclMap[getMangledName(D)];
-  if (!Entry)
-    return Entry = CreateFunctionPrototypeIR(D, 0);
-
-  const llvm::Type *Ty = getTypes().ConvertTypeForMem(D->getType());
-  if (Entry->getType()->getElementType() == Ty)
-    return Entry;
-  
-  const llvm::Type *PTy = llvm::PointerType::getUnqual(Ty);
-  return llvm::ConstantExpr::getBitCast(Entry, PTy);
-}
-
 void CodeGenModule::EmitGlobalFunctionDefinition(const FunctionDecl *D) {
   const llvm::FunctionType *Ty = 
     cast<llvm::FunctionType>(getTypes().ConvertType(D->getType()));
@@ -833,16 +822,18 @@
   // As a special case, make sure that definitions of K&R function
   // "type foo()" aren't declared as varargs (which forces the backend
   // to do unnecessary work).
-  if (Ty->isVarArg() && Ty->getNumParams() == 0 && Ty->isVarArg())
+  // FIXME: what about stret() functions, this doesn't handle them!?
+  if (Ty->isVarArg() && Ty->getNumParams() == 0)
     Ty = llvm::FunctionType::get(Ty->getReturnType(),
                                  std::vector<const llvm::Type*>(), false);
 
-  llvm::GlobalValue *&Entry = GlobalDeclMap[getMangledName(D)];
-  if (!Entry) {
-    Entry = CreateFunctionPrototypeIR(D, Ty);
-  } else if (Entry->getType()->getElementType() != Ty) {
+  // Get or create the prototype for teh function.
+  llvm::Function *Fn = GetAddrOfFunction(D, Ty);
+  
+  if (Fn->getType()->getElementType() != Ty) {
     // If the types mismatch then we have to rewrite the definition.
-    
+    assert(Fn->isDeclaration() && "Shouldn't replace non-declaration");
+
     // 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).
@@ -851,31 +842,31 @@
     // (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 = CreateFunctionPrototypeIR(D, Ty);
-    NewFn->takeName(Entry);
+    GlobalDeclMap.erase(getMangledName(D));
+    llvm::Function *NewFn = GetAddrOfFunction(D, Ty);
+    NewFn->takeName(Fn);
     
     // 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);
+      llvm::ConstantExpr::getBitCast(NewFn, Fn->getType());
+    Fn->replaceAllUsesWith(NewPtrForOldDecl);
     
     // Ok, delete the old function now, which is dead.
-    assert(Entry->isDeclaration() && "Shouldn't replace non-declaration");
-    Entry->eraseFromParent();
+    // FIXME: If it was attribute(used) the pointer will dangle from the
+    // LLVMUsed array!
+    Fn->eraseFromParent();
     
-    Entry = NewFn;
+    Fn = NewFn;
   }
 
-  llvm::Function *Fn = cast<llvm::Function>(Entry);    
   CodeGenFunction(*this).GenerateCode(D, Fn);
 
   SetFunctionAttributesForDefinition(D, Fn);
   
-  if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>()) {
+  if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>())
     AddGlobalCtor(Fn, CA->getPriority());
-  } else if (const DestructorAttr *DA = D->getAttr<DestructorAttr>()) {
+  if (const DestructorAttr *DA = D->getAttr<DestructorAttr>())
     AddGlobalDtor(Fn, DA->getPriority());
-  }
 }
 
 llvm::Function *
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index f35aa09..12da8c1 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -178,9 +178,11 @@
   /// given global variable.
   llvm::Constant *GetAddrOfGlobalVar(const VarDecl *D);
 
-  /// GetAddrOfFunction - Return the llvm::Constant for the address of the given
-  /// function.
-  llvm::Constant *GetAddrOfFunction(const FunctionDecl *D);
+  /// GetAddrOfFunction - Return the address of the given function.  If Ty is
+  /// non-null, then this function will use the specified type if it has to
+  /// create it.
+  llvm::Function *GetAddrOfFunction(const FunctionDecl *D,
+                                    const llvm::Type *Ty = 0);
 
   /// GetStringForStringLiteral - Return the appropriate bytes for a string
   /// literal, properly padded to match the literal type. If only the address of
@@ -315,15 +317,6 @@
 
   void EmitGlobalDefinition(const ValueDecl *D);
 
-  /// CreateFunctionPrototypeIR - Create a new LLVM IR Function for the given
-  /// decl and set attributes as appropriate.
-  ///
-  /// \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 *CreateFunctionPrototypeIR(const FunctionDecl *D,
-                                               const llvm::Type *Ty);
-
   void EmitGlobalFunctionDefinition(const FunctionDecl *D);
   void EmitGlobalVarDefinition(const VarDecl *D);
   void EmitObjCPropertyImplementations(const ObjCImplementationDecl *D);