blob: 8f6bde412ba02fd856c671ac7d0d4bf62b9e50ff [file] [log] [blame]
Daniel Dunbara8f02052008-09-08 21:33:45 +00001//===----- CGCall.h - Encapsulate calling convention details ----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// These classes wrap the information about a call or function
11// definition used to handle ABI compliancy.
12//
13//===----------------------------------------------------------------------===//
14
15#include "CGCall.h"
16#include "CodeGenFunction.h"
17#include "clang/AST/ASTContext.h"
18#include "clang/AST/Decl.h"
19#include "clang/AST/DeclObjC.h"
20#include "llvm/ParameterAttributes.h"
21using namespace clang;
22using namespace CodeGen;
23
24/***/
25
Daniel Dunbara8f02052008-09-08 21:33:45 +000026// FIXME: Use iterator and sidestep silly type array creation.
27
28CGFunctionInfo::CGFunctionInfo(const FunctionDecl *FD)
29 : TheDecl(FD)
30{
31 const FunctionType *FTy = FD->getType()->getAsFunctionType();
32 const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(FTy);
33
34 ArgTypes.push_back(FTy->getResultType());
35 if (FTP)
36 for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
37 ArgTypes.push_back(FTP->getArgType(i));
38}
39
40CGFunctionInfo::CGFunctionInfo(const ObjCMethodDecl *MD,
41 const ASTContext &Context)
42 : TheDecl(MD)
43{
44 ArgTypes.push_back(MD->getResultType());
45 ArgTypes.push_back(MD->getSelfDecl()->getType());
46 ArgTypes.push_back(Context.getObjCSelType());
47 for (ObjCMethodDecl::param_const_iterator i = MD->param_begin(),
48 e = MD->param_end(); i != e; ++i)
49 ArgTypes.push_back((*i)->getType());
50}
51
Daniel Dunbarbccb0682008-09-10 00:32:18 +000052ArgTypeIterator CGFunctionInfo::argtypes_begin() const {
53 return ArgTypes.begin();
54}
55
56ArgTypeIterator CGFunctionInfo::argtypes_end() const {
57 return ArgTypes.end();
Daniel Dunbara8f02052008-09-08 21:33:45 +000058}
59
60/***/
61
Daniel Dunbarbccb0682008-09-10 00:32:18 +000062CGCallInfo::CGCallInfo(QualType _ResultType, const CallArgList &_Args) {
63 ArgTypes.push_back(_ResultType);
64 for (CallArgList::const_iterator i = _Args.begin(), e = _Args.end(); i!=e; ++i)
Daniel Dunbara8f02052008-09-08 21:33:45 +000065 ArgTypes.push_back(i->second);
66}
67
Daniel Dunbarbccb0682008-09-10 00:32:18 +000068ArgTypeIterator CGCallInfo::argtypes_begin() const {
69 return ArgTypes.begin();
70}
71
72ArgTypeIterator CGCallInfo::argtypes_end() const {
73 return ArgTypes.end();
Daniel Dunbara8f02052008-09-08 21:33:45 +000074}
Daniel Dunbarfc1a9c42008-09-09 23:27:19 +000075
76/***/
77
Daniel Dunbar49f5a0d2008-09-09 23:48:28 +000078bool CodeGenFunction::ReturnTypeUsesSret(QualType RetTy) {
79 return hasAggregateLLVMType(RetTy);
80}
81
Daniel Dunbarbccb0682008-09-10 00:32:18 +000082void CodeGenFunction::ConstructParamAttrList(const Decl *TargetDecl,
83 ArgTypeIterator begin,
84 ArgTypeIterator end,
85 ParamAttrListType &PAL) {
86 unsigned FuncAttrs = 0;
87
88 if (TargetDecl) {
89 if (TargetDecl->getAttr<NoThrowAttr>())
90 FuncAttrs |= llvm::ParamAttr::NoUnwind;
91 if (TargetDecl->getAttr<NoReturnAttr>())
92 FuncAttrs |= llvm::ParamAttr::NoReturn;
93 }
94
95 QualType ResTy = *begin;
96 unsigned Index = 1;
97 if (CodeGenFunction::hasAggregateLLVMType(ResTy)) {
98 PAL.push_back(llvm::ParamAttrsWithIndex::get(Index,
99 llvm::ParamAttr::StructRet));
100 ++Index;
101 } else if (ResTy->isPromotableIntegerType()) {
102 if (ResTy->isSignedIntegerType()) {
103 FuncAttrs |= llvm::ParamAttr::SExt;
104 } else if (ResTy->isUnsignedIntegerType()) {
105 FuncAttrs |= llvm::ParamAttr::ZExt;
106 }
107 }
108 if (FuncAttrs)
109 PAL.push_back(llvm::ParamAttrsWithIndex::get(0, FuncAttrs));
110 for (++begin; begin != end; ++begin, ++Index) {
111 QualType ParamType = *begin;
112 unsigned ParamAttrs = 0;
113 if (ParamType->isRecordType())
114 ParamAttrs |= llvm::ParamAttr::ByVal;
115 if (ParamType->isPromotableIntegerType()) {
116 if (ParamType->isSignedIntegerType()) {
117 ParamAttrs |= llvm::ParamAttr::SExt;
118 } else if (ParamType->isUnsignedIntegerType()) {
119 ParamAttrs |= llvm::ParamAttr::ZExt;
120 }
121 }
122 if (ParamAttrs)
123 PAL.push_back(llvm::ParamAttrsWithIndex::get(Index, ParamAttrs));
124 }
125}
126
Daniel Dunbarfc1a9c42008-09-09 23:27:19 +0000127void CodeGenFunction::EmitFunctionProlog(llvm::Function *Fn,
128 QualType RetTy,
129 const FunctionArgList &Args) {
130 // Emit allocs for param decls. Give the LLVM Argument nodes names.
131 llvm::Function::arg_iterator AI = Fn->arg_begin();
132
133 // Name the struct return argument.
134 if (hasAggregateLLVMType(RetTy)) {
135 AI->setName("agg.result");
136 ++AI;
137 }
138
139 for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end();
140 i != e; ++i, ++AI) {
141 const VarDecl *Arg = i->first;
142 QualType T = i->second;
143 assert(AI != Fn->arg_end() && "Argument mismatch!");
144 llvm::Value* V = AI;
145 if (!getContext().typesAreCompatible(T, Arg->getType())) {
146 // This must be a promotion, for something like
147 // "void a(x) short x; {..."
148 V = EmitScalarConversion(V, T, Arg->getType());
149 }
150 EmitParmDecl(*Arg, V);
151 }
152 assert(AI == Fn->arg_end() && "Argument mismatch!");
153}
154
155void CodeGenFunction::EmitFunctionEpilog(QualType RetTy,
156 llvm::Value *ReturnValue) {
157 if (!ReturnValue) {
158 Builder.CreateRetVoid();
159 } else {
160 if (!hasAggregateLLVMType(RetTy)) {
161 Builder.CreateRet(Builder.CreateLoad(ReturnValue));
162 } else if (RetTy->isAnyComplexType()) {
163 EmitAggregateCopy(CurFn->arg_begin(), ReturnValue, RetTy);
164 Builder.CreateRetVoid();
165 } else {
166 EmitAggregateCopy(CurFn->arg_begin(), ReturnValue, RetTy);
167 Builder.CreateRetVoid();
168 }
169 }
170}
171
172RValue CodeGenFunction::EmitCall(llvm::Value *Callee,
173 QualType ResultType,
174 const CallArgList &CallArgs) {
175 // FIXME: Factor out code to load from args into locals into target.
176 llvm::SmallVector<llvm::Value*, 16> Args;
177 llvm::Value *TempArg0 = 0;
178
179 // Handle struct-return functions by passing a pointer to the
180 // location that we would like to return into.
181 if (hasAggregateLLVMType(ResultType)) {
182 // Create a temporary alloca to hold the result of the call. :(
183 TempArg0 = CreateTempAlloca(ConvertType(ResultType));
184 Args.push_back(TempArg0);
185 }
186
187 for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end();
188 I != E; ++I) {
189 RValue RV = I->first;
190 if (RV.isScalar()) {
191 Args.push_back(RV.getScalarVal());
192 } else if (RV.isComplex()) {
193 // Make a temporary alloca to pass the argument.
194 Args.push_back(CreateTempAlloca(ConvertType(I->second)));
195 StoreComplexToAddr(RV.getComplexVal(), Args.back(), false);
196 } else {
197 Args.push_back(RV.getAggregateAddr());
198 }
199 }
200
201 llvm::CallInst *CI = Builder.CreateCall(Callee,&Args[0],&Args[0]+Args.size());
202 CGCallInfo CallInfo(ResultType, CallArgs);
203
Daniel Dunbarbccb0682008-09-10 00:32:18 +0000204 // FIXME: Provide TargetDecl so nounwind, noreturn, etc, etc get set.
Daniel Dunbarfc1a9c42008-09-09 23:27:19 +0000205 CodeGen::ParamAttrListType ParamAttrList;
Daniel Dunbarbccb0682008-09-10 00:32:18 +0000206 ConstructParamAttrList(0, CallInfo.argtypes_begin(), CallInfo.argtypes_end(),
207 ParamAttrList);
Daniel Dunbarfc1a9c42008-09-09 23:27:19 +0000208 CI->setParamAttrs(llvm::PAListPtr::get(ParamAttrList.begin(),
209 ParamAttrList.size()));
210
211 if (const llvm::Function *F = dyn_cast<llvm::Function>(Callee))
212 CI->setCallingConv(F->getCallingConv());
213 if (CI->getType() != llvm::Type::VoidTy)
214 CI->setName("call");
215 else if (ResultType->isAnyComplexType())
216 return RValue::getComplex(LoadComplexFromAddr(TempArg0, false));
217 else if (hasAggregateLLVMType(ResultType))
218 // Struct return.
219 return RValue::getAggregate(TempArg0);
220 else {
221 // void return.
222 assert(ResultType->isVoidType() && "Should only have a void expr here");
223 CI = 0;
224 }
225
226 return RValue::get(CI);
227}