diff options
author | Daniel Dunbar <daniel@zuster.org> | 2008-09-09 23:27:19 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2008-09-09 23:27:19 +0000 |
commit | 17b708d61827cd86278e9580b041dd6cbadf07d3 (patch) | |
tree | 0b200c781e016f556c46b6b68d1a190923767432 /lib/CodeGen/CGCall.cpp | |
parent | 7c086516f3cc9fba2733b1919973206c6ba4b171 (diff) |
Move ABI specific code for functions / calls to CGCall.cpp:
- Factor out EmitFunction{Pro,Epi}log
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@56031 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGCall.cpp')
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index a3a330e5e0..89004325c1 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -114,3 +114,105 @@ void CGCallInfo::constructParamAttrList(ParamAttrListType &PAL) const { // FIXME: Provide TargetDecl so nounwind, noreturn, etc, etc get set. constructParamAttrListInternal(0, ArgTypes, PAL); } + +/***/ + +void CodeGenFunction::EmitFunctionProlog(llvm::Function *Fn, + QualType RetTy, + const FunctionArgList &Args) { + // Emit allocs for param decls. Give the LLVM Argument nodes names. + llvm::Function::arg_iterator AI = Fn->arg_begin(); + + // Name the struct return argument. + if (hasAggregateLLVMType(RetTy)) { + AI->setName("agg.result"); + ++AI; + } + + for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end(); + i != e; ++i, ++AI) { + const VarDecl *Arg = i->first; + QualType T = i->second; + assert(AI != Fn->arg_end() && "Argument mismatch!"); + llvm::Value* V = AI; + if (!getContext().typesAreCompatible(T, Arg->getType())) { + // This must be a promotion, for something like + // "void a(x) short x; {..." + V = EmitScalarConversion(V, T, Arg->getType()); + } + EmitParmDecl(*Arg, V); + } + assert(AI == Fn->arg_end() && "Argument mismatch!"); +} + +void CodeGenFunction::EmitFunctionEpilog(QualType RetTy, + llvm::Value *ReturnValue) { + if (!ReturnValue) { + Builder.CreateRetVoid(); + } else { + if (!hasAggregateLLVMType(RetTy)) { + Builder.CreateRet(Builder.CreateLoad(ReturnValue)); + } else if (RetTy->isAnyComplexType()) { + EmitAggregateCopy(CurFn->arg_begin(), ReturnValue, RetTy); + Builder.CreateRetVoid(); + } else { + EmitAggregateCopy(CurFn->arg_begin(), ReturnValue, RetTy); + Builder.CreateRetVoid(); + } + } +} + +RValue CodeGenFunction::EmitCall(llvm::Value *Callee, + QualType ResultType, + const CallArgList &CallArgs) { + // FIXME: Factor out code to load from args into locals into target. + llvm::SmallVector<llvm::Value*, 16> Args; + llvm::Value *TempArg0 = 0; + + // Handle struct-return functions by passing a pointer to the + // location that we would like to return into. + if (hasAggregateLLVMType(ResultType)) { + // Create a temporary alloca to hold the result of the call. :( + TempArg0 = CreateTempAlloca(ConvertType(ResultType)); + Args.push_back(TempArg0); + } + + for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end(); + I != E; ++I) { + RValue RV = I->first; + if (RV.isScalar()) { + Args.push_back(RV.getScalarVal()); + } else if (RV.isComplex()) { + // Make a temporary alloca to pass the argument. + Args.push_back(CreateTempAlloca(ConvertType(I->second))); + StoreComplexToAddr(RV.getComplexVal(), Args.back(), false); + } else { + Args.push_back(RV.getAggregateAddr()); + } + } + + llvm::CallInst *CI = Builder.CreateCall(Callee,&Args[0],&Args[0]+Args.size()); + CGCallInfo CallInfo(ResultType, CallArgs); + + CodeGen::ParamAttrListType ParamAttrList; + CallInfo.constructParamAttrList(ParamAttrList); + CI->setParamAttrs(llvm::PAListPtr::get(ParamAttrList.begin(), + ParamAttrList.size())); + + if (const llvm::Function *F = dyn_cast<llvm::Function>(Callee)) + CI->setCallingConv(F->getCallingConv()); + if (CI->getType() != llvm::Type::VoidTy) + CI->setName("call"); + else if (ResultType->isAnyComplexType()) + return RValue::getComplex(LoadComplexFromAddr(TempArg0, false)); + else if (hasAggregateLLVMType(ResultType)) + // Struct return. + return RValue::getAggregate(TempArg0); + else { + // void return. + assert(ResultType->isVoidType() && "Should only have a void expr here"); + CI = 0; + } + + return RValue::get(CI); +} |