[cfe-commits] r44506 - in /cfe/trunk: CodeGen/CodeGenFunction.cpp CodeGen/CodeGenModule.cpp CodeGen/CodeGenModule.h test/CodeGen/functions.c
Chris Lattner
sabre at nondot.org
Sat Dec 1 22:27:33 PST 2007
Author: lattner
Date: Sun Dec 2 00:27:33 2007
New Revision: 44506
URL: http://llvm.org/viewvc/llvm-project?rev=44506&view=rev
Log:
implement codegen for functions whose function body type don't match
their prototype.
Added:
cfe/trunk/test/CodeGen/functions.c
Modified:
cfe/trunk/CodeGen/CodeGenFunction.cpp
cfe/trunk/CodeGen/CodeGenModule.cpp
cfe/trunk/CodeGen/CodeGenModule.h
Modified: cfe/trunk/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenFunction.cpp?rev=44506&r1=44505&r2=44506&view=diff
==============================================================================
--- cfe/trunk/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/CodeGen/CodeGenFunction.cpp Sun Dec 2 00:27:33 2007
@@ -58,8 +58,42 @@
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?");
Modified: cfe/trunk/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenModule.cpp?rev=44506&r1=44505&r2=44506&view=diff
==============================================================================
--- cfe/trunk/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/CodeGen/CodeGenModule.cpp Sun Dec 2 00:27:33 2007
@@ -31,6 +31,18 @@
: 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];
Modified: cfe/trunk/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenModule.h?rev=44506&r1=44505&r2=44506&view=diff
==============================================================================
--- cfe/trunk/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/CodeGen/CodeGenModule.h Sun Dec 2 00:27:33 2007
@@ -68,6 +68,15 @@
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".
///
Added: cfe/trunk/test/CodeGen/functions.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/functions.c?rev=44506&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/functions.c (added)
+++ cfe/trunk/test/CodeGen/functions.c Sun Dec 2 00:27:33 2007
@@ -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);
+}
+
More information about the cfe-commits
mailing list