/// rewriteAllocBoxAsAllocStack - Replace uses of the alloc_box with a /// new alloc_stack, but do not delete the alloc_box yet. static bool rewriteAllocBoxAsAllocStack(AllocBoxInst *ABI) { DEBUG(llvm::dbgs() << "*** Promoting alloc_box to stack: " << *ABI); SILValue HeapBox = ABI; Optional<MarkUninitializedInst::Kind> Kind; if (HeapBox->hasOneUse()) { auto *User = HeapBox->getSingleUse()->getUser(); if (auto *MUI = dyn_cast<MarkUninitializedInst>(User)) { HeapBox = MUI; Kind = MUI->getKind(); } } llvm::SmallVector<SILInstruction *, 4> FinalReleases; if (!getFinalReleases(HeapBox, FinalReleases)) return false; // Promote this alloc_box to an alloc_stack. Insert the alloc_stack // at the beginning of the function. SILBuilder Builder(ABI); Builder.setCurrentDebugScope(ABI->getDebugScope()); assert(ABI->getBoxType()->getLayout()->getFields().size() == 1 && "rewriting multi-field box not implemented"); auto *ASI = Builder.createAllocStack( ABI->getLoc(), ABI->getBoxType()->getFieldType(ABI->getModule(), 0), ABI->getVarInfo()); // Transfer a mark_uninitialized if we have one. SILValue StackBox = ASI; if (Kind) { StackBox = Builder.createMarkUninitialized(ASI->getLoc(), ASI, Kind.getValue()); } // Replace all uses of the address of the box's contained value with // the address of the stack location. replaceProjectBoxUsers(HeapBox, StackBox); assert(ABI->getBoxType()->getLayout()->getFields().size() == 1 && "promoting multi-field box not implemented"); auto &Lowering = ABI->getModule() .getTypeLowering(ABI->getBoxType()->getFieldType(ABI->getModule(), 0)); auto Loc = CleanupLocation::get(ABI->getLoc()); for (auto LastRelease : FinalReleases) { SILBuilderWithScope Builder(LastRelease); if (!isa<DeallocBoxInst>(LastRelease)&& !Lowering.isTrivial()) { // For non-trivial types, insert destroys for each final release-like // instruction we found that isn't an explicit dealloc_box. Builder.emitDestroyAddrAndFold(Loc, StackBox); } Builder.createDeallocStack(Loc, ASI); } // Remove any retain and release instructions. Since all uses of project_box // are gone, this only walks through uses of the box itself (the retain count // pointer). llvm::SmallVector<SILInstruction *, 8> Worklist; std::transform(ABI->use_begin(), ABI->use_end(), std::back_inserter(Worklist), [](Operand *Op) -> SILInstruction * { return Op->getUser(); }); while (!Worklist.empty()) { auto *User = Worklist.pop_back_val(); // Look through any mark_uninitialized, copy_values. if (isa<MarkUninitializedInst>(User) || isa<CopyValueInst>(User)) { auto Inst = cast<SingleValueInstruction>(User); transform(Inst->getUses(), std::back_inserter(Worklist), [](Operand *Op) -> SILInstruction * { return Op->getUser(); }); Inst->replaceAllUsesWithUndef(); Inst->eraseFromParent(); continue; } assert(isa<StrongReleaseInst>(User) || isa<StrongRetainInst>(User) || isa<DeallocBoxInst>(User) || isa<ProjectBoxInst>(User) || isa<DestroyValueInst>(User)); User->eraseFromParent(); } return true; }