comparison gen/tocall.cpp @ 723:55f6c2e454d7

Implemented correct parameter order according to x86-32 ABI documentation. Changed AA types to just a void* .
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Sat, 25 Oct 2008 06:03:28 +0200
parents e177ae483f8e
children f04dde6e882c
comparison
equal deleted inserted replaced
722:bd56056a581f 723:55f6c2e454d7
32 32
33 ////////////////////////////////////////////////////////////////////////////////////////// 33 //////////////////////////////////////////////////////////////////////////////////////////
34 34
35 unsigned DtoCallingConv(LINK l) 35 unsigned DtoCallingConv(LINK l)
36 { 36 {
37 if (l == LINKc || l == LINKcpp) 37 if (l == LINKc || l == LINKcpp || l == LINKintrinsic)
38 return llvm::CallingConv::C; 38 return llvm::CallingConv::C;
39 else if (l == LINKd || l == LINKdefault) 39 else if (l == LINKd || l == LINKdefault)
40 { 40 {
41 if (global.params.cpu == ARCHx86) 41 if (global.params.cpu == ARCHx86)
42 return llvm::CallingConv::X86_StdCall; 42 return llvm::CallingConv::X86_StdCall;
109 return NULL; 109 return NULL;
110 } 110 }
111 111
112 ////////////////////////////////////////////////////////////////////////////////////////// 112 //////////////////////////////////////////////////////////////////////////////////////////
113 113
114 void DtoBuildDVarArgList(std::vector<LLValue*>& args, llvm::AttrListPtr& palist, TypeFunction* tf, Expressions* arguments, size_t argidx) 114 void DtoBuildDVarArgList(std::vector<LLValue*>& args, std::vector<llvm::AttributeWithIndex>& attrs, TypeFunction* tf, Expressions* arguments, size_t argidx)
115 { 115 {
116 Logger::println("doing d-style variadic arguments"); 116 Logger::println("doing d-style variadic arguments");
117 117
118 std::vector<const LLType*> vtypes; 118 std::vector<const LLType*> vtypes;
119 119
193 Argument* fnarg = Argument::getNth(tf->parameters, i); 193 Argument* fnarg = Argument::getNth(tf->parameters, i);
194 DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]); 194 DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
195 args.push_back(argval->getRVal()); 195 args.push_back(argval->getRVal());
196 196
197 if (fnarg->llvmAttrs) 197 if (fnarg->llvmAttrs)
198 palist = palist.addAttr(argidx, fnarg->llvmAttrs); 198 {
199 llvm::AttributeWithIndex Attr;
200 Attr.Index = argidx;
201 Attr.Attrs = fnarg->llvmAttrs;
202 attrs.push_back(Attr);
203 }
199 204
200 ++argidx; 205 ++argidx;
201 } 206 }
202 } 207 }
203 208
232 // get callee llvm value 237 // get callee llvm value
233 LLValue* callable = DtoCallableValue(fnval); 238 LLValue* callable = DtoCallableValue(fnval);
234 const LLFunctionType* callableTy = DtoExtractFunctionType(callable->getType()); 239 const LLFunctionType* callableTy = DtoExtractFunctionType(callable->getType());
235 assert(callableTy); 240 assert(callableTy);
236 241
242 if (Logger::enabled())
243 {
244 Logger::cout() << "callable: " << *callable << '\n';
245 }
246
237 // get n arguments 247 // get n arguments
238 size_t n_arguments = arguments ? arguments->dim : 0; 248 size_t n_arguments = arguments ? arguments->dim : 0;
239 249
240 // get llvm argument iterator, for types 250 // get llvm argument iterator, for types
241 LLFunctionType::param_iterator argbegin = callableTy->param_begin(); 251 LLFunctionType::param_iterator argbegin = callableTy->param_begin();
242 LLFunctionType::param_iterator argiter = argbegin; 252 LLFunctionType::param_iterator argiter = argbegin;
243 253
244 // parameter attributes 254 // parameter attributes
245 llvm::AttrListPtr palist; 255 std::vector<llvm::AttributeWithIndex> attrs;
256 llvm::AttributeWithIndex Attr;
246 257
247 // return attrs 258 // return attrs
248 if (tf->retAttrs) 259 if (tf->retAttrs)
249 palist = palist.addAttr(0, tf->retAttrs); 260 {
261 Attr.Index = 0;
262 Attr.Attrs = tf->retAttrs;
263 attrs.push_back(Attr);
264 }
250 265
251 // handle implicit arguments 266 // handle implicit arguments
252 std::vector<LLValue*> args; 267 std::vector<LLValue*> args;
253 268
254 // return in hidden ptr is first 269 // return in hidden ptr is first
257 LLValue* retvar = DtoAlloca(argiter->get()->getContainedType(0), ".rettmp"); 272 LLValue* retvar = DtoAlloca(argiter->get()->getContainedType(0), ".rettmp");
258 ++argiter; 273 ++argiter;
259 args.push_back(retvar); 274 args.push_back(retvar);
260 275
261 // add attrs for hidden ptr 276 // add attrs for hidden ptr
262 palist = palist.addAttr(1, llvm::Attribute::StructRet); 277 Attr.Index = 1;
278 Attr.Attrs = llvm::Attribute::StructRet;
279 attrs.push_back(Attr);
263 } 280 }
264 281
265 // then comes a context argument... 282 // then comes a context argument...
266 if(thiscall || delegatecall || nestedcall) 283 if(thiscall || delegatecall || nestedcall)
267 { 284 {
302 fatal(); 319 fatal();
303 } 320 }
304 321
305 // add attributes for context argument 322 // add attributes for context argument
306 if (tf->thisAttrs) 323 if (tf->thisAttrs)
307 palist = palist.addAttr(retinptr?2:1, tf->thisAttrs); 324 {
325 Attr.Index = retinptr ? 2 : 1;
326 Attr.Attrs = tf->thisAttrs;
327 attrs.push_back(Attr);
328 }
308 } 329 }
309 330
310 // handle the rest of the arguments based on param passing style 331 // handle the rest of the arguments based on param passing style
311 332
312 // variadic instrinsics need some custom casts 333 // variadic instrinsics need some custom casts
324 } 345 }
325 346
326 // d style varargs needs a few more hidden arguments as well as special passing 347 // d style varargs needs a few more hidden arguments as well as special passing
327 else if (dvarargs) 348 else if (dvarargs)
328 { 349 {
329 DtoBuildDVarArgList(args, palist, tf, arguments, argiter-argbegin+1); 350 DtoBuildDVarArgList(args, attrs, tf, arguments, argiter-argbegin+1);
330 } 351 }
331 352
332 // otherwise we're looking at a normal function call 353 // otherwise we're looking at a normal function call
354 // or a C style vararg call
333 else 355 else
334 { 356 {
335 Logger::println("doing normal arguments"); 357 Logger::println("doing normal arguments");
336 for (int i=0; i<n_arguments; i++) { 358
337 int j = argiter-argbegin; 359 size_t n = Argument::dim(tf->parameters);
360
361 LLSmallVector<unsigned, 10> attrptr(n, 0);
362
363 // do formal params
364 int beg = argiter-argbegin;
365 for (int i=0; i<n; i++)
366 {
338 Argument* fnarg = Argument::getNth(tf->parameters, i); 367 Argument* fnarg = Argument::getNth(tf->parameters, i);
368 assert(fnarg);
339 DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]); 369 DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
340 LLValue* arg = argval->getRVal(); 370 LLValue* arg = argval->getRVal();
341 if (fnarg) // can fnarg ever be null in this block? 371
342 { 372 int j = tf->reverseParams ? beg + n - i - 1 : beg + i;
373
374 // parameter type mismatch, this is hard to get rid of
375 if (arg->getType() != callableTy->getParamType(j))
376 {
377 #if 0
343 if (Logger::enabled()) 378 if (Logger::enabled())
344 { 379 {
345 Logger::cout() << "arg: " << *arg << '\n'; 380 Logger::cout() << "arg: " << *arg << '\n';
346 Logger::cout() << "expects: " << *callableTy->getParamType(j) << '\n'; 381 Logger::cout() << "expects: " << *callableTy->getParamType(j) << '\n';
347 } 382 }
348 if (arg->getType() != callableTy->getParamType(j)) 383 #endif
349 arg = DtoBitCast(arg, callableTy->getParamType(j)); 384 arg = DtoBitCast(arg, callableTy->getParamType(j));
350 if (fnarg->llvmAttrs) 385 }
351 palist = palist.addAttr(j+1, fnarg->llvmAttrs); 386
352 } 387 // param attrs
388 attrptr[i] = fnarg->llvmAttrs;
389
353 ++argiter; 390 ++argiter;
354 args.push_back(arg); 391 args.push_back(arg);
392 }
393
394 // reverse the relevant params as well as the param attrs
395 if (tf->reverseParams)
396 {
397 std::reverse(args.begin() + tf->reverseIndex, args.end());
398 std::reverse(attrptr.begin(), attrptr.end());
399 }
400
401 // add attributes
402 for (int i = 0; i < n; i++)
403 {
404 if (attrptr[i])
405 {
406 Attr.Index = beg + i + 1;
407 Attr.Attrs = attrptr[i];
408 attrs.push_back(Attr);
409 }
410 }
411
412 // do C varargs
413 if (n_arguments > n)
414 {
415 for (int i=n; i<n_arguments; i++)
416 {
417 Argument* fnarg = Argument::getNth(tf->parameters, i);
418 DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
419 LLValue* arg = argval->getRVal();
420
421 // FIXME: do we need any param attrs here ?
422
423 ++argiter;
424 args.push_back(arg);
425 }
355 } 426 }
356 } 427 }
357 428
358 #if 0 429 #if 0
359 Logger::println("%d params passed", n); 430 Logger::println("%d params passed", n);
403 Logger::cout() << "final return value: " << *retllval << '\n'; 474 Logger::cout() << "final return value: " << *retllval << '\n';
404 } 475 }
405 } 476 }
406 477
407 // set calling convention and parameter attributes 478 // set calling convention and parameter attributes
479 llvm::AttrListPtr attrlist = llvm::AttrListPtr::get(attrs.begin(), attrs.end());
408 if (dfnval && dfnval->func) 480 if (dfnval && dfnval->func)
409 { 481 {
410 LLFunction* llfunc = llvm::dyn_cast<LLFunction>(dfnval->val); 482 LLFunction* llfunc = llvm::dyn_cast<LLFunction>(dfnval->val);
411 if (llfunc && llfunc->isIntrinsic()) 483 if (llfunc && llfunc->isIntrinsic()) // override intrinsic attrs
412 palist = llvm::Intrinsic::getAttributes((llvm::Intrinsic::ID)llfunc->getIntrinsicID()); 484 attrlist = llvm::Intrinsic::getAttributes((llvm::Intrinsic::ID)llfunc->getIntrinsicID());
413 else 485 else
414 call->setCallingConv(callconv); 486 call->setCallingConv(callconv);
415 } 487 }
416 else 488 else
417 call->setCallingConv(callconv); 489 call->setCallingConv(callconv);
418 call->setAttributes(palist); 490 call->setAttributes(attrlist);
419 491
420 return new DImValue(resulttype, retllval); 492 return new DImValue(resulttype, retllval);
421 } 493 }