From 53d89225560fb9434a68e25019a31a75c0006537 Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Mon, 9 Mar 2009 06:40:26 +0000 Subject: [PATCH] Be sure to never create two functions with the same name, instead arrange to reuse the prior one. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66408 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenModule.cpp | 68 ++++++++++++++++++----------------- lib/CodeGen/CodeGenModule.h | 29 ++++++++------- 2 files changed, 52 insertions(+), 45 deletions(-) diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 16ba94791f..41784cbb81 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -788,7 +788,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { 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 @@ CodeGenModule::EmitForwardFunctionDefinition(const FunctionDecl *D, DoSetAttributes = false; } } - llvm::Function *F = llvm::Function::Create(cast(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(Ty), + llvm::Function::ExternalLinkage, + Name, + &getModule()); if (DoSetAttributes) SetFunctionAttributes(D, F); return F; @@ -838,33 +842,33 @@ void CodeGenModule::EmitGlobalFunctionDefinition(const FunctionDecl *D) { 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(Entry); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index c3a84af0c5..039579ffc5 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -312,14 +312,17 @@ private: 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 @@ private: 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 -- 2.40.0