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
This commit is contained in:
Mike Stump 2009-03-09 06:40:26 +00:00
Родитель b21f07e056
Коммит 53d8922556
2 изменённых файлов: 52 добавлений и 45 удалений

Просмотреть файл

@ -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<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 @@ 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<llvm::Function>(Entry);

Просмотреть файл

@ -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