Mercurial > projects > ldc
comparison gen/functions.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 | 6de2ed4f0abe |
comparison
equal
deleted
inserted
replaced
722:bd56056a581f | 723:55f6c2e454d7 |
---|---|
18 #include "gen/logger.h" | 18 #include "gen/logger.h" |
19 #include "gen/functions.h" | 19 #include "gen/functions.h" |
20 #include "gen/todebug.h" | 20 #include "gen/todebug.h" |
21 #include "gen/classes.h" | 21 #include "gen/classes.h" |
22 #include "gen/dvalue.h" | 22 #include "gen/dvalue.h" |
23 | |
24 #include <algorithm> | |
23 | 25 |
24 const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, const LLType* nesttype, bool ismain) | 26 const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, const LLType* nesttype, bool ismain) |
25 { | 27 { |
26 assert(type->ty == Tfunction); | 28 assert(type->ty == Tfunction); |
27 TypeFunction* f = (TypeFunction*)type; | 29 TypeFunction* f = (TypeFunction*)type; |
109 else if (arrayVararg) | 111 else if (arrayVararg) |
110 { | 112 { |
111 // do nothing? | 113 // do nothing? |
112 } | 114 } |
113 | 115 |
116 // number of formal params | |
114 size_t n = Argument::dim(f->parameters); | 117 size_t n = Argument::dim(f->parameters); |
118 | |
119 // on x86 we need to reverse the formal params in some cases to match the ABI | |
120 if (global.params.cpu == ARCHx86) | |
121 { | |
122 // more than one formal arg, | |
123 // extern(D) linkage | |
124 // not a D-style vararg | |
125 if (n > 1 && f->linkage == LINKd && !typesafeVararg) | |
126 { | |
127 f->reverseParams = true; | |
128 f->reverseIndex = paramvec.size(); | |
129 } | |
130 } | |
131 | |
115 | 132 |
116 for (int i=0; i < n; ++i) { | 133 for (int i=0; i < n; ++i) { |
117 Argument* arg = Argument::getNth(f->parameters, i); | 134 Argument* arg = Argument::getNth(f->parameters, i); |
118 // ensure scalar | 135 // ensure scalar |
119 Type* argT = arg->type->toBasetype(); | 136 Type* argT = arg->type->toBasetype(); |
165 arg->llvmAttrs |= ea; | 182 arg->llvmAttrs |= ea; |
166 paramvec.push_back(at); | 183 paramvec.push_back(at); |
167 } | 184 } |
168 } | 185 } |
169 | 186 |
187 // reverse params? | |
188 if (f->reverseParams) | |
189 { | |
190 std::reverse(paramvec.begin() + f->reverseIndex, paramvec.end()); | |
191 } | |
192 | |
170 // construct function type | 193 // construct function type |
171 bool isvararg = !(typesafeVararg || arrayVararg) && f->varargs; | 194 bool isvararg = !(typesafeVararg || arrayVararg) && f->varargs; |
172 llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg); | 195 llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg); |
173 | 196 |
174 // tell first param to be passed in a register if we can | 197 // tell first param to be passed in a register if we can |
187 f->thisAttrs |= llvm::Attribute::InReg; | 210 f->thisAttrs |= llvm::Attribute::InReg; |
188 } | 211 } |
189 // otherwise check the first formal parameter | 212 // otherwise check the first formal parameter |
190 else | 213 else |
191 { | 214 { |
215 int inreg = f->reverseParams ? n - 1 : 0; | |
192 Argument* arg = Argument::getNth(f->parameters, 0); | 216 Argument* arg = Argument::getNth(f->parameters, 0); |
193 Type* t = arg->type->toBasetype(); | 217 Type* t = arg->type->toBasetype(); |
194 | 218 |
195 // 32bit ints, pointers, classes and static arrays are candidate for being passed in EAX | 219 // 32bit ints, pointers, classes and static arrays are candidate for being passed in EAX |
196 if ((arg->storageClass & STCin) && | 220 if ((arg->storageClass & STCin) && |
338 else if (tempdecl->llvmInternal == LLVMintrinsic) | 362 else if (tempdecl->llvmInternal == LLVMintrinsic) |
339 { | 363 { |
340 Logger::println("overloaded intrinsic found"); | 364 Logger::println("overloaded intrinsic found"); |
341 fdecl->llvmInternal = LLVMintrinsic; | 365 fdecl->llvmInternal = LLVMintrinsic; |
342 DtoOverloadedIntrinsicName(tinst, tempdecl, fdecl->intrinsicName); | 366 DtoOverloadedIntrinsicName(tinst, tempdecl, fdecl->intrinsicName); |
367 fdecl->linkage = LINKintrinsic; | |
368 ((TypeFunction*)fdecl->type)->linkage = LINKintrinsic; | |
343 } | 369 } |
344 } | 370 } |
345 | 371 |
346 DtoFunctionType(fdecl); | 372 DtoFunctionType(fdecl); |
347 | 373 |
352 | 378 |
353 ////////////////////////////////////////////////////////////////////////////////////////// | 379 ////////////////////////////////////////////////////////////////////////////////////////// |
354 | 380 |
355 static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclaration* fdecl) | 381 static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclaration* fdecl) |
356 { | 382 { |
357 int llidx = 1; | 383 int llidx = 0; |
358 if (f->retInPtr) ++llidx; | 384 if (f->retInPtr) ++llidx; |
359 if (f->usesThis) ++llidx; | 385 if (f->usesThis) ++llidx; |
360 else if (f->usesNest) ++llidx; | 386 else if (f->usesNest) ++llidx; |
361 if (f->linkage == LINKd && f->varargs == 1) | 387 if (f->linkage == LINKd && f->varargs == 1) |
362 llidx += 2; | 388 llidx += 2; |
363 | 389 |
364 int funcNumArgs = func->getArgumentList().size(); | 390 int funcNumArgs = func->getArgumentList().size(); |
365 std::vector<llvm::AttributeWithIndex> attrs; | 391 |
366 int k = 0; | 392 LLSmallVector<llvm::AttributeWithIndex, 9> attrs; |
367 | |
368 llvm::AttributeWithIndex PAWI; | 393 llvm::AttributeWithIndex PAWI; |
369 | 394 |
370 // set return value attrs if any | 395 // set return value attrs if any |
371 if (f->retAttrs) | 396 if (f->retAttrs) |
372 { | 397 { |
390 PAWI.Attrs = f->thisAttrs; | 415 PAWI.Attrs = f->thisAttrs; |
391 attrs.push_back(PAWI); | 416 attrs.push_back(PAWI); |
392 } | 417 } |
393 | 418 |
394 // set attrs on the rest of the arguments | 419 // set attrs on the rest of the arguments |
395 for (; llidx <= funcNumArgs && Argument::dim(f->parameters) > k; ++llidx,++k) | 420 size_t n = Argument::dim(f->parameters); |
421 assert(funcNumArgs >= n); // main might mismatch, for the implicit char[][] arg | |
422 | |
423 LLSmallVector<unsigned,8> attrptr(n, 0); | |
424 | |
425 for (size_t k = 0; k < n; ++k) | |
396 { | 426 { |
397 Argument* fnarg = Argument::getNth(f->parameters, k); | 427 Argument* fnarg = Argument::getNth(f->parameters, k); |
398 assert(fnarg); | 428 assert(fnarg); |
399 | 429 |
400 PAWI.Index = llidx; | 430 attrptr[k] = fnarg->llvmAttrs; |
401 PAWI.Attrs = fnarg->llvmAttrs; | 431 } |
402 | 432 |
403 if (PAWI.Attrs) | 433 // reverse params? |
434 if (f->reverseParams) | |
435 { | |
436 std::reverse(attrptr.begin(), attrptr.end()); | |
437 } | |
438 | |
439 // build rest of attrs list | |
440 for (int i = 0; i < n; i++) | |
441 { | |
442 if (attrptr[i]) | |
443 { | |
444 PAWI.Index = llidx+i+1; | |
445 PAWI.Attrs = attrptr[i]; | |
404 attrs.push_back(PAWI); | 446 attrs.push_back(PAWI); |
405 } | 447 } |
406 | 448 } |
407 llvm::AttrListPtr palist = llvm::AttrListPtr::get(attrs.begin(), attrs.end()); | 449 |
408 func->setAttributes(palist); | 450 llvm::AttrListPtr attrlist = llvm::AttrListPtr::get(attrs.begin(), attrs.end()); |
451 func->setAttributes(attrlist); | |
409 } | 452 } |
410 | 453 |
411 ////////////////////////////////////////////////////////////////////////////////////////// | 454 ////////////////////////////////////////////////////////////////////////////////////////// |
412 | 455 |
413 void DtoDeclareFunction(FuncDeclaration* fdecl) | 456 void DtoDeclareFunction(FuncDeclaration* fdecl) |
501 // we never reference parameters of function prototypes | 544 // we never reference parameters of function prototypes |
502 if (!declareOnly) | 545 if (!declareOnly) |
503 { | 546 { |
504 // name parameters | 547 // name parameters |
505 llvm::Function::arg_iterator iarg = func->arg_begin(); | 548 llvm::Function::arg_iterator iarg = func->arg_begin(); |
506 int k = 0; | 549 |
507 if (f->retInPtr) { | 550 if (f->retInPtr) { |
508 iarg->setName(".sretarg"); | 551 iarg->setName(".sretarg"); |
509 fdecl->ir.irFunc->retArg = iarg; | 552 fdecl->ir.irFunc->retArg = iarg; |
510 ++iarg; | 553 ++iarg; |
511 } | 554 } |
512 | 555 |
513 if (f->usesThis) { | 556 if (f->usesThis) { |
514 iarg->setName("this"); | 557 iarg->setName("this"); |
515 fdecl->ir.irFunc->thisArg = iarg; | 558 fdecl->ir.irFunc->thisArg = iarg; |
516 assert(fdecl->ir.irFunc->thisArg); | 559 assert(fdecl->ir.irFunc->thisArg); |
517 ++iarg; | 560 ++iarg; |
530 iarg->setName("_argptr"); | 573 iarg->setName("_argptr"); |
531 fdecl->ir.irFunc->_argptr = iarg; | 574 fdecl->ir.irFunc->_argptr = iarg; |
532 ++iarg; | 575 ++iarg; |
533 } | 576 } |
534 | 577 |
578 int k = 0; | |
579 | |
535 for (; iarg != func->arg_end(); ++iarg) | 580 for (; iarg != func->arg_end(); ++iarg) |
536 { | 581 { |
537 if (fdecl->parameters && fdecl->parameters->dim > k) | 582 if (fdecl->parameters && fdecl->parameters->dim > k) |
538 { | 583 { |
539 Dsymbol* argsym = (Dsymbol*)fdecl->parameters->data[k++]; | 584 Dsymbol* argsym; |
585 if (f->reverseParams) | |
586 argsym = (Dsymbol*)fdecl->parameters->data[fdecl->parameters->dim-k-1]; | |
587 else | |
588 argsym = (Dsymbol*)fdecl->parameters->data[k]; | |
589 | |
540 VarDeclaration* argvd = argsym->isVarDeclaration(); | 590 VarDeclaration* argvd = argsym->isVarDeclaration(); |
541 assert(argvd); | 591 assert(argvd); |
542 assert(!argvd->ir.irLocal); | 592 assert(!argvd->ir.irLocal); |
543 argvd->ir.irLocal = new IrLocal(argvd); | 593 argvd->ir.irLocal = new IrLocal(argvd); |
544 argvd->ir.irLocal->value = iarg; | 594 argvd->ir.irLocal->value = iarg; |
545 iarg->setName(argvd->ident->toChars()); | 595 iarg->setName(argvd->ident->toChars()); |
596 | |
597 k++; | |
546 } | 598 } |
547 else | 599 else |
548 { | 600 { |
549 iarg->setName("unnamed"); | 601 iarg->setName("unnamed"); |
550 } | 602 } |
900 LOG_SCOPE; | 952 LOG_SCOPE; |
901 | 953 |
902 DValue* arg = argexp->toElem(gIR); | 954 DValue* arg = argexp->toElem(gIR); |
903 | 955 |
904 // ref/out arg | 956 // ref/out arg |
905 if (fnarg && ((fnarg->storageClass & STCref) || (fnarg->storageClass & STCout))) | 957 if (fnarg && (fnarg->storageClass & (STCref | STCout))) |
906 { | 958 { |
907 if (arg->isVar() || arg->isLRValue()) | 959 if (arg->isVar() || arg->isLRValue()) |
908 arg = new DImValue(argexp->type, arg->getLVal()); | 960 arg = new DImValue(argexp->type, arg->getLVal()); |
909 else | 961 else |
910 arg = new DImValue(argexp->type, arg->getRVal()); | 962 arg = new DImValue(argexp->type, arg->getRVal()); |