|
22 | 22 | #include "ir/irtypeaggr.h"
|
23 | 23 | #include "llvm/Analysis/ValueTracking.h"
|
24 | 24 |
|
25 |
| -static unsigned getVthisIdx(AggregateDeclaration *ad) { |
| 25 | +namespace { |
| 26 | +unsigned getVthisIdx(AggregateDeclaration *ad) { |
26 | 27 | return getFieldGEPIndex(ad, ad->vthis);
|
27 | 28 | }
|
28 | 29 |
|
| 30 | +bool isNRVOVar(VarDeclaration *vd) { |
| 31 | + if (auto fd = vd->toParent2()->isFuncDeclaration()) |
| 32 | + return fd->nrvo_can && vd == fd->nrvo_var && !fd->needsClosure(); |
| 33 | + return false; |
| 34 | +} |
| 35 | + |
| 36 | +bool captureByRef(VarDeclaration *vd) { |
| 37 | + return vd->isReference() || isNRVOVar(vd); |
| 38 | +} |
| 39 | +} // anonymous namespace |
| 40 | + |
29 | 41 | static void DtoCreateNestedContextType(FuncDeclaration *fd);
|
30 | 42 |
|
31 | 43 | DValue *DtoNestedVariable(const Loc &loc, Type *astype, VarDeclaration *vd,
|
@@ -153,15 +165,14 @@ DValue *DtoNestedVariable(const Loc &loc, Type *astype, VarDeclaration *vd,
|
153 | 165 | Logger::cout() << "Addr: " << *val << '\n';
|
154 | 166 | Logger::cout() << "of type: " << *val->getType() << '\n';
|
155 | 167 | }
|
156 |
| - const bool isRefOrOut = vd->isRef() || vd->isOut(); |
157 | 168 | if (isSpecialRefVar(vd)) {
|
158 | 169 | // Handled appropriately by makeVarDValue() and EmitLocalVariable(), pass
|
159 | 170 | // storage of pointer (reference lvalue).
|
160 |
| - } else if (byref || isRefOrOut) { |
| 171 | + } else if (byref || captureByRef(vd)) { |
161 | 172 | val = DtoAlignedLoad(val);
|
162 | 173 | // ref/out variables get a reference-debuginfo-type in EmitLocalVariable()
|
163 | 174 | // => don't dereference, use reference lvalue as address
|
164 |
| - if (!isRefOrOut) |
| 175 | + if (!vd->isReference()) |
165 | 176 | gIR->DBuilder.OpDeref(dwarfAddrOps);
|
166 | 177 | IF_LOG {
|
167 | 178 | Logger::cout() << "Was byref, now: " << *irLocal->value << '\n';
|
@@ -396,7 +407,7 @@ static void DtoCreateNestedContextType(FuncDeclaration *fd) {
|
396 | 407 | irLocal.nestedDepth = depth;
|
397 | 408 |
|
398 | 409 | LLType *t = nullptr;
|
399 |
| - if (vd->isRef() || vd->isOut()) { |
| 410 | + if (captureByRef(vd)) { |
400 | 411 | t = DtoType(vd->type->pointerTo());
|
401 | 412 | } else if (isParam && (vd->storage_class & STClazy)) {
|
402 | 413 | // the type is a delegate (LL struct)
|
@@ -494,31 +505,37 @@ void DtoCreateNestedContext(FuncGenState &funcGen) {
|
494 | 505 | assert(parm->value);
|
495 | 506 | assert(parm->value->getType()->isPointerTy());
|
496 | 507 |
|
497 |
| - if (vd->isRef() || vd->isOut()) { |
| 508 | + if (vd->isReference()) { |
498 | 509 | Logger::println(
|
499 | 510 | "Captured by reference, copying pointer to nested frame");
|
500 | 511 | DtoAlignedStore(parm->value, gep);
|
501 | 512 | // pass GEP as reference lvalue to EmitLocalVariable()
|
502 | 513 | } else {
|
503 |
| - Logger::println("Copying to nested frame"); |
| 514 | + Logger::println("Moving to nested frame"); |
504 | 515 | // The parameter value is an alloca'd stack slot.
|
505 | 516 | // Copy to the nesting frame and leave the alloca for
|
506 | 517 | // the optimizers to clean up.
|
507 | 518 | DtoMemCpy(gep, parm->value);
|
508 | 519 | gep->takeName(parm->value);
|
509 |
| - parm->value = gep; |
| 520 | + parm->value = gep; // update variable lvalue |
510 | 521 | }
|
| 522 | + } else if (isNRVOVar(vd)) { |
| 523 | + IF_LOG Logger::println( |
| 524 | + "nested NRVO var: %s, copying pointer to nested frame", |
| 525 | + vd->toChars()); |
| 526 | + assert(irFunc.sretArg); |
| 527 | + DtoAlignedStore(irFunc.sretArg, gep); |
| 528 | + assert(!irLocal->value); |
| 529 | + irLocal->value = irFunc.sretArg; |
| 530 | + gep = irFunc.sretArg; // lvalue for debuginfo |
511 | 531 | } else {
|
512 |
| - IF_LOG Logger::println("nested var: %s", vd->toChars()); |
| 532 | + IF_LOG Logger::println("nested var: %s, allocating in nested frame", |
| 533 | + vd->toChars()); |
513 | 534 | assert(!irLocal->value);
|
514 | 535 | irLocal->value = gep;
|
515 | 536 | }
|
516 | 537 |
|
517 |
| - if (global.params.symdebug) { |
518 |
| - LLSmallVector<int64_t, 1> dwarfAddrOps; |
519 |
| - gIR->DBuilder.EmitLocalVariable(gep, vd, nullptr, false, false, false, |
520 |
| - dwarfAddrOps); |
521 |
| - } |
| 538 | + gIR->DBuilder.EmitLocalVariable(gep, vd); |
522 | 539 | }
|
523 | 540 | }
|
524 | 541 | }
|
0 commit comments