bool SILDeserializer::readSILInstruction()

in lib/Serialization/DeserializeSIL.cpp [1082:2896]


bool SILDeserializer::readSILInstruction(SILFunction *Fn,
                                         SILBuilder &Builder,
                                         unsigned RecordKind,
                                         SmallVectorImpl<uint64_t> &scratch) {
  if (Fn)
    Builder.setCurrentDebugScope(Fn->getDebugScope());
  unsigned RawOpCode = 0, TyCategory = 0, TyCategory2 = 0, TyCategory3 = 0,
           Attr = 0, Attr2 = 0, Attr3 = 0, Attr4 = 0, NumSubs = 0,
           NumConformances = 0;
  ValueID ValID, ValID2, ValID3;
  TypeID TyID, TyID2, TyID3;
  TypeID ConcreteTyID;
  SourceLoc SLoc;
  ApplyOptions ApplyOpts;
  ArrayRef<uint64_t> ListOfValues;
  SILLocation Loc = RegularLocation(SLoc);
  ValueOwnershipKind forwardingOwnership(OwnershipKind::Any);
  auto decodeValueOwnership = [](unsigned field){
    // Invalid/Any ownership is never encoded.
    return ValueOwnershipKind(field+1);
  };

  switch (RecordKind) {
  default:
    llvm_unreachable("Record kind for a SIL instruction is not supported.");
  case SIL_ONE_VALUE_ONE_OPERAND:
    SILOneValueOneOperandLayout::readRecord(scratch, RawOpCode, Attr,
                                            ValID, TyID, TyCategory,
                                            ValID2);
    break;
  case SIL_ONE_TYPE:
    SILOneTypeLayout::readRecord(scratch, RawOpCode, Attr, TyID, TyCategory);
    break;
  case SIL_ONE_OPERAND:
    SILOneOperandLayout::readRecord(scratch, RawOpCode, Attr,
                                    TyID, TyCategory, ValID);
    break;
  case SIL_ONE_OPERAND_EXTRA_ATTR:
    SILOneOperandExtraAttributeLayout::readRecord(scratch, RawOpCode, Attr,
                                                  TyID, TyCategory, ValID);
    break;
  case SIL_ONE_TYPE_ONE_OPERAND:
    SILOneTypeOneOperandLayout::readRecord(scratch, RawOpCode, Attr,
                                           TyID, TyCategory,
                                           TyID2, TyCategory2,
                                           ValID);
    break;
  case SIL_ONE_TYPE_ONE_OPERAND_EXTRA_ATTR:
    SILOneTypeOneOperandExtraAttributeLayout::readRecord(scratch, RawOpCode,
                                                         Attr, TyID, TyCategory,
                                                         TyID2, TyCategory2,
                                                         ValID);
    break;
  case SIL_INIT_EXISTENTIAL:
    SILInitExistentialLayout::readRecord(scratch, RawOpCode,
                                         TyID, TyCategory,
                                         TyID2, TyCategory2,
                                         ValID,
                                         ConcreteTyID,
                                         NumConformances);
    break;
  case SIL_ONE_TYPE_VALUES:
    SILOneTypeValuesLayout::readRecord(scratch, RawOpCode, TyID, TyCategory,
                                       ListOfValues);
    break;
  case SIL_ONE_TYPE_OWNERSHIP_VALUES: {
    unsigned ownershipField;
    SILOneTypeOwnershipValuesLayout::readRecord(scratch, RawOpCode,
                                                ownershipField, TyID,
                                                TyCategory, ListOfValues);
    forwardingOwnership = decodeValueOwnership(ownershipField);
    break;
  }
  case SIL_TWO_OPERANDS:
    SILTwoOperandsLayout::readRecord(scratch, RawOpCode, Attr,
                                     TyID, TyCategory, ValID,
                                     TyID2, TyCategory2, ValID2);
    break;
  case SIL_TWO_OPERANDS_EXTRA_ATTR:
    SILTwoOperandsExtraAttributeLayout::readRecord(scratch, RawOpCode, Attr,
                                                   TyID, TyCategory, ValID,
                                                   TyID2, TyCategory2, ValID2);
    break;
  case SIL_TAIL_ADDR:
    SILTailAddrLayout::readRecord(scratch, RawOpCode,
                                  TyID, ValID,
                                  TyID2, ValID2,
                                  TyID3);
    break;
  case SIL_INST_APPLY: {
    unsigned Kind, RawApplyOpts;
    SILInstApplyLayout::readRecord(scratch, Kind, RawApplyOpts, NumSubs, TyID, TyID2,
                                   ValID, ListOfValues);
    switch (Kind) {
    case SIL_APPLY:
      RawOpCode = (unsigned)SILInstructionKind::ApplyInst;
      break;
    case SIL_PARTIAL_APPLY:
      RawOpCode = (unsigned)SILInstructionKind::PartialApplyInst;
      break;
    case SIL_BUILTIN:
      RawOpCode = (unsigned)SILInstructionKind::BuiltinInst;
      break;
    case SIL_TRY_APPLY:
      RawOpCode = (unsigned)SILInstructionKind::TryApplyInst;
      break;
    case SIL_BEGIN_APPLY:
      RawOpCode = (unsigned)SILInstructionKind::BeginApplyInst;
      break;
        
    default:
      llvm_unreachable("unexpected apply inst kind");
    }

    ApplyOpts = ApplyOptions(ApplyFlags(RawApplyOpts));
    break;
  }
  case SIL_INST_NO_OPERAND:
    SILInstNoOperandLayout::readRecord(scratch, RawOpCode);
    break;
  case SIL_INST_WITNESS_METHOD:
    SILInstWitnessMethodLayout::readRecord(
        scratch, TyID, TyCategory, Attr, TyID2, TyCategory2, TyID3,
        TyCategory3, ValID3, ListOfValues);
    RawOpCode = (unsigned)SILInstructionKind::WitnessMethodInst;
    break;
  case SIL_INST_DIFFERENTIABLE_FUNCTION:
    SILInstDifferentiableFunctionLayout::readRecord(
        scratch, /*numParams*/ Attr, /*numResults*/ Attr2,
        /*numDiffParams*/ Attr3,
        /*hasDerivativeFunctions*/ Attr4, ListOfValues);
    RawOpCode = (unsigned)SILInstructionKind::DifferentiableFunctionInst;
    break;
  case SIL_INST_LINEAR_FUNCTION:
    SILInstLinearFunctionLayout::readRecord(scratch, /*numDiffParams*/ Attr,
                                            /*hasTransposeFunction*/ Attr2,
                                            ListOfValues);
    RawOpCode = (unsigned)SILInstructionKind::LinearFunctionInst;
    break;
  case SIL_INST_DIFFERENTIABLE_FUNCTION_EXTRACT:
    SILInstDifferentiableFunctionExtractLayout::readRecord(
        scratch, TyID, TyCategory, ValID, /*extractee*/ Attr,
        /*hasExplicitExtracteeType*/ Attr2, /*explicitExtracteeType*/ TyID2);
    RawOpCode = (unsigned)SILInstructionKind::DifferentiableFunctionExtractInst;
    break;
  case SIL_INST_LINEAR_FUNCTION_EXTRACT:
    SILInstLinearFunctionExtractLayout::readRecord(
        scratch, TyID, TyCategory, ValID, /*extractee*/ Attr);
    RawOpCode = (unsigned)SILInstructionKind::LinearFunctionExtractInst;
    break;
  }

  // FIXME: validate
  SILInstructionKind OpCode = (SILInstructionKind) RawOpCode;

  SILInstruction *ResultInst;
  switch (OpCode) {
  case SILInstructionKind::DebugValueInst:
    llvm_unreachable("not supported");

  case SILInstructionKind::AllocBoxInst:
    assert(RecordKind == SIL_ONE_TYPE && "Layout should be OneType.");
    ResultInst = Builder.createAllocBox(
        Loc, cast<SILBoxType>(MF->getType(TyID)->getCanonicalType()), None,
        /*bool hasDynamicLifetime*/ Attr != 0);
    break;
  case SILInstructionKind::AllocStackInst: {
    assert(RecordKind == SIL_ONE_TYPE && "Layout should be OneType.");
    bool hasDynamicLifetime = Attr & 0x1;
    bool isLexical = (Attr >> 1) & 0x1;
    ResultInst = Builder.createAllocStack(
        Loc, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn),
        None, hasDynamicLifetime, isLexical);
    break;
  }
  case SILInstructionKind::MetatypeInst:
    assert(RecordKind == SIL_ONE_TYPE && "Layout should be OneType.");
    ResultInst = Builder.createMetatype(
        Loc, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn));
    break;
      
  case SILInstructionKind::GetAsyncContinuationInst:
    assert(RecordKind == SIL_ONE_TYPE && "Layout should be OneType.");
    ResultInst = Builder.createGetAsyncContinuation(
        Loc, MF->getType(TyID)->getCanonicalType(),
        /*throws*/ Attr != 0);
    break;
  
  case SILInstructionKind::GetAsyncContinuationAddrInst:
    assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND
           && "Layout should be OneTypeOneOperand.");
    ResultInst = Builder.createGetAsyncContinuationAddr(Loc,
      getLocalValue(ValID, getSILType(MF->getType(TyID2),
                                      (SILValueCategory)TyCategory2, Fn)),
      MF->getType(TyID)->getCanonicalType(),
      /*throws*/ Attr != 0);
    break;

#define ONETYPE_ONEOPERAND_INST(ID)                                            \
  case SILInstructionKind::ID##Inst:                                           \
    assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND &&                           \
           "Layout should be OneTypeOneOperand.");                             \
    ResultInst = Builder.create##ID(                                           \
        Loc, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn),  \
        getLocalValue(ValID, getSILType(MF->getType(TyID2),                    \
                                        (SILValueCategory)TyCategory2, Fn)));  \
    break;
    ONETYPE_ONEOPERAND_INST(ValueMetatype)
    ONETYPE_ONEOPERAND_INST(ExistentialMetatype)
    ONETYPE_ONEOPERAND_INST(ProjectExistentialBox)
