Mercurial > projects > ldc
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 } |