From 82011c98efa311aa6fd37bb24871a364bc6d1027 Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Tue, 23 Sep 2014 02:06:21 +0000 Subject: [PATCH] [Serialization] witness_method should reference existing conformances. Part of a series of commits to remove redundantly-serialized conformances. Swift SVN r22196 --- lib/Serialization/DeserializeSIL.cpp | 39 ++++++++++++++++------- lib/Serialization/SILFormat.h | 15 +++++++++ lib/Serialization/Serialization.cpp | 1 + lib/Serialization/SerializeSIL.cpp | 46 +++++++++++++++++++--------- 4 files changed, 75 insertions(+), 26 deletions(-) diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp index 4f07c04bcd5..014ac2d1759 100644 --- a/lib/Serialization/DeserializeSIL.cpp +++ b/lib/Serialization/DeserializeSIL.cpp @@ -614,6 +614,8 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, ValueID ValID, ValID2; TypeID TyID, TyID2; TypeID ConcreteTyID; + DeclID ProtoID; + ModuleID OwningModuleID; SourceLoc SLoc; ArrayRef ListOfValues; SILLocation Loc = SILFileLocation(SLoc); @@ -673,6 +675,14 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, case SIL_INST_NO_OPERAND: SILInstNoOperandLayout::readRecord(scratch, OpCode); break; + case SIL_INST_WITNESS_METHOD: + SILInstWitnessMethodLayout::readRecord(scratch, TyID, TyCategory, Attr, + TyID2, TyCategory2, + ProtoID, ConcreteTyID, + OwningModuleID, + ListOfValues); + OpCode = (unsigned)ValueKind::WitnessMethodInst; + break; } ValueBase *ResultVal; @@ -1362,7 +1372,6 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, ResultTy); break; } - case ValueKind::WitnessMethodInst: case ValueKind::ProtocolMethodInst: case ValueKind::ClassMethodInst: case ValueKind::SuperMethodInst: @@ -1370,8 +1379,6 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, // Format: a type, an operand and a SILDeclRef. Use SILOneTypeValuesLayout: // type, Attr, SILDeclRef (DeclID, Kind, uncurryLevel, IsObjC), // and an operand. - // WitnessMethodInst is additionally optionally followed by a - // ProtocolConformance record. unsigned NextValueIndex = 1; SILDeclRef DRef = getSILDeclRef(MF, ListOfValues, NextValueIndex); SILType Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory); @@ -1384,14 +1391,6 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, switch ((ValueKind)OpCode) { default: assert(0 && "Out of sync with parent switch"); - case ValueKind::WitnessMethodInst: { - auto conformance = MF->maybeReadConformance(Ty.getSwiftRValueType(), - SILCursor); - ResultVal = Builder.createWitnessMethod(Loc, Ty, - conformance.getValueOr(nullptr), - DRef, operandTy, IsVolatile); - break; - } case ValueKind::ProtocolMethodInst: ResultVal = Builder.createProtocolMethod(Loc, getLocalValue(ListOfValues[NextValueIndex], @@ -1419,6 +1418,24 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, } break; } + case ValueKind::WitnessMethodInst: { + unsigned NextValueIndex = 0; + SILDeclRef DRef = getSILDeclRef(MF, ListOfValues, NextValueIndex); + assert(ListOfValues.size() >= NextValueIndex && + "Out of entries for MethodInst"); + + SILType Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory); + SILType OperandTy = getSILType(MF->getType(TyID2), + (SILValueCategory)TyCategory2); + + auto *Proto = cast_or_null(MF->getDecl(ProtoID)); + auto *Conformance = MF->readReferencedConformance(Proto, ConcreteTyID, + OwningModuleID, + SILCursor); + ResultVal = Builder.createWitnessMethod(Loc, Ty, Conformance, DRef, + OperandTy, Attr); + break; + } case ValueKind::DynamicMethodBranchInst: { // Format: a typed value, a SILDeclRef, a BasicBlock ID for method, // a BasicBlock ID for no method. Use SILOneTypeValuesLayout. diff --git a/lib/Serialization/SILFormat.h b/lib/Serialization/SILFormat.h index 78183db9a42..27dc7f78cd1 100644 --- a/lib/Serialization/SILFormat.h +++ b/lib/Serialization/SILFormat.h @@ -136,6 +136,7 @@ namespace sil_block { SIL_WITNESS_ASSOC_PROTOCOL, SIL_WITNESS_ASSOC_ENTRY, SIL_GENERIC_OUTER_PARAMS, + SIL_INST_WITNESS_METHOD, // We also share these layouts from the decls block. Their enumerators must // not overlap with ours. @@ -346,6 +347,20 @@ namespace sil_block { SIL_GENERIC_OUTER_PARAMS, DeclIDField // The decl id of the outer param if any. >; + + using SILInstWitnessMethodLayout = BCRecordLayout< + SIL_INST_WITNESS_METHOD, + TypeIDField, // result type + SILTypeCategoryField, + BCFixed<1>, // volatile? + TypeIDField, // lookup type + SILTypeCategoryField, + DeclIDField, // conformance proto + TypeIDField, // conformance type + ModuleIDField, // conformance module + BCArray // SILDeclRef + // may be trailed by an inline protocol conformance + >; } } // end namespace serialization diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index ee37a325600..079984af5f2 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -293,6 +293,7 @@ void Serializer::writeBlockInfoBlock() { BLOCK_RECORD(sil_block, SIL_WITNESS_ASSOC_PROTOCOL); BLOCK_RECORD(sil_block, SIL_WITNESS_ASSOC_ENTRY); BLOCK_RECORD(sil_block, SIL_GENERIC_OUTER_PARAMS); + BLOCK_RECORD(sil_block, SIL_INST_WITNESS_METHOD); // These layouts can exist in both decl blocks and sil blocks. #define BLOCK_RECORD_WITH_NAMESPACE(K, X) emitRecordID(Out, X, #X, nameBuffer) diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp index 61f7d38aca2..ec29219243a 100644 --- a/lib/Serialization/SerializeSIL.cpp +++ b/lib/Serialization/SerializeSIL.cpp @@ -382,7 +382,7 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) { for (auto conformance : conformancesToWrite) { S.writeConformance(conformance->getProtocol(), conformance, nullptr, - SILAbbrCodes, /*writeIncomplete=*/true); + SILAbbrCodes); } break; } @@ -1123,23 +1123,38 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) { SILType Ty = AMI->getLookupType(); SILType Ty2 = AMI->getType(0); - SmallVector ListOfValues; - ListOfValues.push_back(AMI->isVolatile()); + SmallVector ListOfValues; handleSILDeclRef(S, AMI->getMember(), ListOfValues); - ListOfValues.push_back(S.addTypeRef(Ty2.getSwiftRValueType())); - ListOfValues.push_back((unsigned)Ty2.getCategory()); - SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord, - SILAbbrCodes[SILOneTypeValuesLayout::Code], (unsigned)SI.getKind(), - S.addTypeRef(Ty.getSwiftRValueType()), - (unsigned)Ty.getCategory(), ListOfValues); + DeclID ConformanceProto; + TypeID AdopterTy; + ModuleID ConformanceModule; + bool WriteConformance = false; - if (AMI->getConformance()) - S.writeConformance( - cast(AMI->getMember().getDecl()->getDeclContext()), - AMI->getConformance(), - nullptr, - SILAbbrCodes); + if (auto *Conformance = AMI->getConformance()) { + ConformanceProto = S.addDeclRef(Conformance->getProtocol()); + WriteConformance = S.encodeReferencedConformance(Conformance, + AdopterTy, + ConformanceModule, + true); + } else { + ConformanceProto = S.addDeclRef(nullptr); + } + + SILInstWitnessMethodLayout::emitRecord(Out, ScratchRecord, + SILAbbrCodes[SILInstWitnessMethodLayout::Code], + S.addTypeRef(Ty.getSwiftRValueType()), (unsigned)Ty.getCategory(), + AMI->isVolatile(), + S.addTypeRef(Ty2.getSwiftRValueType()), (unsigned)Ty2.getCategory(), + ConformanceProto, AdopterTy, ConformanceModule, + ListOfValues); + + if (WriteConformance) { + S.writeConformance(AMI->getConformance()->getProtocol(), + AMI->getConformance(), + nullptr, + SILAbbrCodes); + } break; } @@ -1525,6 +1540,7 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) { registerSILAbbr(); registerSILAbbr(); + registerSILAbbr(); // Register the abbreviation codes so these layouts can exist in both // decl blocks and sil blocks.