#undef ONETYPE_ONEOPERAND_INST
  case SILInstructionKind::DeallocBoxInst:
    assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND &&
           "Layout should be OneTypeOneOperand.");
    ResultInst = Builder.createDeallocBox(
        Loc,
        getLocalValue(ValID, getSILType(MF->getType(TyID2),
                                        (SILValueCategory)TyCategory2, Fn)));
    break;
  case SILInstructionKind::OpenExistentialAddrInst:
    assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND &&
           "Layout should be OneTypeOneOperand.");
    ResultInst = Builder.createOpenExistentialAddr(
        Loc,
        getLocalValue(ValID, getSILType(MF->getType(TyID2),
                                        (SILValueCategory)TyCategory2, Fn)),
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn),
        Attr == 0 ? OpenedExistentialAccess::Immutable
                  : OpenedExistentialAccess::Mutable);
    break;

#define ONEOPERAND_ONETYPE_INST(ID)                                            \
  case SILInstructionKind::ID##Inst:                                           \
    assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND &&                           \
           "Layout should be OneTypeOneOperand.");                             \
    ResultInst = Builder.create##ID(                                           \
        Loc,                                                                   \
        getLocalValue(ValID, getSILType(MF->getType(TyID2),                    \
                                        (SILValueCategory)TyCategory2, Fn)),   \
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn));      \
    break;
    ONEOPERAND_ONETYPE_INST(OpenExistentialRef)
    ONEOPERAND_ONETYPE_INST(OpenExistentialMetatype)
    ONEOPERAND_ONETYPE_INST(OpenExistentialBox)
    ONEOPERAND_ONETYPE_INST(OpenExistentialValue)
    ONEOPERAND_ONETYPE_INST(OpenExistentialBoxValue)
    // Conversion instructions.
