Esempio n. 1
0
/// Replace load sequence which may contain
/// a chain of struct_element_addr followed by a load.
/// The sequence is traversed starting from the load
/// instruction.
static SILValue convertLoadSequence(SILValue oldSequence,
                                    SILValue newRootValue,
                                    SILBuilder &B) {

  if (isa<GlobalAddrInst>(oldSequence))
    return newRootValue;

  if (auto *LI = dyn_cast<LoadInst>(oldSequence)) {
    auto newValue = convertLoadSequence(LI->getOperand(), newRootValue, B);
    LI->replaceAllUsesWith(newValue);
    return newValue;
  }

  // It is a series of struct_element_addr followed by load.
  if (auto *SEAI = dyn_cast<StructElementAddrInst>(oldSequence)) {
    auto newValue = convertLoadSequence(SEAI->getOperand(), newRootValue, B);
    newValue = B.createStructExtract(SEAI->getLoc(), newValue, SEAI->getField());
    return newValue;
  }

  if (auto *TEAI = dyn_cast<TupleElementAddrInst>(oldSequence)) {
    auto newValue = convertLoadSequence(TEAI->getOperand(), newRootValue, B);
    newValue = B.createTupleExtract(TEAI->getLoc(), newValue, TEAI->getFieldNo());
    return newValue;
  }

  llvm_unreachable("Unknown instruction sequence for reading from a global");
  return nullptr;
}
// A utility function for cloning the apply instruction.
static FullApplySite CloneApply(FullApplySite AI, SILBuilder &Builder) {
  // Clone the Apply.
  Builder.setCurrentDebugScope(AI.getDebugScope());
  Builder.addOpenedArchetypeOperands(AI.getInstruction());
  auto Args = AI.getArguments();
  SmallVector<SILValue, 8> Ret(Args.size());
  for (unsigned i = 0, e = Args.size(); i != e; ++i)
    Ret[i] = Args[i];

  FullApplySite NAI;

  switch (AI.getInstruction()->getKind()) {
  case SILInstructionKind::ApplyInst:
    NAI = Builder.createApply(AI.getLoc(), AI.getCallee(),
                                   AI.getSubstitutions(),
                                   Ret,
                                   cast<ApplyInst>(AI)->isNonThrowing());
    break;
  case SILInstructionKind::TryApplyInst: {
    auto *TryApplyI = cast<TryApplyInst>(AI.getInstruction());
    NAI = Builder.createTryApply(AI.getLoc(), AI.getCallee(),
                                      AI.getSubstitutions(),
                                      Ret,
                                      TryApplyI->getNormalBB(),
                                      TryApplyI->getErrorBB());
    }
    break;
  default:
    llvm_unreachable("Trying to clone an unsupported apply instruction");
  }

  NAI.getInstruction();
  return NAI;
}
Esempio n. 3
0
void swift::
addRetainsForConvertedDirectResults(SILBuilder &Builder,
                                    SILLocation Loc,
                                    SILValue ReturnValue,
                                    SILInstruction *AI,
                                    ArrayRef<ResultDescriptor> DirectResults) {
  for (auto I : indices(DirectResults)) {
    auto &RV = DirectResults[I];
    if (RV.CalleeRetain.empty()) continue;

    bool IsSelfRecursionEpilogueRetain = false;
    for (auto &X : RV.CalleeRetain) {
      IsSelfRecursionEpilogueRetain |= (AI == X);
    }

    // We do not create a retain if this ApplyInst is a self-recursion.
    if (IsSelfRecursionEpilogueRetain)
      continue;

    // Extract the return value if necessary.
    SILValue SpecificResultValue = ReturnValue;
    if (DirectResults.size() != 1)
      SpecificResultValue = Builder.createTupleExtract(Loc, ReturnValue, I);

    Builder.createRetainValue(Loc, SpecificResultValue);
  }
}
Esempio n. 4
0
/// Promote a DebugValueAddr to a DebugValue of the given value.
static void
promoteDebugValueAddr(DebugValueAddrInst *DVAI, SILValue Value, SILBuilder &B) {
  assert(Value && "Expected valid value");
  B.setInsertionPoint(DVAI);
  B.setCurrentDebugScope(DVAI->getDebugScope());
  B.createDebugValue(DVAI->getLoc(), Value, DVAI->getVarInfo());
  DVAI->eraseFromParent();
}
Esempio n. 5
0
/// Promote a DebugValueAddr to a DebugValue of the given value.
static void
promoteDebugValueAddr(DebugValueAddrInst *DVAI, SILValue Value, SILBuilder &B) {
  assert(DVAI->getOperand()->getType().isLoadable(DVAI->getModule()) &&
         "Unexpected promotion of address-only type!");
  assert(Value && "Expected valid value");
  B.setInsertionPoint(DVAI);
  B.setCurrentDebugScope(DVAI->getDebugScope());
  B.createDebugValue(DVAI->getLoc(), Value, *DVAI->getVarInfo());
  DVAI->eraseFromParent();
}
Esempio n. 6
0
/// Set up epilogue work for the thunk arguments based in the given argument.
/// Default implementation simply passes it through.
void
FunctionSignatureTransform::
OwnedToGuaranteedAddArgumentRelease(ArgumentDescriptor &AD, SILBuilder &Builder,
                                    SILFunction *F) {
  // If we have any arguments that were consumed but are now guaranteed,
  // insert a release_value.
  if (!AD.OwnedToGuaranteed) {
    return;
  }

  SILInstruction *Call = findOnlyApply(F);
  if (isa<ApplyInst>(Call)) {
    Builder.setInsertionPoint(&*std::next(SILBasicBlock::iterator(Call)));
    Builder.createReleaseValue(RegularLocation(SourceLoc()),
                               F->getArguments()[AD.Index],
                               Builder.getDefaultAtomicity());
  } else {
    SILBasicBlock *NormalBB = dyn_cast<TryApplyInst>(Call)->getNormalBB();
    Builder.setInsertionPoint(&*NormalBB->begin());
    Builder.createReleaseValue(RegularLocation(SourceLoc()),
                               F->getArguments()[AD.Index],
                               Builder.getDefaultAtomicity());

    SILBasicBlock *ErrorBB = dyn_cast<TryApplyInst>(Call)->getErrorBB();
    Builder.setInsertionPoint(&*ErrorBB->begin());
    Builder.createReleaseValue(RegularLocation(SourceLoc()),
                               F->getArguments()[AD.Index],
                               Builder.getDefaultAtomicity());
  }
}
Esempio n. 7
0
/// Subtract a constant from a builtin integer value.
static SILValue getSub(SILLocation Loc, SILValue Val, unsigned SubVal,
                       SILBuilder &B) {
  SmallVector<SILValue, 4> Args(1, Val);
  Args.push_back(B.createIntegerLiteral(Loc, Val->getType(), SubVal));
  Args.push_back(B.createIntegerLiteral(
      Loc, SILType::getBuiltinIntegerType(1, B.getASTContext()), -1));

  auto *AI = B.createBuiltinBinaryFunctionWithOverflow(
      Loc, "ssub_with_overflow", Args);
  return B.createTupleExtract(Loc, AI, 0);
}
Esempio n. 8
0
SILValue 
SROAMemoryUseAnalyzer::createAgg(SILBuilder &B, SILLocation Loc,
                                 SILType Ty,
                                 ArrayRef<SILValue> Elements) {
  if (TT)
    return B.createTuple(Loc, Ty, Elements);

  assert(SD && "SD must not be null here since it or TT must be set to call"
         " this method.");
  return B.createStruct(Loc, Ty, Elements);
}
Esempio n. 9
0
/// Carry out the operations required for an indirect conditional cast
/// using a scalar cast operation.
void swift::emitIndirectConditionalCastWithScalar(
    SILBuilder &B, ModuleDecl *M, SILLocation loc,
    CastConsumptionKind consumption, SILValue src, CanType sourceType,
    SILValue dest, CanType targetType, SILBasicBlock *indirectSuccBB,
    SILBasicBlock *indirectFailBB, ProfileCounter TrueCount,
    ProfileCounter FalseCount) {
  assert(canUseScalarCheckedCastInstructions(B.getModule(),
                                             sourceType, targetType));

  // We only need a different failure block if the cast consumption
  // requires us to destroy the source value.
  SILBasicBlock *scalarFailBB;
  if (!shouldDestroyOnFailure(consumption)) {
    scalarFailBB = indirectFailBB;
  } else {
    scalarFailBB = B.splitBlockForFallthrough();
  }

  // We always need a different success block.
  SILBasicBlock *scalarSuccBB = B.splitBlockForFallthrough();

  auto &srcTL = B.getModule().Types.getTypeLowering(src->getType());

  // Always take; this works under an assumption that retaining the
  // result is equivalent to retaining the source.  That means that
  // these casts would not be appropriate for bridging-like conversions.
  SILValue srcValue = srcTL.emitLoadOfCopy(B, loc, src, IsTake);

  SILType targetValueType = dest->getType().getObjectType();
  B.createCheckedCastBranch(loc, /*exact*/ false, srcValue, targetValueType,
                            scalarSuccBB, scalarFailBB, TrueCount, FalseCount);

  // Emit the success block.
  B.setInsertionPoint(scalarSuccBB); {
    auto &targetTL = B.getModule().Types.getTypeLowering(targetValueType);
    SILValue succValue = scalarSuccBB->createPHIArgument(
        targetValueType, ValueOwnershipKind::Owned);
    if (!shouldTakeOnSuccess(consumption))
      targetTL.emitCopyValue(B, loc, succValue);
    targetTL.emitStoreOfCopy(B, loc, succValue, dest, IsInitialization);
    B.createBranch(loc, indirectSuccBB);
  }

  // Emit the failure block.
  if (shouldDestroyOnFailure(consumption)) {
    B.setInsertionPoint(scalarFailBB);
    srcTL.emitDestroyValue(B, loc, srcValue);
    B.createBranch(loc, indirectFailBB);
  }
}
Esempio n. 10
0
NullablePtr<SILInstruction>
Projection::
createAggFromFirstLevelProjections(SILBuilder &B, SILLocation Loc,
                                   SILType BaseType,
                                   llvm::SmallVectorImpl<SILValue> &Values) {
    if (BaseType.getStructOrBoundGenericStruct()) {
        return B.createStruct(Loc, BaseType, Values);
    }

    if (BaseType.is<TupleType>()) {
        return B.createTuple(Loc, BaseType, Values);
    }

    return nullptr;
}
static void addRetainsForConvertedDirectResults(SILBuilder &Builder,
                                                SILLocation Loc,
                                                SILValue ReturnValue,
                                     ArrayRef<ResultDescriptor> DirectResults) {
  for (auto I : indices(DirectResults)) {
    auto &RV = DirectResults[I];
    if (RV.CalleeRetain.empty()) continue;

    // Extract the return value if necessary.
    SILValue SpecificResultValue = ReturnValue;
    if (DirectResults.size() != 1)
      SpecificResultValue = Builder.createTupleExtract(Loc, ReturnValue, I);

    Builder.createRetainValue(Loc, SpecificResultValue);
  }
}
Esempio n. 12
0
/// Given an RValue of aggregate type, compute the values of the elements by
/// emitting a series of tuple_element instructions.
static void getScalarizedElements(SILValue V,
                                  SmallVectorImpl<SILValue> &ElementVals,
                                  SILLocation Loc, SILBuilder &B) {
  TupleType *TT = V->getType().castTo<TupleType>();
  for (auto Index : indices(TT->getElements())) {
    ElementVals.push_back(B.emitTupleExtract(Loc, V, Index));
  }
}
Esempio n. 13
0
/// Given a pointer to a tuple type, compute the addresses of each element and
/// add them to the ElementAddrs vector.
static void
getScalarizedElementAddresses(SILValue Pointer, SILBuilder &B, SILLocation Loc,
                              SmallVectorImpl<SILValue> &ElementAddrs) {
  TupleType *TT = Pointer->getType().castTo<TupleType>();
  for (auto Index : indices(TT->getElements())) {
    ElementAddrs.push_back(B.createTupleElementAddr(Loc, Pointer, Index));
  }
}
Esempio n. 14
0
  /// If necessary insert an overflow for this induction variable.
  /// If we compare for equality we need to make sure that the range does wrap.
  /// We would have trapped either when overflowing or when accessing an array
  /// out of bounds in the original loop.
  void checkOverflow(SILBuilder &Builder) {
    if (IsOverflowCheckInserted || Cmp != BuiltinValueKind::ICMP_EQ)
      return;

    auto Loc = Inc->getLoc();
    auto ResultTy = SILType::getBuiltinIntegerType(1, Builder.getASTContext());
    auto *CmpSGE = Builder.createBuiltinBinaryFunction(
        Loc, "cmp_sge", Start->getType(), ResultTy, {Start, End});
    Builder.createCondFail(Loc, CmpSGE);
    IsOverflowCheckInserted = true;

    // We can now remove the cond fail on the increment the above comparison
    // guarantees that the addition won't overflow.
    auto *CondFail = isOverflowChecked(cast<BuiltinInst>(Inc));
    if (CondFail)
      CondFail->eraseFromParent();
  }
