aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGCall.cpp
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2008-09-09 23:27:19 +0000
committerDaniel Dunbar <daniel@zuster.org>2008-09-09 23:27:19 +0000
commit17b708d61827cd86278e9580b041dd6cbadf07d3 (patch)
tree0b200c781e016f556c46b6b68d1a190923767432 /lib/CodeGen/CGCall.cpp
parent7c086516f3cc9fba2733b1919973206c6ba4b171 (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.cpp102
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);
+}