Ejemplo n.º 1
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);
  }
}
Ejemplo n.º 2
0
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());
}
Ejemplo n.º 3
0
void GenericFunctionEffectAnalysis<FunctionEffects>::analyzeCall(
    FunctionInfo *functionInfo, FullApplySite fullApply,
    FunctionOrder &bottomUpOrder, int recursionDepth) {

  FunctionEffects applyEffects;
  if (applyEffects.summarizeCall(fullApply)) {
    functionInfo->functionEffects.mergeFromApply(applyEffects, fullApply);
    return;
  }

  if (recursionDepth >= MaxRecursionDepth) {
    functionInfo->functionEffects.setWorstEffects();
    return;
  }
  CalleeList callees = BCA->getCalleeList(fullApply);
  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.
      fullApply.getOrigCalleeType()->isCalleeConsumed()) {
    functionInfo->functionEffects.setWorstEffects();
    return;
  }
  // Derive the effects of the apply from the known callees.
  // Defer merging callee effects until the callee is scheduled
  for (SILFunction *callee : callees) {
    FunctionInfo *calleeInfo = getFunctionInfo(callee);
    calleeInfo->addCaller(functionInfo, fullApply);
    if (!calleeInfo->isVisited()) {
      // Recursively visit the called function.
      analyzeFunction(calleeInfo, bottomUpOrder, recursionDepth + 1);
      bottomUpOrder.tryToSchedule(calleeInfo);
    }
  }
}
Ejemplo n.º 4
0
// Start with the substitutions from the apply.
// Try to propagate them to find out the real substitutions required
// to invoke the method.
static SubstitutionMap
getSubstitutionsForCallee(SILModule &M,
                          CanSILFunctionType baseCalleeType,
                          CanType derivedSelfType,
                          FullApplySite AI) {

  // If the base method is not polymorphic, no substitutions are required,
  // even if we originally had substitutions for calling the derived method.
  if (!baseCalleeType->isPolymorphic())
    return SubstitutionMap();

  // Add any generic substitutions for the base class.
  Type baseSelfType = baseCalleeType->getSelfParameter().getType();
  if (auto metatypeType = baseSelfType->getAs<MetatypeType>())
    baseSelfType = metatypeType->getInstanceType();

  auto *baseClassDecl = baseSelfType->getClassOrBoundGenericClass();
  assert(baseClassDecl && "not a class method");

  unsigned baseDepth = 0;
  SubstitutionMap baseSubMap;
  if (auto baseClassSig = baseClassDecl->getGenericSignatureOfContext()) {
    baseDepth = baseClassSig->getGenericParams().back()->getDepth() + 1;

    // Compute the type of the base class, starting from the
    // derived class type and the type of the method's self
    // parameter.
    Type derivedClass = derivedSelfType;
    if (auto metatypeType = derivedClass->getAs<MetatypeType>())
      derivedClass = metatypeType->getInstanceType();
    baseSubMap = derivedClass->getContextSubstitutionMap(
        M.getSwiftModule(), baseClassDecl);
  }

  SubstitutionMap origSubMap = AI.getSubstitutionMap();

  Type calleeSelfType = AI.getOrigCalleeType()->getSelfParameter().getType();
  if (auto metatypeType = calleeSelfType->getAs<MetatypeType>())
    calleeSelfType = metatypeType->getInstanceType();
  auto *calleeClassDecl = calleeSelfType->getClassOrBoundGenericClass();
  assert(calleeClassDecl && "self is not a class type");

  // Add generic parameters from the method itself, ignoring any generic
  // parameters from the derived class.
  unsigned origDepth = 0;
  if (auto calleeClassSig = calleeClassDecl->getGenericSignatureOfContext())
    origDepth = calleeClassSig->getGenericParams().back()->getDepth() + 1;

  auto baseCalleeSig = baseCalleeType->getGenericSignature();

  return
    SubstitutionMap::combineSubstitutionMaps(baseSubMap,
                                             origSubMap,
                                             CombineSubstitutionMaps::AtDepth,
                                             baseDepth,
                                             origDepth,
                                             baseCalleeSig);
}
Ejemplo n.º 5
0
void GenericFunctionEffectAnalysis<FunctionEffects>::getCalleeEffects(
    FunctionEffects &calleeEffects, FullApplySite fullApply) {
  if (calleeEffects.summarizeCall(fullApply))
    return;

  auto callees = BCA->getCalleeList(fullApply);
  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.
      fullApply.getOrigCalleeType()->isCalleeConsumed()) {
    calleeEffects.setWorstEffects();
    return;
  }

  // We can see all the callees, so merge the effects from all of them.
  for (auto *callee : callees)
    calleeEffects.mergeFrom(getEffects(callee));
}
Ejemplo n.º 6
0
// Start with the substitutions from the apply.
// Try to propagate them to find out the real substitutions required
// to invoke the method.
static void
getSubstitutionsForCallee(SILModule &M,
                          CanSILFunctionType baseCalleeType,
                          CanType derivedSelfType,
                          FullApplySite AI,
                          SmallVectorImpl<Substitution> &newSubs) {

  // If the base method is not polymorphic, no substitutions are required,
  // even if we originally had substitutions for calling the derived method.
  if (!baseCalleeType->isPolymorphic())
    return;

  auto derivedClass = derivedSelfType;
  if (auto metatypeType = dyn_cast<MetatypeType>(derivedClass))
    derivedClass = CanType(metatypeType->getInstanceType());

  SubstitutionMap subMap;

  if (auto origCalleeSig = AI.getOrigCalleeType()->getGenericSignature()) {
    auto calleeSelfType = AI.getSubstCalleeType()->getSelfParameter().getType();
    if (auto metatypeType = dyn_cast<MetatypeType>(calleeSelfType))
      calleeSelfType = CanType(metatypeType->getInstanceType());
    auto *calleeClassDecl = calleeSelfType->getClassOrBoundGenericClass();
    assert(calleeClassDecl && "self is not a class type");

    auto origSubs = AI.getSubstitutions();

    // Add generic parameters from the method itself, ignoring any generic
    // parameters from the derived class.
    unsigned minDepth = 0;
    if (auto derivedClassSig = calleeClassDecl->getGenericSignatureOfContext())
      minDepth = derivedClassSig->getGenericParams().back()->getDepth() + 1;

    for (auto depTy : origCalleeSig->getAllDependentTypes()) {
      // Grab the next substitution.
      auto sub = origSubs.front();
      origSubs = origSubs.slice(1);

      // If the dependent type doesn't contain any generic parameter with
      // a depth of at least the minimum, skip this type.
      auto canTy = depTy->getCanonicalType();
      auto hasInnerGenericParameter = [minDepth](Type type) -> bool {
        if (auto gp = type->getAs<GenericTypeParamType>()) {
          return gp->getDepth() >= minDepth;
        }
        return false;
      };

      if (!Type(canTy.getPointer()).findIf(hasInnerGenericParameter))
        continue;

      // Otherwise, record the replacement and conformances for the mapped
      // type.
      subMap.addSubstitution(canTy, sub.getReplacement());
      subMap.addConformances(canTy, sub.getConformances());
    }
    assert(origSubs.empty());
  }

  // Add any generic substitutions for the base class.
  auto baseSelfType = baseCalleeType->getSelfParameter().getType();
  if (auto metatypeType = dyn_cast<MetatypeType>(baseSelfType))
    baseSelfType = CanType(metatypeType->getInstanceType());

  auto *baseClassDecl = baseSelfType.getClassOrBoundGenericClass();
  assert(baseClassDecl && "not a class method");

  if (auto baseClassSig = baseClassDecl->getGenericSignatureOfContext()) {
    // Compute the type of the base class, starting from the
    // derived class type and the type of the method's self
    // parameter.
    auto baseClass = derivedClass->getSuperclassForDecl(baseClassDecl, nullptr)
        ->getCanonicalType();
    auto baseClassSubs = baseClass->gatherAllSubstitutions(
        M.getSwiftModule(), nullptr);

    // Decompose the base class substitutions, adding them to the same
    // substitution maps as above.
    baseClassSig->getSubstitutionMap(baseClassSubs, subMap);
  }

  // Build the new substitutions using the base method signature.
  auto baseCalleeSig = baseCalleeType->getGenericSignature();
  baseCalleeSig->getSubstitutions(subMap, newSubs);
}