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());