#define LOADABLE_REF_STORAGE(Name, ...) \
  ONEOPERAND_ONETYPE_INST(RefTo##Name) \
  ONEOPERAND_ONETYPE_INST(Name##ToRef)
#include "swift/AST/ReferenceStorage.def"
  ONEOPERAND_ONETYPE_INST(UncheckedRefCast)
  ONEOPERAND_ONETYPE_INST(UncheckedAddrCast)
  ONEOPERAND_ONETYPE_INST(UncheckedTrivialBitCast)
  ONEOPERAND_ONETYPE_INST(UncheckedBitwiseCast)
  ONEOPERAND_ONETYPE_INST(UncheckedValueCast)
  ONEOPERAND_ONETYPE_INST(BridgeObjectToRef)
  ONEOPERAND_ONETYPE_INST(BridgeObjectToWord)
  ONEOPERAND_ONETYPE_INST(Upcast)
  ONEOPERAND_ONETYPE_INST(AddressToPointer)
  ONEOPERAND_ONETYPE_INST(RefToRawPointer)
  ONEOPERAND_ONETYPE_INST(RawPointerToRef)
  ONEOPERAND_ONETYPE_INST(ThinToThickFunction)
  ONEOPERAND_ONETYPE_INST(ThickToObjCMetatype)
  ONEOPERAND_ONETYPE_INST(ObjCToThickMetatype)
  ONEOPERAND_ONETYPE_INST(ObjCMetatypeToObject)
  ONEOPERAND_ONETYPE_INST(ObjCExistentialMetatypeToObject)
  ONEOPERAND_ONETYPE_INST(ThinFunctionToPointer)
  ONEOPERAND_ONETYPE_INST(PointerToThinFunction)
  ONEOPERAND_ONETYPE_INST(ProjectBlockStorage)
#undef ONEOPERAND_ONETYPE_INST

  case SILInstructionKind::ProjectBoxInst: {
    assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND &&
           "Layout should be OneTypeOneOperand.");
    ResultInst = Builder.createProjectBox(
        Loc,
        getLocalValue(ValID, getSILType(MF->getType(TyID2),
                                        (SILValueCategory)TyCategory2, Fn)),
        TyID);
    break;
  }
  case  SILInstructionKind::ConvertEscapeToNoEscapeInst: {
    assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND &&
           "Layout should be OneTypeOneOperand.");
    bool isLifetimeGuaranteed = Attr & 0x01;
    ResultInst = Builder.createConvertEscapeToNoEscape(
        Loc,
        getLocalValue(ValID, getSILType(MF->getType(TyID2),
                                        (SILValueCategory)TyCategory2, Fn)),
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn),
        isLifetimeGuaranteed);
    break;
  }
  case SILInstructionKind::ConvertFunctionInst: {
    assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND
           && "Layout should be OneTypeOneOperand.");
    bool withoutActuallyEscaping = Attr & 0x01;
    ResultInst = Builder.createConvertFunction(
        Loc,
        getLocalValue(ValID, getSILType(MF->getType(TyID2),
                                        (SILValueCategory)TyCategory2, Fn)),
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn),
        withoutActuallyEscaping);
    break;
  }
  case SILInstructionKind::PointerToAddressInst: {
    assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND_EXTRA_ATTR &&
           "Layout should be OneTypeOneOperand.");
    auto alignment = llvm::decodeMaybeAlign(Attr & 0xFF);
    bool isStrict = Attr & 0x100;
    bool isInvariant = Attr & 0x200;
    ResultInst = Builder.createPointerToAddress(
        Loc,
        getLocalValue(ValID, getSILType(MF->getType(TyID2),
                                        (SILValueCategory)TyCategory2, Fn)),
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn),
        isStrict, isInvariant, alignment);
    break;
  }
  case SILInstructionKind::DeallocExistentialBoxInst: {
    assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND &&
           "Layout should be OneTypeOneOperand.");
    ResultInst = Builder.createDeallocExistentialBox(
        Loc, MF->getType(TyID)->getCanonicalType(),
        getLocalValue(ValID, getSILType(MF->getType(TyID2),
                                        (SILValueCategory)TyCategory2, Fn)));
    break;

  }
  
  case SILInstructionKind::RefToBridgeObjectInst: {
    auto RefTy =
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn);
    auto Ref = getLocalValue(ValID, RefTy);
    auto BitsTy =
        getSILType(MF->getType(TyID2), (SILValueCategory)TyCategory2, Fn);
    auto Bits = getLocalValue(ValID2, BitsTy);

    ResultInst = Builder.createRefToBridgeObject(Loc, Ref, Bits);
    break;
  }

  case SILInstructionKind::ObjCProtocolInst: {
    auto Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn);
    auto Proto = MF->getDecl(ValID);
    ResultInst = Builder.createObjCProtocol(Loc, cast<ProtocolDecl>(Proto), Ty);
    break;
  }

  case SILInstructionKind::InitExistentialAddrInst:
  case SILInstructionKind::InitExistentialValueInst:
  case SILInstructionKind::InitExistentialMetatypeInst:
  case SILInstructionKind::InitExistentialRefInst:
  case SILInstructionKind::AllocExistentialBoxInst: {

    auto Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn);
    auto Ty2 = MF->getType(TyID2);
    CanType ConcreteTy;
    if (OpCode != SILInstructionKind::InitExistentialMetatypeInst)
      ConcreteTy = MF->getType(ConcreteTyID)->getCanonicalType();
    SILValue operand;
    if (OpCode != SILInstructionKind::AllocExistentialBoxInst)
      operand = getLocalValue(
          ValID, getSILType(Ty2, (SILValueCategory)TyCategory2, Fn));

    SmallVector<ProtocolConformanceRef, 2> conformances;
    while (NumConformances--) {
      auto conformance = MF->readConformance(SILCursor);
      conformances.push_back(conformance);
    }

    auto ctxConformances = MF->getContext().AllocateCopy(conformances);

    switch (OpCode) {
    default: llvm_unreachable("Out of sync with parent switch");
    case SILInstructionKind::InitExistentialAddrInst:
      ResultInst = Builder.createInitExistentialAddr(Loc, operand, ConcreteTy,
                                                     Ty, ctxConformances);
      break;
    case SILInstructionKind::InitExistentialValueInst:
      ResultInst = Builder.createInitExistentialValue(Loc, Ty, ConcreteTy,
                                                      operand, ctxConformances);
      break;
    case SILInstructionKind::InitExistentialMetatypeInst:
      ResultInst = Builder.createInitExistentialMetatype(Loc, operand, Ty,
                                                         ctxConformances);
      break;
    case SILInstructionKind::InitExistentialRefInst:
      ResultInst = Builder.createInitExistentialRef(Loc, Ty, ConcreteTy,
                                                    operand, ctxConformances);
      break;
    case SILInstructionKind::AllocExistentialBoxInst:
      ResultInst = Builder.createAllocExistentialBox(Loc, Ty, ConcreteTy,
                                                     ctxConformances);
      break;
    }
    break;
  }
  case SILInstructionKind::AllocRefInst:
  case SILInstructionKind::AllocRefDynamicInst: {
    assert(RecordKind == SIL_ONE_TYPE_VALUES &&
           "Layout should be OneTypeValues.");
    unsigned NumVals = ListOfValues.size();
    assert(NumVals >= 1 && "Not enough values");
    unsigned Flags = ListOfValues[0];
    bool isObjC = (bool)(Flags & 1);
    bool canAllocOnStack = (bool)((Flags >> 1) & 1);
    SILType ClassTy =
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn);
    SmallVector<SILValue, 4> Counts;
    SmallVector<SILType, 4> TailTypes;
    unsigned i = 1;
    for (; i + 2 < NumVals; i += 3) {
      SILType TailType = getSILType(MF->getType(ListOfValues[i]),
                                    SILValueCategory::Object, Fn);
      TailTypes.push_back(TailType);
      SILType CountType = getSILType(MF->getType(ListOfValues[i + 2]),
                                     SILValueCategory::Object, Fn);
      SILValue CountVal = getLocalValue(ListOfValues[i+1], CountType);
      Counts.push_back(CountVal);
    }
    if (OpCode == SILInstructionKind::AllocRefDynamicInst) {
      assert(i + 2 == NumVals);
      assert(!canAllocOnStack);
      SILType MetadataType = getSILType(MF->getType(ListOfValues[i+1]),
                                        SILValueCategory::Object, Fn);
      SILValue MetadataOp = getLocalValue(ListOfValues[i], MetadataType);
      ResultInst = Builder.createAllocRefDynamic(Loc, MetadataOp, ClassTy,
                                                 isObjC, TailTypes, Counts);
    } else {
      assert(i == NumVals);
      ResultInst = Builder.createAllocRef(Loc, ClassTy, isObjC, canAllocOnStack,
                                          TailTypes, Counts);
    }
    break;
  }
  case SILInstructionKind::ApplyInst:
  case SILInstructionKind::BeginApplyInst: {
    // Format: attributes such as transparent, the callee's type, a value for
    // the callee and a list of values for the arguments. Each value in the list
    // is represented with 2 IDs: ValueID and ValueResultNumber.
    auto Ty = MF->getType(TyID);
    auto Ty2 = MF->getType(TyID2);
    SILType FnTy = getSILType(Ty, SILValueCategory::Object, Fn);
    SILType SubstFnTy = getSILType(Ty2, SILValueCategory::Object, Fn);
    SILFunctionConventions substConventions(SubstFnTy.castTo<SILFunctionType>(),
                                            Builder.getModule());
    assert(substConventions.getNumSILArguments() == ListOfValues.size()
           && "Argument number mismatch in ApplyInst.");
    SmallVector<SILValue, 4> Args;
    for (unsigned I = 0, E = ListOfValues.size(); I < E; ++I)
      Args.push_back(getLocalValue(ListOfValues[I],
                                   substConventions.getSILArgumentType(
                                       I, Builder.getTypeExpansionContext())));
    SubstitutionMap Substitutions = MF->getSubstitutionMap(NumSubs);

    if (OpCode == SILInstructionKind::ApplyInst) {
      ResultInst =
          Builder.createApply(Loc, getLocalValue(ValID, FnTy), Substitutions,
                              Args, ApplyOpts);
    } else {
      ResultInst = Builder.createBeginApply(Loc, getLocalValue(ValID, FnTy),
                                            Substitutions, Args, ApplyOpts);
    }
    break;
  }
  case SILInstructionKind::TryApplyInst: {
    // Format: attributes such as transparent, the callee's type, a value for
    // the callee and a list of values for the arguments. Each value in the list
    // is represented with 2 IDs: ValueID and ValueResultNumber.  The final
    // two values in the list are the basic block identifiers.
    auto Ty = MF->getType(TyID);
    auto Ty2 = MF->getType(TyID2);
    SILType FnTy = getSILType(Ty, SILValueCategory::Object, Fn);
    SILType SubstFnTy = getSILType(Ty2, SILValueCategory::Object, Fn);

    SILBasicBlock *errorBB = getBBForReference(Fn, ListOfValues.back());
    ListOfValues = ListOfValues.drop_back();
    SILBasicBlock *normalBB = getBBForReference(Fn, ListOfValues.back());
    ListOfValues = ListOfValues.drop_back();

    SILFunctionConventions substConventions(SubstFnTy.castTo<SILFunctionType>(),
                                            Builder.getModule());
    assert(substConventions.getNumSILArguments() == ListOfValues.size()
           && "Argument number mismatch in ApplyInst.");
    SmallVector<SILValue, 4> Args;
    for (unsigned I = 0, E = ListOfValues.size(); I < E; ++I)
      Args.push_back(getLocalValue(ListOfValues[I],
                                   substConventions.getSILArgumentType(
                                       I, Builder.getTypeExpansionContext())));
    SubstitutionMap Substitutions = MF->getSubstitutionMap(NumSubs);

    ResultInst = Builder.createTryApply(Loc, getLocalValue(ValID, FnTy),
                                        Substitutions, Args, normalBB, errorBB,
                                        ApplyOpts);
    break;
  }
  case SILInstructionKind::PartialApplyInst: {
    auto Ty = MF->getType(TyID);
    auto Ty2 = MF->getType(TyID2);
    SILType FnTy = getSILType(Ty, SILValueCategory::Object, Fn);
    SILType closureTy = getSILType(Ty2, SILValueCategory::Object, Fn);

    SubstitutionMap Substitutions = MF->getSubstitutionMap(NumSubs);

    auto SubstFnTy = SILType::getPrimitiveObjectType(
        FnTy.castTo<SILFunctionType>()->substGenericArgs(
            Builder.getModule(), Substitutions,
            Builder.getTypeExpansionContext()));
    SILFunctionConventions fnConv(SubstFnTy.castTo<SILFunctionType>(),
                                  Builder.getModule());

    unsigned numArgs = fnConv.getNumSILArguments();
    assert(numArgs >= ListOfValues.size()
           && "Argument number mismatch in PartialApplyInst.");

    SILValue FnVal = getLocalValue(ValID, FnTy);
    SmallVector<SILValue, 4> Args;
    unsigned unappliedArgs = numArgs - ListOfValues.size();
    for (unsigned I = 0, E = ListOfValues.size(); I < E; ++I)
      Args.push_back(getLocalValue(
          ListOfValues[I],
          fnConv.getSILArgumentType(I + unappliedArgs,
                                    Builder.getTypeExpansionContext())));
    auto onStack = closureTy.castTo<SILFunctionType>()->isNoEscape()
                       ? PartialApplyInst::OnStackKind::OnStack
                       : PartialApplyInst::OnStackKind::NotOnStack;
    // FIXME: Why the arbitrary order difference in IRBuilder type argument?
    ResultInst = Builder.createPartialApply(
        Loc, FnVal, Substitutions, Args,
        closureTy.castTo<SILFunctionType>()->getCalleeConvention(), onStack);
    break;
  }
  case SILInstructionKind::BuiltinInst: {
    auto ASTTy = MF->getType(TyID);
    auto ResultTy = getSILType(ASTTy, (SILValueCategory)(unsigned)TyID2, Fn);
    SmallVector<SILValue, 4> Args;
    for (unsigned i = 0, e = ListOfValues.size(); i < e; i += 3) {
      auto ArgASTTy = MF->getType(ListOfValues[i+1]);
      auto ArgTy = getSILType(
          ArgASTTy, (SILValueCategory)(unsigned)ListOfValues[i + 2], Fn);
      Args.push_back(getLocalValue(ListOfValues[i], ArgTy));
    }
    SubstitutionMap Substitutions = MF->getSubstitutionMap(NumSubs);
    Identifier Name = MF->getIdentifier(ValID);

    ResultInst =
        Builder.createBuiltin(Loc, Name, ResultTy, Substitutions, Args);
    break;
  }
  case SILInstructionKind::AllocGlobalInst: {
    // Format: Name and type. Use SILOneOperandLayout.
    StringRef Name = MF->getIdentifierText(ValID);

    // Find the global variable.
    SILGlobalVariable *g = getGlobalForReference(Name);
    assert(g && "Can't deserialize global variable");

    ResultInst = Builder.createAllocGlobal(Loc, g);
    break;
  }
  case SILInstructionKind::GlobalAddrInst:
  case SILInstructionKind::GlobalValueInst: {
    // Format: Name and type. Use SILOneOperandLayout.
    auto Ty = MF->getType(TyID);
    StringRef Name = MF->getIdentifierText(ValID);

    // Find the global variable.
    SILGlobalVariable *g = getGlobalForReference(Name);
    assert(g && "Can't deserialize global variable");
    SILType expectedType =
        (OpCode == SILInstructionKind::GlobalAddrInst
             ? g->getLoweredTypeInContext(TypeExpansionContext(*Fn))
                   .getAddressType()
             : g->getLoweredTypeInContext(TypeExpansionContext(*Fn)));
    assert(expectedType == getSILType(Ty, (SILValueCategory)TyCategory, Fn) &&
           "Type of a global variable does not match GlobalAddr.");
    (void)Ty;
    (void)expectedType;
    if (OpCode == SILInstructionKind::GlobalAddrInst) {
      ResultInst = Builder.createGlobalAddr(Loc, g);
    } else {
      ResultInst = Builder.createGlobalValue(Loc, g);
    }
    break;
  }
  case SILInstructionKind::BaseAddrForOffsetInst:
    assert(RecordKind == SIL_ONE_TYPE && "Layout should be OneType.");
    ResultInst = Builder.createBaseAddrForOffset(
        Loc, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn));
    break;
  case SILInstructionKind::DeallocStackInst: {
    auto Ty = MF->getType(TyID);
    ResultInst = Builder.createDeallocStack(
        Loc,
        getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)));
    break;
  }
  case SILInstructionKind::DeallocStackRefInst: {
    auto Ty = MF->getType(TyID);
    ResultInst = Builder.createDeallocStackRef(
        Loc,
        getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)));
    break;
  }
  case SILInstructionKind::DeallocRefInst: {
    auto Ty = MF->getType(TyID);
    ResultInst = Builder.createDeallocRef(
        Loc,
        getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)));
    break;
  }
  case SILInstructionKind::DeallocPartialRefInst: {
    auto Ty = MF->getType(TyID);
    auto Ty2 = MF->getType(TyID2);
    ResultInst = Builder.createDeallocPartialRef(
        Loc,
        getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)),
        getLocalValue(ValID2,
                      getSILType(Ty2, (SILValueCategory)TyCategory2, Fn)));
    break;
  }
  case SILInstructionKind::FunctionRefInst: {
    auto Ty = MF->getType(TyID);
    StringRef FuncName = MF->getIdentifierText(ValID);
    ResultInst = Builder.createFunctionRef(
        Loc,
        getFuncForReference(
            FuncName, getSILType(Ty, (SILValueCategory)TyCategory, nullptr)));
    break;
  }
  case SILInstructionKind::DynamicFunctionRefInst: {
    auto Ty = MF->getType(TyID);
    StringRef FuncName = MF->getIdentifierText(ValID);
    ResultInst = Builder.createDynamicFunctionRef(
        Loc,
        getFuncForReference(
            FuncName, getSILType(Ty, (SILValueCategory)TyCategory, nullptr)));
    break;
  }
  case SILInstructionKind::PreviousDynamicFunctionRefInst: {
    auto Ty = MF->getType(TyID);
    StringRef FuncName = MF->getIdentifierText(ValID);
    ResultInst = Builder.createPreviousDynamicFunctionRef(
        Loc,
        getFuncForReference(
            FuncName, getSILType(Ty, (SILValueCategory)TyCategory, nullptr)));
    break;
  }
  case SILInstructionKind::MarkDependenceInst: {
    auto Ty = MF->getType(TyID);
    auto Ty2 = MF->getType(TyID2);
    ResultInst = Builder.createMarkDependence(
        Loc,
        getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)),
        getLocalValue(ValID2,
                      getSILType(Ty2, (SILValueCategory)TyCategory2, Fn)));
    break;
  }
  case SILInstructionKind::CopyBlockWithoutEscapingInst: {
    auto Ty = MF->getType(TyID);
    auto Ty2 = MF->getType(TyID2);
    ResultInst = Builder.createCopyBlockWithoutEscaping(
        Loc,
        getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)),
        getLocalValue(ValID2,
                      getSILType(Ty2, (SILValueCategory)TyCategory2, Fn)));
    break;
  }
  case SILInstructionKind::IndexAddrInst: {
    auto Ty = MF->getType(TyID);
    auto Ty2 = MF->getType(TyID2);
    ResultInst = Builder.createIndexAddr(
        Loc,
        getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)),
        getLocalValue(ValID2,
                      getSILType(Ty2, (SILValueCategory)TyCategory2, Fn)));
    break;
  }
  case SILInstructionKind::TailAddrInst: {
    auto Ty = MF->getType(TyID);
    auto Ty2 = MF->getType(TyID2);
    auto ResultTy = MF->getType(TyID3);
    ResultInst = Builder.createTailAddr(
        Loc,
        getLocalValue(ValID, getSILType(Ty, SILValueCategory::Address, Fn)),
        getLocalValue(ValID2, getSILType(Ty2, SILValueCategory::Object, Fn)),
        getSILType(ResultTy, SILValueCategory::Address, Fn));
    break;
  }
  case SILInstructionKind::IndexRawPointerInst: {
    auto Ty = MF->getType(TyID);
    auto Ty2 = MF->getType(TyID2);
    ResultInst = Builder.createIndexRawPointer(
        Loc,
        getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)),
        getLocalValue(ValID2,
                      getSILType(Ty2, (SILValueCategory)TyCategory2, Fn)));
    break;
  }
  case SILInstructionKind::IntegerLiteralInst: {
    auto Ty = MF->getType(TyID);
    auto intTy = Ty->castTo<AnyBuiltinIntegerType>();
    StringRef text = MF->getIdentifierText(ValID);
    bool negate = text[0] == '-';
    if (negate) text = text.drop_front();
    APInt value = intTy->getWidth().parse(text, 10, negate);
    ResultInst = Builder.createIntegerLiteral(
        Loc, getSILType(Ty, (SILValueCategory)TyCategory, Fn), value);
    break;
  }
  case SILInstructionKind::FloatLiteralInst: {
    auto Ty = MF->getType(TyID);
    auto floatTy = Ty->castTo<BuiltinFloatType>();
    StringRef StringVal = MF->getIdentifierText(ValID);
    // Build APInt from string.
    APInt bits(floatTy->getBitWidth(), StringVal, 16);
    if (bits.getBitWidth() != floatTy->getBitWidth())
      bits = bits.zextOrTrunc(floatTy->getBitWidth());

    APFloat value(floatTy->getAPFloatSemantics(), bits);

    ResultInst = Builder.createFloatLiteral(
        Loc, getSILType(Ty, (SILValueCategory)TyCategory, Fn), value);
    break;
  }
  case SILInstructionKind::StringLiteralInst: {
    StringRef StringVal = MF->getIdentifierText(ValID);
    auto encoding = fromStableStringEncoding(Attr);
    if (!encoding) return true;
    ResultInst =
        Builder.createStringLiteral(Loc, StringVal, encoding.getValue());
    break;
  }
  case SILInstructionKind::CondFailInst: {
    SILValue Op = getLocalValue(
        ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn));
    StringRef StringVal = MF->getIdentifierText(ValID2);
    ResultInst = Builder.createCondFail(Loc, Op, StringVal);
    break;
  }
  case SILInstructionKind::MarkFunctionEscapeInst: {
    // Format: a list of typed values. A typed value is expressed by 4 IDs:
    // TypeID, TypeCategory, ValueID, ValueResultNumber.
    SmallVector<SILValue, 4> OpList;
    for (unsigned I = 0, E = ListOfValues.size(); I < E; I += 3) {
      auto EltTy = MF->getType(ListOfValues[I]);
      OpList.push_back(getLocalValue(
          ListOfValues[I + 2],
          getSILType(EltTy, (SILValueCategory)ListOfValues[I + 1], Fn)));
    }
    ResultInst = Builder.createMarkFunctionEscape(Loc, OpList);
    break;
  }
  // Checked Conversion instructions.
  case SILInstructionKind::UnconditionalCheckedCastInst: {
    SILType srcLoweredType = getSILType(MF->getType(ListOfValues[1]),
                                        (SILValueCategory)ListOfValues[2], Fn);
    SILValue src = getLocalValue(ListOfValues[0], srcLoweredType);

    SILType targetLoweredType =
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn);
    CanType targetFormalType =
        MF->getType(ListOfValues[3])->getCanonicalType();
    ResultInst = Builder.createUnconditionalCheckedCast(
        Loc, src, targetLoweredType, targetFormalType);
    break;
  }

