[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