blob: 358e5660dea019566690525f89a0c16ea8cafb8e [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
Daniel Dunbar45c25ba2008-09-10 04:01:49 +000029CGFunctionInfo::CGFunctionInfo(const FunctionTypeNoProto *FTNP)
30 : IsVariadic(true)
31{
32 ArgTypes.push_back(FTNP->getResultType());
33}
34
35CGFunctionInfo::CGFunctionInfo(const FunctionTypeProto *FTP)
36 : IsVariadic(FTP->isVariadic())
37{
38 ArgTypes.push_back(FTP->getResultType());
39 for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
40 ArgTypes.push_back(FTP->getArgType(i));
41}
42
43// FIXME: Is there really any reason to have this still?
Daniel Dunbar0dbe2272008-09-08 21:33:45 +000044CGFunctionInfo::CGFunctionInfo(const FunctionDecl *FD)
Daniel Dunbar0dbe2272008-09-08 21:33:45 +000045{
46 const FunctionType *FTy = FD->getType()->getAsFunctionType();
47 const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(FTy);
Daniel Dunbar45c25ba2008-09-10 04:01:49 +000048
Daniel Dunbar0dbe2272008-09-08 21:33:45 +000049 ArgTypes.push_back(FTy->getResultType());
Daniel Dunbar45c25ba2008-09-10 04:01:49 +000050 if (FTP) {
51 IsVariadic = FTP->isVariadic();
Daniel Dunbar0dbe2272008-09-08 21:33:45 +000052 for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
53 ArgTypes.push_back(FTP->getArgType(i));
Daniel Dunbar45c25ba2008-09-10 04:01:49 +000054 } else {
55 IsVariadic = true;
56 }
Daniel Dunbar0dbe2272008-09-08 21:33:45 +000057}
58
59CGFunctionInfo::CGFunctionInfo(const ObjCMethodDecl *MD,
60 const ASTContext &Context)
Daniel Dunbar45c25ba2008-09-10 04:01:49 +000061 : IsVariadic(MD->isVariadic())
Daniel Dunbar0dbe2272008-09-08 21:33:45 +000062{
63 ArgTypes.push_back(MD->getResultType());
64 ArgTypes.push_back(MD->getSelfDecl()->getType());
65 ArgTypes.push_back(Context.getObjCSelType());
66 for (ObjCMethodDecl::param_const_iterator i = MD->param_begin(),
67 e = MD->param_end(); i != e; ++i)
68 ArgTypes.push_back((*i)->getType());
69}
70
Daniel Dunbar5323a4b2008-09-10 00:32:18 +000071ArgTypeIterator CGFunctionInfo::argtypes_begin() const {
72 return ArgTypes.begin();
73}
74
75ArgTypeIterator CGFunctionInfo::argtypes_end() const {
76 return ArgTypes.end();
Daniel Dunbar0dbe2272008-09-08 21:33:45 +000077}
78
79/***/
80
Daniel Dunbar5323a4b2008-09-10 00:32:18 +000081CGCallInfo::CGCallInfo(QualType _ResultType, const CallArgList &_Args) {
82 ArgTypes.push_back(_ResultType);
83 for (CallArgList::const_iterator i = _Args.begin(), e = _Args.end(); i!=e; ++i)
Daniel Dunbar0dbe2272008-09-08 21:33:45 +000084 ArgTypes.push_back(i->second);
85}
86
Daniel Dunbar5323a4b2008-09-10 00:32:18 +000087ArgTypeIterator CGCallInfo::argtypes_begin() const {
88 return ArgTypes.begin();
89}
90
91ArgTypeIterator CGCallInfo::argtypes_end() const {
92 return ArgTypes.end();
Daniel Dunbar0dbe2272008-09-08 21:33:45 +000093}
Daniel Dunbar17b708d2008-09-09 23:27:19 +000094
95/***/
96
Daniel Dunbar8951dbd2008-09-11 01:48:57 +000097/// ABIArgInfo - Helper class to encapsulate information about how a
98/// specific C type should be passed to or returned from a function.
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +000099class ABIArgInfo {
100public:
101 enum Kind {
102 Default,
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000103 StructRet, /// Only valid for aggregate return types.
104
105 Coerce, /// Only valid for aggregate types, the argument should
106 /// be accessed by coercion to a provided type.
107
108 ByVal, /// Only valid for aggregate argument types. The
109 /// structure should be passed "byval" with the
110 /// specified alignment (0 indicates default
111 /// alignment).
112
113 Expand, /// Only valid for aggregate argument types. The
114 /// structure should be expanded into consecutive
115 /// arguments for its constituent fields.
116
117 KindFirst=Default, KindLast=Expand
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000118 };
119
120private:
121 Kind TheKind;
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000122 const llvm::Type *TypeData;
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000123 unsigned UIntData;
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000124
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000125 ABIArgInfo(Kind K, const llvm::Type *TD=0,
126 unsigned UI=0) : TheKind(K),
127 TypeData(TD),
128 UIntData(0) {}
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000129public:
130 static ABIArgInfo getDefault() {
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000131 return ABIArgInfo(Default);
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000132 }
133 static ABIArgInfo getStructRet() {
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000134 return ABIArgInfo(StructRet);
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000135 }
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000136 static ABIArgInfo getCoerce(const llvm::Type *T) {
137 assert(T->isSingleValueType() && "Can only coerce to simple types");
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000138 return ABIArgInfo(Coerce, T);
139 }
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000140 static ABIArgInfo getByVal(unsigned Alignment) {
141 return ABIArgInfo(ByVal, 0, Alignment);
142 }
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000143
144 Kind getKind() const { return TheKind; }
145 bool isDefault() const { return TheKind == Default; }
146 bool isStructRet() const { return TheKind == StructRet; }
147 bool isCoerce() const { return TheKind == Coerce; }
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000148 bool isByVal() const { return TheKind == ByVal; }
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000149
150 // Coerce accessors
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000151 const llvm::Type *getCoerceToType() const {
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000152 assert(TheKind == Coerce && "Invalid kind!");
153 return TypeData;
154 }
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000155
156 // ByVal accessors
157 unsigned getByValAlignment() const {
158 assert(TheKind == ByVal && "Invalid kind!");
159 return UIntData;
160 }
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000161};
162
163/***/
164
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000165static ABIArgInfo classifyReturnType(QualType RetTy,
166 ASTContext &Context) {
Daniel Dunbar6660c8a2008-09-11 00:04:36 +0000167 assert(!RetTy->isArrayType() &&
168 "Array types cannot be passed directly.");
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000169 if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000170 uint64_t Size = Context.getTypeSize(RetTy);
171 if (Size == 8) {
172 return ABIArgInfo::getCoerce(llvm::Type::Int8Ty);
173 } else if (Size == 16) {
174 return ABIArgInfo::getCoerce(llvm::Type::Int16Ty);
175 } else if (Size == 32) {
176 return ABIArgInfo::getCoerce(llvm::Type::Int32Ty);
177 } else if (Size == 64) {
178 return ABIArgInfo::getCoerce(llvm::Type::Int64Ty);
179 } else {
180 return ABIArgInfo::getStructRet();
181 }
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000182 } else {
183 return ABIArgInfo::getDefault();
184 }
185}
186
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000187static ABIArgInfo classifyArgumentType(QualType Ty,
188 ASTContext &Context,
189 CodeGenTypes &Types) {
190 assert(!Ty->isArrayType() && "Array types cannot be passed directly.");
191
192 if (!Types.ConvertType(Ty)->isSingleValueType()) {
193 return ABIArgInfo::getByVal(0);
194 } else {
195 return ABIArgInfo::getDefault();
196 }
197}
198
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000199/***/
200
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000201const llvm::FunctionType *
Daniel Dunbar62d5c1b2008-09-10 07:00:50 +0000202CodeGenTypes::GetFunctionType(const CGCallInfo &CI, bool IsVariadic) {
203 return GetFunctionType(CI.argtypes_begin(), CI.argtypes_end(), IsVariadic);
204}
205
206const llvm::FunctionType *
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000207CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) {
Daniel Dunbar62d5c1b2008-09-10 07:00:50 +0000208 return GetFunctionType(FI.argtypes_begin(), FI.argtypes_end(), FI.isVariadic());
209}
210
211const llvm::FunctionType *
212CodeGenTypes::GetFunctionType(ArgTypeIterator begin, ArgTypeIterator end,
213 bool IsVariadic) {
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000214 std::vector<const llvm::Type*> ArgTys;
215
216 const llvm::Type *ResultType = 0;
217
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000218 QualType RetTy = *begin;
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000219 ABIArgInfo RetAI = classifyReturnType(RetTy, getContext());
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000220 switch (RetAI.getKind()) {
221 case ABIArgInfo::ByVal:
222 case ABIArgInfo::Expand:
223 assert(0 && "Invalid ABI kind for return argument");
224
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000225 case ABIArgInfo::Default:
226 if (RetTy->isVoidType()) {
227 ResultType = llvm::Type::VoidTy;
228 } else {
Daniel Dunbar62d5c1b2008-09-10 07:00:50 +0000229 ResultType = ConvertType(RetTy);
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000230 }
231 break;
232
233 case ABIArgInfo::StructRet: {
234 ResultType = llvm::Type::VoidTy;
Daniel Dunbar62d5c1b2008-09-10 07:00:50 +0000235 const llvm::Type *STy = ConvertType(RetTy);
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000236 ArgTys.push_back(llvm::PointerType::get(STy, RetTy.getAddressSpace()));
237 break;
238 }
239
240 case ABIArgInfo::Coerce:
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000241 ResultType = RetAI.getCoerceToType();
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000242 break;
243 }
244
245 for (++begin; begin != end; ++begin) {
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000246 ABIArgInfo AI = classifyArgumentType(*begin, getContext(), *this);
Daniel Dunbar62d5c1b2008-09-10 07:00:50 +0000247 const llvm::Type *Ty = ConvertType(*begin);
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000248
249 switch (AI.getKind()) {
250 case ABIArgInfo::StructRet:
251 assert(0 && "Invalid ABI kind for non-return argument");
252
253 case ABIArgInfo::ByVal:
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000254 // byval arguments are always on the stack, which is addr space #0.
255 ArgTys.push_back(llvm::PointerType::getUnqual(Ty));
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000256 assert(AI.getByValAlignment() == 0 && "FIXME: alignment unhandled");
257 break;
258
259 case ABIArgInfo::Default:
260 ArgTys.push_back(Ty);
261 break;
262
263 case ABIArgInfo::Coerce:
264 assert(0 && "FIXME: ABIArgInfo::Coerce unhandled for arguments");
265 break;
266
267 case ABIArgInfo::Expand:
268 assert(0 && "FIXME: ABIArgInfo::Expand unhandled for arguments");
269 break;
270 }
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000271 }
272
Daniel Dunbar62d5c1b2008-09-10 07:00:50 +0000273 return llvm::FunctionType::get(ResultType, ArgTys, IsVariadic);
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000274}
275
Daniel Dunbarb7688072008-09-10 00:41:16 +0000276bool CodeGenModule::ReturnTypeUsesSret(QualType RetTy) {
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000277 return classifyReturnType(RetTy, getContext()).isStructRet();
Daniel Dunbar3913f182008-09-09 23:48:28 +0000278}
279
Daniel Dunbarb7688072008-09-10 00:41:16 +0000280void CodeGenModule::ConstructParamAttrList(const Decl *TargetDecl,
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000281 ArgTypeIterator begin,
282 ArgTypeIterator end,
283 ParamAttrListType &PAL) {
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000284 unsigned FuncAttrs = 0;
285
286 if (TargetDecl) {
287 if (TargetDecl->getAttr<NoThrowAttr>())
288 FuncAttrs |= llvm::ParamAttr::NoUnwind;
289 if (TargetDecl->getAttr<NoReturnAttr>())
290 FuncAttrs |= llvm::ParamAttr::NoReturn;
291 }
292
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000293 QualType RetTy = *begin;
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000294 unsigned Index = 1;
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000295 ABIArgInfo RetAI = classifyReturnType(RetTy, getContext());
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000296 switch (RetAI.getKind()) {
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000297 case ABIArgInfo::Default:
298 if (RetTy->isPromotableIntegerType()) {
299 if (RetTy->isSignedIntegerType()) {
300 FuncAttrs |= llvm::ParamAttr::SExt;
301 } else if (RetTy->isUnsignedIntegerType()) {
302 FuncAttrs |= llvm::ParamAttr::ZExt;
303 }
304 }
305 break;
306
307 case ABIArgInfo::StructRet:
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000308 PAL.push_back(llvm::ParamAttrsWithIndex::get(Index,
309 llvm::ParamAttr::StructRet));
310 ++Index;
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000311 break;
312
313 case ABIArgInfo::Coerce:
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000314 break;
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000315
316 case ABIArgInfo::ByVal:
317 case ABIArgInfo::Expand:
318 assert(0 && "Invalid ABI kind for return argument");
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000319 }
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000320
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000321 if (FuncAttrs)
322 PAL.push_back(llvm::ParamAttrsWithIndex::get(0, FuncAttrs));
323 for (++begin; begin != end; ++begin, ++Index) {
324 QualType ParamType = *begin;
325 unsigned ParamAttrs = 0;
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000326 ABIArgInfo AI = classifyArgumentType(ParamType, getContext(), getTypes());
327
328 switch (AI.getKind()) {
329 case ABIArgInfo::StructRet:
330 assert(0 && "Invalid ABI kind for non-return argument");
331
332 case ABIArgInfo::ByVal:
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000333 ParamAttrs |= llvm::ParamAttr::ByVal;
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000334 assert(AI.getByValAlignment() == 0 && "FIXME: alignment unhandled");
335 break;
336
337 case ABIArgInfo::Default:
338 if (ParamType->isPromotableIntegerType()) {
339 if (ParamType->isSignedIntegerType()) {
340 ParamAttrs |= llvm::ParamAttr::SExt;
341 } else if (ParamType->isUnsignedIntegerType()) {
342 ParamAttrs |= llvm::ParamAttr::ZExt;
343 }
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000344 }
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000345 break;
346
347 case ABIArgInfo::Coerce:
348 assert(0 && "FIXME: ABIArgInfo::Coerce unhandled for arguments");
349 break;
350
351 case ABIArgInfo::Expand:
352 assert(0 && "FIXME: ABIArgInfo::Expand unhandled for arguments");
353 break;
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000354 }
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000355
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000356 if (ParamAttrs)
357 PAL.push_back(llvm::ParamAttrsWithIndex::get(Index, ParamAttrs));
358 }
359}
360
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000361void CodeGenFunction::EmitFunctionProlog(llvm::Function *Fn,
362 QualType RetTy,
363 const FunctionArgList &Args) {
364 // Emit allocs for param decls. Give the LLVM Argument nodes names.
365 llvm::Function::arg_iterator AI = Fn->arg_begin();
366
367 // Name the struct return argument.
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000368 if (CGM.ReturnTypeUsesSret(RetTy)) {
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000369 AI->setName("agg.result");
370 ++AI;
371 }
372
373 for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end();
374 i != e; ++i, ++AI) {
375 const VarDecl *Arg = i->first;
376 QualType T = i->second;
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000377 ABIArgInfo ArgI = classifyArgumentType(T, getContext(), CGM.getTypes());
378
379 switch (ArgI.getKind()) {
380 case ABIArgInfo::ByVal:
381 case ABIArgInfo::Default: {
382 assert(AI != Fn->arg_end() && "Argument mismatch!");
383 llvm::Value* V = AI;
384 if (!getContext().typesAreCompatible(T, Arg->getType())) {
385 // This must be a promotion, for something like
386 // "void a(x) short x; {..."
387 V = EmitScalarConversion(V, T, Arg->getType());
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000388 }
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000389 EmitParmDecl(*Arg, V);
390 break;
391 }
392
393 case ABIArgInfo::Coerce:
394 assert(0 && "FIXME: ABIArgInfo::Coerce unhandled for arguments");
395 break;
396
397 case ABIArgInfo::Expand:
398 assert(0 && "FIXME: ABIArgInfo::Expand unhandled for arguments");
399 break;
400
401 case ABIArgInfo::StructRet:
402 assert(0 && "Invalid ABI kind for non-return argument");
403 }
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000404 }
405 assert(AI == Fn->arg_end() && "Argument mismatch!");
406}
407
408void CodeGenFunction::EmitFunctionEpilog(QualType RetTy,
409 llvm::Value *ReturnValue) {
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000410 llvm::Value *RV = 0;
411
412 // Functions with no result always return void.
413 if (ReturnValue) {
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000414 ABIArgInfo RetAI = classifyReturnType(RetTy, getContext());
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000415
416 switch (RetAI.getKind()) {
417 case ABIArgInfo::StructRet:
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000418 EmitAggregateCopy(CurFn->arg_begin(), ReturnValue, RetTy);
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000419 break;
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000420
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000421 case ABIArgInfo::Default:
422 RV = Builder.CreateLoad(ReturnValue);
423 break;
424
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000425 case ABIArgInfo::Coerce: {
426 const llvm::Type *CoerceToPTy =
427 llvm::PointerType::getUnqual(RetAI.getCoerceToType());
428 RV = Builder.CreateLoad(Builder.CreateBitCast(ReturnValue, CoerceToPTy));
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000429 break;
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000430 }
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000431
432 case ABIArgInfo::ByVal:
433 case ABIArgInfo::Expand:
434 assert(0 && "Invalid ABI kind for return argument");
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000435 }
436 }
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000437
438 if (RV) {
439 Builder.CreateRet(RV);
440 } else {
441 Builder.CreateRetVoid();
442 }
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000443}
444
445RValue CodeGenFunction::EmitCall(llvm::Value *Callee,
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000446 QualType RetTy,
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000447 const CallArgList &CallArgs) {
448 // FIXME: Factor out code to load from args into locals into target.
449 llvm::SmallVector<llvm::Value*, 16> Args;
450 llvm::Value *TempArg0 = 0;
451
452 // Handle struct-return functions by passing a pointer to the
453 // location that we would like to return into.
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000454 ABIArgInfo RetAI = classifyReturnType(RetTy, getContext());
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000455 switch (RetAI.getKind()) {
456 case ABIArgInfo::StructRet:
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000457 // Create a temporary alloca to hold the result of the call. :(
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000458 TempArg0 = CreateTempAlloca(ConvertType(RetTy));
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000459 Args.push_back(TempArg0);
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000460 break;
461
462 case ABIArgInfo::Default:
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000463 case ABIArgInfo::Coerce:
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000464 break;
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000465
466 case ABIArgInfo::ByVal:
467 case ABIArgInfo::Expand:
468 assert(0 && "Invalid ABI kind for return argument");
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000469 }
470
471 for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end();
472 I != E; ++I) {
473 RValue RV = I->first;
474 if (RV.isScalar()) {
475 Args.push_back(RV.getScalarVal());
476 } else if (RV.isComplex()) {
477 // Make a temporary alloca to pass the argument.
478 Args.push_back(CreateTempAlloca(ConvertType(I->second)));
479 StoreComplexToAddr(RV.getComplexVal(), Args.back(), false);
480 } else {
481 Args.push_back(RV.getAggregateAddr());
482 }
483 }
484
485 llvm::CallInst *CI = Builder.CreateCall(Callee,&Args[0],&Args[0]+Args.size());
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000486 CGCallInfo CallInfo(RetTy, CallArgs);
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000487
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000488 // FIXME: Provide TargetDecl so nounwind, noreturn, etc, etc get set.
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000489 CodeGen::ParamAttrListType ParamAttrList;
Daniel Dunbarb7688072008-09-10 00:41:16 +0000490 CGM.ConstructParamAttrList(0,
491 CallInfo.argtypes_begin(), CallInfo.argtypes_end(),
492 ParamAttrList);
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000493 CI->setParamAttrs(llvm::PAListPtr::get(ParamAttrList.begin(),
494 ParamAttrList.size()));
495
496 if (const llvm::Function *F = dyn_cast<llvm::Function>(Callee))
497 CI->setCallingConv(F->getCallingConv());
498 if (CI->getType() != llvm::Type::VoidTy)
499 CI->setName("call");
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000500
501 switch (RetAI.getKind()) {
502 case ABIArgInfo::StructRet:
503 if (RetTy->isAnyComplexType())
504 return RValue::getComplex(LoadComplexFromAddr(TempArg0, false));
505 else
506 // Struct return.
507 return RValue::getAggregate(TempArg0);
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000508
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000509 case ABIArgInfo::Default:
510 return RValue::get(RetTy->isVoidType() ? 0 : CI);
511
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000512 case ABIArgInfo::Coerce: {
513 const llvm::Type *CoerceToPTy =
514 llvm::PointerType::getUnqual(RetAI.getCoerceToType());
515 llvm::Value *V = CreateTempAlloca(ConvertType(RetTy), "tmp");
516 Builder.CreateStore(CI, Builder.CreateBitCast(V, CoerceToPTy));
517 return RValue::getAggregate(V);
518 }
Daniel Dunbar8951dbd2008-09-11 01:48:57 +0000519
520 case ABIArgInfo::ByVal:
521 case ABIArgInfo::Expand:
522 assert(0 && "Invalid ABI kind for return argument");
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000523 }
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000524
525 assert(0 && "Unhandled ABIArgInfo::Kind");
526 return RValue::get(0);
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000527}