mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Rework the serialization schema for conformances and requirements.
We now schedule conformance emissions in basically the same way we do for types and declarations, which means that we'll emit them uniquely in the module file instead of redundantly at every use. This should produce substantially smaller module files overall, especially for modules that heavily use generics. It also means that we can remove all the unfortunate code to support using different abbrev codes for them in different bitcode blocks. Requirement lists are now emitted inline in the records that need them instead of as trailing records. I think this will improve space usage, but mostly it assists in eliminating the problem where abbrev codes are shared between blocks.
This commit is contained in:
@@ -258,7 +258,7 @@ namespace {
|
||||
/// Helper function to update ListOfValues for MethodInst. Format:
|
||||
/// Attr, SILDeclRef (DeclID, Kind, uncurryLevel), and an operand.
|
||||
void handleMethodInst(const MethodInst *MI, SILValue operand,
|
||||
SmallVectorImpl<ValueID> &ListOfValues);
|
||||
SmallVectorImpl<uint64_t> &ListOfValues);
|
||||
|
||||
void writeSILFunction(const SILFunction &F, bool DeclOnly = false);
|
||||
void writeSILBasicBlock(const SILBasicBlock &BB);
|
||||
@@ -306,8 +306,7 @@ namespace {
|
||||
|
||||
void writeKeyPathPatternComponent(
|
||||
const KeyPathPatternComponent &component,
|
||||
SmallVectorImpl<ValueID> &ListOfValues,
|
||||
SmallVectorImpl<ProtocolConformanceRef> &serializeAfter);
|
||||
SmallVectorImpl<uint64_t> &ListOfValues);
|
||||
|
||||
/// Helper function to determine if given the current state of the
|
||||
/// deserialization if the function body for F should be deserialized.
|
||||
@@ -634,7 +633,7 @@ void SILSerializer::writeSILBasicBlock(const SILBasicBlock &BB) {
|
||||
/// Add SILDeclRef to ListOfValues, so we can reconstruct it at
|
||||
/// deserialization.
|
||||
static void handleSILDeclRef(Serializer &S, const SILDeclRef &Ref,
|
||||
SmallVectorImpl<ValueID> &ListOfValues) {
|
||||
SmallVectorImpl<uint64_t> &ListOfValues) {
|
||||
ListOfValues.push_back(S.addDeclRef(Ref.getDecl()));
|
||||
ListOfValues.push_back((unsigned)Ref.kind);
|
||||
ListOfValues.push_back(Ref.isForeign);
|
||||
@@ -651,7 +650,7 @@ IdentifierID SILSerializer::addSILFunctionRef(SILFunction *F) {
|
||||
/// Attr, SILDeclRef (DeclID, Kind, uncurryLevel), and an operand.
|
||||
void SILSerializer::handleMethodInst(const MethodInst *MI,
|
||||
SILValue operand,
|
||||
SmallVectorImpl<ValueID> &ListOfValues) {
|
||||
SmallVectorImpl<uint64_t> &ListOfValues) {
|
||||
handleSILDeclRef(S, MI->getMember(), ListOfValues);
|
||||
ListOfValues.push_back(
|
||||
S.addTypeRef(operand->getType().getASTType()));
|
||||
@@ -770,8 +769,7 @@ void SILSerializer::writeConversionLikeInstruction(
|
||||
void
|
||||
SILSerializer::writeKeyPathPatternComponent(
|
||||
const KeyPathPatternComponent &component,
|
||||
SmallVectorImpl<ValueID> &ListOfValues,
|
||||
SmallVectorImpl<ProtocolConformanceRef> &serializeAfter) {
|
||||
SmallVectorImpl<uint64_t> &ListOfValues) {
|
||||
|
||||
auto handleComponentCommon = [&](KeyPathComponentKindEncoding kind) {
|
||||
ListOfValues.push_back((unsigned)kind);
|
||||
@@ -810,7 +808,7 @@ SILSerializer::writeKeyPathPatternComponent(
|
||||
ListOfValues.push_back(
|
||||
S.addTypeRef(index.LoweredType.getASTType()));
|
||||
ListOfValues.push_back((unsigned)index.LoweredType.getCategory());
|
||||
serializeAfter.push_back(index.Hashable);
|
||||
ListOfValues.push_back(S.addConformanceRef(index.Hashable));
|
||||
}
|
||||
if (!indices.empty()) {
|
||||
ListOfValues.push_back(
|
||||
@@ -954,6 +952,9 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
|
||||
operandID = addValueRef(operand);
|
||||
}
|
||||
|
||||
TypeID formalConcreteTypeID = S.addTypeRef(FormalConcreteType);
|
||||
auto conformanceIDs = S.addConformanceRefs(conformances);
|
||||
|
||||
unsigned abbrCode = SILAbbrCodes[SILInitExistentialLayout::Code];
|
||||
SILInitExistentialLayout::emitRecord(Out, ScratchRecord, abbrCode,
|
||||
(unsigned)SI.getKind(),
|
||||
@@ -962,12 +963,8 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
|
||||
operandType,
|
||||
(unsigned)operandCategory,
|
||||
operandID,
|
||||
S.addTypeRef(FormalConcreteType),
|
||||
conformances.size());
|
||||
|
||||
for (auto conformance : conformances) {
|
||||
S.writeConformance(conformance, SILAbbrCodes);
|
||||
}
|
||||
formalConcreteTypeID,
|
||||
conformanceIDs);
|
||||
break;
|
||||
}
|
||||
case SILInstructionKind::DeallocBoxInst: {
|
||||
@@ -2152,7 +2149,7 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
|
||||
CanType Ty = WMI->getLookupType();
|
||||
SILType Ty2 = WMI->getType();
|
||||
|
||||
SmallVector<ValueID, 8> ListOfValues;
|
||||
SmallVector<uint64_t, 8> ListOfValues;
|
||||
handleSILDeclRef(S, WMI->getMember(), ListOfValues);
|
||||
|
||||
// Add an optional operand.
|
||||
@@ -2160,15 +2157,14 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
|
||||
unsigned OperandTyCategory = 0;
|
||||
SILValue OptionalOpenedExistential = SILValue();
|
||||
auto OperandValueId = addValueRef(OptionalOpenedExistential);
|
||||
auto ConformanceId = S.addConformanceRef(WMI->getConformance());
|
||||
|
||||
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);
|
||||
|
||||
OperandTy, OperandTyCategory, OperandValueId, ConformanceId,
|
||||
ListOfValues);
|
||||
break;
|
||||
}
|
||||
case SILInstructionKind::ClassMethodInst: {
|
||||
@@ -2177,7 +2173,7 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
|
||||
// and an operand.
|
||||
const ClassMethodInst *CMI = cast<ClassMethodInst>(&SI);
|
||||
SILType Ty = CMI->getType();
|
||||
SmallVector<ValueID, 9> ListOfValues;
|
||||
SmallVector<uint64_t, 9> ListOfValues;
|
||||
handleMethodInst(CMI, CMI->getOperand(), ListOfValues);
|
||||
|
||||
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
|
||||
@@ -2192,7 +2188,7 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
|
||||
// and an operand.
|
||||
const SuperMethodInst *SMI = cast<SuperMethodInst>(&SI);
|
||||
SILType Ty = SMI->getType();
|
||||
SmallVector<ValueID, 9> ListOfValues;
|
||||
SmallVector<uint64_t, 9> ListOfValues;
|
||||
handleMethodInst(SMI, SMI->getOperand(), ListOfValues);
|
||||
|
||||
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
|
||||
@@ -2207,7 +2203,7 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
|
||||
// and an operand.
|
||||
const ObjCMethodInst *OMI = cast<ObjCMethodInst>(&SI);
|
||||
SILType Ty = OMI->getType();
|
||||
SmallVector<ValueID, 9> ListOfValues;
|
||||
SmallVector<uint64_t, 9> ListOfValues;
|
||||
handleMethodInst(OMI, OMI->getOperand(), ListOfValues);
|
||||
|
||||
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
|
||||
@@ -2222,7 +2218,7 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
|
||||
// and an operand.
|
||||
const ObjCSuperMethodInst *SMI = cast<ObjCSuperMethodInst>(&SI);
|
||||
SILType Ty = SMI->getType();
|
||||
SmallVector<ValueID, 9> ListOfValues;
|
||||
SmallVector<uint64_t, 9> ListOfValues;
|
||||
handleMethodInst(SMI, SMI->getOperand(), ListOfValues);
|
||||
|
||||
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
|
||||
@@ -2235,7 +2231,7 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
|
||||
// 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;
|
||||
SmallVector<uint64_t, 8> ListOfValues;
|
||||
ListOfValues.push_back(addValueRef(DMB->getOperand()));
|
||||
handleSILDeclRef(S, DMB->getMember(), ListOfValues);
|
||||
ListOfValues.push_back(BasicBlockMap[DMB->getHasMethodBB()]);
|
||||
@@ -2333,7 +2329,7 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
|
||||
}
|
||||
case SILInstructionKind::KeyPathInst: {
|
||||
auto KPI = cast<KeyPathInst>(&SI);
|
||||
SmallVector<ValueID, 6> ListOfValues;
|
||||
SmallVector<uint64_t, 6> ListOfValues;
|
||||
|
||||
auto pattern = KPI->getPattern();
|
||||
ListOfValues.push_back(S.addTypeRef(pattern->getRootType()));
|
||||
@@ -2344,21 +2340,19 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
|
||||
|
||||
ListOfValues.push_back(S.addUniquedStringRef(pattern->getObjCString()));
|
||||
|
||||
ArrayRef<Requirement> reqts;
|
||||
if (auto sig = pattern->getGenericSignature()) {
|
||||
assert(sig.getGenericParams().size() > 0);
|
||||
ListOfValues.push_back(sig.getGenericParams().size());
|
||||
for (auto param : sig.getGenericParams())
|
||||
ListOfValues.push_back(S.addTypeRef(param));
|
||||
reqts = sig.getRequirements();
|
||||
auto reqts = sig.getRequirements();
|
||||
S.serializeGenericRequirements(reqts, ListOfValues);
|
||||
} else {
|
||||
ListOfValues.push_back(0);
|
||||
}
|
||||
|
||||
SmallVector<ProtocolConformanceRef, 4> serializeAfter;
|
||||
|
||||
for (auto &component : pattern->getComponents()) {
|
||||
writeKeyPathPatternComponent(component,
|
||||
ListOfValues, serializeAfter);
|
||||
writeKeyPathPatternComponent(component, ListOfValues);
|
||||
}
|
||||
|
||||
for (auto &operand : KPI->getAllOperands()) {
|
||||
@@ -2373,10 +2367,6 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
|
||||
S.addTypeRef(KPI->getType().getASTType()),
|
||||
(unsigned)KPI->getType().getCategory(),
|
||||
ListOfValues);
|
||||
for (const auto &conf : serializeAfter) {
|
||||
S.writeConformance(conf, SILAbbrCodes);
|
||||
}
|
||||
S.writeGenericRequirements(reqts, SILAbbrCodes);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -2610,7 +2600,7 @@ void SILSerializer::writeSILVTable(const SILVTable &vt) {
|
||||
vt.isSerialized() == IsSerialized ? 1 : 0);
|
||||
|
||||
for (auto &entry : vt.getEntries()) {
|
||||
SmallVector<ValueID, 4> ListOfValues;
|
||||
SmallVector<uint64_t, 4> ListOfValues;
|
||||
// Do not emit entries which are not public or serialized, unless everything
|
||||
// has to be serialized.
|
||||
if (!ShouldSerializeAll && entry.getImplementation() &&
|
||||
@@ -2633,11 +2623,10 @@ void SILSerializer::writeSILVTable(const SILVTable &vt) {
|
||||
void SILSerializer::writeSILProperty(const SILProperty &prop) {
|
||||
PropertyOffset.push_back(Out.GetCurrentBitNo());
|
||||
|
||||
SmallVector<ValueID, 4> componentValues;
|
||||
SmallVector<ProtocolConformanceRef, 4> serializeAfter;
|
||||
SmallVector<uint64_t, 4> componentValues;
|
||||
|
||||
if (auto component = prop.getComponent()) {
|
||||
writeKeyPathPatternComponent(*component, componentValues, serializeAfter);
|
||||
writeKeyPathPatternComponent(*component, componentValues);
|
||||
} else {
|
||||
componentValues.push_back((unsigned)KeyPathComponentKindEncoding::Trivial);
|
||||
}
|
||||
@@ -2648,24 +2637,20 @@ void SILSerializer::writeSILProperty(const SILProperty &prop) {
|
||||
S.addDeclRef(prop.getDecl()),
|
||||
prop.isSerialized(),
|
||||
componentValues);
|
||||
|
||||
for (const auto &conf : serializeAfter) {
|
||||
S.writeConformance(conf, SILAbbrCodes);
|
||||
}
|
||||
}
|
||||
|
||||
void SILSerializer::writeSILWitnessTable(const SILWitnessTable &wt) {
|
||||
WitnessTableList[wt.getName()] = NextWitnessTableID++;
|
||||
WitnessTableOffset.push_back(Out.GetCurrentBitNo());
|
||||
|
||||
auto conformanceID = S.addConformanceRef(wt.getConformance());
|
||||
WitnessTableLayout::emitRecord(
|
||||
Out, ScratchRecord,
|
||||
SILAbbrCodes[WitnessTableLayout::Code],
|
||||
toStableSILLinkage(wt.getLinkage()),
|
||||
unsigned(wt.isDeclaration()),
|
||||
wt.isSerialized() == IsSerialized ? 1 : 0);
|
||||
|
||||
S.writeConformance(wt.getConformance(), SILAbbrCodes);
|
||||
wt.isSerialized() == IsSerialized ? 1 : 0,
|
||||
conformanceID);
|
||||
|
||||
// If we have a declaration, do not attempt to serialize entries.
|
||||
if (wt.isDeclaration())
|
||||
@@ -2676,13 +2661,12 @@ void SILSerializer::writeSILWitnessTable(const SILWitnessTable &wt) {
|
||||
}
|
||||
|
||||
for (auto conditional : wt.getConditionalConformances()) {
|
||||
auto requirementID = S.addTypeRef(conditional.Requirement);
|
||||
auto conformanceID = S.addConformanceRef(conditional.Conformance);
|
||||
WitnessConditionalConformanceLayout::emitRecord(
|
||||
Out, ScratchRecord,
|
||||
SILAbbrCodes[WitnessConditionalConformanceLayout::Code],
|
||||
S.addTypeRef(conditional.Requirement));
|
||||
|
||||
S.writeConformance(conditional.Conformance, SILAbbrCodes);
|
||||
continue;
|
||||
requirementID, conformanceID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2691,24 +2675,26 @@ void SILSerializer::writeSILWitnessTableEntry(
|
||||
if (entry.getKind() == SILWitnessTable::BaseProtocol) {
|
||||
auto &baseWitness = entry.getBaseProtocolWitness();
|
||||
|
||||
auto requirementID = S.addDeclRef(baseWitness.Requirement);
|
||||
auto conformanceID = S.addConformanceRef(baseWitness.Witness);
|
||||
|
||||
WitnessBaseEntryLayout::emitRecord(Out, ScratchRecord,
|
||||
SILAbbrCodes[WitnessBaseEntryLayout::Code],
|
||||
S.addDeclRef(baseWitness.Requirement));
|
||||
|
||||
S.writeConformance(baseWitness.Witness, SILAbbrCodes);
|
||||
requirementID, conformanceID);
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry.getKind() == SILWitnessTable::AssociatedTypeProtocol) {
|
||||
auto &assoc = entry.getAssociatedTypeProtocolWitness();
|
||||
|
||||
auto requirementID = S.addTypeRef(assoc.Requirement);
|
||||
auto protocolID = S.addDeclRef(assoc.Protocol);
|
||||
auto conformanceID = S.addConformanceRef(assoc.Witness);
|
||||
|
||||
WitnessAssocProtocolLayout::emitRecord(
|
||||
Out, ScratchRecord,
|
||||
SILAbbrCodes[WitnessAssocProtocolLayout::Code],
|
||||
S.addTypeRef(assoc.Requirement),
|
||||
S.addDeclRef(assoc.Protocol));
|
||||
|
||||
S.writeConformance(assoc.Witness, SILAbbrCodes);
|
||||
requirementID, protocolID, conformanceID);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2722,7 +2708,7 @@ void SILSerializer::writeSILWitnessTableEntry(
|
||||
}
|
||||
|
||||
auto &methodWitness = entry.getMethodWitness();
|
||||
SmallVector<ValueID, 4> ListOfValues;
|
||||
SmallVector<uint64_t, 4> ListOfValues;
|
||||
handleSILDeclRef(S, methodWitness.Requirement, ListOfValues);
|
||||
IdentifierID witnessID = 0;
|
||||
SILFunction *witness = methodWitness.Witness;
|
||||
@@ -2883,19 +2869,6 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) {
|
||||
registerSILAbbr<PropertyLayout>();
|
||||
registerSILAbbr<DifferentiabilityWitnessLayout>();
|
||||
|
||||
// Register the abbreviation codes so these layouts can exist in both
|
||||
// decl blocks and sil blocks.
|
||||
registerSILAbbr<decls_block::AbstractProtocolConformanceLayout>();
|
||||
registerSILAbbr<decls_block::NormalProtocolConformanceLayout>();
|
||||
registerSILAbbr<decls_block::SelfProtocolConformanceLayout>();
|
||||
registerSILAbbr<decls_block::SpecializedProtocolConformanceLayout>();
|
||||
registerSILAbbr<decls_block::InheritedProtocolConformanceLayout>();
|
||||
registerSILAbbr<decls_block::BuiltinProtocolConformanceLayout>();
|
||||
registerSILAbbr<decls_block::NormalProtocolConformanceIdLayout>();
|
||||
registerSILAbbr<decls_block::ProtocolConformanceXrefLayout>();
|
||||
registerSILAbbr<decls_block::GenericRequirementLayout>();
|
||||
registerSILAbbr<decls_block::LayoutRequirementLayout>();
|
||||
|
||||
// Write out VTables first because it may require serializations of
|
||||
// non-transparent SILFunctions (body is not needed).
|
||||
// Go through all SILVTables in SILMod and write them if we should
|
||||
|
||||
Reference in New Issue
Block a user