#define UNARY_INSTRUCTION(ID)                                                  \
  case SILInstructionKind::ID##Inst:                                           \
    assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand.");   \
    ResultInst = Builder.create##ID(                                           \
        Loc,                                                                   \
        getLocalValue(ValID, getSILType(MF->getType(TyID),                     \
                                        (SILValueCategory)TyCategory, Fn)));   \
    break;

#define REFCOUNTING_INSTRUCTION(ID)                                            \
  case SILInstructionKind::ID##Inst:                                           \
    assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand.");   \
    ResultInst = Builder.create##ID(                                           \
        Loc,                                                                   \
        getLocalValue(ValID, getSILType(MF->getType(TyID),                     \
                                        (SILValueCategory)TyCategory, Fn)),    \
        (Atomicity)Attr);                                                      \
    break;

#define UNCHECKED_REF_STORAGE(Name, ...)                                       \
  UNARY_INSTRUCTION(StrongCopy##Name##Value)
#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...)            \
  REFCOUNTING_INSTRUCTION(Name##Retain)                                        \
  REFCOUNTING_INSTRUCTION(Name##Release)                                       \
  REFCOUNTING_INSTRUCTION(StrongRetain##Name)                                  \
  UNARY_INSTRUCTION(StrongCopy##Name##Value)
#include "swift/AST/ReferenceStorage.def"
  REFCOUNTING_INSTRUCTION(RetainValue)
  REFCOUNTING_INSTRUCTION(RetainValueAddr)
  REFCOUNTING_INSTRUCTION(UnmanagedRetainValue)
  UNARY_INSTRUCTION(CopyValue)
  UNARY_INSTRUCTION(ExplicitCopyValue)
  REFCOUNTING_INSTRUCTION(ReleaseValue)
  REFCOUNTING_INSTRUCTION(ReleaseValueAddr)
  REFCOUNTING_INSTRUCTION(UnmanagedReleaseValue)
  REFCOUNTING_INSTRUCTION(AutoreleaseValue)
  REFCOUNTING_INSTRUCTION(UnmanagedAutoreleaseValue)
  REFCOUNTING_INSTRUCTION(SetDeallocating)
  UNARY_INSTRUCTION(DeinitExistentialAddr)
  UNARY_INSTRUCTION(DeinitExistentialValue)
  UNARY_INSTRUCTION(EndBorrow)
  UNARY_INSTRUCTION(DestroyAddr)
  UNARY_INSTRUCTION(Return)
  UNARY_INSTRUCTION(Throw)
  UNARY_INSTRUCTION(ClassifyBridgeObject)
  UNARY_INSTRUCTION(ValueToBridgeObject)
  UNARY_INSTRUCTION(FixLifetime)
  UNARY_INSTRUCTION(EndLifetime)
  UNARY_INSTRUCTION(CopyBlock)
  UNARY_INSTRUCTION(LoadBorrow)
  REFCOUNTING_INSTRUCTION(StrongRetain)
  REFCOUNTING_INSTRUCTION(StrongRelease)
  UNARY_INSTRUCTION(IsUnique)
  UNARY_INSTRUCTION(AbortApply)
  UNARY_INSTRUCTION(EndApply)
  UNARY_INSTRUCTION(ExtractExecutor)
#undef UNARY_INSTRUCTION
#undef REFCOUNTING_INSTRUCTION

  case SILInstructionKind::BeginBorrowInst: {
    assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand.");
    bool isLexical = Attr & 0x1;
    ResultInst = Builder.createBeginBorrow(
        Loc,
        getLocalValue(ValID, getSILType(MF->getType(TyID),
                                        (SILValueCategory)TyCategory, Fn)),
        isLexical);
    break;
  }

  case SILInstructionKind::IsEscapingClosureInst: {
    assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand.");
    unsigned verificationType = Attr;
    ResultInst = Builder.createIsEscapingClosure(
        Loc,
        getLocalValue(ValID, getSILType(MF->getType(TyID),
                                        (SILValueCategory)TyCategory, Fn)),
        verificationType);
    break;
  }

  case SILInstructionKind::HopToExecutorInst: {
    assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand.");
    unsigned mandatory = Attr;
    ResultInst = Builder.createHopToExecutor(
        Loc,
        getLocalValue(ValID, getSILType(MF->getType(TyID),
                                        (SILValueCategory)TyCategory, Fn)),
        mandatory != 0);
    break;
  }
  case SILInstructionKind::DestroyValueInst: {
    assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand.");
    unsigned poisonRefs = Attr;
    ResultInst = Builder.createDestroyValue(
        Loc,
        getLocalValue(ValID, getSILType(MF->getType(TyID),
                                        (SILValueCategory)TyCategory, Fn)),
        poisonRefs != 0);
    break;
  }

  case SILInstructionKind::BeginCOWMutationInst: {
    assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand.");
    unsigned isNative = Attr;
    ResultInst = Builder.createBeginCOWMutation(
        Loc,
        getLocalValue(ValID, getSILType(MF->getType(TyID),
                                        (SILValueCategory)TyCategory, Fn)),
        isNative != 0);
    break;
  }

  case SILInstructionKind::EndCOWMutationInst: {
    assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand.");
    unsigned keepUnique = Attr;
    ResultInst = Builder.createEndCOWMutation(
        Loc,
        getLocalValue(ValID, getSILType(MF->getType(TyID),
                                        (SILValueCategory)TyCategory, Fn)),
        keepUnique != 0);
    break;
  }

  case SILInstructionKind::DestructureTupleInst: {
    assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand.");
    SILValue Operand = getLocalValue(
        ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn));
    ResultInst = Builder.createDestructureTuple(Loc, Operand);
    break;
  }
  case SILInstructionKind::DestructureStructInst: {
    assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand.");
    SILValue Operand = getLocalValue(
        ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn));
    ResultInst = Builder.createDestructureStruct(Loc, Operand);
    break;
  }
  case SILInstructionKind::UncheckedOwnershipConversionInst: {
    auto Ty = MF->getType(TyID);
    auto ResultKind = decodeValueOwnership(Attr);
    ResultInst = Builder.createUncheckedOwnershipConversion(
        Loc,
        getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)),
        ResultKind);
    break;
  }

  case SILInstructionKind::MoveValueInst: {
    auto Ty = MF->getType(TyID);
    bool AllowsDiagnostics = Attr & 0x1;
    bool IsLexical = (Attr >> 1) & 0x1;
    auto *MVI = Builder.createMoveValue(
        Loc,
        getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)),
        IsLexical);
    MVI->setAllowsDiagnostics(AllowsDiagnostics);
    ResultInst = MVI;
    break;
  }

  case SILInstructionKind::LoadInst: {
    auto Ty = MF->getType(TyID);
    auto Qualifier = LoadOwnershipQualifier(Attr);
    ResultInst = Builder.createLoad(
        Loc,
        getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)),
        Qualifier);
    break;
  }

