blob: b684b4463ee3f754f548ac3964dae1b1a7cabb3f [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 Dunbar2c8e0f32008-09-10 02:41:04 +000097class ABIArgInfo {
98public:
99 enum Kind {
100 Default,
101 StructRet, // Only valid for struct return types
102 Coerce // Only valid for return types
103 };
104
105private:
106 Kind TheKind;
107 QualType TypeData;
108
109 ABIArgInfo(Kind K, QualType TD) : TheKind(K),
110 TypeData(TD) {}
111public:
112 static ABIArgInfo getDefault() {
113 return ABIArgInfo(Default, QualType());
114 }
115 static ABIArgInfo getStructRet() {
116 return ABIArgInfo(StructRet, QualType());
117 }
118 static ABIArgInfo getCoerce(QualType T) {
119 return ABIArgInfo(Coerce, T);
120 }
121
122 Kind getKind() const { return TheKind; }
123 bool isDefault() const { return TheKind == Default; }
124 bool isStructRet() const { return TheKind == StructRet; }
125 bool isCoerce() const { return TheKind == Coerce; }
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000126
127 // Coerce accessors
128 QualType getCoerceToType() const {
129 assert(TheKind == Coerce && "Invalid kind!");
130 return TypeData;
131 }
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000132};
133
134/***/
135
136static ABIArgInfo classifyReturnType(QualType RetTy) {
137 if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
138 return ABIArgInfo::getStructRet();
139 } else {
140 return ABIArgInfo::getDefault();
141 }
142}
143
144/***/
145
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000146const llvm::FunctionType *
147CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) {
148 std::vector<const llvm::Type*> ArgTys;
149
150 const llvm::Type *ResultType = 0;
151
152 ArgTypeIterator begin = FI.argtypes_begin(), end = FI.argtypes_end();
153 QualType RetTy = *begin;
154 ABIArgInfo RetAI = classifyReturnType(RetTy);
155 switch (RetAI.getKind()) {
156 case ABIArgInfo::Default:
157 if (RetTy->isVoidType()) {
158 ResultType = llvm::Type::VoidTy;
159 } else {
160 ResultType = ConvertTypeRecursive(RetTy);
161 }
162 break;
163
164 case ABIArgInfo::StructRet: {
165 ResultType = llvm::Type::VoidTy;
166 const llvm::Type *STy = ConvertTypeRecursive(RetTy);
167 ArgTys.push_back(llvm::PointerType::get(STy, RetTy.getAddressSpace()));
168 break;
169 }
170
171 case ABIArgInfo::Coerce:
172 ResultType = llvm::Type::VoidTy;
173 ArgTys.push_back(ConvertTypeRecursive(RetAI.getCoerceToType()));
174 break;
175 }
176
177 for (++begin; begin != end; ++begin) {
178 const llvm::Type *Ty = ConvertTypeRecursive(*begin);
179 if (Ty->isSingleValueType())
180 ArgTys.push_back(Ty);
181 else
182 // byval arguments are always on the stack, which is addr space #0.
183 ArgTys.push_back(llvm::PointerType::getUnqual(Ty));
184 }
185
186 return llvm::FunctionType::get(ResultType, ArgTys, FI.isVariadic());
187}
188
Daniel Dunbarb7688072008-09-10 00:41:16 +0000189bool CodeGenModule::ReturnTypeUsesSret(QualType RetTy) {
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000190 return classifyReturnType(RetTy).isStructRet();
Daniel Dunbar3913f182008-09-09 23:48:28 +0000191}
192
Daniel Dunbarb7688072008-09-10 00:41:16 +0000193void CodeGenModule::ConstructParamAttrList(const Decl *TargetDecl,
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000194 ArgTypeIterator begin,
195 ArgTypeIterator end,
196 ParamAttrListType &PAL) {
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000197 unsigned FuncAttrs = 0;
198
199 if (TargetDecl) {
200 if (TargetDecl->getAttr<NoThrowAttr>())
201 FuncAttrs |= llvm::ParamAttr::NoUnwind;
202 if (TargetDecl->getAttr<NoReturnAttr>())
203 FuncAttrs |= llvm::ParamAttr::NoReturn;
204 }
205
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000206 QualType RetTy = *begin;
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000207 unsigned Index = 1;
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000208 ABIArgInfo RetAI = classifyReturnType(RetTy);
209 switch (RetAI.getKind()) {
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000210 case ABIArgInfo::Default:
211 if (RetTy->isPromotableIntegerType()) {
212 if (RetTy->isSignedIntegerType()) {
213 FuncAttrs |= llvm::ParamAttr::SExt;
214 } else if (RetTy->isUnsignedIntegerType()) {
215 FuncAttrs |= llvm::ParamAttr::ZExt;
216 }
217 }
218 break;
219
220 case ABIArgInfo::StructRet:
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000221 PAL.push_back(llvm::ParamAttrsWithIndex::get(Index,
222 llvm::ParamAttr::StructRet));
223 ++Index;
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000224 break;
225
226 case ABIArgInfo::Coerce:
227 assert(0 && "FIXME: ABIArgInfo::Coerce not handled\n");
228 break;
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000229 }
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000230
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000231 if (FuncAttrs)
232 PAL.push_back(llvm::ParamAttrsWithIndex::get(0, FuncAttrs));
233 for (++begin; begin != end; ++begin, ++Index) {
234 QualType ParamType = *begin;
235 unsigned ParamAttrs = 0;
236 if (ParamType->isRecordType())
237 ParamAttrs |= llvm::ParamAttr::ByVal;
238 if (ParamType->isPromotableIntegerType()) {
239 if (ParamType->isSignedIntegerType()) {
240 ParamAttrs |= llvm::ParamAttr::SExt;
241 } else if (ParamType->isUnsignedIntegerType()) {
242 ParamAttrs |= llvm::ParamAttr::ZExt;
243 }
244 }
245 if (ParamAttrs)
246 PAL.push_back(llvm::ParamAttrsWithIndex::get(Index, ParamAttrs));
247 }
248}
249
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000250void CodeGenFunction::EmitFunctionProlog(llvm::Function *Fn,
251 QualType RetTy,
252 const FunctionArgList &Args) {
253 // Emit allocs for param decls. Give the LLVM Argument nodes names.
254 llvm::Function::arg_iterator AI = Fn->arg_begin();
255
256 // Name the struct return argument.
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000257 if (CGM.ReturnTypeUsesSret(RetTy)) {
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000258 AI->setName("agg.result");
259 ++AI;
260 }
261
262 for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end();
263 i != e; ++i, ++AI) {
264 const VarDecl *Arg = i->first;
265 QualType T = i->second;
266 assert(AI != Fn->arg_end() && "Argument mismatch!");
267 llvm::Value* V = AI;
268 if (!getContext().typesAreCompatible(T, Arg->getType())) {
269 // This must be a promotion, for something like
270 // "void a(x) short x; {..."
271 V = EmitScalarConversion(V, T, Arg->getType());
272 }
273 EmitParmDecl(*Arg, V);
274 }
275 assert(AI == Fn->arg_end() && "Argument mismatch!");
276}
277
278void CodeGenFunction::EmitFunctionEpilog(QualType RetTy,
279 llvm::Value *ReturnValue) {
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000280 llvm::Value *RV = 0;
281
282 // Functions with no result always return void.
283 if (ReturnValue) {
284 ABIArgInfo RetAI = classifyReturnType(RetTy);
285
286 switch (RetAI.getKind()) {
287 case ABIArgInfo::StructRet:
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000288 EmitAggregateCopy(CurFn->arg_begin(), ReturnValue, RetTy);
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000289 break;
290
291 case ABIArgInfo::Default:
292 RV = Builder.CreateLoad(ReturnValue);
293 break;
294
295 case ABIArgInfo::Coerce:
296 assert(0 && "FIXME: ABIArgInfo::Coerce not handled\n");
297 break;
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000298 }
299 }
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000300
301 if (RV) {
302 Builder.CreateRet(RV);
303 } else {
304 Builder.CreateRetVoid();
305 }
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000306}
307
308RValue CodeGenFunction::EmitCall(llvm::Value *Callee,
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000309 QualType RetTy,
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000310 const CallArgList &CallArgs) {
311 // FIXME: Factor out code to load from args into locals into target.
312 llvm::SmallVector<llvm::Value*, 16> Args;
313 llvm::Value *TempArg0 = 0;
314
315 // Handle struct-return functions by passing a pointer to the
316 // location that we would like to return into.
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000317 ABIArgInfo RetAI = classifyReturnType(RetTy);
318 switch (RetAI.getKind()) {
319 case ABIArgInfo::StructRet:
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000320 // Create a temporary alloca to hold the result of the call. :(
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000321 TempArg0 = CreateTempAlloca(ConvertType(RetTy));
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000322 Args.push_back(TempArg0);
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000323 break;
324
325 case ABIArgInfo::Default:
326 break;
327
328 case ABIArgInfo::Coerce:
329 assert(0 && "FIXME: ABIArgInfo::Coerce not handled\n");
330 break;
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000331 }
332
333 for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end();
334 I != E; ++I) {
335 RValue RV = I->first;
336 if (RV.isScalar()) {
337 Args.push_back(RV.getScalarVal());
338 } else if (RV.isComplex()) {
339 // Make a temporary alloca to pass the argument.
340 Args.push_back(CreateTempAlloca(ConvertType(I->second)));
341 StoreComplexToAddr(RV.getComplexVal(), Args.back(), false);
342 } else {
343 Args.push_back(RV.getAggregateAddr());
344 }
345 }
346
347 llvm::CallInst *CI = Builder.CreateCall(Callee,&Args[0],&Args[0]+Args.size());
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000348 CGCallInfo CallInfo(RetTy, CallArgs);
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000349
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000350 // FIXME: Provide TargetDecl so nounwind, noreturn, etc, etc get set.
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000351 CodeGen::ParamAttrListType ParamAttrList;
Daniel Dunbarb7688072008-09-10 00:41:16 +0000352 CGM.ConstructParamAttrList(0,
353 CallInfo.argtypes_begin(), CallInfo.argtypes_end(),
354 ParamAttrList);
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000355 CI->setParamAttrs(llvm::PAListPtr::get(ParamAttrList.begin(),
356 ParamAttrList.size()));
357
358 if (const llvm::Function *F = dyn_cast<llvm::Function>(Callee))
359 CI->setCallingConv(F->getCallingConv());
360 if (CI->getType() != llvm::Type::VoidTy)
361 CI->setName("call");
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000362
363 switch (RetAI.getKind()) {
364 case ABIArgInfo::StructRet:
365 if (RetTy->isAnyComplexType())
366 return RValue::getComplex(LoadComplexFromAddr(TempArg0, false));
367 else
368 // Struct return.
369 return RValue::getAggregate(TempArg0);
370
371 case ABIArgInfo::Default:
372 return RValue::get(RetTy->isVoidType() ? 0 : CI);
373
374 case ABIArgInfo::Coerce:
375 assert(0 && "FIXME: ABIArgInfo::Coerce not handled\n");
376 return RValue::get(0);
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000377 }
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000378
379 assert(0 && "Unhandled ABIArgInfo::Kind");
380 return RValue::get(0);
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000381}