blob: 7095165ec8ba49fd77466684bd4f4b4b7f01528a [file] [log] [blame]
Daniel Dunbar0dbe2272008-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"
Daniel Dunbarb7688072008-09-10 00:41:16 +000017#include "CodeGenModule.h"
Daniel Dunbar0dbe2272008-09-08 21:33:45 +000018#include "clang/AST/ASTContext.h"
19#include "clang/AST/Decl.h"
20#include "clang/AST/DeclObjC.h"
21#include "llvm/ParameterAttributes.h"
22using namespace clang;
23using namespace CodeGen;
24
25/***/
26
Daniel Dunbar0dbe2272008-09-08 21:33:45 +000027// FIXME: Use iterator and sidestep silly type array creation.
28
29CGFunctionInfo::CGFunctionInfo(const FunctionDecl *FD)
30 : TheDecl(FD)
31{
32 const FunctionType *FTy = FD->getType()->getAsFunctionType();
33 const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(FTy);
34
35 ArgTypes.push_back(FTy->getResultType());
36 if (FTP)
37 for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
38 ArgTypes.push_back(FTP->getArgType(i));
39}
40
41CGFunctionInfo::CGFunctionInfo(const ObjCMethodDecl *MD,
42 const ASTContext &Context)
43 : TheDecl(MD)
44{
45 ArgTypes.push_back(MD->getResultType());
46 ArgTypes.push_back(MD->getSelfDecl()->getType());
47 ArgTypes.push_back(Context.getObjCSelType());
48 for (ObjCMethodDecl::param_const_iterator i = MD->param_begin(),
49 e = MD->param_end(); i != e; ++i)
50 ArgTypes.push_back((*i)->getType());
51}
52
Daniel Dunbar5323a4b2008-09-10 00:32:18 +000053ArgTypeIterator CGFunctionInfo::argtypes_begin() const {
54 return ArgTypes.begin();
55}
56
57ArgTypeIterator CGFunctionInfo::argtypes_end() const {
58 return ArgTypes.end();
Daniel Dunbar0dbe2272008-09-08 21:33:45 +000059}
60
61/***/
62
Daniel Dunbar5323a4b2008-09-10 00:32:18 +000063CGCallInfo::CGCallInfo(QualType _ResultType, const CallArgList &_Args) {
64 ArgTypes.push_back(_ResultType);
65 for (CallArgList::const_iterator i = _Args.begin(), e = _Args.end(); i!=e; ++i)
Daniel Dunbar0dbe2272008-09-08 21:33:45 +000066 ArgTypes.push_back(i->second);
67}
68
Daniel Dunbar5323a4b2008-09-10 00:32:18 +000069ArgTypeIterator CGCallInfo::argtypes_begin() const {
70 return ArgTypes.begin();
71}
72
73ArgTypeIterator CGCallInfo::argtypes_end() const {
74 return ArgTypes.end();
Daniel Dunbar0dbe2272008-09-08 21:33:45 +000075}
Daniel Dunbar17b708d2008-09-09 23:27:19 +000076
77/***/
78
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +000079class ABIArgInfo {
80public:
81 enum Kind {
82 Default,
83 StructRet, // Only valid for struct return types
84 Coerce // Only valid for return types
85 };
86
87private:
88 Kind TheKind;
89 QualType TypeData;
90
91 ABIArgInfo(Kind K, QualType TD) : TheKind(K),
92 TypeData(TD) {}
93public:
94 static ABIArgInfo getDefault() {
95 return ABIArgInfo(Default, QualType());
96 }
97 static ABIArgInfo getStructRet() {
98 return ABIArgInfo(StructRet, QualType());
99 }
100 static ABIArgInfo getCoerce(QualType T) {
101 return ABIArgInfo(Coerce, T);
102 }
103
104 Kind getKind() const { return TheKind; }
105 bool isDefault() const { return TheKind == Default; }
106 bool isStructRet() const { return TheKind == StructRet; }
107 bool isCoerce() const { return TheKind == Coerce; }
108};
109
110/***/
111
112static ABIArgInfo classifyReturnType(QualType RetTy) {
113 if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
114 return ABIArgInfo::getStructRet();
115 } else {
116 return ABIArgInfo::getDefault();
117 }
118}
119
120/***/
121
Daniel Dunbarb7688072008-09-10 00:41:16 +0000122bool CodeGenModule::ReturnTypeUsesSret(QualType RetTy) {
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000123 return classifyReturnType(RetTy).isStructRet();
Daniel Dunbar3913f182008-09-09 23:48:28 +0000124}
125
Daniel Dunbarb7688072008-09-10 00:41:16 +0000126void CodeGenModule::ConstructParamAttrList(const Decl *TargetDecl,
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000127 ArgTypeIterator begin,
128 ArgTypeIterator end,
129 ParamAttrListType &PAL) {
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000130 unsigned FuncAttrs = 0;
131
132 if (TargetDecl) {
133 if (TargetDecl->getAttr<NoThrowAttr>())
134 FuncAttrs |= llvm::ParamAttr::NoUnwind;
135 if (TargetDecl->getAttr<NoReturnAttr>())
136 FuncAttrs |= llvm::ParamAttr::NoReturn;
137 }
138
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000139 QualType RetTy = *begin;
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000140 unsigned Index = 1;
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000141 ABIArgInfo ResAI = classifyReturnType(RetTy);
142 switch (ResAI.getKind()) {
143 case ABIArgInfo::Default:
144 if (RetTy->isPromotableIntegerType()) {
145 if (RetTy->isSignedIntegerType()) {
146 FuncAttrs |= llvm::ParamAttr::SExt;
147 } else if (RetTy->isUnsignedIntegerType()) {
148 FuncAttrs |= llvm::ParamAttr::ZExt;
149 }
150 }
151 break;
152
153 case ABIArgInfo::StructRet:
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000154 PAL.push_back(llvm::ParamAttrsWithIndex::get(Index,
155 llvm::ParamAttr::StructRet));
156 ++Index;
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000157 break;
158
159 case ABIArgInfo::Coerce:
160 assert(0 && "FIXME: ABIArgInfo::Coerce not handled\n");
161 break;
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000162 }
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000163
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000164 if (FuncAttrs)
165 PAL.push_back(llvm::ParamAttrsWithIndex::get(0, FuncAttrs));
166 for (++begin; begin != end; ++begin, ++Index) {
167 QualType ParamType = *begin;
168 unsigned ParamAttrs = 0;
169 if (ParamType->isRecordType())
170 ParamAttrs |= llvm::ParamAttr::ByVal;
171 if (ParamType->isPromotableIntegerType()) {
172 if (ParamType->isSignedIntegerType()) {
173 ParamAttrs |= llvm::ParamAttr::SExt;
174 } else if (ParamType->isUnsignedIntegerType()) {
175 ParamAttrs |= llvm::ParamAttr::ZExt;
176 }
177 }
178 if (ParamAttrs)
179 PAL.push_back(llvm::ParamAttrsWithIndex::get(Index, ParamAttrs));
180 }
181}
182
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000183void CodeGenFunction::EmitFunctionProlog(llvm::Function *Fn,
184 QualType RetTy,
185 const FunctionArgList &Args) {
186 // Emit allocs for param decls. Give the LLVM Argument nodes names.
187 llvm::Function::arg_iterator AI = Fn->arg_begin();
188
189 // Name the struct return argument.
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000190 if (CGM.ReturnTypeUsesSret(RetTy)) {
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000191 AI->setName("agg.result");
192 ++AI;
193 }
194
195 for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end();
196 i != e; ++i, ++AI) {
197 const VarDecl *Arg = i->first;
198 QualType T = i->second;
199 assert(AI != Fn->arg_end() && "Argument mismatch!");
200 llvm::Value* V = AI;
201 if (!getContext().typesAreCompatible(T, Arg->getType())) {
202 // This must be a promotion, for something like
203 // "void a(x) short x; {..."
204 V = EmitScalarConversion(V, T, Arg->getType());
205 }
206 EmitParmDecl(*Arg, V);
207 }
208 assert(AI == Fn->arg_end() && "Argument mismatch!");
209}
210
211void CodeGenFunction::EmitFunctionEpilog(QualType RetTy,
212 llvm::Value *ReturnValue) {
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000213 llvm::Value *RV = 0;
214
215 // Functions with no result always return void.
216 if (ReturnValue) {
217 ABIArgInfo RetAI = classifyReturnType(RetTy);
218
219 switch (RetAI.getKind()) {
220 case ABIArgInfo::StructRet:
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000221 EmitAggregateCopy(CurFn->arg_begin(), ReturnValue, RetTy);
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000222 break;
223
224 case ABIArgInfo::Default:
225 RV = Builder.CreateLoad(ReturnValue);
226 break;
227
228 case ABIArgInfo::Coerce:
229 assert(0 && "FIXME: ABIArgInfo::Coerce not handled\n");
230 break;
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000231 }
232 }
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000233
234 if (RV) {
235 Builder.CreateRet(RV);
236 } else {
237 Builder.CreateRetVoid();
238 }
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000239}
240
241RValue CodeGenFunction::EmitCall(llvm::Value *Callee,
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000242 QualType RetTy,
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000243 const CallArgList &CallArgs) {
244 // FIXME: Factor out code to load from args into locals into target.
245 llvm::SmallVector<llvm::Value*, 16> Args;
246 llvm::Value *TempArg0 = 0;
247
248 // Handle struct-return functions by passing a pointer to the
249 // location that we would like to return into.
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000250 ABIArgInfo RetAI = classifyReturnType(RetTy);
251 switch (RetAI.getKind()) {
252 case ABIArgInfo::StructRet:
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000253 // Create a temporary alloca to hold the result of the call. :(
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000254 TempArg0 = CreateTempAlloca(ConvertType(RetTy));
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000255 Args.push_back(TempArg0);
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000256 break;
257
258 case ABIArgInfo::Default:
259 break;
260
261 case ABIArgInfo::Coerce:
262 assert(0 && "FIXME: ABIArgInfo::Coerce not handled\n");
263 break;
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000264 }
265
266 for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end();
267 I != E; ++I) {
268 RValue RV = I->first;
269 if (RV.isScalar()) {
270 Args.push_back(RV.getScalarVal());
271 } else if (RV.isComplex()) {
272 // Make a temporary alloca to pass the argument.
273 Args.push_back(CreateTempAlloca(ConvertType(I->second)));
274 StoreComplexToAddr(RV.getComplexVal(), Args.back(), false);
275 } else {
276 Args.push_back(RV.getAggregateAddr());
277 }
278 }
279
280 llvm::CallInst *CI = Builder.CreateCall(Callee,&Args[0],&Args[0]+Args.size());
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000281 CGCallInfo CallInfo(RetTy, CallArgs);
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000282
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000283 // FIXME: Provide TargetDecl so nounwind, noreturn, etc, etc get set.
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000284 CodeGen::ParamAttrListType ParamAttrList;
Daniel Dunbarb7688072008-09-10 00:41:16 +0000285 CGM.ConstructParamAttrList(0,
286 CallInfo.argtypes_begin(), CallInfo.argtypes_end(),
287 ParamAttrList);
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000288 CI->setParamAttrs(llvm::PAListPtr::get(ParamAttrList.begin(),
289 ParamAttrList.size()));
290
291 if (const llvm::Function *F = dyn_cast<llvm::Function>(Callee))
292 CI->setCallingConv(F->getCallingConv());
293 if (CI->getType() != llvm::Type::VoidTy)
294 CI->setName("call");
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000295
296 switch (RetAI.getKind()) {
297 case ABIArgInfo::StructRet:
298 if (RetTy->isAnyComplexType())
299 return RValue::getComplex(LoadComplexFromAddr(TempArg0, false));
300 else
301 // Struct return.
302 return RValue::getAggregate(TempArg0);
303
304 case ABIArgInfo::Default:
305 return RValue::get(RetTy->isVoidType() ? 0 : CI);
306
307 case ABIArgInfo::Coerce:
308 assert(0 && "FIXME: ABIArgInfo::Coerce not handled\n");
309 return RValue::get(0);
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000310 }
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000311
312 assert(0 && "Unhandled ABIArgInfo::Kind");
313 return RValue::get(0);
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000314}