blob: bbe43703cbf459277540f34110495bc0dc0a84e9 [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;
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000107 const llvm::Type *TypeData;
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000108
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000109 ABIArgInfo(Kind K, const llvm::Type *TD) : TheKind(K),
110 TypeData(TD) {}
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000111public:
112 static ABIArgInfo getDefault() {
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000113 return ABIArgInfo(Default, 0);
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000114 }
115 static ABIArgInfo getStructRet() {
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000116 return ABIArgInfo(StructRet, 0);
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000117 }
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000118 static ABIArgInfo getCoerce(const llvm::Type *T) {
119 assert(T->isSingleValueType() && "Can only coerce to simple types");
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000120 return ABIArgInfo(Coerce, T);
121 }
122
123 Kind getKind() const { return TheKind; }
124 bool isDefault() const { return TheKind == Default; }
125 bool isStructRet() const { return TheKind == StructRet; }
126 bool isCoerce() const { return TheKind == Coerce; }
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000127
128 // Coerce accessors
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000129 const llvm::Type *getCoerceToType() const {
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000130 assert(TheKind == Coerce && "Invalid kind!");
131 return TypeData;
132 }
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000133};
134
135/***/
136
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000137static ABIArgInfo classifyReturnType(QualType RetTy,
138 ASTContext &Context) {
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000139 if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000140 uint64_t Size = Context.getTypeSize(RetTy);
141 if (Size == 8) {
142 return ABIArgInfo::getCoerce(llvm::Type::Int8Ty);
143 } else if (Size == 16) {
144 return ABIArgInfo::getCoerce(llvm::Type::Int16Ty);
145 } else if (Size == 32) {
146 return ABIArgInfo::getCoerce(llvm::Type::Int32Ty);
147 } else if (Size == 64) {
148 return ABIArgInfo::getCoerce(llvm::Type::Int64Ty);
149 } else {
150 return ABIArgInfo::getStructRet();
151 }
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000152 } else {
153 return ABIArgInfo::getDefault();
154 }
155}
156
157/***/
158
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000159const llvm::FunctionType *
Daniel Dunbar62d5c1b2008-09-10 07:00:50 +0000160CodeGenTypes::GetFunctionType(const CGCallInfo &CI, bool IsVariadic) {
161 return GetFunctionType(CI.argtypes_begin(), CI.argtypes_end(), IsVariadic);
162}
163
164const llvm::FunctionType *
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000165CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) {
Daniel Dunbar62d5c1b2008-09-10 07:00:50 +0000166 return GetFunctionType(FI.argtypes_begin(), FI.argtypes_end(), FI.isVariadic());
167}
168
169const llvm::FunctionType *
170CodeGenTypes::GetFunctionType(ArgTypeIterator begin, ArgTypeIterator end,
171 bool IsVariadic) {
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000172 std::vector<const llvm::Type*> ArgTys;
173
174 const llvm::Type *ResultType = 0;
175
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000176 QualType RetTy = *begin;
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000177 ABIArgInfo RetAI = classifyReturnType(RetTy, getContext());
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000178 switch (RetAI.getKind()) {
179 case ABIArgInfo::Default:
180 if (RetTy->isVoidType()) {
181 ResultType = llvm::Type::VoidTy;
182 } else {
Daniel Dunbar62d5c1b2008-09-10 07:00:50 +0000183 ResultType = ConvertType(RetTy);
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000184 }
185 break;
186
187 case ABIArgInfo::StructRet: {
188 ResultType = llvm::Type::VoidTy;
Daniel Dunbar62d5c1b2008-09-10 07:00:50 +0000189 const llvm::Type *STy = ConvertType(RetTy);
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000190 ArgTys.push_back(llvm::PointerType::get(STy, RetTy.getAddressSpace()));
191 break;
192 }
193
194 case ABIArgInfo::Coerce:
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000195 ResultType = RetAI.getCoerceToType();
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000196 break;
197 }
198
199 for (++begin; begin != end; ++begin) {
Daniel Dunbar62d5c1b2008-09-10 07:00:50 +0000200 const llvm::Type *Ty = ConvertType(*begin);
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000201 if (Ty->isSingleValueType())
202 ArgTys.push_back(Ty);
203 else
204 // byval arguments are always on the stack, which is addr space #0.
205 ArgTys.push_back(llvm::PointerType::getUnqual(Ty));
206 }
207
Daniel Dunbar62d5c1b2008-09-10 07:00:50 +0000208 return llvm::FunctionType::get(ResultType, ArgTys, IsVariadic);
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000209}
210
Daniel Dunbarb7688072008-09-10 00:41:16 +0000211bool CodeGenModule::ReturnTypeUsesSret(QualType RetTy) {
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000212 return classifyReturnType(RetTy, getContext()).isStructRet();
Daniel Dunbar3913f182008-09-09 23:48:28 +0000213}
214
Daniel Dunbarb7688072008-09-10 00:41:16 +0000215void CodeGenModule::ConstructParamAttrList(const Decl *TargetDecl,
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000216 ArgTypeIterator begin,
217 ArgTypeIterator end,
218 ParamAttrListType &PAL) {
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000219 unsigned FuncAttrs = 0;
220
221 if (TargetDecl) {
222 if (TargetDecl->getAttr<NoThrowAttr>())
223 FuncAttrs |= llvm::ParamAttr::NoUnwind;
224 if (TargetDecl->getAttr<NoReturnAttr>())
225 FuncAttrs |= llvm::ParamAttr::NoReturn;
226 }
227
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000228 QualType RetTy = *begin;
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000229 unsigned Index = 1;
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000230 ABIArgInfo RetAI = classifyReturnType(RetTy, getContext());
Daniel Dunbar45c25ba2008-09-10 04:01:49 +0000231 switch (RetAI.getKind()) {
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000232 case ABIArgInfo::Default:
233 if (RetTy->isPromotableIntegerType()) {
234 if (RetTy->isSignedIntegerType()) {
235 FuncAttrs |= llvm::ParamAttr::SExt;
236 } else if (RetTy->isUnsignedIntegerType()) {
237 FuncAttrs |= llvm::ParamAttr::ZExt;
238 }
239 }
240 break;
241
242 case ABIArgInfo::StructRet:
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000243 PAL.push_back(llvm::ParamAttrsWithIndex::get(Index,
244 llvm::ParamAttr::StructRet));
245 ++Index;
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000246 break;
247
248 case ABIArgInfo::Coerce:
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000249 break;
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000250 }
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000251
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000252 if (FuncAttrs)
253 PAL.push_back(llvm::ParamAttrsWithIndex::get(0, FuncAttrs));
254 for (++begin; begin != end; ++begin, ++Index) {
255 QualType ParamType = *begin;
256 unsigned ParamAttrs = 0;
257 if (ParamType->isRecordType())
258 ParamAttrs |= llvm::ParamAttr::ByVal;
259 if (ParamType->isPromotableIntegerType()) {
260 if (ParamType->isSignedIntegerType()) {
261 ParamAttrs |= llvm::ParamAttr::SExt;
262 } else if (ParamType->isUnsignedIntegerType()) {
263 ParamAttrs |= llvm::ParamAttr::ZExt;
264 }
265 }
266 if (ParamAttrs)
267 PAL.push_back(llvm::ParamAttrsWithIndex::get(Index, ParamAttrs));
268 }
269}
270
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000271void CodeGenFunction::EmitFunctionProlog(llvm::Function *Fn,
272 QualType RetTy,
273 const FunctionArgList &Args) {
274 // Emit allocs for param decls. Give the LLVM Argument nodes names.
275 llvm::Function::arg_iterator AI = Fn->arg_begin();
276
277 // Name the struct return argument.
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000278 if (CGM.ReturnTypeUsesSret(RetTy)) {
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000279 AI->setName("agg.result");
280 ++AI;
281 }
282
283 for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end();
284 i != e; ++i, ++AI) {
285 const VarDecl *Arg = i->first;
286 QualType T = i->second;
287 assert(AI != Fn->arg_end() && "Argument mismatch!");
288 llvm::Value* V = AI;
289 if (!getContext().typesAreCompatible(T, Arg->getType())) {
290 // This must be a promotion, for something like
291 // "void a(x) short x; {..."
292 V = EmitScalarConversion(V, T, Arg->getType());
293 }
294 EmitParmDecl(*Arg, V);
295 }
296 assert(AI == Fn->arg_end() && "Argument mismatch!");
297}
298
299void CodeGenFunction::EmitFunctionEpilog(QualType RetTy,
300 llvm::Value *ReturnValue) {
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000301 llvm::Value *RV = 0;
302
303 // Functions with no result always return void.
304 if (ReturnValue) {
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000305 ABIArgInfo RetAI = classifyReturnType(RetTy, getContext());
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000306
307 switch (RetAI.getKind()) {
308 case ABIArgInfo::StructRet:
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000309 EmitAggregateCopy(CurFn->arg_begin(), ReturnValue, RetTy);
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000310 break;
311
312 case ABIArgInfo::Default:
313 RV = Builder.CreateLoad(ReturnValue);
314 break;
315
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000316 case ABIArgInfo::Coerce: {
317 const llvm::Type *CoerceToPTy =
318 llvm::PointerType::getUnqual(RetAI.getCoerceToType());
319 RV = Builder.CreateLoad(Builder.CreateBitCast(ReturnValue, CoerceToPTy));
320 }
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000321 }
322 }
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000323
324 if (RV) {
325 Builder.CreateRet(RV);
326 } else {
327 Builder.CreateRetVoid();
328 }
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000329}
330
331RValue CodeGenFunction::EmitCall(llvm::Value *Callee,
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000332 QualType RetTy,
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000333 const CallArgList &CallArgs) {
334 // FIXME: Factor out code to load from args into locals into target.
335 llvm::SmallVector<llvm::Value*, 16> Args;
336 llvm::Value *TempArg0 = 0;
337
338 // Handle struct-return functions by passing a pointer to the
339 // location that we would like to return into.
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000340 ABIArgInfo RetAI = classifyReturnType(RetTy, getContext());
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000341 switch (RetAI.getKind()) {
342 case ABIArgInfo::StructRet:
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000343 // Create a temporary alloca to hold the result of the call. :(
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000344 TempArg0 = CreateTempAlloca(ConvertType(RetTy));
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000345 Args.push_back(TempArg0);
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000346 break;
347
348 case ABIArgInfo::Default:
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000349 case ABIArgInfo::Coerce:
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000350 break;
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000351 }
352
353 for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end();
354 I != E; ++I) {
355 RValue RV = I->first;
356 if (RV.isScalar()) {
357 Args.push_back(RV.getScalarVal());
358 } else if (RV.isComplex()) {
359 // Make a temporary alloca to pass the argument.
360 Args.push_back(CreateTempAlloca(ConvertType(I->second)));
361 StoreComplexToAddr(RV.getComplexVal(), Args.back(), false);
362 } else {
363 Args.push_back(RV.getAggregateAddr());
364 }
365 }
366
367 llvm::CallInst *CI = Builder.CreateCall(Callee,&Args[0],&Args[0]+Args.size());
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000368 CGCallInfo CallInfo(RetTy, CallArgs);
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000369
Daniel Dunbar5323a4b2008-09-10 00:32:18 +0000370 // FIXME: Provide TargetDecl so nounwind, noreturn, etc, etc get set.
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000371 CodeGen::ParamAttrListType ParamAttrList;
Daniel Dunbarb7688072008-09-10 00:41:16 +0000372 CGM.ConstructParamAttrList(0,
373 CallInfo.argtypes_begin(), CallInfo.argtypes_end(),
374 ParamAttrList);
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000375 CI->setParamAttrs(llvm::PAListPtr::get(ParamAttrList.begin(),
376 ParamAttrList.size()));
377
378 if (const llvm::Function *F = dyn_cast<llvm::Function>(Callee))
379 CI->setCallingConv(F->getCallingConv());
380 if (CI->getType() != llvm::Type::VoidTy)
381 CI->setName("call");
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000382
383 switch (RetAI.getKind()) {
384 case ABIArgInfo::StructRet:
385 if (RetTy->isAnyComplexType())
386 return RValue::getComplex(LoadComplexFromAddr(TempArg0, false));
387 else
388 // Struct return.
389 return RValue::getAggregate(TempArg0);
390
391 case ABIArgInfo::Default:
392 return RValue::get(RetTy->isVoidType() ? 0 : CI);
393
Daniel Dunbar639ffe42008-09-10 07:04:09 +0000394 case ABIArgInfo::Coerce: {
395 const llvm::Type *CoerceToPTy =
396 llvm::PointerType::getUnqual(RetAI.getCoerceToType());
397 llvm::Value *V = CreateTempAlloca(ConvertType(RetTy), "tmp");
398 Builder.CreateStore(CI, Builder.CreateBitCast(V, CoerceToPTy));
399 return RValue::getAggregate(V);
400 }
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000401 }
Daniel Dunbar2c8e0f32008-09-10 02:41:04 +0000402
403 assert(0 && "Unhandled ABIArgInfo::Kind");
404 return RValue::get(0);
Daniel Dunbar17b708d2008-09-09 23:27:19 +0000405}