void SILCombiner::eraseApply(FullApplySite FAS, const UserListTy &Users) {
    // Make sure to release and destroy any owned or in-arguments.
    auto FuncType = FAS.getOrigCalleeType();
    assert(FuncType->getParameters().size() == FAS.getNumArguments() &&
           "mismatching number of arguments");
    for (int i = 0, e = FAS.getNumArguments(); i < e; ++i) {
        SILParameterInfo PI = FuncType->getParameters()[i];
        auto Arg = FAS.getArgument(i);
        switch (PI.getConvention()) {
        case ParameterConvention::Indirect_In:
            Builder.createDestroyAddr(FAS.getLoc(), Arg);
            break;
        case ParameterConvention::Direct_Owned:
            Builder.createReleaseValue(FAS.getLoc(), Arg, Atomicity::Atomic);
            break;
        case ParameterConvention::Indirect_In_Guaranteed:
        case ParameterConvention::Indirect_Inout:
        case ParameterConvention::Indirect_InoutAliasable:
        case ParameterConvention::Direct_Unowned:
        case ParameterConvention::Direct_Deallocating:
        case ParameterConvention::Direct_Guaranteed:
            break;
        }
    }

    // Erase all of the reference counting instructions (in reverse order to have
    // no dangling uses).
    for (auto rit = Users.rbegin(), re = Users.rend(); rit != re; ++rit)
        eraseInstFromFunction(**rit);

    // And the Apply itself.
    eraseInstFromFunction(*FAS.getInstruction());
}
Example #2
0
bool AliasAnalysis::canApplyDecrementRefCount(FullApplySite FAS, SILValue Ptr) {
  // Treat applications of @noreturn functions as decrementing ref counts. This
  // causes the apply to become a sink barrier for ref count increments.
  if (FAS.getCallee().getType().getAs<SILFunctionType>()->isNoReturn())
    return true;

  /// If the pointer cannot escape to the function we are done.
  if (!EA->canEscapeTo(Ptr, FAS))
    return false;

  SideEffectAnalysis::FunctionEffects ApplyEffects;
  SEA->getEffects(ApplyEffects, FAS);

  auto &GlobalEffects = ApplyEffects.getGlobalEffects();
  if (ApplyEffects.mayReadRC() || GlobalEffects.mayRelease())
    return true;

  /// The function has no unidentified releases, so let's look at the arguments
  // in detail.
  for (unsigned Idx = 0, End = FAS.getNumArguments(); Idx < End; ++Idx) {
    auto &ArgEffect = ApplyEffects.getParameterEffects()[Idx];
    if (ArgEffect.mayRelease()) {
      // The function may release this argument, so check if the pointer can
      // escape to it.
      if (EA->canEscapeToValue(Ptr, FAS.getArgument(Idx)))
        return true;
    }
  }
  return false;
}
void ArgumentDescriptor::addCallerArgs(
    SILBuilder &B, FullApplySite FAS,
    llvm::SmallVectorImpl<SILValue> &NewArgs) const {
  if (IsDead)
    return;

  SILValue Arg = FAS.getArgument(Index);
  if (!shouldExplode()) {
    NewArgs.push_back(Arg);
    return;
  }

  ProjTree.createTreeFromValue(B, FAS.getLoc(), Arg, NewArgs);
}
Example #4
0
bool FunctionEffects::mergeFromApply(
                  const FunctionEffects &ApplyEffects, FullApplySite FAS) {
  bool Changed = mergeFlags(ApplyEffects);
  Changed |= GlobalEffects.mergeFrom(ApplyEffects.GlobalEffects);
  unsigned numCallerArgs = FAS.getNumArguments();
  unsigned numCalleeArgs = ApplyEffects.ParamEffects.size();
  assert(numCalleeArgs >= numCallerArgs);
  for (unsigned Idx = 0; Idx < numCalleeArgs; Idx++) {
    // Map the callee argument effects to parameters of this function.
    // If there are more callee parameters than arguments it means that the
    // callee is the result of a partial_apply.
    Effects *E = (Idx < numCallerArgs ? getEffectsOn(FAS.getArgument(Idx)) :
                  &GlobalEffects);
    Changed |= E->mergeFrom(ApplyEffects.ParamEffects[Idx]);
  }
  return Changed;
}
/// Returns the argument of the full apply or partial apply corresponding to the
/// callee's parameter index, or returns an invalid SILValue if the applied
/// closure cannot be found. This walks up the apply chain starting at the given
/// `fullApply` to find the applied argument.
static SILValue getCallerArg(FullApplySite fullApply, unsigned paramIndex) {
  if (paramIndex < fullApply.getNumArguments())
    return fullApply.getArgument(paramIndex);

  SILValue callee = fullApply.getCalleeOrigin();
  auto *PAI = dyn_cast<PartialApplyInst>(callee);
  if (!PAI)
    return SILValue();

  unsigned appliedIndex =
    paramIndex - ApplySite(PAI).getCalleeArgIndexOfFirstAppliedArg();
  if (appliedIndex < PAI->getNumArguments())
    return PAI->getArgument(appliedIndex);

  // This must be a chain of partial_applies. We don't expect this in practice,
  // so handle it conservatively.
  return SILValue();
}