/// 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();
}
Пример #2
0
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");
}