コード例 #1
0
ファイル: Devirtualize.cpp プロジェクト: joewillsher/swift
/// Check if we can pass/convert all arguments of the original apply
/// as required by the found devirtualized method.
static bool
canPassOrConvertAllArguments(ApplySite AI,
                             CanSILFunctionType SubstCalleeCanType) {
  for (unsigned ArgN = 0, ArgE = AI.getNumArguments(); ArgN != ArgE; ++ArgN) {
    SILValue A = AI.getArgument(ArgN);
    auto ParamType = SubstCalleeCanType->getSILArgumentType(
      SubstCalleeCanType->getNumSILArguments() - AI.getNumArguments() + ArgN);
    // Check if we can cast the provided argument into the required
    // parameter type.
    auto FromTy = A->getType();
    auto ToTy = ParamType;
    // If types are the same, no conversion will be required.
    if (FromTy == ToTy)
      continue;
    // Otherwise, it should be possible to upcast the arguments.
    if (!isLegalUpcast(FromTy, ToTy))
      return false;
  }
  return true;
}
コード例 #2
0
/// For each argument in the range of the callee arguments being applied at the
/// given apply site, use the summary analysis to determine whether the
/// arguments will be accessed in a way that conflicts with any currently in
/// progress accesses. If so, diagnose.
static void checkCaptureAccess(ApplySite Apply, AccessState &State) {
  SILFunction *Callee = Apply.getCalleeFunction();
  if (!Callee || Callee->empty())
    return;

  const AccessSummaryAnalysis::FunctionSummary &FS =
      State.ASA->getOrCreateSummary(Callee);

  for (unsigned ArgumentIndex : range(Apply.getNumArguments())) {

    unsigned CalleeIndex =
        Apply.getCalleeArgIndexOfFirstAppliedArg() + ArgumentIndex;

    const AccessSummaryAnalysis::ArgumentSummary &AS =
        FS.getAccessForArgument(CalleeIndex);

    const auto &SubAccesses = AS.getSubAccesses();

    // Is the capture accessed in the callee?
    if (SubAccesses.empty())
      continue;

    SILValue Argument = Apply.getArgument(ArgumentIndex);
    assert(Argument->getType().isAddress());

    // A valid AccessedStorage should alway sbe found because Unsafe accesses
    // are not tracked by AccessSummaryAnalysis.
    const AccessedStorage &Storage = findValidAccessedStorage(Argument);
    auto AccessIt = State.Accesses->find(Storage);

    // Are there any accesses in progress at the time of the call?
    if (AccessIt == State.Accesses->end())
      continue;

    const AccessInfo &Info = AccessIt->getSecond();
    if (auto Conflict = findConflictingArgumentAccess(AS, Storage, Info))
      State.ConflictingAccesses.push_back(*Conflict);
  }
}
コード例 #3
0
ファイル: Devirtualize.cpp プロジェクト: asdfeng/swift
/// Generate a new apply of a function_ref to replace an apply of a
/// witness_method when we've determined the actual function we'll end
/// up calling.
static ApplySite devirtualizeWitnessMethod(ApplySite AI, SILFunction *F,
                                           ArrayRef<Substitution> Subs) {
  // We know the witness thunk and the corresponding set of substitutions
  // required to invoke the protocol method at this point.
  auto &Module = AI.getModule();

  // Collect all the required substitutions.
  //
  // The complete set of substitutions may be different, e.g. because the found
  // witness thunk F may have been created by a  specialization pass and have
  // additional generic parameters.
  SmallVector<Substitution, 16> NewSubstList(Subs.begin(), Subs.end());

  // Add the non-self-derived substitutions from the original application.
  ArrayRef<Substitution>  SubstList;
  SubstList = AI.getSubstitutionsWithoutSelfSubstitution();

  for (auto &origSub : SubstList)
    if (!origSub.getArchetype()->isSelfDerived())
      NewSubstList.push_back(origSub);

  // Figure out the exact bound type of the function to be called by
  // applying all substitutions.
  auto CalleeCanType = F->getLoweredFunctionType();
  auto SubstCalleeCanType = CalleeCanType->substGenericArgs(
    Module, Module.getSwiftModule(), NewSubstList);

  // Collect arguments from the apply instruction.
  auto Arguments = SmallVector<SILValue, 4>();

  auto ParamTypes = SubstCalleeCanType->getParameterSILTypes();

  // Iterate over the non self arguments and add them to the
  // new argument list, upcasting when required.
  SILBuilderWithScope B(AI.getInstruction());
  for (unsigned ArgN = 0, ArgE = AI.getNumArguments(); ArgN != ArgE; ++ArgN) {
    SILValue A = AI.getArgument(ArgN);
    auto ParamType = ParamTypes[ParamTypes.size() - AI.getNumArguments() + ArgN];
    if (A.getType() != ParamType)
      A = B.createUpcast(AI.getLoc(), A, ParamType);

    Arguments.push_back(A);
  }

  // Replace old apply instruction by a new apply instruction that invokes
  // the witness thunk.
  SILBuilderWithScope Builder(AI.getInstruction());
  SILLocation Loc = AI.getLoc();
  FunctionRefInst *FRI = Builder.createFunctionRef(Loc, F);

  auto SubstCalleeSILType = SILType::getPrimitiveObjectType(SubstCalleeCanType);
  auto ResultSILType = SubstCalleeCanType->getSILResult();
  ApplySite SAI;

  if (auto *A = dyn_cast<ApplyInst>(AI))
    SAI = Builder.createApply(Loc, FRI, SubstCalleeSILType,
                              ResultSILType, NewSubstList, Arguments,
                              A->isNonThrowing());
  if (auto *TAI = dyn_cast<TryApplyInst>(AI))
    SAI = Builder.createTryApply(Loc, FRI, SubstCalleeSILType,
                                 NewSubstList, Arguments,
                                 TAI->getNormalBB(), TAI->getErrorBB());
  if (auto *PAI = dyn_cast<PartialApplyInst>(AI))
    SAI = Builder.createPartialApply(Loc, FRI, SubstCalleeSILType,
                                     NewSubstList, Arguments, PAI->getType());

  NumWitnessDevirt++;
  return SAI;
}
コード例 #4
0
/// Generate a new apply of a function_ref to replace an apply of a
/// witness_method when we've determined the actual function we'll end
/// up calling.
static ApplySite devirtualizeWitnessMethod(ApplySite AI, SILFunction *F,
                                           ArrayRef<Substitution> Subs) {
  // We know the witness thunk and the corresponding set of substitutions
  // required to invoke the protocol method at this point.
  auto &Module = AI.getModule();

  // Collect all the required substitutions.
  //
  // The complete set of substitutions may be different, e.g. because the found
  // witness thunk F may have been created by a specialization pass and have
  // additional generic parameters.
  SmallVector<Substitution, 16> NewSubstList(Subs.begin(), Subs.end());
  if (auto generics = AI.getOrigCalleeType()->getGenericSignature()) {
    ArrayRef<Substitution> origSubs = AI.getSubstitutions();
    for (auto genericParam : generics->getAllDependentTypes()) {
      auto origSub = origSubs.front();
      origSubs = origSubs.slice(1);

      // Ignore generic parameters derived from 'self', the generic
      // parameter at depth 0, index 0.
      auto type = genericParam->getCanonicalType();
      while (auto memberType = dyn_cast<DependentMemberType>(type)) {
        type = memberType.getBase();
      }
      auto paramType = cast<GenericTypeParamType>(type);
      if (paramType->getDepth() == 0) {
        // There shouldn't be any other parameters at this depth.
        assert(paramType->getIndex() == 0);
        continue;
      }

      // Okay, remember this substitution.
      NewSubstList.push_back(origSub);
    }

    assert(origSubs.empty() && "subs not parallel to dependent types");
  }

  // Figure out the exact bound type of the function to be called by
  // applying all substitutions.
  auto CalleeCanType = F->getLoweredFunctionType();
  auto SubstCalleeCanType = CalleeCanType->substGenericArgs(
    Module, Module.getSwiftModule(), NewSubstList);

  // Collect arguments from the apply instruction.
  auto Arguments = SmallVector<SILValue, 4>();

  // Iterate over the non self arguments and add them to the
  // new argument list, upcasting when required.
  SILBuilderWithScope B(AI.getInstruction());
  for (unsigned ArgN = 0, ArgE = AI.getNumArguments(); ArgN != ArgE; ++ArgN) {
    SILValue A = AI.getArgument(ArgN);
    auto ParamType = SubstCalleeCanType->getSILArgumentType(
      SubstCalleeCanType->getNumSILArguments() - AI.getNumArguments() + ArgN);
    if (A->getType() != ParamType)
      A = B.createUpcast(AI.getLoc(), A, ParamType);

    Arguments.push_back(A);
  }

  // Replace old apply instruction by a new apply instruction that invokes
  // the witness thunk.
  SILBuilderWithScope Builder(AI.getInstruction());
  SILLocation Loc = AI.getLoc();
  FunctionRefInst *FRI = Builder.createFunctionRef(Loc, F);

  auto SubstCalleeSILType = SILType::getPrimitiveObjectType(SubstCalleeCanType);
  auto ResultSILType = SubstCalleeCanType->getSILResult();
  ApplySite SAI;

  if (auto *A = dyn_cast<ApplyInst>(AI))
    SAI = Builder.createApply(Loc, FRI, SubstCalleeSILType,
                              ResultSILType, NewSubstList, Arguments,
                              A->isNonThrowing());
  if (auto *TAI = dyn_cast<TryApplyInst>(AI))
    SAI = Builder.createTryApply(Loc, FRI, SubstCalleeSILType,
                                 NewSubstList, Arguments,
                                 TAI->getNormalBB(), TAI->getErrorBB());
  if (auto *PAI = dyn_cast<PartialApplyInst>(AI))
    SAI = Builder.createPartialApply(Loc, FRI, SubstCalleeSILType,
                                     NewSubstList, Arguments, PAI->getType());

  NumWitnessDevirt++;
  return SAI;
}
コード例 #5
0
ファイル: Devirtualize.cpp プロジェクト: joewillsher/swift
/// Generate a new apply of a function_ref to replace an apply of a
/// witness_method when we've determined the actual function we'll end
/// up calling.
static ApplySite devirtualizeWitnessMethod(ApplySite AI, SILFunction *F,
                                           ProtocolConformanceRef C) {
  // We know the witness thunk and the corresponding set of substitutions
  // required to invoke the protocol method at this point.
  auto &Module = AI.getModule();

  // Collect all the required substitutions.
  //
  // The complete set of substitutions may be different, e.g. because the found
  // witness thunk F may have been created by a specialization pass and have
  // additional generic parameters.
  SmallVector<Substitution, 4> NewSubs;

  getWitnessMethodSubstitutions(AI, F, C, NewSubs);

  // Figure out the exact bound type of the function to be called by
  // applying all substitutions.
  auto CalleeCanType = F->getLoweredFunctionType();
  auto SubstCalleeCanType = CalleeCanType->substGenericArgs(Module, NewSubs);

  // Bail if some of the arguments cannot be converted into
  // types required by the found devirtualized method.
  if (!canPassOrConvertAllArguments(AI, SubstCalleeCanType))
    return ApplySite();

  // Collect arguments from the apply instruction.
  auto Arguments = SmallVector<SILValue, 4>();

  // Iterate over the non self arguments and add them to the
  // new argument list, upcasting when required.
  SILBuilderWithScope B(AI.getInstruction());
  for (unsigned ArgN = 0, ArgE = AI.getNumArguments(); ArgN != ArgE; ++ArgN) {
    SILValue A = AI.getArgument(ArgN);
    auto ParamType = SubstCalleeCanType->getSILArgumentType(
      SubstCalleeCanType->getNumSILArguments() - AI.getNumArguments() + ArgN);
    if (A->getType() != ParamType)
      A = B.createUpcast(AI.getLoc(), A, ParamType);

    Arguments.push_back(A);
  }

  // Replace old apply instruction by a new apply instruction that invokes
  // the witness thunk.
  SILBuilderWithScope Builder(AI.getInstruction());
  SILLocation Loc = AI.getLoc();
  FunctionRefInst *FRI = Builder.createFunctionRef(Loc, F);

  auto SubstCalleeSILType = SILType::getPrimitiveObjectType(SubstCalleeCanType);
  auto ResultSILType = SubstCalleeCanType->getSILResult();
  ApplySite SAI;

  if (auto *A = dyn_cast<ApplyInst>(AI))
    SAI = Builder.createApply(Loc, FRI, SubstCalleeSILType,
                              ResultSILType, NewSubs, Arguments,
                              A->isNonThrowing());
  if (auto *TAI = dyn_cast<TryApplyInst>(AI))
    SAI = Builder.createTryApply(Loc, FRI, SubstCalleeSILType,
                                 NewSubs, Arguments,
                                 TAI->getNormalBB(), TAI->getErrorBB());
  if (auto *PAI = dyn_cast<PartialApplyInst>(AI))
    SAI = Builder.createPartialApply(Loc, FRI, SubstCalleeSILType,
                                     NewSubs, Arguments, PAI->getType());

  NumWitnessDevirt++;
  return SAI;
}