comparison gen/llvmhelpers.cpp @ 468:45a67b6f1310

Removed the 'needsstorage' thing from Dsymbol. Arguments are not always given storage when applicable. This is not longer treat specially in this regard. Code for accessing nested variables and contexts rewritten. Probably more. Fairly well tested.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Mon, 04 Aug 2008 02:59:34 +0200
parents 60332cd85308
children 672eb4893b55
comparison
equal deleted inserted replaced
467:261b05cf4d1c 468:45a67b6f1310
328 /****************************************************************************************/ 328 /****************************************************************************************/
329 /*//////////////////////////////////////////////////////////////////////////////////////// 329 /*////////////////////////////////////////////////////////////////////////////////////////
330 // NESTED VARIABLE HELPERS 330 // NESTED VARIABLE HELPERS
331 ////////////////////////////////////////////////////////////////////////////////////////*/ 331 ////////////////////////////////////////////////////////////////////////////////////////*/
332 332
333 static const LLType* get_next_frame_ptr_type(Dsymbol* sc) 333 /*
334 { 334
335 assert(sc->isFuncDeclaration() || sc->isClassDeclaration()); 335 got:
336 Dsymbol* p = sc->toParent2(); 336
337 if (!p->isFuncDeclaration() && !p->isClassDeclaration()) 337 context pointer of 'this' function
338 Logger::println("unexpected parent symbol found while resolving frame pointer - '%s' kind: '%s'", p->toChars(), p->kind()); 338
339 assert(p->isFuncDeclaration() || p->isClassDeclaration()); 339 declaration for target context's function
340 if (FuncDeclaration* fd = p->isFuncDeclaration()) 340
341 { 341 want:
342 LLValue* v = fd->ir.irFunc->nestedVar; 342
343 assert(v); 343 context pointer of target function in call chain
344 return v->getType(); 344
345 } 345 */
346 else if (ClassDeclaration* cd = p->isClassDeclaration()) 346
347 { 347 static LLValue* dive_into_nested(Dsymbol* from, LLValue* val)
348 return DtoType(cd->type); 348 {
349 } 349 from = from->toParent2();
350
351 // parent is a function
352 if (FuncDeclaration* f = from->isFuncDeclaration())
353 {
354 IrFunction* irfunc = f->ir.irFunc;
355 // parent has nested var struct
356 if (irfunc->nestedVar)
357 {
358 return DtoBitCast(val, irfunc->nestedVar->getType());
359 }
360 // parent has this argument
361 else if (irfunc->thisVar)
362 {
363 return DtoBitCast(val, irfunc->thisVar->getType()->getContainedType(0));
364 }
365 // none of the above, means no context is required, dummy.
366 else
367 {
368 return getNullPtr(getVoidPtrType());
369 }
370 }
371 // parent is a class
372 else if (ClassDeclaration* c = from->isClassDeclaration())
373 {
374 return DtoBitCast(DtoLoad(val), DtoType(c->type));
375 }
376 // parent is not valid
350 else 377 else
351 { 378 {
352 Logger::println("symbol: '%s' kind: '%s'", sc->toChars(), sc->kind()); 379 assert(0 && "!(class|function)");
353 assert(0); 380 }
354 } 381 }
355 } 382
356 383 LLValue* DtoNestedContext(FuncDeclaration* func)
357 ////////////////////////////////////////////////////////////////////////////////////////// 384 {
358 385 Logger::println("listing context frame list for funcdecl '%s'", func->toPrettyChars());
359 static LLValue* get_frame_ptr_impl(FuncDeclaration* func, Dsymbol* sc, LLValue* v)
360 {
361 LOG_SCOPE; 386 LOG_SCOPE;
362 if (sc == func) 387
363 { 388 int level = 0;
364 return v; 389
365 } 390 IrFunction* irfunc = gIR->func();
366 else if (FuncDeclaration* fd = sc->isFuncDeclaration()) 391 Dsymbol* current = irfunc->decl;
367 { 392
368 Logger::println("scope is function: %s", fd->toChars()); 393 // this context ?
369 394 if (current == func)
370 if (fd->toParent2() == func) 395 {
371 { 396 return irfunc->nestedVar;
372 if (!func->ir.irFunc->nestedVar) 397 }
373 return NULL; 398
374 return DtoBitCast(v, func->ir.irFunc->nestedVar->getType()); 399 // otherwise use the context argument
375 } 400 LLValue* val = dive_into_nested(current, irfunc->thisVar);
376 401 current = current->toParent2();
377 v = DtoBitCast(v, get_next_frame_ptr_type(fd)); 402 assert(val);
378 Logger::cout() << "v = " << *v << '\n'; 403
379 404 for (;;)
380 if (fd->toParent2()->isFuncDeclaration()) 405 {
381 { 406 Logger::cout() << "context: " << *val << '\n';
382 v = DtoGEPi(v, 0,0, "tmp"); 407 Logger::println("(%d) looking in: %s (%s)", level, current->toPrettyChars(), current->kind());
408 if (FuncDeclaration* f = current->isFuncDeclaration())
409 {
410 if (f == func)
411 {
412 Logger::println("-> found <-");
413 Logger::cout() << "-> val: " << *val << '\n';
414 return val;
415 }
416 else
417 {
418 val = DtoLoad(DtoGEPi(val,0,0));
419 }
420 }
421 else if (ClassDeclaration* c = current->isClassDeclaration())
422 {
423 val = DtoLoad(DtoGEPi(val, 0, 2+c->vthis->ir.irField->index));
424 val = dive_into_nested(current, val);
425 }
426 else
427 {
428 Logger::cout() << "val: " << *val << '\n';
429 assert(0 && "!(class|function)");
430 }
431 current = current->toParent2();
432 ++level;
433 }
434
435 assert(0);
436 return val;
437 }
438
439 DValue* DtoNestedVariable(Type* astype, VarDeclaration* vd)
440 {
441 IrFunction* irfunc = gIR->func();
442
443 // var parent (the scope we're looking for)
444 Dsymbol* varParent = vd->toParent2();
445
446 // on level 0
447 if (varParent == irfunc->decl)
448 {
449 LLValue* nest = irfunc->nestedVar;
450 LLValue* v = DtoGEPi(nest, 0, vd->ir.irLocal->nestedIndex, "tmp");
451 // references must be loaded to get the variable address
452 if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type)))
383 v = DtoLoad(v); 453 v = DtoLoad(v);
384 } 454 return new DVarValue(astype, vd, v, true);
385 else if (ClassDeclaration* cd = fd->toParent2()->isClassDeclaration()) 455 }
386 { 456
387 v = DtoGEPi(v,0,2+cd->vthis->ir.irField->index,"tmp"); 457 // on level n != 0
388 v = DtoLoad(v); 458 FuncDeclaration* varFunc = varParent->isFuncDeclaration();
389 } 459 assert(varFunc);
390 else 460
391 { 461 // get context of variable
392 assert(0); 462 LLValue* ctx = DtoNestedContext(varFunc);
393 } 463
394 return get_frame_ptr_impl(func, fd->toParent2(), v); 464 // if no local var, it's the context itself (class this)
395 } 465 if (!vd->ir.irLocal)
396 else if (ClassDeclaration* cd = sc->isClassDeclaration()) 466 return new DImValue(astype, ctx);
397 { 467
398 Logger::println("scope is class: %s", cd->toChars()); 468 // extract variable
399 return get_frame_ptr_impl(func, cd->toParent2(), v); 469 IrLocal* local = vd->ir.irLocal;
400 } 470 assert(local);
401 else 471 assert(local->nestedIndex >= 0);
402 { 472 LLValue* val = DtoGEPi(ctx, 0, local->nestedIndex);
403 Logger::println("symbol: '%s'", sc->toPrettyChars()); 473
404 assert(0); 474 // references must be loaded to get the variable address
405 }
406 }
407
408 //////////////////////////////////////////////////////////////////////////////////////////
409
410 static LLValue* get_frame_ptr(FuncDeclaration* func)
411 {
412 Logger::println("Resolving context pointer for nested function: '%s'", func->toPrettyChars());
413 LOG_SCOPE;
414 IrFunction* irfunc = gIR->func();
415
416 // in the right scope already
417 if (func == irfunc->decl)
418 return irfunc->decl->ir.irFunc->nestedVar;
419
420 // use the 'this' pointer
421 LLValue* ptr = irfunc->decl->ir.irFunc->thisVar;
422 assert(ptr);
423
424 // return the fully resolved frame pointer
425 ptr = get_frame_ptr_impl(func, irfunc->decl, ptr);
426 if (ptr) Logger::cout() << "Found context!" << *ptr;
427 else Logger::cout() << "NULL context!\n";
428
429 return ptr;
430 }
431
432 //////////////////////////////////////////////////////////////////////////////////////////
433
434 LLValue* DtoNestedContext(FuncDeclaration* func)
435 {
436 // resolve frame ptr
437 LLValue* ptr = get_frame_ptr(func);
438 Logger::cout() << "Nested context ptr = ";
439 if (ptr) Logger::cout() << *ptr;
440 else Logger::cout() << "NULL";
441 Logger::cout() << '\n';
442 return ptr;
443 }
444
445 //////////////////////////////////////////////////////////////////////////////////////////
446
447 static void print_frame_worker(VarDeclaration* vd, Dsymbol* par)
448 {
449 if (vd->toParent2() == par)
450 {
451 Logger::println("found: '%s' kind: '%s'", par->toChars(), par->kind());
452 return;
453 }
454
455 Logger::println("diving into: '%s' kind: '%s'", par->toChars(), par->kind());
456 LOG_SCOPE;
457 print_frame_worker(vd, par->toParent2());
458 }
459
460 //////////////////////////////////////////////////////////////////////////////////////////
461
462 static void print_nested_frame_list(VarDeclaration* vd, Dsymbol* par)
463 {
464 Logger::println("Frame pointer list for nested var: '%s'", vd->toPrettyChars());
465 LOG_SCOPE;
466 if (vd->toParent2() != par)
467 print_frame_worker(vd, par);
468 else
469 Logger::println("Found at level 0");
470 Logger::println("Done");
471 }
472
473 //////////////////////////////////////////////////////////////////////////////////////////
474
475 LLValue* DtoNestedVariable(VarDeclaration* vd)
476 {
477 // log the frame list
478 IrFunction* irfunc = gIR->func();
479 if (Logger::enabled())
480 print_nested_frame_list(vd, irfunc->decl);
481
482 // resolve frame ptr
483 FuncDeclaration* func = vd->toParent2()->isFuncDeclaration();
484 assert(func);
485 LLValue* ptr = DtoNestedContext(func);
486 assert(ptr && "nested var, but no context");
487
488 // if there is no nestedVar the context itself is what we're after
489 if (!func->ir.irFunc->nestedVar)
490 {
491 return ptr;
492 }
493
494 // handle a "normal" nested variable
495
496 // we must cast here to be sure. nested classes just have a void*
497 ptr = DtoBitCast(ptr, func->ir.irFunc->nestedVar->getType());
498
499 // index nested var and load (if necessary)
500 LLValue* v = DtoGEPi(ptr, 0, vd->ir.irLocal->nestedIndex, "tmp");
501 // references must be loaded, for normal variables this IS already the variable storage!!!
502 if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))) 475 if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type)))
503 v = DtoLoad(v); 476 val = DtoLoad(val);
504 477
505 // log and return 478 Logger::cout() << "value: " << *val << '\n';
506 Logger::cout() << "Nested var ptr = " << *v << '\n'; 479
507 return v; 480 return new DVarValue(astype, vd, val, true);
508 } 481 }
509 482
510 /****************************************************************************************/ 483 /****************************************************************************************/
511 /*//////////////////////////////////////////////////////////////////////////////////////// 484 /*////////////////////////////////////////////////////////////////////////////////////////
512 // ASSIGNMENT HELPER (store this in that) 485 // ASSIGNMENT HELPER (store this in that)
574 DtoAggrCopy(l, r); 547 DtoAggrCopy(l, r);
575 } 548 }
576 } 549 }
577 else if (t->ty == Tclass) { 550 else if (t->ty == Tclass) {
578 assert(t2->ty == Tclass); 551 assert(t2->ty == Tclass);
579 // assignment to this in constructor special case 552 LLValue* l = lhs->getLVal();
580 if (lhs->isThis()) { 553 LLValue* r = rhs->getRVal();
581 LLValue* tmp = rhs->getRVal(); 554 Logger::cout() << "l : " << *l << '\n';
582 FuncDeclaration* fdecl = gIR->func()->decl; 555 Logger::cout() << "r : " << *r << '\n';
583 // respecify the this param 556 r = DtoBitCast(r, l->getType()->getContainedType(0));
584 if (!llvm::isa<llvm::AllocaInst>(fdecl->ir.irFunc->thisVar)) 557 DtoStore(r, l);
585 fdecl->ir.irFunc->thisVar = new llvm::AllocaInst(tmp->getType(), "newthis", gIR->topallocapoint());
586 DtoStore(tmp, fdecl->ir.irFunc->thisVar);
587 }
588 // regular class ref -> class ref assignment
589 else {
590 DtoStore(rhs->getRVal(), lhs->getLVal());
591 }
592 } 558 }
593 else if (t->iscomplex()) { 559 else if (t->iscomplex()) {
594 assert(!lhs->isComplex()); 560 assert(!lhs->isComplex());
595 561
596 LLValue* dst; 562 LLValue* dst;
1538 } 1504 }
1539 // pointer/class 1505 // pointer/class
1540 else if (ty == Tpointer || ty == Tclass) { 1506 else if (ty == Tpointer || ty == Tclass) {
1541 LLValue* val = dval->getRVal(); 1507 LLValue* val = dval->getRVal();
1542 LLValue* zero = LLConstant::getNullValue(val->getType()); 1508 LLValue* zero = LLConstant::getNullValue(val->getType());
1509 Logger::cout() << "val: " << *val << '\n';
1510 Logger::cout() << "zero: " << *zero << '\n';
1543 return gIR->ir->CreateICmpNE(val, zero, "tmp"); 1511 return gIR->ir->CreateICmpNE(val, zero, "tmp");
1544 } 1512 }
1545 // dynamic array 1513 // dynamic array
1546 else if (ty == Tarray) 1514 else if (ty == Tarray)
1547 { 1515 {