#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...)             \
  case SILInstructionKind::Load##Name##Inst: {                                 \
    auto Ty = MF->getType(TyID);                                               \
    bool isTake = (Attr > 0);                                                  \
    auto Val = getLocalValue(                                                  \
        ValID, getSILType(Ty, SILValueCategory(TyCategory), Fn));              \
    ResultInst = Builder.createLoad##Name(Loc, Val, IsTake_t(isTake));         \
    break;                                                                     \
  }                                                                            \
  case SILInstructionKind::Store##Name##Inst: {                                \
    auto Ty = MF->getType(TyID);                                               \
    SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory, Fn);       \
    auto refType = addrType.castTo<Name##StorageType>();                       \
    auto ValType = SILType::getPrimitiveObjectType(refType.getReferentType()); \
    bool isInit = (Attr > 0);                                                  \
    ResultInst = Builder.createStore##Name(Loc, getLocalValue(ValID, ValType), \
                                           getLocalValue(ValID2, addrType),    \
                                           IsInitialization_t(isInit));        \
    break;                                                                     \
  }
#include "swift/AST/ReferenceStorage.def"
  case SILInstructionKind::MarkUninitializedInst: {
    auto Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn);
    auto Kind = (MarkUninitializedInst::Kind)Attr;
    auto Val = getLocalValue(ValID, Ty);
    ResultInst = Builder.createMarkUninitialized(Loc, Val, Kind);
    break;
  }
  case SILInstructionKind::StoreInst: {
    auto Ty = MF->getType(TyID);
    SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory, Fn);
    SILType ValType = addrType.getObjectType();
    auto Qualifier = StoreOwnershipQualifier(Attr);
    ResultInst =
        Builder.createStore(Loc, getLocalValue(ValID, ValType),
                            getLocalValue(ValID2, addrType), Qualifier);
    break;
  }
  case SILInstructionKind::StoreBorrowInst: {
    auto Ty = MF->getType(TyID);
    SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory, Fn);
    SILType ValType = addrType.getObjectType();
    ResultInst = Builder.createStoreBorrow(Loc, getLocalValue(ValID, ValType),
                                           getLocalValue(ValID2, addrType));
    break;
  }
  case SILInstructionKind::BeginAccessInst: {
    SILValue op = getLocalValue(
        ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn));
    auto accessKind = SILAccessKind(Attr & 0x3);
    auto enforcement = SILAccessEnforcement((Attr >> 2) & 0x3);
    bool noNestedConflict = (Attr >> 4) & 0x01;
    bool fromBuiltin = (Attr >> 5) & 0x01;
    ResultInst = Builder.createBeginAccess(Loc, op, accessKind, enforcement,
                                           noNestedConflict, fromBuiltin);
    break;
  }
  case SILInstructionKind::EndAccessInst: {
    SILValue op = getLocalValue(
        ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn));
    bool aborted = Attr & 0x1;
    ResultInst = Builder.createEndAccess(Loc, op, aborted);
    break;
  }
  case SILInstructionKind::BeginUnpairedAccessInst: {
    SILValue source = getLocalValue(
        ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn));
    SILValue buffer =
        getLocalValue(ValID2, getSILType(MF->getType(TyID2),
                                         (SILValueCategory)TyCategory2, Fn));
    auto accessKind = SILAccessKind(Attr & 0x3);
    auto enforcement = SILAccessEnforcement((Attr >> 2) & 0x03);
    bool noNestedConflict = (Attr >> 4) & 0x01;
    bool fromBuiltin = (Attr >> 5) & 0x01;
    ResultInst = Builder.createBeginUnpairedAccess(
        Loc, source, buffer, accessKind, enforcement, noNestedConflict,
        fromBuiltin);
    break;
  }
  case SILInstructionKind::EndUnpairedAccessInst: {
    SILValue op = getLocalValue(
        ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn));
    bool aborted = Attr & 0x1;
    auto enforcement = SILAccessEnforcement((Attr >> 1) & 0x03);
    bool fromBuiltin = (Attr >> 3) & 0x01;
    ResultInst = Builder.createEndUnpairedAccess(Loc, op, enforcement, aborted,
                                                 fromBuiltin);
    break;
  }
  case SILInstructionKind::CopyAddrInst: {
    auto Ty = MF->getType(TyID);
    SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory, Fn);
    bool isInit = (Attr & 0x2) > 0;
    bool isTake = (Attr & 0x1) > 0;
    ResultInst = Builder.createCopyAddr(
        Loc, getLocalValue(ValID, addrType), getLocalValue(ValID2, addrType),
        IsTake_t(isTake), IsInitialization_t(isInit));
    break;
  }

  case SILInstructionKind::MarkUnresolvedMoveAddrInst: {
    auto Ty = MF->getType(TyID);
    SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory, Fn);
    ResultInst = Builder.createMarkUnresolvedMoveAddr(
        Loc, getLocalValue(ValID, addrType), getLocalValue(ValID2, addrType));
    break;
  }

  case SILInstructionKind::AssignInst: {
    auto Ty = MF->getType(TyID);
    SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory, Fn);
    SILType valType = addrType.getObjectType();
    auto qualifier = AssignOwnershipQualifier(Attr);
    ResultInst =
        Builder.createAssign(Loc, getLocalValue(ValID, valType),
                             getLocalValue(ValID2, addrType), qualifier);
    break;
  }
  case SILInstructionKind::AssignByWrapperInst:
    llvm_unreachable("not supported");
  case SILInstructionKind::BindMemoryInst: {
    assert(RecordKind == SIL_ONE_TYPE_VALUES &&
           "Layout should be OneTypeValues.");
    auto Ty = MF->getType(TyID);   // BoundTy
    ResultInst = Builder.createBindMemory(
        Loc,
        getLocalValue(ListOfValues[2],
                      getSILType(MF->getType(ListOfValues[0]),
                                 (SILValueCategory)ListOfValues[1], Fn)),
        getLocalValue(ListOfValues[5],
                      getSILType(MF->getType(ListOfValues[3]),
                                 (SILValueCategory)ListOfValues[4], Fn)),
        getSILType(Ty, (SILValueCategory)TyCategory, Fn));
    break;
  }
  case SILInstructionKind::RebindMemoryInst: {
    assert(RecordKind == SIL_TWO_OPERANDS && "Layout should be TwoOperands.");
    auto Ty = MF->getType(TyID);
    auto Ty2 = MF->getType(TyID2);
    ResultInst = Builder.createRebindMemory(
        Loc,
        getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)),
        getLocalValue(ValID2,
                      getSILType(Ty2, (SILValueCategory)TyCategory2, Fn)));
    break;
  }
  case SILInstructionKind::StructElementAddrInst:
  case SILInstructionKind::StructExtractInst: {
    // Use SILOneValueOneOperandLayout.
    VarDecl *Field = cast<VarDecl>(MF->getDecl(ValID));
    auto Ty = MF->getType(TyID);
    auto Val =
        getLocalValue(ValID2, getSILType(Ty, (SILValueCategory)TyCategory, Fn));
    auto ResultTy = Val->getType().getFieldType(
        Field, SILMod, Builder.getTypeExpansionContext());
    if (OpCode == SILInstructionKind::StructElementAddrInst)
      ResultInst = Builder.createStructElementAddr(Loc, Val, Field,
                                                   ResultTy.getAddressType());
    else
      ResultInst = Builder.createStructExtract(Loc, Val, Field,
                                               ResultTy.getObjectType());
    break;
  }
  case SILInstructionKind::StructInst: {
    // Format: a type followed by a list of typed values. A typed value is
    // expressed by 4 IDs: TypeID, TypeCategory, ValueID, ValueResultNumber.
    auto Ty = MF->getType(TyID);
    SmallVector<SILValue, 4> OpList;
    for (unsigned I = 0, E = ListOfValues.size(); I < E; I += 3) {
      auto EltTy = MF->getType(ListOfValues[I]);
      OpList.push_back(getLocalValue(
          ListOfValues[I + 2],
          getSILType(EltTy, (SILValueCategory)ListOfValues[I + 1], Fn)));
    }
    ResultInst = Builder.createStruct(
        Loc, getSILType(Ty, (SILValueCategory)TyCategory, Fn), OpList);
    break;
  }
  case SILInstructionKind::TupleElementAddrInst:
  case SILInstructionKind::TupleExtractInst: {
    // Use OneTypeOneOperand layout where the field number is stored in TypeID.
    auto Ty2 = MF->getType(TyID2);
    SILType ST = getSILType(Ty2, (SILValueCategory)TyCategory2, Fn);
    TupleType *TT = ST.castTo<TupleType>();

    auto ResultTy = TT->getElement(TyID).getType();
    switch (OpCode) {
    default: llvm_unreachable("Out of sync with parent switch");
    case SILInstructionKind::TupleElementAddrInst:
      ResultInst = Builder.createTupleElementAddr(
          Loc, getLocalValue(ValID, ST), TyID,
          getSILType(ResultTy, SILValueCategory::Address, Fn));
      break;
    case SILInstructionKind::TupleExtractInst:
      ResultInst = Builder.createTupleExtract(
          Loc, getLocalValue(ValID, ST), TyID,
          getSILType(ResultTy, SILValueCategory::Object, Fn));
      break;
    }
    break;
  }
  case SILInstructionKind::TupleInst: {
    // Format: a type followed by a list of values. A value is expressed by
    // 2 IDs: ValueID, ValueResultNumber.
    auto Ty = MF->getType(TyID);
    TupleType *TT = Ty->castTo<TupleType>();
    assert(TT && "Type of a TupleInst should be TupleType");
    SmallVector<SILValue, 4> OpList;
    for (unsigned I = 0, E = ListOfValues.size(); I < E; ++I) {
      Type EltTy = TT->getElement(I).getType();
      OpList.push_back(
        getLocalValue(ListOfValues[I],
                      getSILType(EltTy, SILValueCategory::Object, Fn)));
    }
    ResultInst = Builder.createTuple(
        Loc, getSILType(Ty, (SILValueCategory)TyCategory, Fn), OpList);
    break;
  }
  case SILInstructionKind::ObjectInst: {
    assert(RecordKind == SIL_ONE_TYPE_VALUES &&
           "Layout should be OneTypeValues.");
    unsigned NumVals = ListOfValues.size();
    assert(NumVals >= 1 && "Not enough values");
    unsigned numBaseElements = ListOfValues[0];
    SILType ClassTy =
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn);
    SmallVector<SILValue, 4> elements;
    for (unsigned i = 1; i < NumVals; i += 2) {
      SILType elementType = getSILType(MF->getType(ListOfValues[i + 1]),
                                       SILValueCategory::Object, Fn);
      SILValue elementVal = getLocalValue(ListOfValues[i], elementType);
      elements.push_back(elementVal);
    }
    ResultInst = Builder.createObject(Loc, ClassTy, elements, numBaseElements);
    break;
  }
  case SILInstructionKind::BranchInst: {
    SmallVector<SILValue, 4> Args;
    for (unsigned I = 0, E = ListOfValues.size(); I < E; I += 3)
      Args.push_back(
          getLocalValue(ListOfValues[I + 2],
                        getSILType(MF->getType(ListOfValues[I]),
                                   (SILValueCategory)ListOfValues[I + 1], Fn)));

    ResultInst = Builder.createBranch(Loc, getBBForReference(Fn, TyID), Args);
    break;
  }
  case SILInstructionKind::CondBranchInst: {
    // Format: condition, true basic block ID, a list of arguments, false basic
    // block ID, a list of arguments. Use SILOneTypeValuesLayout: the type is
    // for condition, the list has value for condition, true basic block ID,
    // false basic block ID, number of true arguments, and a list of true|false
    // arguments.
    SILValue Cond = getLocalValue(
        ListOfValues[0],
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn));

    unsigned NumTrueArgs = ListOfValues[3];
    unsigned StartOfTrueArg = 4;
    unsigned StartOfFalseArg = StartOfTrueArg + 3*NumTrueArgs;
    SmallVector<SILValue, 4> TrueArgs;
    for (unsigned I = StartOfTrueArg, E = StartOfFalseArg; I < E; I += 3)
      TrueArgs.push_back(
          getLocalValue(ListOfValues[I + 2],
                        getSILType(MF->getType(ListOfValues[I]),
                                   (SILValueCategory)ListOfValues[I + 1], Fn)));

    SmallVector<SILValue, 4> FalseArgs;
    for (unsigned I = StartOfFalseArg, E = ListOfValues.size(); I < E; I += 3)
      FalseArgs.push_back(
          getLocalValue(ListOfValues[I + 2],
                        getSILType(MF->getType(ListOfValues[I]),
                                   (SILValueCategory)ListOfValues[I + 1], Fn)));

    ResultInst = Builder.createCondBranch(
        Loc, Cond, getBBForReference(Fn, ListOfValues[1]), TrueArgs,
        getBBForReference(Fn, ListOfValues[2]), FalseArgs);
    break;
  }
  case SILInstructionKind::AwaitAsyncContinuationInst: {
    // Format: continuation, resume block ID, error block ID if given
    SILValue Cont = getLocalValue(
              ListOfValues[0],
              getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn));
    
    SILBasicBlock *resultBB = getBBForReference(Fn, ListOfValues[1]);
    SILBasicBlock *errorBB = nullptr;
    if (ListOfValues.size() >= 3) {
      errorBB = getBBForReference(Fn, ListOfValues[2]);
    }
    
    ResultInst = Builder.createAwaitAsyncContinuation(Loc, Cont, resultBB, errorBB);
    break;
  }
  case SILInstructionKind::SwitchEnumInst:
  case SILInstructionKind::SwitchEnumAddrInst: {
    // Format: condition, a list of cases (EnumElementDecl + Basic Block ID),
    // default basic block ID. Use SILOneTypeValuesLayout: the type is
    // for condition, the list has value for condition, hasDefault, default
    // basic block ID, a list of (DeclID, BasicBlock ID).
    SILValue Cond = getLocalValue(
        ListOfValues[0],
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn));

    SILBasicBlock *DefaultBB = nullptr;
    if (ListOfValues[1])
      DefaultBB = getBBForReference(Fn, ListOfValues[2]);

    SmallVector<std::pair<EnumElementDecl*, SILBasicBlock*>, 4> CaseBBs;
    for (unsigned I = 3, E = ListOfValues.size(); I < E; I += 2) {
      CaseBBs.push_back( {cast<EnumElementDecl>(MF->getDecl(ListOfValues[I])),
                            getBBForReference(Fn, ListOfValues[I+1])} );
    }
    if (OpCode == SILInstructionKind::SwitchEnumInst) {
      ResultInst = Builder.createSwitchEnum(Loc, Cond, DefaultBB, CaseBBs,
                                            None, ProfileCounter(),
                                            forwardingOwnership);
    } else {
      ResultInst = Builder.createSwitchEnumAddr(Loc, Cond, DefaultBB, CaseBBs);
    }
    break;
  }
  case SILInstructionKind::SelectEnumInst:
  case SILInstructionKind::SelectEnumAddrInst: {
    // Format: condition, a list of cases (EnumElementDecl + Value ID),
    // default value ID. Use SILOneTypeValuesLayout: the type is
    // for condition, the list has value for condition, result type,
    //   hasDefault, default
    // basic block ID, a list of (DeclID, BasicBlock ID).
    SILValue Cond = getLocalValue(ListOfValues[0],
                                  getSILType(MF->getType(TyID),
                                             (SILValueCategory)TyCategory, Fn));

    Type ResultLoweredTy = MF->getType(ListOfValues[1]);
    SILValueCategory ResultCategory = (SILValueCategory)ListOfValues[2];
    SILType ResultTy = getSILType(ResultLoweredTy, ResultCategory, Fn);

    SILValue DefaultVal = nullptr;
    if (ListOfValues[3])
      DefaultVal = getLocalValue(ListOfValues[4], ResultTy);

    SmallVector<std::pair<EnumElementDecl*, SILValue>, 4> CaseVals;
    for (unsigned I = 5, E = ListOfValues.size(); I < E; I += 2) {
      auto Value = getLocalValue(ListOfValues[I+1], ResultTy);
      CaseVals.push_back({cast<EnumElementDecl>(MF->getDecl(ListOfValues[I])),
                         Value});
    }
    if (OpCode == SILInstructionKind::SelectEnumInst)
      ResultInst =
          Builder.createSelectEnum(Loc, Cond, ResultTy, DefaultVal, CaseVals);
    else
      ResultInst = Builder.createSelectEnumAddr(Loc, Cond, ResultTy, DefaultVal,
                                                CaseVals);
    break;
  }
  case SILInstructionKind::SwitchValueInst: {
    // Format: condition, a list of cases (Value ID + Basic Block ID),
    // default basic block ID. Use SILOneTypeValuesLayout: the type is
    // for condition, the list contains value for condition, hasDefault, default
    // basic block ID, a list of (Value ID, BasicBlock ID).
    SILType ResultTy = getSILType(MF->getType(TyID),
                                             (SILValueCategory)TyCategory, Fn);
    SILValue Cond = getLocalValue(
        ListOfValues[0],
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn));

    SILBasicBlock *DefaultBB = nullptr;
    if (ListOfValues[1])
      DefaultBB = getBBForReference(Fn, ListOfValues[2]);

    SmallVector<std::pair<SILValue, SILBasicBlock*>, 4> CaseBBs;
    for (unsigned I = 3, E = ListOfValues.size(); I < E; I += 2) {
      auto value = getLocalValue(ListOfValues[I], ResultTy);
      CaseBBs.push_back( {value, getBBForReference(Fn, ListOfValues[I+1])} );
    }
    ResultInst = Builder.createSwitchValue(Loc, Cond, DefaultBB, CaseBBs);
    break;
  }
  case SILInstructionKind::SelectValueInst: {
    // Format: condition, a list of cases (ValueID + Value ID),
    // default value ID. Use SILOneTypeValuesLayout: the type is
    // for condition, the list has value for condition, result type,
    // hasDefault, default,
    // basic block ID, a list of (Value ID, Value ID).
    SILValue Cond = getLocalValue(
        ListOfValues[0],
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn));

    Type ResultLoweredTy = MF->getType(ListOfValues[1]);
    SILValueCategory ResultCategory = (SILValueCategory)ListOfValues[2];
    SILType ResultTy = getSILType(ResultLoweredTy, ResultCategory, Fn);

    SILValue DefaultVal = nullptr;
    if (ListOfValues[3])
      DefaultVal = getLocalValue(ListOfValues[4], ResultTy);

    SmallVector<std::pair<SILValue, SILValue>, 4> CaseValuesAndResults;
    for (unsigned I = 5, E = ListOfValues.size(); I < E; I += 2) {
      auto CaseValue = getLocalValue(ListOfValues[I], Cond->getType());
      auto Result = getLocalValue(ListOfValues[I+1], ResultTy);
      CaseValuesAndResults.push_back({CaseValue, Result});
    }

    ResultInst = Builder.createSelectValue(Loc, Cond, ResultTy, DefaultVal,
                                           CaseValuesAndResults);
    break;
  }  
  case SILInstructionKind::EnumInst: {
    // Format: a type, an operand and a decl ID. Use SILTwoOperandsLayout: type,
    // (DeclID + hasOperand), and an operand.
    SILValue Operand;
    if (Attr)
      Operand =
          getLocalValue(ValID2, getSILType(MF->getType(TyID2),
                                           (SILValueCategory)TyCategory2, Fn));
    ResultInst = Builder.createEnum(
        Loc, Operand, cast<EnumElementDecl>(MF->getDecl(ValID)),
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn));
    break;
  }
  case SILInstructionKind::InitEnumDataAddrInst: {
    // Use SILOneValueOneOperandLayout.
    EnumElementDecl *Elt = cast<EnumElementDecl>(MF->getDecl(ValID));
    SILType OperandTy = getSILType(MF->getType(TyID),
                                   (SILValueCategory) TyCategory, Fn);
    SILType ResultTy = OperandTy.getEnumElementType(
        Elt, SILMod, Builder.getTypeExpansionContext());
    ResultInst = Builder.createInitEnumDataAddr(
        Loc, getLocalValue(ValID2, OperandTy), Elt, ResultTy);
    break;
  }
  case SILInstructionKind::UncheckedEnumDataInst: {
    // Use SILOneValueOneOperandLayout.
    EnumElementDecl *Elt = cast<EnumElementDecl>(MF->getDecl(ValID));
    SILType OperandTy =
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn);
    SILType ResultTy = OperandTy.getEnumElementType(
        Elt, SILMod, Builder.getTypeExpansionContext());
    ResultInst = Builder.createUncheckedEnumData(
        Loc, getLocalValue(ValID2, OperandTy), Elt, ResultTy);
    break;
  }
  case SILInstructionKind::UncheckedTakeEnumDataAddrInst: {
    // Use SILOneValueOneOperandLayout.
    EnumElementDecl *Elt = cast<EnumElementDecl>(MF->getDecl(ValID));
    SILType OperandTy =
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn);
    SILType ResultTy = OperandTy.getEnumElementType(
        Elt, SILMod, Builder.getTypeExpansionContext());
    ResultInst = Builder.createUncheckedTakeEnumDataAddr(
        Loc, getLocalValue(ValID2, OperandTy), Elt, ResultTy);
    break;
  }
  case SILInstructionKind::InjectEnumAddrInst: {
    // Use SILOneValueOneOperandLayout.
    EnumElementDecl *Elt = cast<EnumElementDecl>(MF->getDecl(ValID));
    auto Ty = MF->getType(TyID);
    ResultInst = Builder.createInjectEnumAddr(
        Loc,
        getLocalValue(ValID2, getSILType(Ty, (SILValueCategory)TyCategory, Fn)),
        Elt);
    break;
  }
  case SILInstructionKind::RefElementAddrInst: {
    // Use SILOneValueOneOperandLayout.
    VarDecl *Field = cast<VarDecl>(MF->getDecl(ValID));
    auto Ty = MF->getType(TyID);
    auto Val = getLocalValue(ValID2,
                             getSILType(Ty, (SILValueCategory)TyCategory, Fn));
    auto ResultTy = Val->getType().getFieldType(
        Field, SILMod, Builder.getTypeExpansionContext());
    ResultInst = Builder.createRefElementAddr(Loc, Val, Field, ResultTy,
                                              /*Immutable*/ Attr & 0x1);
    break;
  }
  case SILInstructionKind::RefTailAddrInst: {
    assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND &&
           "Layout should be OneTypeOneOperand.");
    assert((SILValueCategory)TyCategory == SILValueCategory::Address);
    ResultInst = Builder.createRefTailAddr(
        Loc,
        getLocalValue(ValID, getSILType(MF->getType(TyID2),
                                        (SILValueCategory)TyCategory2, Fn)),
        getSILType(MF->getType(TyID), SILValueCategory::Address, Fn),
        /*Immutable*/ Attr & 0x1);
    break;
  }
  case SILInstructionKind::ClassMethodInst:
  case SILInstructionKind::SuperMethodInst:
  case SILInstructionKind::ObjCMethodInst:
  case SILInstructionKind::ObjCSuperMethodInst: {
    // Format: a type, an operand and a SILDeclRef. Use SILOneTypeValuesLayout:
    // type, Attr, SILDeclRef (DeclID, Kind, uncurryLevel), and an operand.
    unsigned NextValueIndex = 0;
    SILDeclRef DRef = getSILDeclRef(MF, ListOfValues, NextValueIndex);
    SILType Ty =
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn);
    assert(ListOfValues.size() >= NextValueIndex + 2 &&
           "Out of entries for MethodInst");
    SILType operandTy =
        getSILType(MF->getType(ListOfValues[NextValueIndex]),
                   (SILValueCategory)ListOfValues[NextValueIndex + 1], Fn);
    NextValueIndex += 2;

    switch (OpCode) {
    default: llvm_unreachable("Out of sync with parent switch");
    case SILInstructionKind::ClassMethodInst:
      ResultInst = Builder.createClassMethod(
          Loc, getLocalValue(ListOfValues[NextValueIndex], operandTy), DRef,
          Ty);
      break;
    case SILInstructionKind::SuperMethodInst:
      ResultInst = Builder.createSuperMethod(
          Loc, getLocalValue(ListOfValues[NextValueIndex], operandTy), DRef,
          Ty);
      break;
    case SILInstructionKind::ObjCMethodInst:
      ResultInst = Builder.createObjCMethod(
          Loc, getLocalValue(ListOfValues[NextValueIndex], operandTy), DRef,
          Ty);
      break;
    case SILInstructionKind::ObjCSuperMethodInst:
      ResultInst = Builder.createObjCSuperMethod(
          Loc, getLocalValue(ListOfValues[NextValueIndex], operandTy), DRef,
          Ty);
      break;
    }
    break;
  }
  case SILInstructionKind::WitnessMethodInst: {
    unsigned NextValueIndex = 0;
    SILDeclRef DRef = getSILDeclRef(MF, ListOfValues, NextValueIndex);
    assert(ListOfValues.size() >= NextValueIndex &&
           "Out of entries for MethodInst");

    CanType Ty = MF->getType(TyID)->getCanonicalType();
    SILType OperandTy =
        getSILType(MF->getType(TyID2), (SILValueCategory)TyCategory2, Fn);

    auto Conformance = MF->readConformance(SILCursor);
    // Read the optional opened existential.
    SILValue ExistentialOperand;
    if (TyID3) {
      SILType ExistentialOperandTy =
          getSILType(MF->getType(TyID3), (SILValueCategory)TyCategory3, Fn);
      if (ValID3)
        ExistentialOperand = getLocalValue(ValID3, ExistentialOperandTy);
    }
    ResultInst =
        Builder.createWitnessMethod(Loc, Ty, Conformance, DRef, OperandTy);
    break;
  }
  case SILInstructionKind::DynamicMethodBranchInst: {
    // Format: a typed value, a SILDeclRef, a BasicBlock ID for method,
    // a BasicBlock ID for no method. Use SILOneTypeValuesLayout.
    unsigned NextValueIndex = 1;
    SILDeclRef DRef = getSILDeclRef(MF, ListOfValues, NextValueIndex);
    assert(ListOfValues.size() == NextValueIndex + 2 &&
           "Wrong number of entries for DynamicMethodBranchInst");
    ResultInst = Builder.createDynamicMethodBranch(
        Loc,
        getLocalValue(
            ListOfValues[0],
            getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)),
        DRef, getBBForReference(Fn, ListOfValues[NextValueIndex]),
        getBBForReference(Fn, ListOfValues[NextValueIndex + 1]));
    break;
  }
  case SILInstructionKind::CheckedCastBranchInst: {
    // Format: the cast kind, a typed value, a BasicBlock ID for success,
    // a BasicBlock ID for failure. Uses SILOneTypeValuesLayout.
    bool isExact = ListOfValues[0] != 0;
    SILType opTy = getSILType(MF->getType(ListOfValues[2]),
                              (SILValueCategory)ListOfValues[3], Fn);
    SILValue op = getLocalValue(ListOfValues[1], opTy);
    SILType targetLoweredType =
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn);
    CanType targetFormalType =
        MF->getType(ListOfValues[4])->getCanonicalType();
    auto *successBB = getBBForReference(Fn, ListOfValues[5]);
    auto *failureBB = getBBForReference(Fn, ListOfValues[6]);

    ResultInst =
        Builder.createCheckedCastBranch(Loc, isExact, op, targetLoweredType,
                                        targetFormalType, successBB, failureBB,
                                        forwardingOwnership);
    break;
  }
  case SILInstructionKind::CheckedCastValueBranchInst: {
    CanType srcFormalType = MF->getType(ListOfValues[0])->getCanonicalType();
    SILType srcLoweredType = getSILType(MF->getType(ListOfValues[2]),
                                        (SILValueCategory)ListOfValues[3], Fn);
    SILValue op = getLocalValue(ListOfValues[1], srcLoweredType);
    SILType targetLoweredType =
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn);
    CanType targetFormalType =
        MF->getType(ListOfValues[4])->getCanonicalType();
    auto *successBB = getBBForReference(Fn, ListOfValues[5]);
    auto *failureBB = getBBForReference(Fn, ListOfValues[6]);

    ResultInst = Builder.createCheckedCastValueBranch(
        Loc, op, srcFormalType, targetLoweredType, targetFormalType, successBB,
        failureBB);
    break;
  }
  case SILInstructionKind::UnconditionalCheckedCastValueInst: {
    CanType srcFormalType = MF->getType(ListOfValues[0])->getCanonicalType();
    SILType srcLoweredType = getSILType(MF->getType(ListOfValues[2]),
                                      (SILValueCategory)ListOfValues[3], Fn);
    SILValue src = getLocalValue(ListOfValues[1], srcLoweredType);

    SILType targetLoweredType =
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn);
    CanType targetFormalType = MF->getType(ListOfValues[4])->getCanonicalType();
    ResultInst = Builder.createUnconditionalCheckedCastValue(
        Loc, src, srcFormalType, targetLoweredType, targetFormalType);
    break;
  }
  case SILInstructionKind::UnconditionalCheckedCastAddrInst: {
    // ignore attr.
    CanType srcFormalType = MF->getType(ListOfValues[0])->getCanonicalType();
    SILType srcLoweredType = getSILType(MF->getType(ListOfValues[2]),
                                       (SILValueCategory)ListOfValues[3], Fn);
    SILValue src = getLocalValue(ListOfValues[1], srcLoweredType);

    CanType targetFormalType = MF->getType(ListOfValues[4])->getCanonicalType();
    SILType targetLoweredType =
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn);
    SILValue dest = getLocalValue(ListOfValues[5], targetLoweredType);

    ResultInst = Builder.createUnconditionalCheckedCastAddr(
        Loc, src, srcFormalType, dest, targetFormalType);
    break;
  }
  case SILInstructionKind::CheckedCastAddrBranchInst: {
    CastConsumptionKind consumption = getCastConsumptionKind(ListOfValues[0]);

    CanType srcFormalType = MF->getType(ListOfValues[1])->getCanonicalType();
    SILType srcLoweredType = getSILType(MF->getType(ListOfValues[3]),
                                        (SILValueCategory)ListOfValues[4], Fn);
    SILValue src = getLocalValue(ListOfValues[2], srcLoweredType);

    CanType targetFormalType =
        MF->getType(ListOfValues[5])->getCanonicalType();
    SILType targetLoweredType =
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn);
    SILValue dest = getLocalValue(ListOfValues[6], targetLoweredType);

    auto *successBB = getBBForReference(Fn, ListOfValues[7]);
    auto *failureBB = getBBForReference(Fn, ListOfValues[8]);
    ResultInst = Builder.createCheckedCastAddrBranch(
        Loc, consumption, src, srcFormalType, dest, targetFormalType, successBB,
        failureBB);
    break;
  }
  case SILInstructionKind::UncheckedRefCastAddrInst: {
    CanType sourceType = MF->getType(ListOfValues[0])->getCanonicalType();
    // ignore attr.
    SILType srcAddrTy = getSILType(MF->getType(ListOfValues[2]),
                                   (SILValueCategory)ListOfValues[3], Fn);
    SILValue src = getLocalValue(ListOfValues[1], srcAddrTy);

    CanType targetType = MF->getType(ListOfValues[4])->getCanonicalType();
    SILType destAddrTy =
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn);
    SILValue dest = getLocalValue(ListOfValues[5], destAddrTy);

    ResultInst = Builder.createUncheckedRefCastAddr(Loc, src, sourceType, dest,
                                                    targetType);
    break;
  }
  case SILInstructionKind::InitBlockStorageHeaderInst: {
    assert(ListOfValues.size() == 5 &&
           "expected 5 values for InitBlockStorageHeader");
    SILType blockTy =
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn);

    SILType storageTy = getSILType(MF->getType(ListOfValues[1]),
                                   SILValueCategory::Address, Fn);
    SILValue storage
      = getLocalValue(ListOfValues[0], storageTy);

    SILType invokeTy =
        getSILType(MF->getType(ListOfValues[3]), SILValueCategory::Object, Fn);
    SILValue invoke
      = getLocalValue(ListOfValues[2], invokeTy);
    
    auto SubMap = MF->getSubstitutionMap(ListOfValues[4]);

    ResultInst = Builder.createInitBlockStorageHeader(Loc, storage, invoke,
                                                      blockTy, SubMap);
    break;
  }
  case SILInstructionKind::UnreachableInst: {
    ResultInst = Builder.createUnreachable(Loc);
    break;
  }
  case SILInstructionKind::UnwindInst: {
    ResultInst = Builder.createUnwind(Loc);
    break;
  }
  case SILInstructionKind::YieldInst: {
    SILBasicBlock *unwindBB = getBBForReference(Fn, ListOfValues.back());
    ListOfValues = ListOfValues.drop_back();
    SILBasicBlock *resumeBB = getBBForReference(Fn, ListOfValues.back());
    ListOfValues = ListOfValues.drop_back();

    SmallVector<SILValue, 4> yieldedValues;
    for (unsigned I = 0, E = ListOfValues.size(); I < E; I += 3) {
      auto valueTy = MF->getType(ListOfValues[I]);
      auto valueCategory = (SILValueCategory) ListOfValues[I+1];
      yieldedValues.push_back(getLocalValue(
          ListOfValues[I + 2], getSILType(valueTy, valueCategory, Fn)));
    }

    ResultInst = Builder.createYield(Loc, yieldedValues, resumeBB, unwindBB);
    break;
  }
  case SILInstructionKind::KeyPathInst: {
    unsigned nextValue = 0;
    SILType kpTy =
        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn);

    auto rootTy = MF->getType(ListOfValues[nextValue++]);
    auto valueTy = MF->getType(ListOfValues[nextValue++]);
    auto numComponents = ListOfValues[nextValue++];
    auto numOperands = ListOfValues[nextValue++];
    auto subMap = MF->getSubstitutionMap(ListOfValues[nextValue++]);
    auto objcString = MF->getIdentifierText(ListOfValues[nextValue++]);
    auto numGenericParams = ListOfValues[nextValue++];
    
    SmallVector<GenericTypeParamType *, 4> genericParams;
    while (numGenericParams-- > 0) {
      genericParams.push_back(MF->getType(ListOfValues[nextValue++])
                                ->castTo<GenericTypeParamType>());
    }
    
    SmallVector<KeyPathPatternComponent, 4> components;
    components.reserve(numComponents);
    while (numComponents-- > 0) {
      components.push_back(*readKeyPathComponent(ListOfValues, nextValue));
    }
    
    SmallVector<Requirement, 4> requirements;
    MF->readGenericRequirements(requirements, SILCursor);
    
    CanGenericSignature sig = CanGenericSignature();
    if (!genericParams.empty() || !requirements.empty())
      sig = GenericSignature::get(genericParams, requirements)
                .getCanonicalSignature();

    auto pattern = KeyPathPattern::get(SILMod, sig,
                                       rootTy->getCanonicalType(),
                                       valueTy->getCanonicalType(),
                                       components,
                                       objcString);
    
    SmallVector<SILValue, 4> operands;
    
    operands.reserve(numOperands);
    while (numOperands-- > 0) {
      auto opValue = ListOfValues[nextValue++];
      auto opTy = MF->getType(ListOfValues[nextValue++]);
      auto opCat = (SILValueCategory)ListOfValues[nextValue++];
      operands.push_back(getLocalValue(opValue, getSILType(opTy, opCat, Fn)));
    }

    ResultInst = Builder.createKeyPath(Loc, pattern, subMap, operands, kpTy);
    break;
  }
  case SILInstructionKind::DifferentiableFunctionInst: {
    auto numParams = Attr;
    auto numResults = Attr2;
    auto numParamIndices = Attr3;
    bool hasDerivativeFunctions = (bool)Attr4;
    unsigned numOperands = hasDerivativeFunctions ? 3 : 1;
    auto numResultIndices =
        ListOfValues.size() - numOperands * 3 - numParamIndices;
    assert(ListOfValues.size() ==
           numParamIndices + numResultIndices + numOperands * 3);
    auto rawParamIndices =
        map<SmallVector<unsigned, 8>>(ListOfValues.take_front(numParamIndices),
                                      [](uint64_t i) { return (unsigned)i; });
    auto *paramIndices =
        IndexSubset::get(MF->getContext(), numParams, rawParamIndices);
    auto rawResultIndices = map<SmallVector<unsigned, 8>>(
        ListOfValues.slice(numParamIndices, numResultIndices),
        [](uint64_t i) { return (unsigned)i; });
    auto *resultIndices =
        IndexSubset::get(MF->getContext(), numResults, rawResultIndices);
    SmallVector<SILValue, 3> operands;
    for (auto i = numParamIndices + numResultIndices;
         i < numParamIndices + numOperands * 3; i += 3) {
      auto astTy = MF->getType(ListOfValues[i]);
      auto silTy = getSILType(astTy, (SILValueCategory)ListOfValues[i + 1], Fn);
      operands.push_back(getLocalValue(ListOfValues[i + 2], silTy));
    }
    Optional<std::pair<SILValue, SILValue>> derivativeFunctions = None;
    if (hasDerivativeFunctions)
      derivativeFunctions = std::make_pair(operands[1], operands[2]);
    ResultInst = Builder.createDifferentiableFunction(
        Loc, paramIndices, resultIndices, operands[0], derivativeFunctions);
    break;
  }
  case SILInstructionKind::LinearFunctionInst: {
    auto numDiffParams = Attr;
    bool hasLinearFunction = (bool)Attr2;
    unsigned numOperands = hasLinearFunction ? 2 : 1;
    auto numParamIndices = ListOfValues.size() - numOperands * 3;
    assert(ListOfValues.size() == numParamIndices + numOperands * 3);
    auto rawParamIndices =
       map<SmallVector<unsigned, 8>>(ListOfValues.take_front(numParamIndices),
                                     [](uint64_t i) { return (unsigned)i; });
    auto *paramIndices =
        IndexSubset::get(MF->getContext(), numDiffParams, rawParamIndices);
    SmallVector<SILValue, 3> operands;
    for (auto i = numParamIndices;
         i < numParamIndices + numOperands * 3; i += 3) {
      auto astTy = MF->getType(ListOfValues[i]);
      auto silTy = getSILType(astTy, (SILValueCategory)ListOfValues[i+1], Fn);
      operands.push_back(getLocalValue(ListOfValues[i+2], silTy));
    }
    Optional<SILValue> transposeFunction = None;
    if (hasLinearFunction)
      transposeFunction = operands[1];
    ResultInst = Builder.createLinearFunction(Loc, paramIndices, operands[0],
                                              transposeFunction);
    break;
  }
  case SILInstructionKind::DifferentiableFunctionExtractInst: {
    auto astTy = MF->getType(TyID);
    auto silTy = getSILType(astTy, SILValueCategory::Object, Fn);
    auto val = getLocalValue(ValID, silTy);
    NormalDifferentiableFunctionTypeComponent extractee(Attr);
    Optional<SILType> explicitExtracteeType = None;
    if (Attr2) {
      auto extracteeASTType = MF->getType(TyID2);
      explicitExtracteeType =
          getSILType(extracteeASTType, SILValueCategory::Object, Fn);
    }
    ResultInst = Builder.createDifferentiableFunctionExtract(
        Loc, extractee, val, explicitExtracteeType);
    break;
  }
  case SILInstructionKind::LinearFunctionExtractInst: {
    auto astTy = MF->getType(TyID);
    auto silTy = getSILType(astTy, SILValueCategory::Object, Fn);
    auto val = getLocalValue(ValID, silTy);
    LinearDifferentiableFunctionTypeComponent extractee(Attr);
    ResultInst = Builder.createLinearFunctionExtract(Loc, extractee, val);
    break;
  }
  case SILInstructionKind::DifferentiabilityWitnessFunctionInst: {
    StringRef mangledKey = MF->getIdentifierText(ValID);
    auto *witness = getSILDifferentiabilityWitnessForReference(mangledKey);
    assert(witness && "SILDifferentiabilityWitness not found");
    DifferentiabilityWitnessFunctionKind witnessKind(Attr);
    Optional<SILType> explicitFnTy = None;
    auto astTy = MF->getType(TyID);
    if (TyID)
      explicitFnTy = getSILType(astTy, SILValueCategory::Object, Fn);
    ResultInst = Builder.createDifferentiabilityWitnessFunction(
        Loc, witnessKind, witness, explicitFnTy);
    break;
  }
  }

  for (auto result : ResultInst->getResults()) {
    LastValueID = LastValueID + 1;
    setLocalValue(result, LastValueID);
  }

  return false;
}