code cleanups, rename EmitForwardFunctionDefinition ->

CreateFunctionPrototypeIR, though my next patch will eliminate
it entirely.

llvm-svn: 67443
This commit is contained in:
Chris Lattner 2009-03-21 08:38:50 +00:00
parent 6574906818
commit 5eaee5692c
2 changed files with 47 additions and 46 deletions

View File

@ -782,10 +782,16 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *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 *
CodeGenModule::EmitForwardFunctionDefinition(const FunctionDecl *D,
const llvm::Type *Ty) {
bool DoSetAttributes = true;
CodeGenModule::CreateFunctionPrototypeIR(const FunctionDecl *D,
const llvm::Type *Ty) {
bool ShouldSetAttributes = true;
if (!Ty) {
Ty = getTypes().ConvertType(D->getType());
if (!isa<llvm::FunctionType>(Ty)) {
@ -794,31 +800,30 @@ CodeGenModule::EmitForwardFunctionDefinition(const FunctionDecl *D,
// sure not to try to set attributes.
Ty = llvm::FunctionType::get(llvm::Type::VoidTy,
std::vector<const llvm::Type*>(), false);
DoSetAttributes = false;
ShouldSetAttributes = false;
}
}
llvm::Function *F = llvm::Function::Create(cast<llvm::FunctionType>(Ty),
llvm::Function::ExternalLinkage,
getMangledName(D),
&getModule());
if (DoSetAttributes)
if (ShouldSetAttributes)
SetFunctionAttributes(D, F);
return F;
}
llvm::Constant *CodeGenModule::GetAddrOfFunction(const FunctionDecl *D) {
QualType ASTTy = D->getType();
const llvm::Type *Ty = getTypes().ConvertTypeForMem(ASTTy);
const llvm::Type *PTy = llvm::PointerType::get(Ty, ASTTy.getAddressSpace());
// Lookup the entry, lazily creating it if necessary.
llvm::GlobalValue *&Entry = GlobalDeclMap[getMangledName(D)];
if (!Entry)
return Entry = EmitForwardFunctionDefinition(D, 0);
return Entry = CreateFunctionPrototypeIR(D, 0);
if (Entry->getType() != PTy)
return llvm::ConstantExpr::getBitCast(Entry, PTy);
return Entry;
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) {
@ -830,39 +835,35 @@ void CodeGenModule::EmitGlobalFunctionDefinition(const FunctionDecl *D) {
// to do unnecessary work).
if (Ty->isVarArg() && Ty->getNumParams() == 0 && Ty->isVarArg())
Ty = llvm::FunctionType::get(Ty->getReturnType(),
std::vector<const llvm::Type*>(),
false);
std::vector<const llvm::Type*>(), false);
llvm::GlobalValue *&Entry = GlobalDeclMap[getMangledName(D)];
if (!Entry) {
Entry = EmitForwardFunctionDefinition(D, Ty);
} else {
Entry = CreateFunctionPrototypeIR(D, Ty);
} else if (Entry->getType()->getElementType() != Ty) {
// 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;
}
// 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 = CreateFunctionPrototypeIR(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;
}
llvm::Function *Fn = cast<llvm::Function>(Entry);

View File

@ -315,14 +315,14 @@ private:
void EmitGlobalDefinition(const ValueDecl *D);
/// EmitForwardFunctionDefinition - Create a new function for the
/// given decl and set attributes as appropriate.
/// 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 *EmitForwardFunctionDefinition(const FunctionDecl *D,
const llvm::Type *Ty);
llvm::GlobalValue *CreateFunctionPrototypeIR(const FunctionDecl *D,
const llvm::Type *Ty);
void EmitGlobalFunctionDefinition(const FunctionDecl *D);
void EmitGlobalVarDefinition(const VarDecl *D);