[llvm-commits] CVS: llvm/lib/Target/CBackend/Writer.cpp
Chris Lattner
lattner at cs.uiuc.edu
Sat Nov 13 14:22:08 PST 2004
Changes in directory llvm/lib/Target/CBackend:
Writer.cpp updated: 1.207 -> 1.208
---
Log message:
Hack around stupidity in GCC, fixing Burg with the CBE and
CBackend/2004-11-13-FunctionPointerCast.llx
---
Diffs of the changes: (+56 -9)
Index: llvm/lib/Target/CBackend/Writer.cpp
diff -u llvm/lib/Target/CBackend/Writer.cpp:1.207 llvm/lib/Target/CBackend/Writer.cpp:1.208
--- llvm/lib/Target/CBackend/Writer.cpp:1.207 Mon Oct 25 13:41:50 2004
+++ llvm/lib/Target/CBackend/Writer.cpp Sat Nov 13 16:21:56 2004
@@ -182,7 +182,6 @@
void visitCastInst (CastInst &I);
void visitSelectInst(SelectInst &I);
void visitCallInst (CallInst &I);
- void visitCallSite (CallSite CS);
void visitShiftInst(ShiftInst &I) { visitBinaryOperator(I); }
void visitMallocInst(MallocInst &I);
@@ -1466,23 +1465,71 @@
return;
}
}
- visitCallSite(&I);
-}
-void CWriter::visitCallSite(CallSite CS) {
- const PointerType *PTy = cast<PointerType>(CS.getCalledValue()->getType());
+ Value *Callee = I.getCalledValue();
+
+ // GCC is really a PITA. It does not permit codegening casts of functions to
+ // function pointers if they are in a call (it generates a trap instruction
+ // instead!). We work around this by inserting a cast to void* in between the
+ // function and the function pointer cast. Unfortunately, we can't just form
+ // the constant expression here, because the folder will immediately nuke it.
+ //
+ // Note finally, that this is completely unsafe. ANSI C does not guarantee
+ // that void* and function pointers have the same size. :( To deal with this
+ // in the common case, we handle casts where the number of arguments passed
+ // match exactly.
+ //
+ bool WroteCallee = false;
+ if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Callee))
+ if (CE->getOpcode() == Instruction::Cast)
+ if (Function *RF = dyn_cast<Function>(CE->getOperand(0))) {
+ const FunctionType *RFTy = RF->getFunctionType();
+ if (RFTy->getNumParams() == I.getNumOperands()-1) {
+ // If the call site expects a value, and the actual callee doesn't
+ // provide one, return 0.
+ if (I.getType() != Type::VoidTy &&
+ RFTy->getReturnType() == Type::VoidTy)
+ Out << "0 /*actual callee doesn't return value*/; ";
+ Callee = RF;
+ } else {
+ // Ok, just cast the pointer type.
+ Out << "((";
+ printType(Out, CE->getType());
+ Out << ")(void*)";
+ printConstant(RF);
+ Out << ")";
+ WroteCallee = true;
+ }
+ }
+
+ const PointerType *PTy = cast<PointerType>(Callee->getType());
const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
const Type *RetTy = FTy->getReturnType();
- writeOperand(CS.getCalledValue());
+ if (!WroteCallee) writeOperand(Callee);
Out << "(";
- if (CS.arg_begin() != CS.arg_end()) {
- CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
+ unsigned NumDeclaredParams = FTy->getNumParams();
+
+ if (I.getNumOperands() != 1) {
+ CallSite::arg_iterator AI = I.op_begin()+1, AE = I.op_end();
+ if (NumDeclaredParams && (*AI)->getType() != FTy->getParamType(0)) {
+ Out << "(";
+ printType(Out, FTy->getParamType(0));
+ Out << ")";
+ }
+
writeOperand(*AI);
- for (++AI; AI != AE; ++AI) {
+ unsigned ArgNo;
+ for (ArgNo = 1, ++AI; AI != AE; ++AI, ++ArgNo) {
Out << ", ";
+ if (ArgNo < NumDeclaredParams &&
+ (*AI)->getType() != FTy->getParamType(ArgNo)) {
+ Out << "(";
+ printType(Out, FTy->getParamType(ArgNo));
+ Out << ")";
+ }
writeOperand(*AI);
}
}
More information about the llvm-commits
mailing list