forked from OSchip/llvm-project
implement codegen for functions whose function body type don't match
their prototype. llvm-svn: 44506
This commit is contained in:
parent
c5b3aab66b
commit
41af8182d8
|
@ -58,8 +58,42 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD) {
|
|||
getContext().getTypeSize(getContext().getPointerType(getContext().VoidTy),
|
||||
SourceLocation()));
|
||||
|
||||
CurFn = cast<llvm::Function>(CGM.GetAddrOfGlobalDecl(FD));
|
||||
CurFuncDecl = FD;
|
||||
llvm::Constant *CurFnC = CGM.GetAddrOfGlobalDecl(FD);
|
||||
if (!(CurFn = dyn_cast<llvm::Function>(CurFnC))) {
|
||||
// If CurFnC is not a constant, it must be a bitcast of another function.
|
||||
llvm::ConstantExpr *CurFnCE = cast<llvm::ConstantExpr>(CurFnC);
|
||||
assert(CurFnCE->getOpcode() == llvm::Instruction::BitCast &&
|
||||
"Unexpected name collision");
|
||||
llvm::Function *OtherFunc = cast<llvm::Function>(CurFnCE->getOperand(0));
|
||||
|
||||
// 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.
|
||||
const llvm::PointerType *PTy = cast<llvm::PointerType>(CurFnC->getType());
|
||||
const llvm::FunctionType *FTy =
|
||||
cast<llvm::FunctionType>(PTy->getElementType());
|
||||
CurFn = new llvm::Function(FTy, llvm::Function::ExternalLinkage, "",
|
||||
&CGM.getModule());
|
||||
CurFn->takeName(OtherFunc);
|
||||
|
||||
// Replace uses of OtherFunc with the Function we will endow with a body.
|
||||
llvm::Constant *NewPtrForOldDecl =
|
||||
llvm::ConstantExpr::getBitCast(CurFn, OtherFunc->getType());
|
||||
OtherFunc->replaceAllUsesWith(NewPtrForOldDecl);
|
||||
|
||||
// Make sure the GlobalDecl map for FD is up-to-date.
|
||||
CGM.ChangeGlobalDeclMap(FD, CurFn);
|
||||
|
||||
// FIXME: Update the globaldeclmap for the previous decl of this name. We
|
||||
// really want a way to walk all of these, but we don't have it yet. This
|
||||
// is incredibly slow!
|
||||
CGM.ReplaceMapValuesWith(OtherFunc, NewPtrForOldDecl);
|
||||
|
||||
// Ok, delete the old function now, which is dead.
|
||||
assert(OtherFunc->isDeclaration() && "Shouldn't replace non-declaration");
|
||||
OtherFunc->eraseFromParent();
|
||||
}
|
||||
|
||||
assert(CurFn->isDeclaration() && "Function already has body?");
|
||||
|
||||
|
|
|
@ -31,6 +31,18 @@ CodeGenModule::CodeGenModule(ASTContext &C, const LangOptions &LO,
|
|||
: Context(C), Features(LO), TheModule(M), TheTargetData(TD), Diags(diags),
|
||||
Types(C, M, TD), MemCpyFn(0), CFConstantStringClassRef(0) {}
|
||||
|
||||
|
||||
/// ReplaceMapValuesWith - This is a really slow and bad function that
|
||||
/// searches for any entries in GlobalDeclMap that point to OldVal, changing
|
||||
/// them to point to NewVal. This is badbadbad, FIXME!
|
||||
void CodeGenModule::ReplaceMapValuesWith(llvm::Constant *OldVal,
|
||||
llvm::Constant *NewVal) {
|
||||
for (llvm::DenseMap<const Decl*, llvm::Constant*>::iterator
|
||||
I = GlobalDeclMap.begin(), E = GlobalDeclMap.end(); I != E; ++I)
|
||||
if (I->second == OldVal) I->second = NewVal;
|
||||
}
|
||||
|
||||
|
||||
llvm::Constant *CodeGenModule::GetAddrOfGlobalDecl(const ValueDecl *D) {
|
||||
// See if it is already in the map.
|
||||
llvm::Constant *&Entry = GlobalDeclMap[D];
|
||||
|
|
|
@ -68,6 +68,15 @@ public:
|
|||
|
||||
llvm::Constant *GetAddrOfGlobalDecl(const ValueDecl *D);
|
||||
|
||||
void ChangeGlobalDeclMap(const Decl *Decl, llvm::Constant *NewVal) {
|
||||
GlobalDeclMap[Decl] = NewVal;
|
||||
}
|
||||
|
||||
/// ReplaceMapValuesWith - This is a really slow and bad function that
|
||||
/// searches for any entries in GlobalDeclMap that point to OldVal, changing
|
||||
/// them to point to NewVal. This is badbadbad, FIXME!
|
||||
void ReplaceMapValuesWith(llvm::Constant *OldVal, llvm::Constant *NewVal);
|
||||
|
||||
/// getBuiltinLibFunction - Given a builtin id for a function like
|
||||
/// "__builtin_fabsf", return a Function* for "fabsf".
|
||||
///
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// RUN: clang %s -emit-llvm
|
||||
int g();
|
||||
|
||||
int foo(int i) {
|
||||
return g(i);
|
||||
}
|
||||
|
||||
int g(int i) {
|
||||
return g(i);
|
||||
}
|
||||
|
Loading…
Reference in New Issue