in lib/Serialization/SerializeSIL.cpp [860:2471]
void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
PrettyStackTraceSILNode stackTrace("Serializing", &SI);
switch (SI.getKind()) {
case SILInstructionKind::ObjectInst: {
const ObjectInst *OI = cast<ObjectInst>(&SI);
unsigned abbrCode = SILAbbrCodes[SILOneTypeValuesLayout::Code];
SmallVector<ValueID, 4> Args;
Args.push_back((unsigned)OI->getBaseElements().size());
for (const Operand &op : OI->getAllOperands()) {
SILValue OpVal = op.get();
Args.push_back(addValueRef(OpVal));
SILType OpType = OpVal->getType();
assert(OpType.isObject());
Args.push_back(S.addTypeRef(OpType.getASTType()));
}
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord, abbrCode,
(unsigned)SI.getKind(),
S.addTypeRef(
OI->getType().getASTType()),
(unsigned)OI->getType().getCategory(),
Args);
break;
}
case SILInstructionKind::DebugValueInst:
// Currently we don't serialize debug variable infos, so it doesn't make
// sense to write the instruction at all.
// TODO: decide if we want to serialize those instructions.
return;
case SILInstructionKind::UnwindInst:
case SILInstructionKind::UnreachableInst: {
writeNoOperandLayout(&SI);
break;
}
case SILInstructionKind::AllocExistentialBoxInst:
case SILInstructionKind::InitExistentialAddrInst:
case SILInstructionKind::InitExistentialValueInst:
case SILInstructionKind::InitExistentialMetatypeInst:
case SILInstructionKind::InitExistentialRefInst: {
SILValue operand;
SILType Ty;
CanType FormalConcreteType;
ArrayRef<ProtocolConformanceRef> conformances;
switch (SI.getKind()) {
default: llvm_unreachable("out of sync with parent");
case SILInstructionKind::InitExistentialAddrInst: {
auto &IEI = cast<InitExistentialAddrInst>(SI);
operand = IEI.getOperand();
Ty = IEI.getLoweredConcreteType();
FormalConcreteType = IEI.getFormalConcreteType();
conformances = IEI.getConformances();
break;
}
case SILInstructionKind::InitExistentialValueInst: {
auto &IEOI = cast<InitExistentialValueInst>(SI);
operand = IEOI.getOperand();
Ty = IEOI.getType();
FormalConcreteType = IEOI.getFormalConcreteType();
conformances = IEOI.getConformances();
break;
}
case SILInstructionKind::InitExistentialRefInst: {
auto &IERI = cast<InitExistentialRefInst>(SI);
operand = IERI.getOperand();
Ty = IERI.getType();
FormalConcreteType = IERI.getFormalConcreteType();
conformances = IERI.getConformances();
break;
}
case SILInstructionKind::InitExistentialMetatypeInst: {
auto &IEMI = cast<InitExistentialMetatypeInst>(SI);
operand = IEMI.getOperand();
Ty = IEMI.getType();
conformances = IEMI.getConformances();
break;
}
case SILInstructionKind::AllocExistentialBoxInst: {
auto &AEBI = cast<AllocExistentialBoxInst>(SI);
Ty = AEBI.getExistentialType();
FormalConcreteType = AEBI.getFormalConcreteType();
conformances = AEBI.getConformances();
break;
}
}
TypeID operandType = 0;
SILValueCategory operandCategory = SILValueCategory::Object;
ValueID operandID = 0;
if (operand) {
operandType = S.addTypeRef(operand->getType().getASTType());
operandCategory = operand->getType().getCategory();
operandID = addValueRef(operand);
}
unsigned abbrCode = SILAbbrCodes[SILInitExistentialLayout::Code];
SILInitExistentialLayout::emitRecord(Out, ScratchRecord, abbrCode,
(unsigned)SI.getKind(),
S.addTypeRef(Ty.getASTType()),
(unsigned)Ty.getCategory(),
operandType,
(unsigned)operandCategory,
operandID,
S.addTypeRef(FormalConcreteType),
conformances.size());
for (auto conformance : conformances) {
S.writeConformance(conformance, SILAbbrCodes);
}
break;
}
case SILInstructionKind::DeallocBoxInst: {
auto DBI = cast<DeallocBoxInst>(&SI);
writeOneTypeOneOperandLayout(DBI->getKind(), 0,
DBI->getOperand()->getType(),
DBI->getOperand());
break;
}
case SILInstructionKind::DeallocExistentialBoxInst: {
auto DBI = cast<DeallocExistentialBoxInst>(&SI);
writeOneTypeOneOperandLayout(DBI->getKind(), 0,
DBI->getConcreteType(),
DBI->getOperand());
break;
}
case SILInstructionKind::ValueMetatypeInst: {
auto VMI = cast<ValueMetatypeInst>(&SI);
writeOneTypeOneOperandLayout(VMI->getKind(), 0,
VMI->getType(),
VMI->getOperand());
break;
}
case SILInstructionKind::ExistentialMetatypeInst: {
auto EMI = cast<ExistentialMetatypeInst>(&SI);
writeOneTypeOneOperandLayout(EMI->getKind(), 0,
EMI->getType(),
EMI->getOperand());
break;
}
case SILInstructionKind::AllocBoxInst: {
const AllocBoxInst *ABI = cast<AllocBoxInst>(&SI);
writeOneTypeLayout(ABI->getKind(), ABI->hasDynamicLifetime() ? 1 : 0,
ABI->getType());
break;
}
case SILInstructionKind::AllocRefInst:
case SILInstructionKind::AllocRefDynamicInst: {
const AllocRefInstBase *ARI = cast<AllocRefInstBase>(&SI);
unsigned abbrCode = SILAbbrCodes[SILOneTypeValuesLayout::Code];
SmallVector<ValueID, 4> Args;
Args.push_back((unsigned)ARI->isObjC() |
((unsigned)ARI->canAllocOnStack() << 1));
ArrayRef<SILType> TailTypes = ARI->getTailAllocatedTypes();
ArrayRef<Operand> AllOps = ARI->getAllOperands();
unsigned NumTailAllocs = TailTypes.size();
unsigned NumOpsToWrite = NumTailAllocs;
if (SI.getKind() == SILInstructionKind::AllocRefDynamicInst)
++NumOpsToWrite;
for (unsigned Idx = 0; Idx < NumOpsToWrite; ++Idx) {
if (Idx < NumTailAllocs) {
assert(TailTypes[Idx].isObject());
Args.push_back(S.addTypeRef(TailTypes[Idx].getASTType()));
}
SILValue OpVal = AllOps[Idx].get();
Args.push_back(addValueRef(OpVal));
SILType OpType = OpVal->getType();
assert(OpType.isObject());
Args.push_back(S.addTypeRef(OpType.getASTType()));
}
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord, abbrCode,
(unsigned)SI.getKind(),
S.addTypeRef(
ARI->getType().getASTType()),
(unsigned)ARI->getType().getCategory(),
Args);
break;
}
case SILInstructionKind::AllocStackInst: {
const AllocStackInst *ASI = cast<AllocStackInst>(&SI);
unsigned attr =
unsigned(ASI->hasDynamicLifetime()) + unsigned(ASI->isLexical() << 1);
writeOneTypeLayout(ASI->getKind(), attr, ASI->getElementType());
break;
}
case SILInstructionKind::ProjectBoxInst: {
auto PBI = cast<ProjectBoxInst>(&SI);
// Use SILOneTypeOneOperandLayout with the field index crammed in the TypeID
auto boxOperand = PBI->getOperand();
auto boxRef = addValueRef(boxOperand);
auto boxType = boxOperand->getType();
auto boxTypeRef = S.addTypeRef(boxType.getASTType());
SILOneTypeOneOperandLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeOneOperandLayout::Code],
unsigned(PBI->getKind()), 0,
PBI->getFieldIndex(), 0,
boxTypeRef, unsigned(boxType.getCategory()),
boxRef);
break;
}
case SILInstructionKind::ProjectExistentialBoxInst: {
auto PEBI = cast<ProjectExistentialBoxInst>(&SI);
writeOneTypeOneOperandLayout(PEBI->getKind(), 0,
PEBI->getType(),
PEBI->getOperand());
break;
}
case SILInstructionKind::BuiltinInst: {
// Format: substitutions map ID, the builtin name, result type, and
// a list of values for the arguments. Each value in the list
// is represented with 4 IDs:
// ValueID, ValueResultNumber, TypeID, TypeCategory.
// The record is followed by the substitution list.
const BuiltinInst *BI = cast<BuiltinInst>(&SI);
SmallVector<ValueID, 4> Args;
for (auto Arg : BI->getArguments()) {
Args.push_back(addValueRef(Arg));
Args.push_back(S.addTypeRef(Arg->getType().getASTType()));
Args.push_back((unsigned)Arg->getType().getCategory());
}
SILInstApplyLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILInstApplyLayout::Code],
SIL_BUILTIN, 0,
S.addSubstitutionMapRef(BI->getSubstitutions()),
S.addTypeRef(BI->getType().getASTType()),
(unsigned)BI->getType().getCategory(),
S.addDeclBaseNameRef(BI->getName()),
Args);
break;
}
case SILInstructionKind::ApplyInst: {
// Format: attributes such as transparent and number of substitutions,
// the callee's substituted and unsubstituted types, 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 record
// is followed by the substitution list.
const ApplyInst *AI = cast<ApplyInst>(&SI);
SmallVector<ValueID, 4> Args;
for (auto Arg: AI->getArguments()) {
Args.push_back(addValueRef(Arg));
}
SILInstApplyLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILInstApplyLayout::Code],
SIL_APPLY,
unsigned(AI->getApplyOptions().toRaw()),
S.addSubstitutionMapRef(AI->getSubstitutionMap()),
S.addTypeRef(AI->getCallee()->getType().getASTType()),
S.addTypeRef(AI->getSubstCalleeType()),
addValueRef(AI->getCallee()),
Args);
break;
}
case SILInstructionKind::BeginApplyInst: {
// Format: attributes such as transparent and number of substitutions,
// the callee's substituted and unsubstituted types, 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 record
// is followed by the substitution list.
const BeginApplyInst *AI = cast<BeginApplyInst>(&SI);
SmallVector<ValueID, 4> Args;
for (auto Arg: AI->getArguments()) {
Args.push_back(addValueRef(Arg));
}
SILInstApplyLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILInstApplyLayout::Code], SIL_BEGIN_APPLY,
unsigned(AI->getApplyOptions().toRaw()),
S.addSubstitutionMapRef(AI->getSubstitutionMap()),
S.addTypeRef(AI->getCallee()->getType().getASTType()),
S.addTypeRef(AI->getSubstCalleeType()),
addValueRef(AI->getCallee()),
Args);
break;
}
case SILInstructionKind::TryApplyInst: {
// Format: attributes such as transparent and number of substitutions,
// the callee's substituted and unsubstituted types, 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
// entries in the list are the basic block destinations. The record
// is followed by the substitution list.
const TryApplyInst *AI = cast<TryApplyInst>(&SI);
SmallVector<ValueID, 4> Args;
for (auto Arg: AI->getArguments()) {
Args.push_back(addValueRef(Arg));
}
Args.push_back(BasicBlockMap[AI->getNormalBB()]);
Args.push_back(BasicBlockMap[AI->getErrorBB()]);
SILInstApplyLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILInstApplyLayout::Code], SIL_TRY_APPLY,
unsigned(AI->getApplyOptions().toRaw()),
S.addSubstitutionMapRef(AI->getSubstitutionMap()),
S.addTypeRef(AI->getCallee()->getType().getASTType()),
S.addTypeRef(AI->getSubstCalleeType()),
addValueRef(AI->getCallee()),
Args);
break;
}
case SILInstructionKind::PartialApplyInst: {
const PartialApplyInst *PAI = cast<PartialApplyInst>(&SI);
SmallVector<ValueID, 4> Args;
for (auto Arg: PAI->getArguments()) {
Args.push_back(addValueRef(Arg));
}
SILInstApplyLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILInstApplyLayout::Code], SIL_PARTIAL_APPLY,
0,
S.addSubstitutionMapRef(PAI->getSubstitutionMap()),
S.addTypeRef(PAI->getCallee()->getType().getASTType()),
S.addTypeRef(PAI->getType().getASTType()),
addValueRef(PAI->getCallee()),
Args);
break;
}
case SILInstructionKind::AllocGlobalInst: {
// Format: Name and type. Use SILOneOperandLayout.
const AllocGlobalInst *AGI = cast<AllocGlobalInst>(&SI);
auto *G = AGI->getReferencedGlobal();
addReferencedGlobalVariable(G);
SILOneOperandLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneOperandLayout::Code],
(unsigned)SI.getKind(), 0, 0, 0,
S.addUniquedStringRef(G->getName()));
break;
}
case SILInstructionKind::GlobalAddrInst:
case SILInstructionKind::GlobalValueInst: {
// Format: Name and type. Use SILOneOperandLayout.
const GlobalAccessInst *GI = cast<GlobalAccessInst>(&SI);
auto *G = GI->getReferencedGlobal();
addReferencedGlobalVariable(G);
SILOneOperandLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneOperandLayout::Code],
(unsigned)SI.getKind(), 0,
S.addTypeRef(GI->getType().getASTType()),
(unsigned)GI->getType().getCategory(),
S.addUniquedStringRef(G->getName()));
break;
}
case SILInstructionKind::BaseAddrForOffsetInst: {
const BaseAddrForOffsetInst *BAI = cast<BaseAddrForOffsetInst>(&SI);
writeOneTypeLayout(BAI->getKind(), /*attrs*/ 0, BAI->getType());
break;
}
case SILInstructionKind::BranchInst: {
// Format: destination basic block ID, a list of arguments. Use
// SILOneTypeValuesLayout.
const BranchInst *BrI = cast<BranchInst>(&SI);
SmallVector<ValueID, 4> ListOfValues;
for (auto Elt : BrI->getArgs()) {
ListOfValues.push_back(S.addTypeRef(Elt->getType().getASTType()));
ListOfValues.push_back((unsigned)Elt->getType().getCategory());
ListOfValues.push_back(addValueRef(Elt));
}
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code],
(unsigned)SI.getKind(),
BasicBlockMap[BrI->getDestBB()], 0, ListOfValues);
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.
const CondBranchInst *CBI = cast<CondBranchInst>(&SI);
SmallVector<ValueID, 4> ListOfValues;
ListOfValues.push_back(addValueRef(CBI->getCondition()));
ListOfValues.push_back(BasicBlockMap[CBI->getTrueBB()]);
ListOfValues.push_back(BasicBlockMap[CBI->getFalseBB()]);
ListOfValues.push_back(CBI->getTrueArgs().size());
for (auto Elt : CBI->getTrueArgs()) {
ListOfValues.push_back(S.addTypeRef(Elt->getType().getASTType()));
ListOfValues.push_back((unsigned)Elt->getType().getCategory());
ListOfValues.push_back(addValueRef(Elt));
}
for (auto Elt : CBI->getFalseArgs()) {
ListOfValues.push_back(S.addTypeRef(Elt->getType().getASTType()));
ListOfValues.push_back((unsigned)Elt->getType().getCategory());
ListOfValues.push_back(addValueRef(Elt));
}
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code],
(unsigned)SI.getKind(),
S.addTypeRef(CBI->getCondition()->getType().getASTType()),
(unsigned)CBI->getCondition()->getType().getCategory(),
ListOfValues);
break;
}
case SILInstructionKind::AwaitAsyncContinuationInst: {
const AwaitAsyncContinuationInst *AACI
= cast<AwaitAsyncContinuationInst>(&SI);
// Format: continuation, resume block ID, error block ID if given
SmallVector<ValueID, 3> ListOfValues;
ListOfValues.push_back(addValueRef(AACI->getOperand()));
ListOfValues.push_back(BasicBlockMap[AACI->getResumeBB()]);
if (auto errorBB = AACI->getErrorBB()) {
ListOfValues.push_back(BasicBlockMap[errorBB]);
}
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code],
(unsigned)SI.getKind(),
S.addTypeRef(AACI->getOperand()->getType().getASTType()),
(unsigned)AACI->getOperand()->getType().getCategory(),
ListOfValues);
break;
}
case SILInstructionKind::SwitchEnumInst:
case SILInstructionKind::SwitchEnumAddrInst: {
// Format:
// - [ownership]
// - the type of the condition operand,
// - a list a values: operand, hasDefault, defaultBB,
// [EnumElementDecl, Basic Block ID]*
SwitchEnumTermInst SOI(&SI);
assert(SOI);
SmallVector<ValueID, 4> ListOfValues;
ListOfValues.push_back(addValueRef(SOI.getOperand()));
ListOfValues.push_back((unsigned)SOI.hasDefault());
if (SOI.hasDefault())
ListOfValues.push_back(BasicBlockMap[SOI.getDefaultBB()]);
else
ListOfValues.push_back(0);
for (unsigned i = 0, e = SOI.getNumCases(); i < e; ++i) {
EnumElementDecl *elt;
SILBasicBlock *dest;
std::tie(elt, dest) = SOI.getCase(i);
ListOfValues.push_back(S.addDeclRef(elt));
ListOfValues.push_back(BasicBlockMap[dest]);
}
if (auto *switchEnum = dyn_cast<SwitchEnumInst>(&SI)) {
unsigned ownershipField =
encodeValueOwnership(switchEnum->getForwardingOwnershipKind());
SILOneTypeOwnershipValuesLayout::emitRecord(
Out, ScratchRecord,
SILAbbrCodes[SILOneTypeOwnershipValuesLayout::Code],
(unsigned)SI.getKind(), ownershipField,
S.addTypeRef(SOI.getOperand()->getType().getASTType()),
(unsigned)SOI.getOperand()->getType().getCategory(), ListOfValues);
} else {
SILOneTypeValuesLayout::emitRecord(
Out, ScratchRecord, SILAbbrCodes[SILOneTypeValuesLayout::Code],
(unsigned)SI.getKind(),
S.addTypeRef(SOI.getOperand()->getType().getASTType()),
(unsigned)SOI.getOperand()->getType().getCategory(), ListOfValues);
}
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).
const SelectEnumInstBase *SOI = cast<SelectEnumInstBase>(&SI);
SmallVector<ValueID, 4> ListOfValues;
ListOfValues.push_back(addValueRef(SOI->getEnumOperand()));
ListOfValues.push_back(S.addTypeRef(SOI->getType().getASTType()));
ListOfValues.push_back((unsigned)SOI->getType().getCategory());
ListOfValues.push_back((unsigned)SOI->hasDefault());
if (SOI->hasDefault()) {
ListOfValues.push_back(addValueRef(SOI->getDefaultResult()));
} else {
ListOfValues.push_back(0);
}
for (unsigned i = 0, e = SOI->getNumCases(); i < e; ++i) {
EnumElementDecl *elt;
SILValue result;
std::tie(elt, result) = SOI->getCase(i);
ListOfValues.push_back(S.addDeclRef(elt));
ListOfValues.push_back(addValueRef(result));
}
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code],
(unsigned)SI.getKind(),
S.addTypeRef(SOI->getEnumOperand()->getType().getASTType()),
(unsigned)SOI->getEnumOperand()->getType().getCategory(),
ListOfValues);
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).
const SwitchValueInst *SII = cast<SwitchValueInst>(&SI);
SmallVector<ValueID, 4> ListOfValues;
ListOfValues.push_back(addValueRef(SII->getOperand()));
ListOfValues.push_back((unsigned)SII->hasDefault());
if (SII->hasDefault())
ListOfValues.push_back(BasicBlockMap[SII->getDefaultBB()]);
else
ListOfValues.push_back(0);
for (unsigned i = 0, e = SII->getNumCases(); i < e; ++i) {
SILValue value;
SILBasicBlock *dest;
std::tie(value, dest) = SII->getCase(i);
ListOfValues.push_back(addValueRef(value));
ListOfValues.push_back(BasicBlockMap[dest]);
}
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code],
(unsigned)SI.getKind(),
S.addTypeRef(SII->getOperand()->getType().getASTType()),
(unsigned)SII->getOperand()->getType().getCategory(),
ListOfValues);
break;
}
case SILInstructionKind::SelectValueInst: {
// Format: condition, a list of cases (Value ID + 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).
const SelectValueInst *SVI = cast<SelectValueInst>(&SI);
SmallVector<ValueID, 4> ListOfValues;
ListOfValues.push_back(addValueRef(SVI->getOperand()));
ListOfValues.push_back(S.addTypeRef(SVI->getType().getASTType()));
ListOfValues.push_back((unsigned)SVI->getType().getCategory());
ListOfValues.push_back((unsigned)SVI->hasDefault());
if (SVI->hasDefault()) {
ListOfValues.push_back(addValueRef(SVI->getDefaultResult()));
} else {
ListOfValues.push_back(0);
}
for (unsigned i = 0, e = SVI->getNumCases(); i < e; ++i) {
SILValue casevalue;
SILValue result;
std::tie(casevalue, result) = SVI->getCase(i);
ListOfValues.push_back(addValueRef(casevalue));
ListOfValues.push_back(addValueRef(result));
}
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code],
(unsigned)SI.getKind(),
S.addTypeRef(SVI->getOperand()->getType().getASTType()),
(unsigned)SVI->getOperand()->getType().getCategory(),
ListOfValues);
break;
}
#define UNCHECKED_REF_STORAGE(Name, ...) \
case SILInstructionKind::StrongCopy##Name##ValueInst:
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
case SILInstructionKind::Load##Name##Inst:
#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
case SILInstructionKind::Name##RetainInst: \
case SILInstructionKind::Name##ReleaseInst: \
case SILInstructionKind::StrongRetain##Name##Inst: \
case SILInstructionKind::StrongCopy##Name##ValueInst:
#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, "...") \
ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, "...")
#include "swift/AST/ReferenceStorage.def"
case SILInstructionKind::RetainValueInst:
case SILInstructionKind::DestructureStructInst:
case SILInstructionKind::DestructureTupleInst:
case SILInstructionKind::RetainValueAddrInst:
case SILInstructionKind::UnmanagedRetainValueInst:
case SILInstructionKind::EndBorrowInst:
case SILInstructionKind::CopyValueInst:
case SILInstructionKind::ExplicitCopyValueInst:
case SILInstructionKind::MoveValueInst:
case SILInstructionKind::DestroyValueInst:
case SILInstructionKind::ReleaseValueInst:
case SILInstructionKind::ReleaseValueAddrInst:
case SILInstructionKind::UnmanagedReleaseValueInst:
case SILInstructionKind::AutoreleaseValueInst:
case SILInstructionKind::UnmanagedAutoreleaseValueInst:
case SILInstructionKind::SetDeallocatingInst:
case SILInstructionKind::DeallocStackInst:
case SILInstructionKind::DeallocStackRefInst:
case SILInstructionKind::DeallocRefInst:
case SILInstructionKind::DeinitExistentialAddrInst:
case SILInstructionKind::DeinitExistentialValueInst:
case SILInstructionKind::DestroyAddrInst:
case SILInstructionKind::LoadInst:
case SILInstructionKind::LoadBorrowInst:
case SILInstructionKind::BeginBorrowInst:
case SILInstructionKind::ClassifyBridgeObjectInst:
case SILInstructionKind::ValueToBridgeObjectInst:
case SILInstructionKind::FixLifetimeInst:
case SILInstructionKind::EndLifetimeInst:
case SILInstructionKind::CopyBlockInst:
case SILInstructionKind::StrongReleaseInst:
case SILInstructionKind::StrongRetainInst:
case SILInstructionKind::IsUniqueInst:
case SILInstructionKind::BeginCOWMutationInst:
case SILInstructionKind::EndCOWMutationInst:
case SILInstructionKind::HopToExecutorInst:
case SILInstructionKind::ExtractExecutorInst:
case SILInstructionKind::AbortApplyInst:
case SILInstructionKind::EndApplyInst:
case SILInstructionKind::ReturnInst:
case SILInstructionKind::UncheckedOwnershipConversionInst:
case SILInstructionKind::IsEscapingClosureInst:
case SILInstructionKind::ThrowInst: {
unsigned Attr = 0;
if (auto *LI = dyn_cast<LoadInst>(&SI))
Attr = unsigned(LI->getOwnershipQualifier());
#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
else if (auto *LI = dyn_cast<Load##Name##Inst>(&SI)) \
Attr = LI->isTake();
#include "swift/AST/ReferenceStorage.def"
else if (auto *RCI = dyn_cast<RefCountingInst>(&SI))
Attr = RCI->isNonAtomic();
else if (auto *UOCI = dyn_cast<UncheckedOwnershipConversionInst>(&SI)) {
Attr = encodeValueOwnership(UOCI->getOwnershipKind());
} else if (auto *IEC = dyn_cast<IsEscapingClosureInst>(&SI)) {
Attr = IEC->getVerificationType();
} else if (auto *HTE = dyn_cast<HopToExecutorInst>(&SI)) {
Attr = HTE->isMandatory();
} else if (auto *DVI = dyn_cast<DestroyValueInst>(&SI)) {
Attr = DVI->poisonRefs();
} else if (auto *BCMI = dyn_cast<BeginCOWMutationInst>(&SI)) {
Attr = BCMI->isNative();
} else if (auto *ECMI = dyn_cast<EndCOWMutationInst>(&SI)) {
Attr = ECMI->doKeepUnique();
} else if (auto *BBI = dyn_cast<BeginBorrowInst>(&SI)) {
Attr = BBI->isLexical();
} else if (auto *MVI = dyn_cast<MoveValueInst>(&SI)) {
Attr = unsigned(MVI->getAllowDiagnostics()) |
(unsigned(MVI->isLexical() << 1));
}
writeOneOperandLayout(SI.getKind(), Attr, SI.getOperand(0));
break;
}
case SILInstructionKind::MarkUninitializedInst: {
unsigned Attr =
(unsigned)cast<MarkUninitializedInst>(&SI)->getMarkUninitializedKind();
writeOneOperandExtraAttributeLayout(SI.getKind(), Attr, SI.getOperand(0));
break;
}
case SILInstructionKind::YieldInst: {
auto YI = cast<YieldInst>(&SI);
SmallVector<ValueID, 4> args;
for (auto arg: YI->getYieldedValues()) {
args.push_back(S.addTypeRef(arg->getType().getASTType()));
args.push_back((unsigned)arg->getType().getCategory());
args.push_back(addValueRef(arg));
}
args.push_back(BasicBlockMap[YI->getResumeBB()]);
args.push_back(BasicBlockMap[YI->getUnwindBB()]);
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code],
(unsigned)YI->getKind(), 0, 0, args);
break;
}
case SILInstructionKind::FunctionRefInst: {
// Use SILOneOperandLayout to specify the function type and the function
// name (IdentifierID).
const FunctionRefInst *FRI = cast<FunctionRefInst>(&SI);
SILFunction *ReferencedFunction = FRI->getReferencedFunction();
unsigned abbrCode = SILAbbrCodes[SILOneOperandLayout::Code];
SILOneOperandLayout::emitRecord(Out, ScratchRecord, abbrCode,
(unsigned)SI.getKind(), 0,
S.addTypeRef(FRI->getType().getASTType()),
(unsigned)FRI->getType().getCategory(),
addSILFunctionRef(ReferencedFunction));
break;
}
case SILInstructionKind::DynamicFunctionRefInst: {
// Use SILOneOperandLayout to specify the function type and the function
// name (IdentifierID).
const auto *FRI = cast<DynamicFunctionRefInst>(&SI);
SILFunction *ReferencedFunction = FRI->getInitiallyReferencedFunction();
unsigned abbrCode = SILAbbrCodes[SILOneOperandLayout::Code];
SILOneOperandLayout::emitRecord(Out, ScratchRecord, abbrCode,
(unsigned)SI.getKind(), 0,
S.addTypeRef(FRI->getType().getASTType()),
(unsigned)FRI->getType().getCategory(),
addSILFunctionRef(ReferencedFunction));
break;
}
case SILInstructionKind::PreviousDynamicFunctionRefInst: {
// Use SILOneOperandLayout to specify the function type and the function
// name (IdentifierID).
const auto *FRI = cast<PreviousDynamicFunctionRefInst>(&SI);
SILFunction *ReferencedFunction = FRI->getInitiallyReferencedFunction();
unsigned abbrCode = SILAbbrCodes[SILOneOperandLayout::Code];
SILOneOperandLayout::emitRecord(Out, ScratchRecord, abbrCode,
(unsigned)SI.getKind(), 0,
S.addTypeRef(FRI->getType().getASTType()),
(unsigned)FRI->getType().getCategory(),
addSILFunctionRef(ReferencedFunction));
break;
}
case SILInstructionKind::CopyBlockWithoutEscapingInst:
case SILInstructionKind::DeallocPartialRefInst:
case SILInstructionKind::MarkDependenceInst:
case SILInstructionKind::IndexAddrInst:
case SILInstructionKind::IndexRawPointerInst: {
SILValue operand, operand2;
unsigned Attr = 0;
if (SI.getKind() == SILInstructionKind::CopyBlockWithoutEscapingInst) {
const CopyBlockWithoutEscapingInst *C = cast<CopyBlockWithoutEscapingInst>(&SI);
operand = C->getBlock();
operand2 = C->getClosure();
} else if (SI.getKind() == SILInstructionKind::DeallocPartialRefInst) {
const DeallocPartialRefInst *DPRI = cast<DeallocPartialRefInst>(&SI);
operand = DPRI->getInstance();
operand2 = DPRI->getMetatype();
} else if (SI.getKind() == SILInstructionKind::IndexRawPointerInst) {
const IndexRawPointerInst *IRP = cast<IndexRawPointerInst>(&SI);
operand = IRP->getBase();
operand2 = IRP->getIndex();
} else if (SI.getKind() == SILInstructionKind::MarkDependenceInst) {
const MarkDependenceInst *MDI = cast<MarkDependenceInst>(&SI);
operand = MDI->getValue();
operand2 = MDI->getBase();
} else {
const IndexAddrInst *IAI = cast<IndexAddrInst>(&SI);
operand = IAI->getBase();
operand2 = IAI->getIndex();
}
SILTwoOperandsLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILTwoOperandsLayout::Code],
(unsigned)SI.getKind(), Attr,
S.addTypeRef(operand->getType().getASTType()),
(unsigned)operand->getType().getCategory(),
addValueRef(operand),
S.addTypeRef(operand2->getType().getASTType()),
(unsigned)operand2->getType().getCategory(),
addValueRef(operand2));
break;
}
case SILInstructionKind::TailAddrInst: {
const TailAddrInst *TAI = cast<TailAddrInst>(&SI);
SILTailAddrLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILTailAddrLayout::Code],
(unsigned)SI.getKind(),
S.addTypeRef(TAI->getBase()->getType().getASTType()),
addValueRef(TAI->getBase()),
S.addTypeRef(TAI->getIndex()->getType().getASTType()),
addValueRef(TAI->getIndex()),
S.addTypeRef(TAI->getTailType().getASTType()));
break;
}
case SILInstructionKind::CondFailInst: {
auto *CFI = cast<CondFailInst>(&SI);
SILValue operand = CFI->getOperand();
SILTwoOperandsLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILTwoOperandsLayout::Code],
(unsigned)SI.getKind(), /*attributes*/ 0,
S.addTypeRef(operand->getType().getASTType()),
(unsigned)operand->getType().getCategory(),
addValueRef(operand),
0, 0, S.addUniquedStringRef(CFI->getMessage()));
break;
}
case SILInstructionKind::StringLiteralInst: {
auto SLI = cast<StringLiteralInst>(&SI);
StringRef Str = SLI->getValue();
unsigned abbrCode = SILAbbrCodes[SILOneOperandLayout::Code];
unsigned encoding = toStableStringEncoding(SLI->getEncoding());
SILOneOperandLayout::emitRecord(Out, ScratchRecord, abbrCode,
(unsigned)SI.getKind(), encoding, 0, 0,
S.addUniquedStringRef(Str));
break;
}
case SILInstructionKind::FloatLiteralInst:
case SILInstructionKind::IntegerLiteralInst: {
// Use SILOneOperandLayout to specify the type and the literal.
llvm::SmallString<10> Str;
SILType Ty;
switch (SI.getKind()) {
default: llvm_unreachable("Out of sync with parent switch");
case SILInstructionKind::IntegerLiteralInst:
cast<IntegerLiteralInst>(&SI)->getValue().toString(Str, 10,
/*signed*/ true);
Ty = cast<IntegerLiteralInst>(&SI)->getType();
break;
case SILInstructionKind::FloatLiteralInst:
cast<FloatLiteralInst>(&SI)->getBits().toString(Str, 16,
/*signed*/ true);
Ty = cast<FloatLiteralInst>(&SI)->getType();
break;
}
unsigned abbrCode = SILAbbrCodes[SILOneOperandLayout::Code];
SILOneOperandLayout::emitRecord(
Out, ScratchRecord, abbrCode, (unsigned)SI.getKind(), 0,
S.addTypeRef(Ty.getASTType()), (unsigned)Ty.getCategory(),
S.addUniquedStringRef(Str.str()));
break;
}
case SILInstructionKind::MarkFunctionEscapeInst: {
// Format: a list of typed values. A typed value is expressed by 4 IDs:
// TypeID, TypeCategory, ValueID, ValueResultNumber.
const MarkFunctionEscapeInst *MFE = cast<MarkFunctionEscapeInst>(&SI);
SmallVector<ValueID, 4> ListOfValues;
for (auto Elt : MFE->getElements()) {
ListOfValues.push_back(S.addTypeRef(Elt->getType().getASTType()));
ListOfValues.push_back((unsigned)Elt->getType().getCategory());
ListOfValues.push_back(addValueRef(Elt));
}
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code],
(unsigned)SI.getKind(), 0, 0, ListOfValues);
break;
}
case SILInstructionKind::MetatypeInst: {
auto &MI = cast<MetatypeInst>(SI);
writeOneTypeLayout(MI.getKind(), 0, MI.getType());
break;
}
case SILInstructionKind::ObjCProtocolInst: {
const ObjCProtocolInst *PI = cast<ObjCProtocolInst>(&SI);
unsigned abbrCode = SILAbbrCodes[SILOneOperandLayout::Code];
SILOneOperandLayout::emitRecord(Out, ScratchRecord, abbrCode,
(unsigned)SI.getKind(), 0,
S.addTypeRef(PI->getType().getASTType()),
(unsigned)PI->getType().getCategory(),
S.addDeclRef(PI->getProtocol()));
break;
}
case SILInstructionKind::OpenExistentialAddrInst: {
auto &open = cast<OpenExistentialAddrInst>(SI);
assert(open.getNumOperands() - open.getTypeDependentOperands().size() == 1);
unsigned attrs = open.getAccessKind() == OpenedExistentialAccess::Immutable
? 0 : 1;
writeOneTypeOneOperandLayout(open.getKind(), attrs, open.getType(),
open.getOperand());
break;
}
case SILInstructionKind::GetAsyncContinuationAddrInst: {
auto &gaca = cast<GetAsyncContinuationAddrInst>(SI);
writeOneTypeOneOperandLayout(gaca.getKind(), gaca.throws(),
gaca.getFormalResumeType(),
gaca.getOperand());
break;
}
case SILInstructionKind::GetAsyncContinuationInst: {
auto &gaca = cast<GetAsyncContinuationInst>(SI);
writeOneTypeLayout(gaca.getKind(), gaca.throws(),
gaca.getFormalResumeType());
break;
}
// Conversion instructions (and others of similar form).
#define LOADABLE_REF_STORAGE(Name, ...) \
case SILInstructionKind::RefTo##Name##Inst: \
case SILInstructionKind::Name##ToRefInst:
#include "swift/AST/ReferenceStorage.def"
case SILInstructionKind::OpenExistentialRefInst:
case SILInstructionKind::OpenExistentialMetatypeInst:
case SILInstructionKind::OpenExistentialBoxInst:
case SILInstructionKind::OpenExistentialValueInst:
case SILInstructionKind::OpenExistentialBoxValueInst:
case SILInstructionKind::UncheckedRefCastInst:
case SILInstructionKind::UncheckedAddrCastInst:
case SILInstructionKind::UncheckedTrivialBitCastInst:
case SILInstructionKind::UncheckedBitwiseCastInst:
case SILInstructionKind::UncheckedValueCastInst:
case SILInstructionKind::BridgeObjectToRefInst:
case SILInstructionKind::BridgeObjectToWordInst:
case SILInstructionKind::UpcastInst:
case SILInstructionKind::AddressToPointerInst:
case SILInstructionKind::RefToRawPointerInst:
case SILInstructionKind::RawPointerToRefInst:
case SILInstructionKind::ThinToThickFunctionInst:
case SILInstructionKind::ThickToObjCMetatypeInst:
case SILInstructionKind::ObjCToThickMetatypeInst:
case SILInstructionKind::ConvertFunctionInst:
case SILInstructionKind::ConvertEscapeToNoEscapeInst:
case SILInstructionKind::ThinFunctionToPointerInst:
case SILInstructionKind::PointerToThinFunctionInst:
case SILInstructionKind::ObjCMetatypeToObjectInst:
case SILInstructionKind::ObjCExistentialMetatypeToObjectInst:
case SILInstructionKind::ProjectBlockStorageInst: {
unsigned attrs = 0;
if (SI.getKind() == SILInstructionKind::ConvertEscapeToNoEscapeInst) {
if (cast<ConvertEscapeToNoEscapeInst>(SI).isLifetimeGuaranteed())
attrs |= 0x01;
}
if (SI.getKind() == SILInstructionKind::ConvertFunctionInst) {
if (cast<ConvertFunctionInst>(SI).withoutActuallyEscaping())
attrs |= 0x01;
}
writeConversionLikeInstruction(cast<SingleValueInstruction>(&SI), attrs);
break;
}
case SILInstructionKind::PointerToAddressInst: {
auto &PAI = cast<PointerToAddressInst>(SI);
assert(PAI.getNumOperands() - PAI.getTypeDependentOperands().size() == 1);
uint8_t encodedAlignment = llvm::encode(PAI.alignment());
assert(encodedAlignment == llvm::encode(PAI.alignment())
&& "pointer_to_address alignment overflow");
unsigned attrs = encodedAlignment | (PAI.isStrict() ? 0x100 : 0)
| (PAI.isInvariant() ? 0x200 : 0);
writeOneTypeOneOperandExtraAttributeLayout(
PAI.getKind(), attrs, PAI.getType(), PAI.getOperand());
break;
}
case SILInstructionKind::RefToBridgeObjectInst: {
auto RI = cast<RefToBridgeObjectInst>(&SI);
SILTwoOperandsLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILTwoOperandsLayout::Code], (unsigned)SI.getKind(),
/*attr*/ 0,
S.addTypeRef(RI->getConverted()->getType().getASTType()),
(unsigned)RI->getConverted()->getType().getCategory(),
addValueRef(RI->getConverted()),
S.addTypeRef(RI->getBitsOperand()->getType().getASTType()),
(unsigned)RI->getBitsOperand()->getType().getCategory(),
addValueRef(RI->getBitsOperand()));
break;
}
// Checked Conversion instructions.
case SILInstructionKind::UnconditionalCheckedCastInst: {
auto CI = cast<UnconditionalCheckedCastInst>(&SI);
ValueID listOfValues[] = {
addValueRef(CI->getOperand()),
S.addTypeRef(CI->getSourceLoweredType().getASTType()),
(unsigned)CI->getSourceLoweredType().getCategory(),
S.addTypeRef(CI->getTargetFormalType())
};
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code], (unsigned)SI.getKind(),
S.addTypeRef(CI->getTargetLoweredType().getASTType()),
(unsigned)CI->getTargetLoweredType().getCategory(),
llvm::makeArrayRef(listOfValues));
break;
}
case SILInstructionKind::UnconditionalCheckedCastAddrInst: {
auto CI = cast<UnconditionalCheckedCastAddrInst>(&SI);
ValueID listOfValues[] = {
S.addTypeRef(CI->getSourceFormalType()),
addValueRef(CI->getSrc()),
S.addTypeRef(CI->getSourceLoweredType().getASTType()),
(unsigned)CI->getSourceLoweredType().getCategory(),
S.addTypeRef(CI->getTargetFormalType()),
addValueRef(CI->getDest())
};
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code], (unsigned)SI.getKind(),
S.addTypeRef(CI->getTargetLoweredType().getASTType()),
(unsigned)CI->getTargetLoweredType().getCategory(),
llvm::makeArrayRef(listOfValues));
break;
}
case SILInstructionKind::UnconditionalCheckedCastValueInst: {
auto CI = cast<UnconditionalCheckedCastValueInst>(&SI);
ValueID listOfValues[] = {
S.addTypeRef(CI->getSourceFormalType()),
addValueRef(CI->getOperand()),
S.addTypeRef(CI->getSourceLoweredType().getASTType()),
(unsigned)CI->getSourceLoweredType().getCategory(),
S.addTypeRef(CI->getTargetFormalType())
};
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code], (unsigned)SI.getKind(),
S.addTypeRef(CI->getTargetLoweredType().getASTType()),
(unsigned)CI->getTargetLoweredType().getCategory(),
llvm::makeArrayRef(listOfValues));
break;
}
case SILInstructionKind::UncheckedRefCastAddrInst: {
auto CI = cast<UncheckedRefCastAddrInst>(&SI);
ValueID listOfValues[] = {
S.addTypeRef(CI->getSourceFormalType()),
addValueRef(CI->getSrc()),
S.addTypeRef(CI->getSourceLoweredType().getASTType()),
(unsigned)CI->getSourceLoweredType().getCategory(),
S.addTypeRef(CI->getTargetFormalType()),
addValueRef(CI->getDest())
};
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code], (unsigned)SI.getKind(),
S.addTypeRef(CI->getTargetLoweredType().getASTType()),
(unsigned)CI->getTargetLoweredType().getCategory(),
llvm::makeArrayRef(listOfValues));
break;
}
case SILInstructionKind::BeginAccessInst: {
unsigned abbrCode = SILAbbrCodes[SILOneOperandExtraAttributeLayout::Code];
auto *BAI = cast<BeginAccessInst>(&SI);
unsigned attr = unsigned(BAI->getAccessKind())
+ (unsigned(BAI->getEnforcement()) << 2)
+ (BAI->hasNoNestedConflict() << 4)
+ (BAI->isFromBuiltin() << 5);
SILValue operand = BAI->getOperand();
SILOneOperandExtraAttributeLayout::emitRecord(
Out, ScratchRecord, abbrCode, (unsigned)SI.getKind(), attr,
S.addTypeRef(operand->getType().getASTType()),
(unsigned)operand->getType().getCategory(),
addValueRef(operand));
break;
}
case SILInstructionKind::EndAccessInst: {
unsigned abbrCode = SILAbbrCodes[SILOneOperandLayout::Code];
auto *EAI = cast<EndAccessInst>(&SI);
unsigned attr = unsigned(EAI->isAborting());
SILValue operand = EAI->getOperand();
SILOneOperandLayout::emitRecord(
Out, ScratchRecord, abbrCode, (unsigned)SI.getKind(), attr,
S.addTypeRef(operand->getType().getASTType()),
(unsigned)operand->getType().getCategory(),
addValueRef(operand));
break;
}
case SILInstructionKind::BeginUnpairedAccessInst: {
unsigned abbrCode = SILAbbrCodes[SILTwoOperandsExtraAttributeLayout::Code];
auto *BAI = cast<BeginUnpairedAccessInst>(&SI);
unsigned attr = unsigned(BAI->getAccessKind())
+ (unsigned(BAI->getEnforcement()) << 2)
+ (unsigned(BAI->hasNoNestedConflict()) << 4)
+ (unsigned(BAI->isFromBuiltin()) << 5);
SILValue source = BAI->getSource();
SILValue buffer = BAI->getBuffer();
SILTwoOperandsExtraAttributeLayout::emitRecord(
Out, ScratchRecord, abbrCode, (unsigned)SI.getKind(), attr,
S.addTypeRef(source->getType().getASTType()),
(unsigned)source->getType().getCategory(),
addValueRef(source),
S.addTypeRef(buffer->getType().getASTType()),
(unsigned)buffer->getType().getCategory(),
addValueRef(buffer));
break;
}
case SILInstructionKind::EndUnpairedAccessInst: {
unsigned abbrCode = SILAbbrCodes[SILOneOperandExtraAttributeLayout::Code];
auto *EAI = cast<EndUnpairedAccessInst>(&SI);
unsigned attr = unsigned(EAI->isAborting())
+ (unsigned(EAI->getEnforcement()) << 1)
+ (unsigned(EAI->isFromBuiltin()) << 3);
SILValue operand = EAI->getOperand();
SILOneOperandExtraAttributeLayout::emitRecord(
Out, ScratchRecord, abbrCode, (unsigned)SI.getKind(), attr,
S.addTypeRef(operand->getType().getASTType()),
(unsigned)operand->getType().getCategory(),
addValueRef(operand));
break;
}
#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
case SILInstructionKind::Store##Name##Inst:
#include "swift/AST/ReferenceStorage.def"
case SILInstructionKind::AssignInst:
case SILInstructionKind::CopyAddrInst:
case SILInstructionKind::MarkUnresolvedMoveAddrInst:
case SILInstructionKind::StoreInst:
case SILInstructionKind::StoreBorrowInst: {
SILValue operand, value;
unsigned Attr = 0;
if (SI.getKind() == SILInstructionKind::StoreInst) {
Attr = unsigned(cast<StoreInst>(&SI)->getOwnershipQualifier());
operand = cast<StoreInst>(&SI)->getDest();
value = cast<StoreInst>(&SI)->getSrc();
#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
} else if (SI.getKind() == SILInstructionKind::Store##Name##Inst) { \
Attr = cast<Store##Name##Inst>(&SI)->isInitializationOfDest(); \
operand = cast<Store##Name##Inst>(&SI)->getDest(); \
value = cast<Store##Name##Inst>(&SI)->getSrc();
#include "swift/AST/ReferenceStorage.def"
} else if (SI.getKind() == SILInstructionKind::AssignInst) {
Attr = unsigned(cast<AssignInst>(&SI)->getOwnershipQualifier());
operand = cast<AssignInst>(&SI)->getDest();
value = cast<AssignInst>(&SI)->getSrc();
} else if (SI.getKind() == SILInstructionKind::CopyAddrInst) {
const CopyAddrInst *CAI = cast<CopyAddrInst>(&SI);
Attr = (CAI->isInitializationOfDest() << 1) | CAI->isTakeOfSrc();
operand = cast<CopyAddrInst>(&SI)->getDest();
value = cast<CopyAddrInst>(&SI)->getSrc();
} else if (SI.getKind() == SILInstructionKind::MarkUnresolvedMoveAddrInst) {
auto *mai = cast<MarkUnresolvedMoveAddrInst>(&SI);
operand = mai->getDest();
value = mai->getSrc();
} else if (auto *SBI = dyn_cast<StoreBorrowInst>(&SI)) {
operand = SBI->getDest();
value = SBI->getSrc();
} else {
llvm_unreachable("switch out of sync");
}
unsigned abbrCode = SILAbbrCodes[SILOneValueOneOperandLayout::Code];
SILOneValueOneOperandLayout::emitRecord(Out, ScratchRecord, abbrCode,
(unsigned)SI.getKind(), Attr, addValueRef(value),
S.addTypeRef(operand->getType().getASTType()),
(unsigned)operand->getType().getCategory(),
addValueRef(operand));
break;
}
case SILInstructionKind::AssignByWrapperInst:
llvm_unreachable("not supported");
case SILInstructionKind::BindMemoryInst: {
auto *BI = cast<BindMemoryInst>(&SI);
SILValue baseOperand = BI->getBase();
SILValue indexOperand = BI->getIndex();
SILType boundType = BI->getBoundType();
SmallVector<ValueID, 6> ListOfValues;
ListOfValues.push_back(S.addTypeRef(
baseOperand->getType().getASTType()));
ListOfValues.push_back((unsigned)baseOperand->getType().getCategory());
ListOfValues.push_back(addValueRef(baseOperand));
ListOfValues.push_back(S.addTypeRef(
indexOperand->getType().getASTType()));
ListOfValues.push_back((unsigned)indexOperand->getType().getCategory());
ListOfValues.push_back(addValueRef(indexOperand));
SILOneTypeValuesLayout::emitRecord(
Out,
ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code],
(unsigned)SI.getKind(),
S.addTypeRef(boundType.getASTType()),
(unsigned)boundType.getCategory(),
ListOfValues);
break;
}
case SILInstructionKind::RebindMemoryInst: {
auto *RBI = cast<RebindMemoryInst>(&SI);
SILValue baseOperand = RBI->getBase();
SILValue inToken = RBI->getInToken();
SILTwoOperandsLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILTwoOperandsLayout::Code], (unsigned)SI.getKind(),
/*attr*/0,
S.addTypeRef(baseOperand->getType().getASTType()),
(unsigned)baseOperand->getType().getCategory(),
addValueRef(baseOperand),
S.addTypeRef(inToken->getType().getASTType()),
(unsigned)inToken->getType().getCategory(),
addValueRef(inToken));
break;
}
case SILInstructionKind::RefElementAddrInst:
case SILInstructionKind::StructElementAddrInst:
case SILInstructionKind::StructExtractInst:
case SILInstructionKind::InitEnumDataAddrInst:
case SILInstructionKind::UncheckedEnumDataInst:
case SILInstructionKind::UncheckedTakeEnumDataAddrInst:
case SILInstructionKind::InjectEnumAddrInst: {
// Has a typed valueref and a field decl. We use SILOneValueOneOperandLayout
// where the field decl is streamed as a ValueID.
SILValue operand;
Decl *tDecl;
unsigned attr = 0;
switch (SI.getKind()) {
default: llvm_unreachable("Out of sync with parent switch");
case SILInstructionKind::RefElementAddrInst:
operand = cast<RefElementAddrInst>(&SI)->getOperand();
tDecl = cast<RefElementAddrInst>(&SI)->getField();
attr = unsigned(cast<RefElementAddrInst>(&SI)->isImmutable());
break;
case SILInstructionKind::StructElementAddrInst:
operand = cast<StructElementAddrInst>(&SI)->getOperand();
tDecl = cast<StructElementAddrInst>(&SI)->getField();
break;
case SILInstructionKind::StructExtractInst:
operand = cast<StructExtractInst>(&SI)->getOperand();
tDecl = cast<StructExtractInst>(&SI)->getField();
break;
case SILInstructionKind::InitEnumDataAddrInst:
operand = cast<InitEnumDataAddrInst>(&SI)->getOperand();
tDecl = cast<InitEnumDataAddrInst>(&SI)->getElement();
break;
case SILInstructionKind::UncheckedEnumDataInst:
operand = cast<UncheckedEnumDataInst>(&SI)->getOperand();
tDecl = cast<UncheckedEnumDataInst>(&SI)->getElement();
break;
case SILInstructionKind::UncheckedTakeEnumDataAddrInst:
operand = cast<UncheckedTakeEnumDataAddrInst>(&SI)->getOperand();
tDecl = cast<UncheckedTakeEnumDataAddrInst>(&SI)->getElement();
break;
case SILInstructionKind::InjectEnumAddrInst:
operand = cast<InjectEnumAddrInst>(&SI)->getOperand();
tDecl = cast<InjectEnumAddrInst>(&SI)->getElement();
break;
}
SILOneValueOneOperandLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneValueOneOperandLayout::Code],
(unsigned)SI.getKind(), attr, S.addDeclRef(tDecl),
S.addTypeRef(operand->getType().getASTType()),
(unsigned)operand->getType().getCategory(),
addValueRef(operand));
break;
}
case SILInstructionKind::RefTailAddrInst: {
auto *RTAI = cast<RefTailAddrInst>(&SI);
writeOneTypeOneOperandLayout(RTAI->getKind(), unsigned(RTAI->isImmutable()),
RTAI->getType(),
RTAI->getOperand());
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.
const StructInst *StrI = cast<StructInst>(&SI);
SmallVector<ValueID, 4> ListOfValues;
for (auto Elt : StrI->getElements()) {
ListOfValues.push_back(S.addTypeRef(Elt->getType().getASTType()));
ListOfValues.push_back((unsigned)Elt->getType().getCategory());
ListOfValues.push_back(addValueRef(Elt));
}
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code],
(unsigned)SI.getKind(),
S.addTypeRef(StrI->getType().getASTType()),
(unsigned)StrI->getType().getCategory(), ListOfValues);
break;
}
case SILInstructionKind::TupleElementAddrInst:
case SILInstructionKind::TupleExtractInst: {
SILValue operand;
unsigned FieldNo;
switch (SI.getKind()) {
default: llvm_unreachable("Out of sync with parent switch");
case SILInstructionKind::TupleElementAddrInst:
operand = cast<TupleElementAddrInst>(&SI)->getOperand();
FieldNo = cast<TupleElementAddrInst>(&SI)->getFieldIndex();
break;
case SILInstructionKind::TupleExtractInst:
operand = cast<TupleExtractInst>(&SI)->getOperand();
FieldNo = cast<TupleExtractInst>(&SI)->getFieldIndex();
break;
}
// Use OneTypeOneOperand layout where the field number is stored in TypeID.
SILOneTypeOneOperandLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeOneOperandLayout::Code],
(unsigned)SI.getKind(), 0,
FieldNo, 0,
S.addTypeRef(operand->getType().getASTType()),
(unsigned)operand->getType().getCategory(),
addValueRef(operand));
break;
}
case SILInstructionKind::TupleInst: {
// Format: a type followed by a list of values. A value is expressed by
// 2 IDs: ValueID, ValueResultNumber.
const TupleInst *TI = cast<TupleInst>(&SI);
SmallVector<ValueID, 4> ListOfValues;
for (auto Elt : TI->getElements()) {
ListOfValues.push_back(addValueRef(Elt));
}
unsigned abbrCode = SILAbbrCodes[SILOneTypeValuesLayout::Code];
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord, abbrCode,
(unsigned)SI.getKind(),
S.addTypeRef(TI->getType().getASTType()),
(unsigned)TI->getType().getCategory(),
ListOfValues);
break;
}
case SILInstructionKind::EnumInst: {
// Format: a type, an operand and a decl ID. Use SILTwoOperandsLayout: type,
// (DeclID + hasOperand), and an operand.
const EnumInst *UI = cast<EnumInst>(&SI);
TypeID OperandTy = UI->hasOperand() ?
S.addTypeRef(UI->getOperand()->getType().getASTType()) : TypeID();
unsigned OperandTyCategory = UI->hasOperand() ?
(unsigned)UI->getOperand()->getType().getCategory() : 0;
SILTwoOperandsLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILTwoOperandsLayout::Code], (unsigned)SI.getKind(),
UI->hasOperand(),
S.addTypeRef(UI->getType().getASTType()),
(unsigned)UI->getType().getCategory(),
S.addDeclRef(UI->getElement()),
OperandTy, OperandTyCategory,
UI->hasOperand() ? addValueRef(UI->getOperand()) : ValueID());
break;
}
case SILInstructionKind::WitnessMethodInst: {
// Format: a type, an operand and a SILDeclRef. Use SILOneTypeValuesLayout:
// type, Attr, SILDeclRef (DeclID, Kind, uncurryLevel, IsObjC), and a type.
const WitnessMethodInst *WMI = cast<WitnessMethodInst>(&SI);
CanType Ty = WMI->getLookupType();
SILType Ty2 = WMI->getType();
SmallVector<ValueID, 8> ListOfValues;
handleSILDeclRef(S, WMI->getMember(), ListOfValues);
// Add an optional operand.
TypeID OperandTy = TypeID();
unsigned OperandTyCategory = 0;
SILValue OptionalOpenedExistential = SILValue();
auto OperandValueId = addValueRef(OptionalOpenedExistential);
SILInstWitnessMethodLayout::emitRecord(
Out, ScratchRecord, SILAbbrCodes[SILInstWitnessMethodLayout::Code],
S.addTypeRef(Ty), 0, 0,
S.addTypeRef(Ty2.getASTType()), (unsigned)Ty2.getCategory(),
OperandTy, OperandTyCategory, OperandValueId, ListOfValues);
S.writeConformance(WMI->getConformance(), SILAbbrCodes);
break;
}
case SILInstructionKind::ClassMethodInst: {
// Format: a type, an operand and a SILDeclRef. Use SILOneTypeValuesLayout:
// type, Attr, SILDeclRef (DeclID, Kind, uncurryLevel),
// and an operand.
const ClassMethodInst *CMI = cast<ClassMethodInst>(&SI);
SILType Ty = CMI->getType();
SmallVector<ValueID, 9> ListOfValues;
handleMethodInst(CMI, CMI->getOperand(), ListOfValues);
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code], (unsigned)SI.getKind(),
S.addTypeRef(Ty.getASTType()),
(unsigned)Ty.getCategory(), ListOfValues);
break;
}
case SILInstructionKind::SuperMethodInst: {
// Format: a type, an operand and a SILDeclRef. Use SILOneTypeValuesLayout:
// type, Attr, SILDeclRef (DeclID, Kind, uncurryLevel),
// and an operand.
const SuperMethodInst *SMI = cast<SuperMethodInst>(&SI);
SILType Ty = SMI->getType();
SmallVector<ValueID, 9> ListOfValues;
handleMethodInst(SMI, SMI->getOperand(), ListOfValues);
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code], (unsigned)SI.getKind(),
S.addTypeRef(Ty.getASTType()),
(unsigned)Ty.getCategory(), ListOfValues);
break;
}
case SILInstructionKind::ObjCMethodInst: {
// Format: a type, an operand and a SILDeclRef. Use SILOneTypeValuesLayout:
// type, Attr, SILDeclRef (DeclID, Kind, uncurryLevel),
// and an operand.
const ObjCMethodInst *OMI = cast<ObjCMethodInst>(&SI);
SILType Ty = OMI->getType();
SmallVector<ValueID, 9> ListOfValues;
handleMethodInst(OMI, OMI->getOperand(), ListOfValues);
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code], (unsigned)SI.getKind(),
S.addTypeRef(Ty.getASTType()),
(unsigned)Ty.getCategory(), ListOfValues);
break;
}
case SILInstructionKind::ObjCSuperMethodInst: {
// Format: a type, an operand and a SILDeclRef. Use SILOneTypeValuesLayout:
// type, Attr, SILDeclRef (DeclID, Kind, uncurryLevel),
// and an operand.
const ObjCSuperMethodInst *SMI = cast<ObjCSuperMethodInst>(&SI);
SILType Ty = SMI->getType();
SmallVector<ValueID, 9> ListOfValues;
handleMethodInst(SMI, SMI->getOperand(), ListOfValues);
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code], (unsigned)SI.getKind(),
S.addTypeRef(Ty.getASTType()),
(unsigned)Ty.getCategory(), ListOfValues);
break;
}
case SILInstructionKind::DynamicMethodBranchInst: {
// Format: a typed value, a SILDeclRef, a BasicBlock ID for method,
// a BasicBlock ID for no method. Use SILOneTypeValuesLayout.
const DynamicMethodBranchInst *DMB = cast<DynamicMethodBranchInst>(&SI);
SmallVector<ValueID, 8> ListOfValues;
ListOfValues.push_back(addValueRef(DMB->getOperand()));
handleSILDeclRef(S, DMB->getMember(), ListOfValues);
ListOfValues.push_back(BasicBlockMap[DMB->getHasMethodBB()]);
ListOfValues.push_back(BasicBlockMap[DMB->getNoMethodBB()]);
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code], (unsigned)SI.getKind(),
S.addTypeRef(DMB->getOperand()->getType().getASTType()),
(unsigned)DMB->getOperand()->getType().getCategory(), ListOfValues);
break;
}
case SILInstructionKind::CheckedCastBranchInst: {
const CheckedCastBranchInst *CBI = cast<CheckedCastBranchInst>(&SI);
ValueID listOfValues[] = {
CBI->isExact(),
addValueRef(CBI->getOperand()),
S.addTypeRef(CBI->getSourceLoweredType().getASTType()),
(unsigned)CBI->getSourceLoweredType().getCategory(),
S.addTypeRef(CBI->getTargetFormalType()),
BasicBlockMap[CBI->getSuccessBB()],
BasicBlockMap[CBI->getFailureBB()]
};
unsigned ownershipField =
encodeValueOwnership(CBI->getForwardingOwnershipKind());
SILOneTypeOwnershipValuesLayout::emitRecord(
Out, ScratchRecord, SILAbbrCodes[SILOneTypeOwnershipValuesLayout::Code],
(unsigned)SI.getKind(), ownershipField,
S.addTypeRef(CBI->getTargetLoweredType().getASTType()),
(unsigned)CBI->getTargetLoweredType().getCategory(),
llvm::makeArrayRef(listOfValues));
break;
}
case SILInstructionKind::CheckedCastValueBranchInst: {
const CheckedCastValueBranchInst *CBI =
cast<CheckedCastValueBranchInst>(&SI);
ValueID listOfValues[] = {
S.addTypeRef(CBI->getSourceFormalType()),
addValueRef(CBI->getOperand()),
S.addTypeRef(CBI->getSourceLoweredType().getASTType()),
(unsigned)CBI->getSourceLoweredType().getCategory(),
S.addTypeRef(CBI->getTargetFormalType()),
BasicBlockMap[CBI->getSuccessBB()],
BasicBlockMap[CBI->getFailureBB()]
};
SILOneTypeValuesLayout::emitRecord(
Out, ScratchRecord, SILAbbrCodes[SILOneTypeValuesLayout::Code],
(unsigned)SI.getKind(),
S.addTypeRef(CBI->getTargetLoweredType().getASTType()),
(unsigned)CBI->getTargetLoweredType().getCategory(),
llvm::makeArrayRef(listOfValues));
break;
}
case SILInstructionKind::CheckedCastAddrBranchInst: {
auto CBI = cast<CheckedCastAddrBranchInst>(&SI);
ValueID listOfValues[] = {
toStableCastConsumptionKind(CBI->getConsumptionKind()),
S.addTypeRef(CBI->getSourceFormalType()),
addValueRef(CBI->getSrc()),
S.addTypeRef(CBI->getSourceLoweredType().getASTType()),
(unsigned)CBI->getSourceLoweredType().getCategory(),
S.addTypeRef(CBI->getTargetFormalType()),
addValueRef(CBI->getDest()),
BasicBlockMap[CBI->getSuccessBB()],
BasicBlockMap[CBI->getFailureBB()]
};
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code], (unsigned)SI.getKind(),
S.addTypeRef(CBI->getTargetLoweredType().getASTType()),
(unsigned)CBI->getTargetLoweredType().getCategory(),
llvm::makeArrayRef(listOfValues));
break;
}
case SILInstructionKind::InitBlockStorageHeaderInst: {
auto IBSHI = cast<InitBlockStorageHeaderInst>(&SI);
SmallVector<ValueID, 6> ListOfValues;
ListOfValues.push_back(addValueRef(IBSHI->getBlockStorage()));
ListOfValues.push_back(
S.addTypeRef(IBSHI->getBlockStorage()->getType().getASTType()));
// Always an address, don't need to save category
ListOfValues.push_back(addValueRef(IBSHI->getInvokeFunction()));
ListOfValues.push_back(
S.addTypeRef(IBSHI->getInvokeFunction()->getType().getASTType()));
// Always a value, don't need to save category
ListOfValues.push_back(S.addSubstitutionMapRef(IBSHI->getSubstitutions()));
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code], (unsigned)SI.getKind(),
S.addTypeRef(IBSHI->getType().getASTType()),
(unsigned)IBSHI->getType().getCategory(),
ListOfValues);
break;
}
case SILInstructionKind::KeyPathInst: {
auto KPI = cast<KeyPathInst>(&SI);
SmallVector<ValueID, 6> ListOfValues;
auto pattern = KPI->getPattern();
ListOfValues.push_back(S.addTypeRef(pattern->getRootType()));
ListOfValues.push_back(S.addTypeRef(pattern->getValueType()));
ListOfValues.push_back(pattern->getComponents().size());
ListOfValues.push_back(pattern->getNumOperands());
ListOfValues.push_back(S.addSubstitutionMapRef(KPI->getSubstitutions()));
ListOfValues.push_back(S.addUniquedStringRef(pattern->getObjCString()));
ArrayRef<Requirement> reqts;
if (auto sig = pattern->getGenericSignature()) {
ListOfValues.push_back(sig.getGenericParams().size());
for (auto param : sig.getGenericParams())
ListOfValues.push_back(S.addTypeRef(param));
reqts = sig.getRequirements();
} else {
ListOfValues.push_back(0);
}
SmallVector<ProtocolConformanceRef, 4> serializeAfter;
for (auto &component : pattern->getComponents()) {
writeKeyPathPatternComponent(component,
ListOfValues, serializeAfter);
}
for (auto &operand : KPI->getAllOperands()) {
auto value = operand.get();
ListOfValues.push_back(addValueRef(value));
ListOfValues.push_back(S.addTypeRef(value->getType().getASTType()));
ListOfValues.push_back((unsigned)value->getType().getCategory());
}
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILOneTypeValuesLayout::Code], (unsigned)SI.getKind(),
S.addTypeRef(KPI->getType().getASTType()),
(unsigned)KPI->getType().getCategory(),
ListOfValues);
for (const auto &conf : serializeAfter) {
S.writeConformance(conf, SILAbbrCodes);
}
S.writeGenericRequirements(reqts, SILAbbrCodes);
break;
}
case SILInstructionKind::DifferentiableFunctionInst: {
auto *dfi = cast<DifferentiableFunctionInst>(&SI);
SmallVector<ValueID, 4> trailingInfo;
auto *paramIndices = dfi->getParameterIndices();
for (unsigned i : paramIndices->getIndices())
trailingInfo.push_back(i);
auto *resultIndices = dfi->getResultIndices();
for (unsigned i : resultIndices->getIndices())
trailingInfo.push_back(i);
for (auto &op : dfi->getAllOperands()) {
auto val = op.get();
trailingInfo.push_back(S.addTypeRef(val->getType().getASTType()));
trailingInfo.push_back((unsigned)val->getType().getCategory());
trailingInfo.push_back(addValueRef(val));
}
SILInstDifferentiableFunctionLayout::emitRecord(
Out, ScratchRecord,
SILAbbrCodes[SILInstDifferentiableFunctionLayout::Code],
paramIndices->getCapacity(), resultIndices->getCapacity(),
paramIndices->getNumIndices(), dfi->hasDerivativeFunctions(),
trailingInfo);
break;
}
case SILInstructionKind::LinearFunctionInst: {
auto *lfi = cast<LinearFunctionInst>(&SI);
SmallVector<ValueID, 4> trailingInfo;
auto *paramIndices = lfi->getParameterIndices();
for (unsigned idx : paramIndices->getIndices())
trailingInfo.push_back(idx);
for (auto &op : lfi->getAllOperands()) {
auto val = op.get();
trailingInfo.push_back(S.addTypeRef(val->getType().getASTType()));
trailingInfo.push_back((unsigned)val->getType().getCategory());
trailingInfo.push_back(addValueRef(val));
}
SILInstLinearFunctionLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILInstLinearFunctionLayout::Code],
paramIndices->getCapacity(), lfi->hasTransposeFunction(),
trailingInfo);
break;
}
case SILInstructionKind::DifferentiableFunctionExtractInst: {
auto *dfei = cast<DifferentiableFunctionExtractInst>(&SI);
auto operandRef = addValueRef(dfei->getOperand());
auto operandType = dfei->getOperand()->getType();
auto operandTypeRef = S.addTypeRef(operandType.getASTType());
auto rawExtractee = (unsigned)dfei->getExtractee();
auto extracteeTypeRef = S.addTypeRef(dfei->getType().getASTType());
SILInstDifferentiableFunctionExtractLayout::emitRecord(
Out, ScratchRecord,
SILAbbrCodes[SILInstDifferentiableFunctionExtractLayout::Code],
operandTypeRef, (unsigned)operandType.getCategory(), operandRef,
rawExtractee, (unsigned)dfei->hasExplicitExtracteeType(),
extracteeTypeRef);
break;
}
case SILInstructionKind::LinearFunctionExtractInst: {
auto *lfei = cast<LinearFunctionExtractInst>(&SI);
auto operandRef = addValueRef(lfei->getOperand());
auto operandType = lfei->getOperand()->getType();
auto operandTypeRef = S.addTypeRef(operandType.getASTType());
auto rawExtractee = (unsigned)lfei->getExtractee();
SILInstLinearFunctionExtractLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILInstLinearFunctionExtractLayout::Code],
operandTypeRef, (unsigned)operandType.getCategory(), operandRef,
rawExtractee);
break;
}
case SILInstructionKind::DifferentiabilityWitnessFunctionInst: {
auto *dwfi = cast<DifferentiabilityWitnessFunctionInst>(&SI);
auto *witness = dwfi->getWitness();
DifferentiabilityWitnessesToEmit.insert(witness);
Mangle::ASTMangler mangler;
auto mangledKey = mangler.mangleSILDifferentiabilityWitness(
witness->getOriginalFunction()->getName(), witness->getKind(),
witness->getConfig());
auto rawWitnessKind = (unsigned)dwfi->getWitnessKind();
// We only store the type when the instruction has an explicit type.
bool hasExplicitFnTy = dwfi->getHasExplicitFunctionType();
SILOneOperandLayout::emitRecord(
Out, ScratchRecord, SILAbbrCodes[SILOneOperandLayout::Code],
(unsigned)dwfi->getKind(), rawWitnessKind,
hasExplicitFnTy ? S.addTypeRef(dwfi->getType().getASTType()) : TypeID(),
hasExplicitFnTy ? (unsigned)dwfi->getType().getCategory() : 0,
S.addUniquedStringRef(mangledKey));
break;
}
}
// Non-void values get registered in the value table.
for (auto result : SI.getResults()) {
addValueRef(result);
++InstID;
}
}