Beispiel #1
0
bool OwnershipChecker::checkValue(SILValue value) {
  regularUsers.clear();
  lifetimeEndingUsers.clear();
  liveBlocks.clear();

  // Since we do not have SILUndef, we now know that getFunction() should return
  // a real function. Assert in case this assumption is no longer true.
  SILFunction *f = value->getFunction();
  assert(f && "Instructions and arguments should have a function");

  // If the given function has unqualified ownership, there is nothing further
  // to verify.
  if (!f->hasQualifiedOwnership())
    return false;

  ErrorBehaviorKind errorBehavior(ErrorBehaviorKind::ReturnFalse);
  SILValueOwnershipChecker checker(mod, deadEndBlocks, value, errorBehavior,
                                   liveBlocks);
  if (!checker.check()) {
    return false;
  }

  // TODO: Make this more efficient.
  copy(checker.getRegularUsers(), std::back_inserter(regularUsers));
  copy(checker.getLifetimeEndingUsers(),
       std::back_inserter(lifetimeEndingUsers));
  return true;
}
Beispiel #2
0
void SILValue::verifyOwnership(SILModule &mod,
                               DeadEndBlocks *deadEndBlocks) const {
#ifndef NDEBUG
  if (DisableOwnershipVerification)
    return;

  // Since we do not have SILUndef, we now know that getFunction() should return
  // a real function. Assert in case this assumption is no longer true.
  SILFunction *f = (*this)->getFunction();
  assert(f && "Instructions and arguments should have a function");

  // If the given function has unqualified ownership or we have been asked by
  // the user not to verify this function, there is nothing to verify.
  if (!f->hasQualifiedOwnership() || !f->shouldVerifyOwnership())
    return;

  assert(getOwnershipKind() != ValueOwnershipKind::Any &&
         "No values should have any ownership anymore");
  ErrorBehaviorKind errorBehavior;
  if (IsSILOwnershipVerifierTestingEnabled) {
    errorBehavior = ErrorBehaviorKind::PrintMessageAndReturnFalse;
  } else {
    errorBehavior = ErrorBehaviorKind::PrintMessageAndAssert;
  }

  llvm::SmallPtrSet<SILBasicBlock *, 32> liveBlocks;
  if (deadEndBlocks) {
    SILValueOwnershipChecker(mod, *deadEndBlocks, *this, errorBehavior,
                             liveBlocks)
        .check();
  } else {
    DeadEndBlocks deadEndBlocks(f);
    SILValueOwnershipChecker(mod, deadEndBlocks, *this, errorBehavior,
                             liveBlocks)
        .check();
  }
#endif
}
Beispiel #3
0
/// In this function we create the actual cloned function and its proper cloned
/// type. But we do not create any body. This implies that the creation of the
/// actual arguments in the function is in populateCloned.
///
/// \arg PAUser The function that is being passed the partial apply.
/// \arg PAI The partial apply that is being passed to PAUser.
/// \arg ClosureIndex The index of the partial apply in PAUser's function
///                   signature.
/// \arg ClonedName The name of the cloned function that we will create.
SILFunction *
ClosureSpecCloner::initCloned(SILOptFunctionBuilder &FunctionBuilder,
                              const CallSiteDescriptor &CallSiteDesc,
                              StringRef ClonedName) {
  SILFunction *ClosureUser = CallSiteDesc.getApplyCallee();

  // This is the list of new interface parameters of the cloned function.
  llvm::SmallVector<SILParameterInfo, 4> NewParameterInfoList;

  // First add to NewParameterInfoList all of the SILParameterInfo in the
  // original function except for the closure.
  CanSILFunctionType ClosureUserFunTy = ClosureUser->getLoweredFunctionType();
  auto ClosureUserConv = ClosureUser->getConventions();
  unsigned Index = ClosureUserConv.getSILArgIndexOfFirstParam();
  for (auto &param : ClosureUserConv.getParameters()) {
    if (Index != CallSiteDesc.getClosureIndex())
      NewParameterInfoList.push_back(param);
    ++Index;
  }

  // Then add any arguments that are captured in the closure to the function's
  // argument type. Since they are captured, we need to pass them directly into
  // the new specialized function.
  SILFunction *ClosedOverFun = CallSiteDesc.getClosureCallee();
  auto ClosedOverFunConv = ClosedOverFun->getConventions();
  SILModule &M = ClosureUser->getModule();

  // Captured parameters are always appended to the function signature. If the
  // type of the captured argument is:
  // - direct and trivial, pass the argument as Direct_Unowned.
  // - direct and non-trivial, pass the argument as Direct_Owned.
  // - indirect, pass the argument using the same parameter convention as in the
  // original closure.
  //
  // We use the type of the closure here since we allow for the closure to be an
  // external declaration.
  unsigned NumTotalParams = ClosedOverFunConv.getNumParameters();
  unsigned NumNotCaptured = NumTotalParams - CallSiteDesc.getNumArguments();
  for (auto &PInfo : ClosedOverFunConv.getParameters().slice(NumNotCaptured)) {
    ParameterConvention ParamConv;
    if (PInfo.isFormalIndirect()) {
      ParamConv = PInfo.getConvention();
      assert(!SILModuleConventions(M).useLoweredAddresses()
             || ParamConv == ParameterConvention::Indirect_Inout
             || ParamConv == ParameterConvention::Indirect_InoutAliasable);
    } else {
      ParamConv = ClosedOverFunConv.getSILType(PInfo).isTrivial(M)
                      ? ParameterConvention::Direct_Unowned
                      : ParameterConvention::Direct_Owned;
    }

    SILParameterInfo NewPInfo(PInfo.getType(), ParamConv);
    NewParameterInfoList.push_back(NewPInfo);
  }

  // The specialized function is always a thin function. This is important
  // because we may add additional parameters after the Self parameter of
  // witness methods. In this case the new function is not a method anymore.
  auto ExtInfo = ClosureUserFunTy->getExtInfo();
  ExtInfo = ExtInfo.withRepresentation(SILFunctionTypeRepresentation::Thin);

  auto ClonedTy = SILFunctionType::get(
      ClosureUserFunTy->getGenericSignature(), ExtInfo,
      ClosureUserFunTy->getCoroutineKind(),
      ClosureUserFunTy->getCalleeConvention(), NewParameterInfoList,
      ClosureUserFunTy->getYields(), ClosureUserFunTy->getResults(),
      ClosureUserFunTy->getOptionalErrorResult(), M.getASTContext());

  // We make this function bare so we don't have to worry about decls in the
  // SILArgument.
  auto *Fn = FunctionBuilder.createFunction(
      // It's important to use a shared linkage for the specialized function
      // and not the original linkage.
      // Otherwise the new function could have an external linkage (in case the
      // original function was de-serialized) and would not be code-gen'd.
      // It's also important to disconnect this specialized function from any
      // classes (the classSubclassScope), because that may incorrectly
      // influence the linkage.
      getSpecializedLinkage(ClosureUser, ClosureUser->getLinkage()), ClonedName,
      ClonedTy, ClosureUser->getGenericEnvironment(),
      ClosureUser->getLocation(), IsBare, ClosureUser->isTransparent(),
      CallSiteDesc.isSerialized(), IsNotDynamic, ClosureUser->getEntryCount(),
      ClosureUser->isThunk(),
      /*classSubclassScope=*/SubclassScope::NotApplicable,
      ClosureUser->getInlineStrategy(), ClosureUser->getEffectsKind(),
      ClosureUser, ClosureUser->getDebugScope());
  if (!ClosureUser->hasQualifiedOwnership()) {
    Fn->setUnqualifiedOwnership();
  }
  for (auto &Attr : ClosureUser->getSemanticsAttrs())
    Fn->addSemanticsAttr(Attr);
  return Fn;
}