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
void SideEffectAnalysis::getEffects(FunctionEffects &ApplyEffects, FullApplySite FAS) {
  assert(ApplyEffects.ParamEffects.size() == 0 &&
         "Not using a new ApplyEffects?");
  ApplyEffects.ParamEffects.resize(FAS.getNumArguments());

  // Is this a call to a semantics function?
  ArraySemanticsCall ASC(FAS.getInstruction());
  if (ASC && ASC.hasSelf()) {
    if (getSemanticEffects(ApplyEffects, ASC))
      return;
  }

  if (SILFunction *SingleCallee = FAS.getCalleeFunction()) {
    // Does the function have any @effects?
    if (getDefinedEffects(ApplyEffects, SingleCallee))
      return;
  }

  auto Callees = BCA->getCalleeList(FAS);
  if (!Callees.allCalleesVisible() ||
      // @callee_owned function calls implicitly release the context, which
      // may call deinits of boxed values.
      // TODO: be less conservative about what destructors might be called.
      FAS.getOrigCalleeType()->isCalleeConsumed()) {
    ApplyEffects.setWorstEffects();
    return;
  }

  // We can see all the callees. So we just merge the effects from all of
  // them.
  for (auto *Callee : Callees) {
    const FunctionEffects &CalleeFE = getEffects(Callee);
    ApplyEffects.mergeFrom(CalleeFE);
  }
}
Example #3
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;
}
Example #4
0
void SideEffectAnalysis::getEffects(FunctionEffects &ApplyEffects, FullApplySite FAS) {
  assert(ApplyEffects.ParamEffects.size() == 0 &&
         "Not using a new ApplyEffects?");
  ApplyEffects.ParamEffects.resize(FAS.getNumArguments());

  // Is this a call to a semantics function?
  ArraySemanticsCall ASC(FAS.getInstruction());
  if (ASC && ASC.hasSelf()) {
    if (getSemanticEffects(ApplyEffects, ASC))
      return;
  }

  if (SILFunction *SingleCallee = FAS.getCalleeFunction()) {
    // Does the function have any @effects?
    if (getDefinedEffects(ApplyEffects, SingleCallee))
      return;
  }

  auto Callees = BCA->getCalleeList(FAS);
  if (!Callees.allCalleesVisible()) {
    ApplyEffects.setWorstEffects();
    return;
  }

  // We can see all the callees. So we just merge the effects from all of
  // them.
  for (auto *Callee : Callees) {
    const FunctionEffects &CalleeFE = getEffects(Callee);
    ApplyEffects.mergeFrom(CalleeFE);
  }
}
Example #5
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();
}
Example #7
0
// Summarize the callee side effects of a call instruction using this
// FunctionSideEffects object without analyzing the callee function bodies or
// scheduling the callees for bottom-up propagation.
//
// Return true if this call-site's effects are summarized without visiting the
// callee.
bool FunctionSideEffects::summarizeCall(FullApplySite fullApply) {
  assert(ParamEffects.empty() && "Expect uninitialized effects.");
  ParamEffects.resize(fullApply.getNumArguments());

  // Is this a call to a semantics function?
  if (auto apply = dyn_cast<ApplyInst>(fullApply.getInstruction())) {
    ArraySemanticsCall ASC(apply);
    if (ASC && ASC.hasSelf()) {
      if (setSemanticEffects(ASC))
        return true;
    }
  }

  if (SILFunction *SingleCallee = fullApply.getReferencedFunction()) {
    // Does the function have any @effects?
    if (setDefinedEffects(SingleCallee))
      return true;
  }
  return false;
}