/// Returns true when the apply calls the Standard Library swap(). /// Used for fix-its to suggest replacing with Collection.swapAt() /// on exclusivity violations. static bool isCallToStandardLibrarySwap(ApplyInst *AI, ASTContext &Ctx) { SILFunction *SF = AI->getReferencedFunction(); if (!SF) return false; if (!SF->hasLocation()) return false; auto *FD = SF->getLocation().getAsASTNode<FuncDecl>(); if (!FD) return false; return FD == Ctx.getSwap(); }
void StackPromoter::tryPromoteAlloc(SILInstruction *I) { SILInstruction *AllocInsertionPoint = nullptr; SILInstruction *DeallocInsertionPoint = nullptr; if (!canPromoteAlloc(I, AllocInsertionPoint, DeallocInsertionPoint)) return; DEBUG(llvm::dbgs() << "Promoted " << *I); DEBUG(llvm::dbgs() << " in " << I->getFunction()->getName() << '\n'); NumStackPromoted++; SILBuilder B(DeallocInsertionPoint); if (auto *ARI = dyn_cast<AllocRefInst>(I)) { // It's an object allocation. We set the [stack] attribute in the alloc_ref. ARI->setStackAllocatable(); if (AllocInsertionPoint) ARI->moveBefore(AllocInsertionPoint); /// And create a dealloc_ref [stack] at the end of the object's lifetime. B.createDeallocRef(I->getLoc(), I, true); ChangedInsts = true; return; } if (auto *AI = dyn_cast<ApplyInst>(I)) { assert(!AllocInsertionPoint && "can't move call to swift_bufferAlloc"); // It's an array buffer allocation. auto *OldFRI = cast<FunctionRefInst>(AI->getCallee()); SILFunction *OldF = OldFRI->getReferencedFunction(); SILLocation loc = (OldF->hasLocation() ? OldF->getLocation() : AI->getLoc()); SILFunction *DeallocFun = getBufferDeallocFunc(OldF, loc); // We insert a swift_bufferDeallocateFromStack at the end of the buffer's // lifetime. auto *DeallocFRI = B.createFunctionRef(OldFRI->getLoc(), DeallocFun); B.createApply(loc, DeallocFRI, { AI }, false); // And replace the call to swift_bufferAllocate with a call to // swift_bufferAllocateOnStack. B.setInsertionPoint(AI); auto *AllocFRI = B.createFunctionRef(OldFRI->getLoc(), getBufferAllocFunc(OldF, loc)); AI->setOperand(0, AllocFRI); ChangedCalls = true; return; } llvm_unreachable("unhandled allocation instruction"); }