Mercurial > projects > ldc
comparison gen/llvmhelpers.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 | d86af825e8d9 |
children | a3d6c9eedcb6 837af2a63564 |
comparison
equal
deleted
inserted
replaced
485:50f6e2337a6b | 486:a34078905d01 |
---|---|
347 /****************************************************************************************/ | 347 /****************************************************************************************/ |
348 /*//////////////////////////////////////////////////////////////////////////////////////// | 348 /*//////////////////////////////////////////////////////////////////////////////////////// |
349 // NESTED VARIABLE HELPERS | 349 // NESTED VARIABLE HELPERS |
350 ////////////////////////////////////////////////////////////////////////////////////////*/ | 350 ////////////////////////////////////////////////////////////////////////////////////////*/ |
351 | 351 |
352 /* | 352 DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd) |
353 | 353 { |
354 got: | 354 Dsymbol* vdparent = vd->toParent2(); |
355 | 355 assert(vdparent); |
356 context pointer of 'this' function | 356 |
357 | 357 IrFunction* irfunc = gIR->func(); |
358 declaration for target context's function | 358 |
359 | 359 // is the nested variable in this scope? |
360 want: | 360 if (vdparent == irfunc->decl) |
361 | 361 { |
362 context pointer of target function in call chain | 362 LLValue* val = vd->ir.getIrValue(); |
363 | 363 return new DVarValue(astype, vd, val, true); |
364 */ | 364 } |
365 | 365 |
366 static LLValue* dive_into_nested(Dsymbol* from, LLValue* val) | 366 // get it from the nested context |
367 { | 367 LLValue* ctx = 0; |
368 from = from->toParent2(); | 368 if (irfunc->decl->isMember2()) |
369 | 369 { |
370 // parent is a function | 370 ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration(); |
371 if (FuncDeclaration* f = from->isFuncDeclaration()) | 371 LLValue* val = DtoLoad(irfunc->thisArg); |
372 { | 372 ctx = DtoLoad(DtoGEPi(val, 0,2+cd->vthis->ir.irField->index, ".vthis")); |
373 IrFunction* irfunc = f->ir.irFunc; | 373 } |
374 // parent has nested var struct | 374 else |
375 if (irfunc->nestedVar) | 375 ctx = irfunc->nestArg; |
376 { | 376 assert(ctx); |
377 return DtoBitCast(val, irfunc->nestedVar->getType()); | 377 |
378 } | 378 assert(vd->ir.irLocal); |
379 // parent has this argument | 379 LLValue* val = DtoBitCast(ctx, getPtrToType(getVoidPtrType())); |
380 else if (irfunc->thisVar) | 380 val = DtoGEPi1(val, vd->ir.irLocal->nestedIndex); |
381 { | 381 val = DtoLoad(val); |
382 return DtoBitCast(val, irfunc->thisVar->getType()->getContainedType(0)); | 382 assert(vd->ir.irLocal->value); |
383 } | 383 val = DtoBitCast(val, vd->ir.irLocal->value->getType(), vd->toChars()); |
384 // none of the above, means no context is required, dummy. | 384 return new DVarValue(astype, vd, val, true); |
385 else | 385 } |
386 { | 386 |
387 LLValue* DtoNestedContext(Loc loc, Dsymbol* sym) | |
388 { | |
389 Logger::println("DtoNestedContext for %s", sym->toPrettyChars()); | |
390 LOG_SCOPE; | |
391 | |
392 IrFunction* irfunc = gIR->func(); | |
393 | |
394 if (irfunc->nestedVar) | |
395 return irfunc->nestedVar; | |
396 else if (irfunc->nestArg) | |
397 return irfunc->nestArg; | |
398 else if (irfunc->thisArg) | |
399 { | |
400 ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration(); | |
401 assert(cd); | |
402 if (!cd->vthis) | |
387 return getNullPtr(getVoidPtrType()); | 403 return getNullPtr(getVoidPtrType()); |
388 } | 404 LLValue* val = DtoLoad(irfunc->thisArg); |
389 } | 405 return DtoLoad(DtoGEPi(val, 0,2+cd->vthis->ir.irField->index, ".vthis")); |
390 // parent is a class | 406 } |
391 else if (ClassDeclaration* c = from->isClassDeclaration()) | |
392 { | |
393 return DtoBitCast(DtoLoad(val), DtoType(c->type)); | |
394 } | |
395 // parent is not valid | |
396 else | 407 else |
397 { | 408 { |
398 assert(0 && "!(class|function)"); | 409 if (irfunc->decl->isStatic()) |
399 } | 410 { |
400 } | 411 irfunc->decl->error("is static and cannot access nested %s %s", sym->kind(), sym->toChars()); |
401 | 412 fatal(); |
402 LLValue* DtoNestedContext(FuncDeclaration* func) | 413 } |
403 { | 414 return getNullPtr(getVoidPtrType()); |
404 Logger::println("listing context frame list for funcdecl '%s'", func->toPrettyChars()); | 415 } |
405 LOG_SCOPE; | |
406 | |
407 int level = 0; | |
408 | |
409 IrFunction* irfunc = gIR->func(); | |
410 Dsymbol* current = irfunc->decl; | |
411 | |
412 // this context ? | |
413 if (current == func) | |
414 { | |
415 return irfunc->nestedVar; | |
416 } | |
417 | |
418 // otherwise use the context argument | |
419 LLValue* val = dive_into_nested(current, irfunc->thisVar); | |
420 current = current->toParent2(); | |
421 assert(val); | |
422 | |
423 for (;;) | |
424 { | |
425 Logger::cout() << "context: " << *val << '\n'; | |
426 Logger::println("(%d) looking in: %s (%s)", level, current->toPrettyChars(), current->kind()); | |
427 if (FuncDeclaration* f = current->isFuncDeclaration()) | |
428 { | |
429 if (f == func) | |
430 { | |
431 Logger::println("-> found <-"); | |
432 Logger::cout() << "-> val: " << *val << '\n'; | |
433 return val; | |
434 } | |
435 else | |
436 { | |
437 val = DtoLoad(DtoGEPi(val,0,0)); | |
438 } | |
439 } | |
440 else if (ClassDeclaration* c = current->isClassDeclaration()) | |
441 { | |
442 val = DtoLoad(DtoGEPi(val, 0, 2+c->vthis->ir.irField->index)); | |
443 val = dive_into_nested(current, val); | |
444 } | |
445 else | |
446 { | |
447 Logger::cout() << "val: " << *val << '\n'; | |
448 assert(0 && "!(class|function)"); | |
449 } | |
450 current = current->toParent2(); | |
451 ++level; | |
452 } | |
453 | |
454 assert(0); | |
455 return val; | |
456 } | |
457 | |
458 DValue* DtoNestedVariable(Type* astype, VarDeclaration* vd) | |
459 { | |
460 IrFunction* irfunc = gIR->func(); | |
461 | |
462 // var parent (the scope we're looking for) | |
463 Dsymbol* varParent = vd->toParent2(); | |
464 | |
465 // on level 0 | |
466 if (varParent == irfunc->decl) | |
467 { | |
468 LLValue* nest = irfunc->nestedVar; | |
469 LLValue* v = DtoGEPi(nest, 0, vd->ir.irLocal->nestedIndex, "tmp"); | |
470 // references must be loaded to get the variable address | |
471 if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))) | |
472 v = DtoLoad(v); | |
473 return new DVarValue(astype, vd, v, true); | |
474 } | |
475 | |
476 // on level n != 0 | |
477 FuncDeclaration* varFunc = varParent->isFuncDeclaration(); | |
478 assert(varFunc); | |
479 | |
480 // get context of variable | |
481 LLValue* ctx = DtoNestedContext(varFunc); | |
482 | |
483 // if no local var, it's the context itself (class this) | |
484 if (!vd->ir.irLocal) | |
485 return new DImValue(astype, ctx); | |
486 | |
487 // extract variable | |
488 IrLocal* local = vd->ir.irLocal; | |
489 assert(local); | |
490 assert(local->nestedIndex >= 0); | |
491 LLValue* val = DtoGEPi(ctx, 0, local->nestedIndex); | |
492 | |
493 // references must be loaded to get the variable address | |
494 if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))) | |
495 val = DtoLoad(val); | |
496 | |
497 Logger::cout() << "value: " << *val << '\n'; | |
498 | |
499 return new DVarValue(astype, vd, val, true); | |
500 } | 416 } |
501 | 417 |
502 /****************************************************************************************/ | 418 /****************************************************************************************/ |
503 /*//////////////////////////////////////////////////////////////////////////////////////// | 419 /*//////////////////////////////////////////////////////////////////////////////////////// |
504 // ASSIGNMENT HELPER (store this in that) | 420 // ASSIGNMENT HELPER (store this in that) |
507 void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs) | 423 void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs) |
508 { | 424 { |
509 Logger::cout() << "DtoAssign(...);\n"; | 425 Logger::cout() << "DtoAssign(...);\n"; |
510 LOG_SCOPE; | 426 LOG_SCOPE; |
511 | 427 |
512 Type* t = DtoDType(lhs->getType()); | 428 Type* t = lhs->getType()->toBasetype(); |
513 Type* t2 = DtoDType(rhs->getType()); | 429 Type* t2 = rhs->getType()->toBasetype(); |
514 | 430 |
515 if (t->ty == Tstruct) { | 431 if (t->ty == Tstruct) { |
516 if (!t->equals(t2)) { | 432 if (!t->equals(t2)) { |
517 // TODO: fix this, use 'rhs' for something | 433 // TODO: fix this, use 'rhs' for something |
518 DtoAggrZeroInit(lhs->getLVal()); | 434 DtoAggrZeroInit(lhs->getLVal()); |
519 } | 435 } |
520 else if (!rhs->inPlace()) { | 436 else { |
521 DtoAggrCopy(lhs->getLVal(), rhs->getRVal()); | 437 DtoAggrCopy(lhs->getLVal(), rhs->getRVal()); |
522 } | 438 } |
523 } | 439 } |
524 else if (t->ty == Tarray) { | 440 else if (t->ty == Tarray) { |
525 // lhs is slice | 441 // lhs is slice |
557 } | 473 } |
558 } | 474 } |
559 else if (t->ty == Tdelegate) { | 475 else if (t->ty == Tdelegate) { |
560 if (rhs->isNull()) | 476 if (rhs->isNull()) |
561 DtoAggrZeroInit(lhs->getLVal()); | 477 DtoAggrZeroInit(lhs->getLVal()); |
562 else if (!rhs->inPlace()) { | 478 else { |
563 LLValue* l = lhs->getLVal(); | 479 LLValue* l = lhs->getLVal(); |
564 LLValue* r = rhs->getRVal(); | 480 LLValue* r = rhs->getRVal(); |
565 Logger::cout() << "assign\nlhs: " << *l << "rhs: " << *r << '\n'; | 481 Logger::cout() << "assign\nlhs: " << *l << "rhs: " << *r << '\n'; |
566 DtoAggrCopy(l, r); | 482 DtoAggrCopy(l, r); |
567 } | 483 } |
663 | 579 |
664 DValue* DtoCastInt(Loc& loc, DValue* val, Type* _to) | 580 DValue* DtoCastInt(Loc& loc, DValue* val, Type* _to) |
665 { | 581 { |
666 const LLType* tolltype = DtoType(_to); | 582 const LLType* tolltype = DtoType(_to); |
667 | 583 |
668 Type* to = DtoDType(_to); | 584 Type* to = _to->toBasetype(); |
669 Type* from = DtoDType(val->getType()); | 585 Type* from = val->getType()->toBasetype(); |
670 assert(from->isintegral()); | 586 assert(from->isintegral()); |
671 | 587 |
672 size_t fromsz = from->size(); | 588 size_t fromsz = from->size(); |
673 size_t tosz = to->size(); | 589 size_t tosz = to->size(); |
674 | 590 |
718 | 634 |
719 DValue* DtoCastPtr(Loc& loc, DValue* val, Type* to) | 635 DValue* DtoCastPtr(Loc& loc, DValue* val, Type* to) |
720 { | 636 { |
721 const LLType* tolltype = DtoType(to); | 637 const LLType* tolltype = DtoType(to); |
722 | 638 |
723 Type* totype = DtoDType(to); | 639 Type* totype = to->toBasetype(); |
724 Type* fromtype = DtoDType(val->getType()); | 640 Type* fromtype = val->getType()->toBasetype(); |
725 assert(fromtype->ty == Tpointer || fromtype->ty == Tfunction); | 641 assert(fromtype->ty == Tpointer || fromtype->ty == Tfunction); |
726 | 642 |
727 LLValue* rval; | 643 LLValue* rval; |
728 | 644 |
729 if (totype->ty == Tpointer || totype->ty == Tclass) { | 645 if (totype->ty == Tpointer || totype->ty == Tclass) { |
747 if (val->getType() == to) | 663 if (val->getType() == to) |
748 return val; | 664 return val; |
749 | 665 |
750 const LLType* tolltype = DtoType(to); | 666 const LLType* tolltype = DtoType(to); |
751 | 667 |
752 Type* totype = DtoDType(to); | 668 Type* totype = to->toBasetype(); |
753 Type* fromtype = DtoDType(val->getType()); | 669 Type* fromtype = val->getType()->toBasetype(); |
754 assert(fromtype->isfloating()); | 670 assert(fromtype->isfloating()); |
755 | 671 |
756 size_t fromsz = fromtype->size(); | 672 size_t fromsz = fromtype->size(); |
757 size_t tosz = totype->size(); | 673 size_t tosz = totype->size(); |
758 | 674 |
812 return new DImValue(to, res); | 728 return new DImValue(to, res); |
813 } | 729 } |
814 | 730 |
815 DValue* DtoCast(Loc& loc, DValue* val, Type* to) | 731 DValue* DtoCast(Loc& loc, DValue* val, Type* to) |
816 { | 732 { |
817 Type* fromtype = DtoDType(val->getType()); | 733 Type* fromtype = val->getType()->toBasetype(); |
818 Logger::println("Casting from '%s' to '%s'", fromtype->toChars(), to->toChars()); | 734 Logger::println("Casting from '%s' to '%s'", fromtype->toChars(), to->toChars()); |
819 if (fromtype->isintegral()) { | 735 if (fromtype->isintegral()) { |
820 return DtoCastInt(loc, val, to); | 736 return DtoCastInt(loc, val, to); |
821 } | 737 } |
822 else if (fromtype->iscomplex()) { | 738 else if (fromtype->iscomplex()) { |
877 llvm::BasicBlock* endinitbb = llvm::BasicBlock::Create("ifnotinitend",gIR->topfunc(),oldend); | 793 llvm::BasicBlock* endinitbb = llvm::BasicBlock::Create("ifnotinitend",gIR->topfunc(),oldend); |
878 LLValue* cond = gIR->ir->CreateICmpEQ(gIR->ir->CreateLoad(gflag,"tmp"),DtoConstBool(false)); | 794 LLValue* cond = gIR->ir->CreateICmpEQ(gIR->ir->CreateLoad(gflag,"tmp"),DtoConstBool(false)); |
879 gIR->ir->CreateCondBr(cond, initbb, endinitbb); | 795 gIR->ir->CreateCondBr(cond, initbb, endinitbb); |
880 gIR->scope() = IRScope(initbb,endinitbb); | 796 gIR->scope() = IRScope(initbb,endinitbb); |
881 DValue* ie = DtoInitializer(gvar, init); | 797 DValue* ie = DtoInitializer(gvar, init); |
882 if (!ie->inPlace()) { | 798 |
883 DValue* dst = new DVarValue(t, gvar, true); | 799 DVarValue dst(t, gvar, true); |
884 DtoAssign(init->loc, dst, ie); | 800 DtoAssign(init->loc, &dst, ie); |
885 } | 801 |
886 gIR->ir->CreateStore(DtoConstBool(true), gflag); | 802 gIR->ir->CreateStore(DtoConstBool(true), gflag); |
887 gIR->ir->CreateBr(endinitbb); | 803 gIR->ir->CreateBr(endinitbb); |
888 gIR->scope() = IRScope(endinitbb,oldend); | 804 gIR->scope() = IRScope(endinitbb,oldend); |
889 } | 805 } |
890 | 806 |
999 else { | 915 else { |
1000 _init = DtoConstInitializer(vd->type, vd->init); | 916 _init = DtoConstInitializer(vd->type, vd->init); |
1001 } | 917 } |
1002 | 918 |
1003 const LLType* _type = DtoType(vd->type); | 919 const LLType* _type = DtoType(vd->type); |
1004 Type* t = DtoDType(vd->type); | 920 Type* t = vd->type->toBasetype(); |
1005 | 921 |
1006 //Logger::cout() << "initializer: " << *_init << '\n'; | 922 //Logger::cout() << "initializer: " << *_init << '\n'; |
1007 if (_type != _init->getType()) { | 923 if (_type != _init->getType()) { |
1008 Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n"; | 924 Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n"; |
1009 // zero initalizer | 925 // zero initalizer |
1216 | 1132 |
1217 // referenced by nested delegate? | 1133 // referenced by nested delegate? |
1218 if (vd->nestedref) { | 1134 if (vd->nestedref) { |
1219 Logger::println("has nestedref set"); | 1135 Logger::println("has nestedref set"); |
1220 assert(vd->ir.irLocal); | 1136 assert(vd->ir.irLocal); |
1221 vd->ir.irLocal->value = gIR->func()->decl->ir.irFunc->nestedVar; | 1137 |
1222 assert(vd->ir.irLocal->value); | 1138 // alloca as usual is no value already |
1139 if (!vd->ir.irLocal->value) | |
1140 { | |
1141 vd->ir.irLocal->value = DtoAlloca(DtoType(vd->type), vd->toChars()); | |
1142 } | |
1143 | |
1144 // store the address into the nested vars array | |
1145 | |
1223 assert(vd->ir.irLocal->nestedIndex >= 0); | 1146 assert(vd->ir.irLocal->nestedIndex >= 0); |
1147 LLValue* gep = DtoGEPi(gIR->func()->decl->ir.irFunc->nestedVar, 0, vd->ir.irLocal->nestedIndex); | |
1148 | |
1149 assert(isaPointer(vd->ir.irLocal->value)); | |
1150 LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType()); | |
1151 | |
1152 DtoStore(val, gep); | |
1153 | |
1224 } | 1154 } |
1225 // normal stack variable, allocate storage on the stack if it has not already been done | 1155 // normal stack variable, allocate storage on the stack if it has not already been done |
1226 else if(!vd->ir.irLocal) { | 1156 else if(!vd->ir.irLocal) { |
1227 const LLType* lltype = DtoType(vd->type); | 1157 const LLType* lltype = DtoType(vd->type); |
1228 | 1158 |
1238 | 1168 |
1239 if (global.params.symdebug) | 1169 if (global.params.symdebug) |
1240 { | 1170 { |
1241 DtoDwarfLocalVariable(allocainst, vd); | 1171 DtoDwarfLocalVariable(allocainst, vd); |
1242 } | 1172 } |
1173 } | |
1174 else | |
1175 { | |
1176 assert(vd->ir.irLocal->value); | |
1243 } | 1177 } |
1244 | 1178 |
1245 Logger::cout() << "llvm value for decl: " << *vd->ir.irLocal->value << '\n'; | 1179 Logger::cout() << "llvm value for decl: " << *vd->ir.irLocal->value << '\n'; |
1246 DValue* ie = DtoInitializer(vd->ir.irLocal->value, vd->init); | 1180 DValue* ie = DtoInitializer(vd->ir.irLocal->value, vd->init); |
1247 } | 1181 } |