diff options
author | ed <ed@FreeBSD.org> | 2009-06-14 09:24:02 +0000 |
---|---|---|
committer | ed <ed@FreeBSD.org> | 2009-06-14 09:24:02 +0000 |
commit | b8e7410b22fa573fb0078712439f343bc69208dd (patch) | |
tree | d472a7615b5c7e413aa62a77d0777c1a9cf76478 /lib/CodeGen/CGCall.cpp | |
parent | 6514d87c1aa5b544d02c3822fe41217e2051673d (diff) | |
download | FreeBSD-src-b8e7410b22fa573fb0078712439f343bc69208dd.zip FreeBSD-src-b8e7410b22fa573fb0078712439f343bc69208dd.tar.gz |
Import Clang r73340.
Diffstat (limited to 'lib/CodeGen/CGCall.cpp')
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index b10b9c2..4037f32 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -682,10 +682,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // location that we would like to return into. QualType RetTy = CallInfo.getReturnType(); const ABIArgInfo &RetAI = CallInfo.getReturnInfo(); - if (CGM.ReturnTypeUsesSret(CallInfo)) { - // Create a temporary alloca to hold the result of the call. :( + + + // If the call returns a temporary with struct return, create a temporary + // alloca to hold the result. + if (CGM.ReturnTypeUsesSret(CallInfo)) Args.push_back(CreateTempAlloca(ConvertTypeForMem(RetTy))); - } assert(CallInfo.arg_size() == CallArgs.size() && "Mismatch between function signature & arguments."); @@ -747,6 +749,35 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, break; } } + + // If the callee is a bitcast of a function to a varargs pointer to function + // type, check to see if we can remove the bitcast. This handles some cases + // with unprototyped functions. + if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Callee)) + if (llvm::Function *CalleeF = dyn_cast<llvm::Function>(CE->getOperand(0))) { + const llvm::PointerType *CurPT=cast<llvm::PointerType>(Callee->getType()); + const llvm::FunctionType *CurFT = + cast<llvm::FunctionType>(CurPT->getElementType()); + const llvm::FunctionType *ActualFT = CalleeF->getFunctionType(); + + if (CE->getOpcode() == llvm::Instruction::BitCast && + ActualFT->getReturnType() == CurFT->getReturnType() && + ActualFT->getNumParams() == CurFT->getNumParams()) { + bool ArgsMatch = true; + for (unsigned i = 0, e = ActualFT->getNumParams(); i != e; ++i) + if (ActualFT->getParamType(i) != CurFT->getParamType(i)) { + ArgsMatch = false; + break; + } + + // Strip the cast if we can get away with it. This is a nice cleanup, + // but also allows us to inline the function at -O0 if it is marked + // always_inline. + if (ArgsMatch) + Callee = CalleeF; + } + } + llvm::BasicBlock *InvokeDest = getInvokeDest(); CodeGen::AttributeListType AttributeList; @@ -765,7 +796,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } CS.setAttributes(Attrs); - if (const llvm::Function *F = dyn_cast<llvm::Function>(Callee->stripPointerCasts())) + if (const llvm::Function *F = + dyn_cast<llvm::Function>(Callee->stripPointerCasts())) CS.setCallingConv(F->getCallingConv()); // If the call doesn't return, finish the basic block and clear the |