Esempio n. 15
0
SILValue
SROAMemoryUseAnalyzer::createAggProjection(SILBuilder &B, SILLocation Loc,
                                           SILValue Operand,
                                           unsigned EltNo) {
  if (TT)
    return B.createTupleExtract(Loc, Operand, EltNo);

  assert(SD && "SD should not be null since either it or TT must be set at "
         "this point.");

  auto Properties = SD->getStoredProperties();
  unsigned Counter = 0;
  for (auto *D : Properties)
    if (Counter++ == EltNo)
      return B.createStructExtract(Loc, Operand, D);
  llvm_unreachable("Unknown field.");
}
Esempio n. 16
0
// Clone a chain of ConvertFunctionInsts.
SILValue ClosureSpecCloner::cloneCalleeConversion(SILValue calleeValue,
                                                  SILValue NewClosure,
                                                  SILBuilder &Builder) {
  if (calleeValue == CallSiteDesc.getClosure())
    return NewClosure;

  if (auto *CFI = dyn_cast<ConvertFunctionInst>(calleeValue)) {
    calleeValue = cloneCalleeConversion(CFI->getOperand(), NewClosure, Builder);
    return Builder.createConvertFunction(CallSiteDesc.getLoc(), calleeValue,
                                         CFI->getType());
  }

  auto *Cvt = cast<ConvertEscapeToNoEscapeInst>(calleeValue);
  calleeValue = cloneCalleeConversion(Cvt->getOperand(), NewClosure, Builder);
  return Builder.createConvertEscapeToNoEscape(
      CallSiteDesc.getLoc(), calleeValue, Cvt->getType(), false, true);
}
Esempio n. 17
0
void SILInstruction::setDebugScope(SILBuilder &B, const SILDebugScope *DS) {
  if (getDebugScope() && getDebugScope()->InlinedCallSite)
    assert(DS->InlinedCallSite && "throwing away inlined scope info");

  assert(DS->InlinedCallSite || DS->SILFn == getFunction() &&
         "scope of a non-inlined instruction points to different function");

  Location = *B.getOrCreateDebugLocation(getLoc(), DS);
}
Esempio n. 18
0
/// Given an aggregate value and an access path, extract the value indicated by
/// the path.
static SILValue ExtractSubElement(SILValue Val, unsigned SubElementNumber,
                                  SILBuilder &B, SILLocation Loc) {
  SILType ValTy = Val.getType();
  
  // Extract tuple elements.
  if (auto TT = ValTy.getAs<TupleType>()) {
    for (unsigned EltNo : indices(TT.getElementTypes())) {
      // Keep track of what subelement is being referenced.
      SILType EltTy = ValTy.getTupleElementType(EltNo);
      unsigned NumSubElt = getNumSubElements(EltTy, B.getModule());
      if (SubElementNumber < NumSubElt) {
        Val = B.emitTupleExtract(Loc, Val, EltNo, EltTy);
        return ExtractSubElement(Val, SubElementNumber, B, Loc);
      }
      
      SubElementNumber -= NumSubElt;
    }
    
    llvm_unreachable("Didn't find field");
  }
  
  // Extract struct elements.
  if (auto *SD = getFullyReferenceableStruct(ValTy)) {
    for (auto *D : SD->getStoredProperties()) {
      auto fieldType = ValTy.getFieldType(D, B.getModule());
      unsigned NumSubElt = getNumSubElements(fieldType, B.getModule());
      
      if (SubElementNumber < NumSubElt) {
        Val = B.emitStructExtract(Loc, Val, D);
        return ExtractSubElement(Val, SubElementNumber, B, Loc);
      }
      
      SubElementNumber -= NumSubElt;
      
    }
    llvm_unreachable("Didn't find field");
  }
  
  // Otherwise, we're down to a scalar.
  assert(SubElementNumber == 0 && "Miscalculation indexing subelements");
  return Val;
}
Esempio n. 19
0
void swift::
addReleasesForConvertedOwnedParameter(SILBuilder &Builder,
                                      SILLocation Loc,
                                      OperandValueArrayRef Parameters,
                                      ArrayRef<ArgumentDescriptor> &ArgDescs) {
  // If we have any arguments that were consumed but are now guaranteed,
  // insert a release_value.
  for (auto &ArgDesc : ArgDescs) {
    // The argument is dead. Make sure we have a release to balance out
    // the retain for creating the @owned parameter.
    if (ArgDesc.IsEntirelyDead && 
        ArgDesc.Arg->getKnownParameterInfo().getConvention() ==
        ParameterConvention::Direct_Owned) {
       Builder.createReleaseValue(Loc, Parameters[ArgDesc.Index]);
       continue;
    }
    if (ArgDesc.CalleeRelease.empty())
      continue;
    Builder.createReleaseValue(Loc, Parameters[ArgDesc.Index]);
  }
}
Esempio n. 20
0
bool swift::emitSuccessfulIndirectUnconditionalCast(SILBuilder &B, Module *M,
                                                    SILLocation loc,
                                               CastConsumptionKind consumption,
                                                    SILValue src,
                                                    CanType sourceType,
                                                    SILValue dest,
                                                    CanType targetType,
                                                    SILInstruction *existingCast) {
  assert(classifyDynamicCast(M, sourceType, targetType)
           == DynamicCastFeasibility::WillSucceed);

  assert(src->getType().isAddress());
  assert(dest->getType().isAddress());

  // Casts between the same types can be always handled here.
  // Casts from non-existentials into existentials and
  // vice-versa cannot be improved yet.
  // Casts between a value type and a class cannot be optimized.
  // Therefore generate a simple unconditional_checked_cast_aadr.

  if (src->getType() != dest->getType())
  if (src->getType().isAnyExistentialType() !=
      dest->getType().isAnyExistentialType() ||
      !(src->getType().getClassOrBoundGenericClass() &&
       dest->getType().getClassOrBoundGenericClass())) {
    // If there is an existing cast with the same arguments,
    // indicate we cannot improve it.
    if (existingCast) {
      auto *UCCAI = dyn_cast<UnconditionalCheckedCastAddrInst>(existingCast);
      if (UCCAI && UCCAI->getSrc() == src && UCCAI->getDest() == dest &&
          UCCAI->getSourceType() == sourceType &&
          UCCAI->getTargetType() == targetType &&
          UCCAI->getConsumptionKind() == consumption) {
        // Indicate that the existing cast cannot be further improved.
        return false;
      }
    }

    B.createUnconditionalCheckedCastAddr(loc, consumption, src, sourceType,
                                         dest, targetType);
    return true;
  }

  Source source(src, sourceType, consumption);
  Target target(dest, targetType);
  Source result = CastEmitter(B, M, loc).emitTopLevel(source, target);
  assert(result.isAddress());
  assert(result.Value == dest);
  assert(result.Consumption == CastConsumptionKind::TakeAlways);
  (void) result;
  return true;
}
Esempio n. 21
0
void swift::
addReleasesForConvertedOwnedParameter(SILBuilder &Builder,
                                      SILLocation Loc,
                                      ArrayRef<SILArgument*> Parameters,
                                      ArrayRef<ArgumentDescriptor> &ArgDescs) {
  // If we have any arguments that were consumed but are now guaranteed,
  // insert a release_value.
  for (auto &ArgDesc : ArgDescs) {
    if (ArgDesc.CalleeRelease.empty())
      continue;
    Builder.createReleaseValue(Loc, Parameters[ArgDesc.Index]);
  }
}
Esempio n. 22
0
void
FunctionSignatureTransform::
OwnedToGuaranteedAddResultRelease(ResultDescriptor &RD, SILBuilder &Builder,
                                  SILFunction *F) {
 // If we have any result that were consumed but are now guaranteed,
  // insert a release_value.
  if (!RD.OwnedToGuaranteed) {
    return;
  }

  SILInstruction *Call = findOnlyApply(F);
  if (isa<ApplyInst>(Call)) {
    Builder.setInsertionPoint(&*std::next(SILBasicBlock::iterator(Call)));
    Builder.createRetainValue(RegularLocation(SourceLoc()), Call,
                              Atomicity::Atomic);
  } else {
    SILBasicBlock *NormalBB = dyn_cast<TryApplyInst>(Call)->getNormalBB();
    Builder.setInsertionPoint(&*NormalBB->begin());
    Builder.createRetainValue(RegularLocation(SourceLoc()),
                              NormalBB->getArgument(0), Atomicity::Atomic);
  }
}
Esempio n. 23
0
NullablePtr<SILInstruction>
Projection::
createValueProjection(SILBuilder &B, SILLocation Loc, SILValue Base) const {
    // Grab Base's type.
    SILType BaseTy = Base.getType();

    // If BaseTy is not an object type, bail.
    if (!BaseTy.isObject())
        return nullptr;

    // If this projection is associated with an address type, convert its type to
    // an object type.
    //
    // We explicitly do not convert Type to be an object if it is a local storage
    // type since we want it to fail.
    SILType Ty = Type.isAddress()? Type.getObjectType() : Type;

    if (!Ty.isObject())
        return nullptr;

    // Ok, we now know that the type of Base and the type represented by the base
    // of this projection match and that this projection can be represented as
    // value. Create the instruction if we can. Otherwise, return nullptr.
    switch (getKind()) {
    case ProjectionKind::Struct:
        return B.createStructExtract(Loc, Base, cast<VarDecl>(getDecl()));
    case ProjectionKind::Tuple:
        return B.createTupleExtract(Loc, Base, getIndex());
    case ProjectionKind::Index:
        return nullptr;
    case ProjectionKind::Enum:
        return B.createUncheckedEnumData(Loc, Base,
                                         cast<EnumElementDecl>(getDecl()));
    case ProjectionKind::Class:
        return nullptr;
    }
}
Esempio n. 24
0
// Clone a chain of ConvertFunctionInsts.
SILValue ClosureSpecCloner::cloneCalleeConversion(
    SILValue calleeValue, SILValue NewClosure, SILBuilder &Builder,
    SmallVectorImpl<PartialApplyInst *> &NeedsRelease) {
  if (calleeValue == CallSiteDesc.getClosure())
    return NewClosure;

  if (auto *CFI = dyn_cast<ConvertFunctionInst>(calleeValue)) {
    calleeValue = cloneCalleeConversion(CFI->getOperand(), NewClosure, Builder,
                                        NeedsRelease);
    return Builder.createConvertFunction(CallSiteDesc.getLoc(), calleeValue,
                                         CFI->getType(),
                                         CFI->withoutActuallyEscaping());
  }

  if (auto *PAI = dyn_cast<PartialApplyInst>(calleeValue)) {
    assert(isPartialApplyOfReabstractionThunk(PAI) && isSupportedClosure(PAI) &&
           PAI->getArgument(0)
               ->getType()
               .getAs<SILFunctionType>()
               ->isTrivialNoEscape());
    calleeValue = cloneCalleeConversion(PAI->getArgument(0), NewClosure,
                                        Builder, NeedsRelease);
    auto FunRef = Builder.createFunctionRef(CallSiteDesc.getLoc(),
                                            PAI->getReferencedFunction());
    auto NewPA = Builder.createPartialApply(
        CallSiteDesc.getLoc(), FunRef, {}, {calleeValue},
        PAI->getType().getAs<SILFunctionType>()->getCalleeConvention());
    NeedsRelease.push_back(NewPA);
    return NewPA;
  }

  auto *Cvt = cast<ConvertEscapeToNoEscapeInst>(calleeValue);
  calleeValue = cloneCalleeConversion(Cvt->getOperand(), NewClosure, Builder,
                                      NeedsRelease);
  return Builder.createConvertEscapeToNoEscape(
      CallSiteDesc.getLoc(), calleeValue, Cvt->getType(), false, true);
}
Esempio n. 25
0
/// Given an index_raw_pointer Ptr, size_of(Metatype) * Distance create an
/// address_to_pointer (index_addr ptr, Distance : $*Metatype) : $RawPointer
/// instruction.
static SILValue createIndexAddrFrom(IndexRawPointerInst *I,
                                    MetatypeInst *Metatype,
                                    BuiltinInst *TruncOrBitCast,
                                    SILValue Ptr, SILValue Distance,
                                    SILType RawPointerTy,
                                    SILBuilder &Builder) {
  Builder.setCurrentDebugScope(I->getDebugScope());
  SILType InstanceType =
    Metatype->getType().getMetatypeInstanceType(I->getModule());

  // index_raw_pointer's address type is currently always strict.
  auto *NewPTAI = Builder.createPointerToAddress(
    I->getLoc(), Ptr, InstanceType.getAddressType(),
    /*isStrict*/ true, /*isInvariant*/ false);

  auto *DistanceAsWord =
      Builder.createBuiltin(I->getLoc(), TruncOrBitCast->getName(),
                             TruncOrBitCast->getType(), {}, Distance);

  auto *NewIAI = Builder.createIndexAddr(I->getLoc(), NewPTAI, DistanceAsWord);
  auto *NewATPI =
    Builder.createAddressToPointer(I->getLoc(), NewIAI, RawPointerTy);
  return NewATPI;
}
Esempio n. 26
0
NullablePtr<SILInstruction>
Projection::
createAddrProjection(SILBuilder &B, SILLocation Loc, SILValue Base) const {
    // Grab Base's type.
    SILType BaseTy = Base.getType();

    // If BaseTy is not an address type, bail.
    if (!BaseTy.isAddress())
        return nullptr;

    // If this projection is associated with an object type, convert its type to
    // an address type.
    //
    // *NOTE* We purposely do not handle local storage types here since we want to
    // always fail in such a case. That is handled by checking that Ty is an
    // address.
    SILType Ty = Type.isObject()? Type.getAddressType() : Type;

    if (!Ty.isAddress())
        return nullptr;

    // Ok, we now know that the type of Base and the type represented by the base
    // of this projection match and that this projection can be represented as
    // value. Create the instruction if we can. Otherwise, return nullptr.
    switch (getKind()) {
    case ProjectionKind::Struct:
        return B.createStructElementAddr(Loc, Base, cast<VarDecl>(getDecl()));
    case ProjectionKind::Tuple:
        return B.createTupleElementAddr(Loc, Base, getIndex());
    case ProjectionKind::Index: {
        auto Ty = SILType::getBuiltinIntegerType(32, B.getASTContext());
        auto *IntLiteral = B.createIntegerLiteral(Loc, Ty, getIndex());
        return B.createIndexAddr(Loc, Base, IntLiteral);
    }
    case ProjectionKind::Enum:
        return B.createUncheckedTakeEnumDataAddr(Loc, Base,
                cast<EnumElementDecl>(getDecl()));
    case ProjectionKind::Class:
        return B.createRefElementAddr(Loc, Base, cast<VarDecl>(getDecl()));
    }
}
Esempio n. 27
0
unsigned ArgumentDescriptor::updateOptimizedBBArgs(SILBuilder &Builder,
                                                   SILBasicBlock *BB,
                                                   unsigned ArgOffset) {
  // If this argument is completely dead, delete this argument and return
  // ArgOffset.
  if (IsDead) {
    // If we have a callee release and we are dead, set the callee release's
    // operand to undef. We do not need it to have the argument anymore, but we
    // do need the instruction to be non-null.
    //
    // TODO: This should not be necessary.
    if (CalleeRelease) {
      SILType CalleeReleaseTy = CalleeRelease->getOperand(0).getType();
      CalleeRelease->setOperand(
          0, SILUndef::get(CalleeReleaseTy, Builder.getModule()));

      // TODO: Currently we cannot mark arguments as dead if they are released
      // in a throw block. But as soon as we can do this, we have to handle
      // CalleeReleaseInThrowBlock as well.
      assert(!CalleeReleaseInThrowBlock &&
             "released arg in throw block cannot be dead");
    }

    // We should be able to recursively delete all of the remaining
    // instructions.
    SILArgument *Arg = BB->getBBArg(ArgOffset);
    eraseUsesOfValue(Arg);
    BB->eraseBBArg(ArgOffset);
    return ArgOffset;
  }

  // If this argument is not dead and we did not perform SROA, increment the
  // offset and return.
  if (!shouldExplode()) {
    return ArgOffset + 1;
  }

  // Create values for the leaf types.
  llvm::SmallVector<SILValue, 8> LeafValues;

  // Create a reference to the old arg offset and increment arg offset so we can
  // create the new arguments.
  unsigned OldArgOffset = ArgOffset++;

  // We do this in the same order as leaf types since ProjTree expects that the
  // order of leaf values matches the order of leaf types.
  {
    llvm::SmallVector<SILType, 8> LeafTypes;
    ProjTree.getLeafTypes(LeafTypes);
    for (auto Ty : LeafTypes) {
      LeafValues.push_back(BB->insertBBArg(
          ArgOffset++, Ty, BB->getBBArg(OldArgOffset)->getDecl()));
    }
  }

  // Then go through the projection tree constructing aggregates and replacing
  // uses.
  //
  // TODO: What is the right location to use here?
  ProjTree.replaceValueUsesWithLeafUses(Builder, BB->getParent()->getLocation(),
                                        LeafValues);

  // Replace all uses of the original arg with undef so it does not have any
  // uses.
  SILValue OrigArg = SILValue(BB->getBBArg(OldArgOffset));
  OrigArg.replaceAllUsesWith(SILUndef::get(OrigArg.getType(), BB->getModule()));

  // Now erase the old argument since it does not have any uses. We also
  // decrement ArgOffset since we have one less argument now.
  BB->eraseBBArg(OldArgOffset);
  --ArgOffset;

  return ArgOffset;
}
Esempio n. 28
0
void BridgedReturn::outline(SILFunction *Fun, ApplyInst *NewOutlinedCall) {
// Outline the bridged return result blocks.
//   switch_enum %20 : $Optional<NSString>, case #O.some: bb1, case #O.none: bb2
//
// bb1(%23 : $NSString):
//   %24 = function_ref @$SSS10FoundationE36_unconditionallyBridgeFromObjectiveC
//   %25 = enum $Optional<NSString>, #Optional.some!enumelt.1, %23 : $NSString
//   %26 = metatype $@thin String.Type
//   %27 = apply %24(%25, %26)
//   %28 = enum $Optional<String>, #Optional.some!enumelt.1, %27 : $String
//   br bb3(%28 : $Optional<String>)
//
// bb2:
//   %30 = enum $Optional<String>, #Optional.none!enumelt
//   br bb3(%30 : $Optional<String>)
//
// bb3(%32 : $Optional<String>):

  auto *StartBB = switchInfo.SwitchEnum->getParent();
  auto *OutlinedEntryBB = StartBB->split(SILBasicBlock::iterator(switchInfo.SwitchEnum));
  auto *OldMergeBB = switchInfo.Br->getDestBB();
  auto *NewTailBB = OldMergeBB->split(OldMergeBB->begin());
	auto Loc = switchInfo.SwitchEnum->getLoc();

  {
    SILBuilder Builder(StartBB);
    Builder.createBranch(Loc, NewTailBB);
    OldMergeBB->getArgument(0)->replaceAllUsesWith(NewOutlinedCall);
  }

  // Outlined function already existed. Just delete instructions and wire up
  // blocks.
  if (!Fun) {
    OutlinedEntryBB->eraseInstructions();
    OutlinedEntryBB->eraseFromParent();
    switchInfo.NoneBB->eraseInstructions();
    switchInfo.NoneBB->eraseFromParent();
    switchInfo.SomeBB->eraseInstructions();
    switchInfo.SomeBB->eraseFromParent();
    OldMergeBB->eraseInstructions();
    OldMergeBB->eraseFromParent();
    return;
  }

  // Move the blocks into the new function.
  assert(Fun->begin() != Fun->end() &&
         "The entry block must already have been created");
  SILBasicBlock *EntryBB = &*Fun->begin();
  auto &FromBlockList = OutlinedEntryBB->getParent()->getBlocks();
  Fun->getBlocks().splice(Fun->begin(), FromBlockList, OldMergeBB);
  OldMergeBB->moveAfter(EntryBB);
	auto InsertPt = SILFunction::iterator(OldMergeBB);
  Fun->getBlocks().splice(InsertPt, FromBlockList, OutlinedEntryBB);
  Fun->getBlocks().splice(InsertPt, FromBlockList, switchInfo.NoneBB);
  Fun->getBlocks().splice(InsertPt, FromBlockList, switchInfo.SomeBB);

	SILBuilder Builder (EntryBB);
  Builder.createBranch(Loc, OutlinedEntryBB);

  Builder.setInsertionPoint(OldMergeBB);
  Builder.createReturn(Loc, OldMergeBB->getArgument(0));
}
unsigned ArgumentDescriptor::updateOptimizedBBArgs(SILBuilder &Builder,
                                                   SILBasicBlock *BB,
                                                   unsigned ArgOffset) {
  // If this argument is completely dead, delete this argument and return
  // ArgOffset.
  if (IsDead) {
    // If we have a callee release and we are dead, set the callee release's
    // operand to undef. We do not need it to have the argument anymore, but we
    // do need the instruction to be non-null.
    //
    // TODO: This should not be necessary.
    for (auto &X : CalleeRelease) {
      SILType CalleeReleaseTy = X->getOperand(0)->getType();
      X->setOperand(
          0, SILUndef::get(CalleeReleaseTy, Builder.getModule()));
    }

    // We should be able to recursively delete all of the remaining
    // instructions.
    SILArgument *Arg = BB->getBBArg(ArgOffset);
    eraseUsesOfValue(Arg);
    BB->eraseBBArg(ArgOffset);
    return ArgOffset;
  }

  // If this argument is not dead and we did not perform SROA, increment the
  // offset and return.
  if (!shouldExplode()) {
    return ArgOffset + 1;
  }

  // Create values for the leaf types.
  llvm::SmallVector<SILValue, 8> LeafValues;

  // Create a reference to the old arg offset and increment arg offset so we can
  // create the new arguments.
  unsigned OldArgOffset = ArgOffset++;

  // We do this in the same order as leaf types since ProjTree expects that the
  // order of leaf values matches the order of leaf types.
  {
    llvm::SmallVector<SILType, 8> LeafTypes;
    ProjTree.getLeafTypes(LeafTypes);
    for (auto Ty : LeafTypes) {
      LeafValues.push_back(BB->insertBBArg(
          ArgOffset++, Ty, BB->getBBArg(OldArgOffset)->getDecl()));
    }
  }

  // Then go through the projection tree constructing aggregates and replacing
  // uses.
  //
  // TODO: What is the right location to use here?
  ProjTree.replaceValueUsesWithLeafUses(Builder, BB->getParent()->getLocation(),
                                        LeafValues);

  // We ignored debugvalue uses when we constructed the new arguments, in order
  // to preserve as much information as possible, we construct a new value for
  // OrigArg from the leaf values and use that in place of the OrigArg.
  SILValue NewOrigArgValue = ProjTree.computeExplodedArgumentValue(Builder,
                                           BB->getParent()->getLocation(),
                                           LeafValues);

  // Replace all uses of the original arg with the new value.
  SILArgument *OrigArg = BB->getBBArg(OldArgOffset);
  OrigArg->replaceAllUsesWith(NewOrigArgValue);

  // Now erase the old argument since it does not have any uses. We also
  // decrement ArgOffset since we have one less argument now.
  BB->eraseBBArg(OldArgOffset);
  --ArgOffset;

  return ArgOffset;
}