Mercurial > projects > ldc
comparison gen/functions.cpp @ 486:a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Reimplemented support for nested functions/class using a new approach.
Added error on taking address of intrinsic.
Fixed problems with the ->syntaxCopy of TypeFunction delegate exp.
Removed DtoDType and replaced all uses with ->toBasetype() instead.
Removed unused inplace stuff.
Fixed a bunch of issues in the runtime unittests, not complete yet.
Added mini tests.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Sun, 10 Aug 2008 08:37:38 +0200 |
parents | 672eb4893b55 |
children | c9a606d6e641 |
comparison
equal
deleted
inserted
replaced
485:50f6e2337a6b | 486:a34078905d01 |
---|---|
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 | 23 |
24 const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bool ismain) | 24 const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, const LLType* nesttype, bool ismain) |
25 { | 25 { |
26 assert(type->ty == Tfunction); | 26 assert(type->ty == Tfunction); |
27 TypeFunction* f = (TypeFunction*)type; | 27 TypeFunction* f = (TypeFunction*)type; |
28 | 28 |
29 if (type->ir.type != NULL) { | 29 if (type->ir.type != NULL) { |
44 const LLType* rettype; | 44 const LLType* rettype; |
45 const LLType* actualRettype; | 45 const LLType* actualRettype; |
46 Type* rt = f->next; | 46 Type* rt = f->next; |
47 bool retinptr = false; | 47 bool retinptr = false; |
48 bool usesthis = false; | 48 bool usesthis = false; |
49 bool usesnest = false; | |
49 | 50 |
50 // parameter types | 51 // parameter types |
51 std::vector<const LLType*> paramvec; | 52 std::vector<const LLType*> paramvec; |
52 | 53 |
53 if (ismain) | 54 if (ismain) |
64 else{ | 65 else{ |
65 assert(rt); | 66 assert(rt); |
66 if (DtoIsReturnedInArg(rt)) { | 67 if (DtoIsReturnedInArg(rt)) { |
67 rettype = getPtrToType(DtoType(rt)); | 68 rettype = getPtrToType(DtoType(rt)); |
68 actualRettype = LLType::VoidTy; | 69 actualRettype = LLType::VoidTy; |
69 f->llvmRetInPtr = retinptr = true; | 70 f->retInPtr = retinptr = true; |
70 } | 71 } |
71 else { | 72 else { |
72 rettype = DtoType(rt); | 73 rettype = DtoType(rt); |
73 actualRettype = rettype; | 74 actualRettype = rettype; |
74 } | 75 } |
75 | 76 |
76 if (unsigned ea = DtoShouldExtend(rt)) | 77 if (unsigned ea = DtoShouldExtend(rt)) |
77 { | 78 { |
78 f->llvmRetAttrs |= ea; | 79 f->retAttrs |= ea; |
79 } | 80 } |
80 } | 81 } |
81 | 82 |
82 if (retinptr) { | 83 if (retinptr) { |
83 //Logger::cout() << "returning through pointer parameter: " << *rettype << '\n'; | 84 //Logger::cout() << "returning through pointer parameter: " << *rettype << '\n'; |
85 } | 86 } |
86 | 87 |
87 if (thistype) { | 88 if (thistype) { |
88 paramvec.push_back(thistype); | 89 paramvec.push_back(thistype); |
89 usesthis = true; | 90 usesthis = true; |
91 } | |
92 else if (nesttype) { | |
93 paramvec.push_back(nesttype); | |
94 usesnest = true; | |
90 } | 95 } |
91 | 96 |
92 if (typesafeVararg) { | 97 if (typesafeVararg) { |
93 ClassDeclaration* ti = Type::typeinfo; | 98 ClassDeclaration* ti = Type::typeinfo; |
94 ti->toObjFile(0); // TODO: multiobj | 99 ti->toObjFile(0); // TODO: multiobj |
109 size_t n = Argument::dim(f->parameters); | 114 size_t n = Argument::dim(f->parameters); |
110 | 115 |
111 for (int i=0; i < n; ++i) { | 116 for (int i=0; i < n; ++i) { |
112 Argument* arg = Argument::getNth(f->parameters, i); | 117 Argument* arg = Argument::getNth(f->parameters, i); |
113 // ensure scalar | 118 // ensure scalar |
114 Type* argT = DtoDType(arg->type); | 119 Type* argT = arg->type->toBasetype(); |
115 assert(argT); | 120 assert(argT); |
116 | 121 |
117 bool refOrOut = ((arg->storageClass & STCref) || (arg->storageClass & STCout)); | 122 bool refOrOut = ((arg->storageClass & STCref) || (arg->storageClass & STCout)); |
118 | 123 |
119 const LLType* at = DtoType(argT); | 124 const LLType* at = DtoType(argT); |
164 | 169 |
165 // construct function type | 170 // construct function type |
166 bool isvararg = !(typesafeVararg || arrayVararg) && f->varargs; | 171 bool isvararg = !(typesafeVararg || arrayVararg) && f->varargs; |
167 llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg); | 172 llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg); |
168 | 173 |
169 f->llvmRetInPtr = retinptr; | 174 f->retInPtr = retinptr; |
170 f->llvmUsesThis = usesthis; | 175 f->usesThis = usesthis; |
176 f->usesNest = usesnest; | |
171 | 177 |
172 f->ir.type = new llvm::PATypeHolder(functype); | 178 f->ir.type = new llvm::PATypeHolder(functype); |
173 | 179 |
174 return functype; | 180 return functype; |
175 } | 181 } |
208 | 214 |
209 // type has already been resolved | 215 // type has already been resolved |
210 if (fdecl->type->ir.type != 0) | 216 if (fdecl->type->ir.type != 0) |
211 return llvm::cast<llvm::FunctionType>(fdecl->type->ir.type->get()); | 217 return llvm::cast<llvm::FunctionType>(fdecl->type->ir.type->get()); |
212 | 218 |
213 const LLType* thisty = NULL; | 219 const LLType* thisty = 0; |
220 const LLType* nestty = 0; | |
221 | |
214 if (fdecl->needThis()) { | 222 if (fdecl->needThis()) { |
215 if (AggregateDeclaration* ad = fdecl->isMember2()) { | 223 if (AggregateDeclaration* ad = fdecl->isMember2()) { |
216 Logger::println("isMember = this is: %s", ad->type->toChars()); | 224 Logger::println("isMember = this is: %s", ad->type->toChars()); |
217 thisty = DtoType(ad->type); | 225 thisty = DtoType(ad->type); |
218 //Logger::cout() << "this llvm type: " << *thisty << '\n'; | 226 //Logger::cout() << "this llvm type: " << *thisty << '\n'; |
223 Logger::println("chars: %s type: %s kind: %s", fdecl->toChars(), fdecl->type->toChars(), fdecl->kind()); | 231 Logger::println("chars: %s type: %s kind: %s", fdecl->toChars(), fdecl->type->toChars(), fdecl->kind()); |
224 assert(0); | 232 assert(0); |
225 } | 233 } |
226 } | 234 } |
227 else if (fdecl->isNested()) { | 235 else if (fdecl->isNested()) { |
228 thisty = getPtrToType(LLType::Int8Ty); | 236 nestty = getPtrToType(LLType::Int8Ty); |
229 } | 237 } |
230 | 238 |
231 const llvm::FunctionType* functype = DtoFunctionType(fdecl->type, thisty, fdecl->isMain()); | 239 const llvm::FunctionType* functype = DtoFunctionType(fdecl->type, thisty, nestty, fdecl->isMain()); |
232 | 240 |
233 return functype; | 241 return functype; |
234 } | 242 } |
235 | 243 |
236 ////////////////////////////////////////////////////////////////////////////////////////// | 244 ////////////////////////////////////////////////////////////////////////////////////////// |
237 | 245 |
238 static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl) | 246 static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl) |
239 { | 247 { |
240 TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type); | 248 TypeFunction* f = (TypeFunction*)fdecl->type->toBasetype(); |
241 const llvm::FunctionType* fty = DtoVaFunctionType(fdecl); | 249 const llvm::FunctionType* fty = DtoVaFunctionType(fdecl); |
242 llvm::Function* func = 0; | 250 llvm::Function* func = 0; |
243 | 251 |
244 if (fdecl->llvmInternal == LLVMva_start) | 252 if (fdecl->llvmInternal == LLVMva_start) |
245 func = GET_INTRINSIC_DECL(vastart); | 253 func = GET_INTRINSIC_DECL(vastart); |
304 ////////////////////////////////////////////////////////////////////////////////////////// | 312 ////////////////////////////////////////////////////////////////////////////////////////// |
305 | 313 |
306 static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclaration* fdecl) | 314 static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclaration* fdecl) |
307 { | 315 { |
308 int llidx = 1; | 316 int llidx = 1; |
309 if (f->llvmRetInPtr) ++llidx; | 317 if (f->retInPtr) ++llidx; |
310 if (f->llvmUsesThis) ++llidx; | 318 if (f->usesThis) ++llidx; |
319 else if (f->usesNest) ++llidx; | |
311 if (f->linkage == LINKd && f->varargs == 1) | 320 if (f->linkage == LINKd && f->varargs == 1) |
312 llidx += 2; | 321 llidx += 2; |
313 | 322 |
314 int funcNumArgs = func->getArgumentList().size(); | 323 int funcNumArgs = func->getArgumentList().size(); |
315 std::vector<llvm::ParamAttrsWithIndex> attrs; | 324 std::vector<llvm::ParamAttrsWithIndex> attrs; |
316 int k = 0; | 325 int k = 0; |
317 | 326 |
318 llvm::ParamAttrsWithIndex PAWI; | 327 llvm::ParamAttrsWithIndex PAWI; |
319 | 328 |
320 // set return value attrs if any | 329 // set return value attrs if any |
321 if (f->llvmRetAttrs) | 330 if (f->retAttrs) |
322 { | 331 { |
323 PAWI.Index = 0; | 332 PAWI.Index = 0; |
324 PAWI.Attrs = f->llvmRetAttrs; | 333 PAWI.Attrs = f->retAttrs; |
325 attrs.push_back(PAWI); | 334 attrs.push_back(PAWI); |
326 } | 335 } |
327 | 336 |
328 // set sret param | 337 // set sret param |
329 if (f->llvmRetInPtr) | 338 if (f->retInPtr) |
330 { | 339 { |
331 PAWI.Index = 1; | 340 PAWI.Index = 1; |
332 PAWI.Attrs = llvm::ParamAttr::StructRet; | 341 PAWI.Attrs = llvm::ParamAttr::StructRet; |
333 attrs.push_back(PAWI); | 342 attrs.push_back(PAWI); |
334 } | 343 } |
376 error(fdecl->loc, "intrinsics cannot have function bodies"); | 385 error(fdecl->loc, "intrinsics cannot have function bodies"); |
377 fatal(); | 386 fatal(); |
378 } | 387 } |
379 | 388 |
380 // get TypeFunction* | 389 // get TypeFunction* |
381 Type* t = DtoDType(fdecl->type); | 390 Type* t = fdecl->type->toBasetype(); |
382 TypeFunction* f = (TypeFunction*)t; | 391 TypeFunction* f = (TypeFunction*)t; |
383 | 392 |
384 bool declareOnly = false; | 393 bool declareOnly = false; |
385 bool templInst = fdecl->parent && DtoIsTemplateInstance(fdecl->parent); | 394 bool templInst = fdecl->parent && DtoIsTemplateInstance(fdecl->parent); |
386 if (!templInst && fdecl->getModule() != gIR->dmodule) | 395 if (!templInst && fdecl->getModule() != gIR->dmodule) |
415 // construct function | 424 // construct function |
416 const llvm::FunctionType* functype = DtoFunctionType(fdecl); | 425 const llvm::FunctionType* functype = DtoFunctionType(fdecl); |
417 llvm::Function* func = vafunc ? vafunc : gIR->module->getFunction(mangled_name); | 426 llvm::Function* func = vafunc ? vafunc : gIR->module->getFunction(mangled_name); |
418 if (!func) | 427 if (!func) |
419 func = llvm::Function::Create(functype, DtoLinkage(fdecl), mangled_name, gIR->module); | 428 func = llvm::Function::Create(functype, DtoLinkage(fdecl), mangled_name, gIR->module); |
420 else | |
421 assert(func->getFunctionType() == functype); | |
422 | 429 |
423 // add func to IRFunc | 430 // add func to IRFunc |
424 fdecl->ir.irFunc->func = func; | 431 fdecl->ir.irFunc->func = func; |
425 | 432 |
426 // calling convention | 433 // calling convention |
455 if (!declareOnly) | 462 if (!declareOnly) |
456 { | 463 { |
457 // name parameters | 464 // name parameters |
458 llvm::Function::arg_iterator iarg = func->arg_begin(); | 465 llvm::Function::arg_iterator iarg = func->arg_begin(); |
459 int k = 0; | 466 int k = 0; |
460 if (f->llvmRetInPtr) { | 467 if (f->retInPtr) { |
461 iarg->setName("retval"); | 468 iarg->setName(".sretarg"); |
462 fdecl->ir.irFunc->retArg = iarg; | 469 fdecl->ir.irFunc->retArg = iarg; |
463 ++iarg; | 470 ++iarg; |
464 } | 471 } |
465 if (f->llvmUsesThis) { | 472 |
466 iarg->setName(fdecl->isNested()?".context":"this"); | 473 if (f->usesThis) { |
467 fdecl->ir.irFunc->thisVar = iarg; | 474 iarg->setName("this"); |
468 assert(fdecl->ir.irFunc->thisVar); | 475 fdecl->ir.irFunc->thisArg = iarg; |
476 assert(fdecl->ir.irFunc->thisArg); | |
477 ++iarg; | |
478 } | |
479 else if (f->usesNest) { | |
480 iarg->setName(".nest"); | |
481 fdecl->ir.irFunc->nestArg = iarg; | |
482 assert(fdecl->ir.irFunc->nestArg); | |
469 ++iarg; | 483 ++iarg; |
470 } | 484 } |
471 | 485 |
472 if (f->linkage == LINKd && f->varargs == 1) { | 486 if (f->linkage == LINKd && f->varargs == 1) { |
473 iarg->setName("_arguments"); | 487 iarg->setName("_arguments"); |
518 assert(fd->ir.declared); | 532 assert(fd->ir.declared); |
519 | 533 |
520 Logger::println("DtoDefineFunc(%s): %s", fd->toPrettyChars(), fd->loc.toChars()); | 534 Logger::println("DtoDefineFunc(%s): %s", fd->toPrettyChars(), fd->loc.toChars()); |
521 LOG_SCOPE; | 535 LOG_SCOPE; |
522 | 536 |
537 // warn about naked | |
538 if (fd->naked) | |
539 { | |
540 warning("%s: naked is currently ignored", fd->locToChars()); | |
541 } | |
542 | |
523 // debug info | 543 // debug info |
524 if (global.params.symdebug) { | 544 if (global.params.symdebug) { |
525 Module* mo = fd->getModule(); | 545 Module* mo = fd->getModule(); |
526 fd->ir.irFunc->dwarfSubProg = DtoDwarfSubProgram(fd); | 546 fd->ir.irFunc->dwarfSubProg = DtoDwarfSubProgram(fd); |
527 } | 547 } |
528 | 548 |
529 Type* t = DtoDType(fd->type); | 549 Type* t = fd->type->toBasetype(); |
530 TypeFunction* f = (TypeFunction*)t; | 550 TypeFunction* f = (TypeFunction*)t; |
531 assert(f->ir.type); | 551 assert(f->ir.type); |
532 | 552 |
533 llvm::Function* func = fd->ir.irFunc->func; | 553 llvm::Function* func = fd->ir.irFunc->func; |
534 const llvm::FunctionType* functype = func->getFunctionType(); | 554 const llvm::FunctionType* functype = func->getFunctionType(); |
566 irfunction->allocapoint = allocaPoint; | 586 irfunction->allocapoint = allocaPoint; |
567 | 587 |
568 // debug info - after all allocas, but before any llvm.dbg.declare etc | 588 // debug info - after all allocas, but before any llvm.dbg.declare etc |
569 if (global.params.symdebug) DtoDwarfFuncStart(fd); | 589 if (global.params.symdebug) DtoDwarfFuncStart(fd); |
570 | 590 |
571 // need result variable? (not nested) | 591 // need result variable? |
572 if (fd->vresult && !fd->vresult->nestedref) { | 592 if (fd->vresult) { |
573 Logger::println("non-nested vresult value"); | 593 Logger::println("vresult value"); |
574 fd->vresult->ir.irLocal = new IrLocal(fd->vresult); | 594 fd->vresult->ir.irLocal = new IrLocal(fd->vresult); |
575 fd->vresult->ir.irLocal->value = DtoAlloca(DtoType(fd->vresult->type),"function_vresult"); | 595 fd->vresult->ir.irLocal->value = DtoAlloca(DtoType(fd->vresult->type), "function_vresult"); |
576 } | 596 } |
577 | 597 |
578 // give the 'this' argument storage and debug info | 598 // give the 'this' argument storage and debug info |
579 // only if not referenced by nested functions | 599 if (f->usesThis) |
580 if (fd->needThis() && !fd->vthis->nestedref) | 600 { |
581 { | 601 LLValue* thisvar = irfunction->thisArg; |
582 LLValue* thisvar = irfunction->thisVar; | |
583 assert(thisvar); | 602 assert(thisvar); |
584 | 603 |
585 LLValue* thismem = DtoAlloca(thisvar->getType(), ".newthis"); | 604 LLValue* thismem = DtoAlloca(thisvar->getType(), ".this"); |
586 DtoStore(thisvar, thismem); | 605 DtoStore(thisvar, thismem); |
587 irfunction->thisVar = thismem; | 606 irfunction->thisArg = thismem; |
607 | |
608 assert(!fd->vthis->ir.irLocal); | |
609 fd->vthis->ir.irLocal = new IrLocal(fd->vthis); | |
610 fd->vthis->ir.irLocal->value = thismem; | |
588 | 611 |
589 if (global.params.symdebug) | 612 if (global.params.symdebug) |
590 DtoDwarfLocalVariable(thismem, fd->vthis); | 613 DtoDwarfLocalVariable(thismem, fd->vthis); |
614 | |
615 if (fd->vthis->nestedref) | |
616 fd->nestedVars.insert(fd->vthis); | |
591 } | 617 } |
592 | 618 |
593 // give arguments storage | 619 // give arguments storage |
594 // and debug info | 620 // and debug info |
595 if (fd->parameters) | 621 if (fd->parameters) |
598 for (int i=0; i < n; ++i) | 624 for (int i=0; i < n; ++i) |
599 { | 625 { |
600 Dsymbol* argsym = (Dsymbol*)fd->parameters->data[i]; | 626 Dsymbol* argsym = (Dsymbol*)fd->parameters->data[i]; |
601 VarDeclaration* vd = argsym->isVarDeclaration(); | 627 VarDeclaration* vd = argsym->isVarDeclaration(); |
602 assert(vd); | 628 assert(vd); |
629 | |
630 if (vd->nestedref) | |
631 fd->nestedVars.insert(vd); | |
603 | 632 |
604 IrLocal* irloc = vd->ir.irLocal; | 633 IrLocal* irloc = vd->ir.irLocal; |
605 assert(irloc); | 634 assert(irloc); |
606 | 635 |
607 bool refoutlazy = vd->storage_class & (STCref | STCout | STClazy); | 636 bool refoutlazy = vd->storage_class & (STCref | STCout | STClazy); |
608 | 637 |
609 if (vd->nestedref || refoutlazy) | 638 if (refoutlazy) |
610 { | 639 { |
611 continue; | 640 continue; |
612 } | 641 } |
613 else if (DtoIsPassedByRef(vd->type)) | 642 else if (DtoIsPassedByRef(vd->type)) |
614 { | 643 { |
623 DtoStore(a,v); | 652 DtoStore(a,v); |
624 irloc->value = v; | 653 irloc->value = v; |
625 } | 654 } |
626 } | 655 } |
627 | 656 |
628 LLValue* parentNested = NULL; | |
629 if (FuncDeclaration* fd2 = fd->toParent2()->isFuncDeclaration()) { | |
630 if (!fd->isStatic()) // huh? | |
631 parentNested = fd2->ir.irFunc->nestedVar; | |
632 } | |
633 | |
634 // need result variable? (nested) | 657 // need result variable? (nested) |
635 if (fd->vresult && fd->vresult->nestedref) { | 658 if (fd->vresult && fd->vresult->nestedref) { |
636 Logger::println("nested vresult value: %s", fd->vresult->toChars()); | 659 Logger::println("nested vresult value: %s", fd->vresult->toChars()); |
637 fd->nestedVars.insert(fd->vresult); | 660 fd->nestedVars.insert(fd->vresult); |
638 } | 661 } |
639 | 662 |
640 // construct nested variables struct | 663 // construct nested variables array |
641 if (!fd->nestedVars.empty() || parentNested) { | 664 if (!fd->nestedVars.empty()) |
642 std::vector<const LLType*> nestTypes; | 665 { |
643 int j = 0; | 666 Logger::println("has nested frame"); |
644 if (parentNested) { | 667 // start with add all enclosing parent frames |
645 nestTypes.push_back(parentNested->getType()); | 668 int nparelems = 0; |
646 j++; | 669 Dsymbol* par = fd->toParent2(); |
647 } | 670 while (par) |
648 for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i) { | 671 { |
672 if (FuncDeclaration* parfd = par->isFuncDeclaration()) | |
673 { | |
674 nparelems += parfd->nestedVars.size(); | |
675 } | |
676 else if (ClassDeclaration* parcd = par->isClassDeclaration()) | |
677 { | |
678 // nothing needed | |
679 } | |
680 else | |
681 { | |
682 break; | |
683 } | |
684 par = par->toParent2(); | |
685 } | |
686 int nelems = fd->nestedVars.size() + nparelems; | |
687 | |
688 // make array type for nested vars | |
689 const LLType* nestedVarsTy = LLArrayType::get(getVoidPtrType(), nelems); | |
690 | |
691 // alloca it | |
692 LLValue* nestedVars = DtoAlloca(nestedVarsTy, ".nested_vars"); | |
693 | |
694 // copy parent frame into beginning | |
695 if (nparelems) | |
696 { | |
697 LLValue* src = irfunction->nestArg; | |
698 if (!src) | |
699 { | |
700 assert(irfunction->thisArg); | |
701 assert(fd->isMember2()); | |
702 LLValue* thisval = DtoLoad(irfunction->thisArg); | |
703 ClassDeclaration* cd = fd->isMember2()->isClassDeclaration(); | |
704 assert(cd); | |
705 assert(cd->vthis); | |
706 src = DtoLoad(DtoGEPi(thisval, 0,2+cd->vthis->ir.irField->index, ".vthis")); | |
707 } | |
708 DtoMemCpy(nestedVars, src, DtoConstSize_t(nparelems*PTRSIZE)); | |
709 } | |
710 | |
711 // store in IrFunction | |
712 irfunction->nestedVar = nestedVars; | |
713 | |
714 // go through all nested vars and assign indices | |
715 int idx = nparelems; | |
716 for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i) | |
717 { | |
649 VarDeclaration* vd = *i; | 718 VarDeclaration* vd = *i; |
650 Logger::println("referenced nested variable %s", vd->toChars()); | |
651 if (!vd->ir.irLocal) | 719 if (!vd->ir.irLocal) |
652 vd->ir.irLocal = new IrLocal(vd); | 720 vd->ir.irLocal = new IrLocal(vd); |
653 vd->ir.irLocal->nestedIndex = j++; | 721 |
654 if (vd->isParameter()) { | 722 if (vd->isParameter()) |
655 if (!vd->ir.irLocal->value) { | 723 { |
656 assert(vd == fd->vthis); | 724 Logger::println("nested param: %s", vd->toChars()); |
657 vd->ir.irLocal->value = fd->ir.irFunc->thisVar; | 725 LLValue* gep = DtoGEPi(nestedVars, 0, idx); |
658 } | 726 LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType()); |
659 assert(vd->ir.irLocal->value); | 727 DtoStore(val, gep); |
660 nestTypes.push_back(vd->ir.irLocal->value->getType()); | 728 } |
661 } | 729 else |
662 else { | 730 { |
663 nestTypes.push_back(DtoType(vd->type)); | 731 Logger::println("nested var: %s", vd->toChars()); |
664 } | 732 } |
665 } | 733 |
666 const llvm::StructType* nestSType = llvm::StructType::get(nestTypes); | 734 vd->ir.irLocal->nestedIndex = idx++; |
667 Logger::cout() << "nested var struct has type:" << *nestSType << '\n'; | 735 } |
668 fd->ir.irFunc->nestedVar = DtoAlloca(nestSType,"nestedvars"); | 736 |
669 if (parentNested) { | 737 // fixup nested result variable |
670 assert(fd->ir.irFunc->thisVar); | 738 if (fd->vresult && fd->vresult->nestedref) { |
671 LLValue* ptr = gIR->ir->CreateBitCast(fd->ir.irFunc->thisVar, parentNested->getType(), "tmp"); | 739 Logger::println("nested vresult value: %s", fd->vresult->toChars()); |
672 gIR->ir->CreateStore(ptr, DtoGEPi(fd->ir.irFunc->nestedVar, 0,0, "tmp")); | 740 LLValue* gep = DtoGEPi(nestedVars, 0, fd->vresult->ir.irLocal->nestedIndex); |
673 } | 741 LLValue* val = DtoBitCast(fd->vresult->ir.irLocal->value, getVoidPtrType()); |
674 for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i) { | 742 DtoStore(val, gep); |
675 VarDeclaration* vd = *i; | |
676 if (vd->isParameter()) { | |
677 assert(vd->ir.irLocal); | |
678 gIR->ir->CreateStore(vd->ir.irLocal->value, DtoGEPi(fd->ir.irFunc->nestedVar, 0, vd->ir.irLocal->nestedIndex, "tmp")); | |
679 vd->ir.irLocal->value = fd->ir.irFunc->nestedVar; | |
680 } | |
681 } | 743 } |
682 } | 744 } |
683 | 745 |
684 // copy _argptr to a memory location | 746 // copy _argptr to a memory location |
685 if (f->linkage == LINKd && f->varargs == 1) | 747 if (f->linkage == LINKd && f->varargs == 1) |
686 { | 748 { |
687 LLValue* argptrmem = DtoAlloca(fd->ir.irFunc->_argptr->getType(), "_argptrmem"); | 749 LLValue* argptrmem = DtoAlloca(fd->ir.irFunc->_argptr->getType(), "_argptr_mem"); |
688 new llvm::StoreInst(fd->ir.irFunc->_argptr, argptrmem, gIR->scopebb()); | 750 new llvm::StoreInst(fd->ir.irFunc->_argptr, argptrmem, gIR->scopebb()); |
689 fd->ir.irFunc->_argptr = argptrmem; | 751 fd->ir.irFunc->_argptr = argptrmem; |
690 } | 752 } |
691 | 753 |
692 // output function body | 754 // output function body |
782 | 844 |
783 // ref/out arg | 845 // ref/out arg |
784 if (fnarg && ((fnarg->storageClass & STCref) || (fnarg->storageClass & STCout))) | 846 if (fnarg && ((fnarg->storageClass & STCref) || (fnarg->storageClass & STCout))) |
785 { | 847 { |
786 if (arg->isVar() || arg->isLRValue()) | 848 if (arg->isVar() || arg->isLRValue()) |
787 arg = new DImValue(argexp->type, arg->getLVal(), false); | 849 arg = new DImValue(argexp->type, arg->getLVal()); |
788 else | 850 else |
789 arg = new DImValue(argexp->type, arg->getRVal(), false); | 851 arg = new DImValue(argexp->type, arg->getRVal()); |
790 } | 852 } |
791 // byval arg, but expr has no storage yet | 853 // byval arg, but expr has no storage yet |
792 else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isComplex() || arg->isNull())) | 854 else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isComplex() || arg->isNull())) |
793 { | 855 { |
794 LLValue* alloc = DtoAlloca(DtoType(argexp->type), "tmpparam"); | 856 LLValue* alloc = DtoAlloca(DtoType(argexp->type), ".tmp_arg"); |
795 DVarValue* vv = new DVarValue(argexp->type, alloc, true); | 857 DVarValue* vv = new DVarValue(argexp->type, alloc, true); |
796 DtoAssign(argexp->loc, vv, arg); | 858 DtoAssign(argexp->loc, vv, arg); |
797 arg = vv; | 859 arg = vv; |
798 } | 860 } |
799 | 861 |