[Serialization] witness_method should reference existing conformances.

Part of a series of commits to remove redundantly-serialized conformances.

Swift SVN r22196
This commit is contained in:
Jordan Rose
2014-09-23 02:06:21 +00:00
parent eea6c17456
commit 82011c98ef
4 changed files with 75 additions and 26 deletions

View File

@@ -614,6 +614,8 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
ValueID ValID, ValID2; ValueID ValID, ValID2;
TypeID TyID, TyID2; TypeID TyID, TyID2;
TypeID ConcreteTyID; TypeID ConcreteTyID;
DeclID ProtoID;
ModuleID OwningModuleID;
SourceLoc SLoc; SourceLoc SLoc;
ArrayRef<uint64_t> ListOfValues; ArrayRef<uint64_t> ListOfValues;
SILLocation Loc = SILFileLocation(SLoc); SILLocation Loc = SILFileLocation(SLoc);
@@ -673,6 +675,14 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
case SIL_INST_NO_OPERAND: case SIL_INST_NO_OPERAND:
SILInstNoOperandLayout::readRecord(scratch, OpCode); SILInstNoOperandLayout::readRecord(scratch, OpCode);
break; 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; ValueBase *ResultVal;
@@ -1362,7 +1372,6 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
ResultTy); ResultTy);
break; break;
} }
case ValueKind::WitnessMethodInst:
case ValueKind::ProtocolMethodInst: case ValueKind::ProtocolMethodInst:
case ValueKind::ClassMethodInst: case ValueKind::ClassMethodInst:
case ValueKind::SuperMethodInst: case ValueKind::SuperMethodInst:
@@ -1370,8 +1379,6 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
// Format: a type, an operand and a SILDeclRef. Use SILOneTypeValuesLayout: // Format: a type, an operand and a SILDeclRef. Use SILOneTypeValuesLayout:
// type, Attr, SILDeclRef (DeclID, Kind, uncurryLevel, IsObjC), // type, Attr, SILDeclRef (DeclID, Kind, uncurryLevel, IsObjC),
// and an operand. // and an operand.
// WitnessMethodInst is additionally optionally followed by a
// ProtocolConformance record.
unsigned NextValueIndex = 1; unsigned NextValueIndex = 1;
SILDeclRef DRef = getSILDeclRef(MF, ListOfValues, NextValueIndex); SILDeclRef DRef = getSILDeclRef(MF, ListOfValues, NextValueIndex);
SILType Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory); SILType Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory);
@@ -1384,14 +1391,6 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
switch ((ValueKind)OpCode) { switch ((ValueKind)OpCode) {
default: assert(0 && "Out of sync with parent switch"); 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: case ValueKind::ProtocolMethodInst:
ResultVal = Builder.createProtocolMethod(Loc, ResultVal = Builder.createProtocolMethod(Loc,
getLocalValue(ListOfValues[NextValueIndex], getLocalValue(ListOfValues[NextValueIndex],
@@ -1419,6 +1418,24 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
} }
break; 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<ProtocolDecl>(MF->getDecl(ProtoID));
auto *Conformance = MF->readReferencedConformance(Proto, ConcreteTyID,
OwningModuleID,
SILCursor);
ResultVal = Builder.createWitnessMethod(Loc, Ty, Conformance, DRef,
OperandTy, Attr);
break;
}
case ValueKind::DynamicMethodBranchInst: { case ValueKind::DynamicMethodBranchInst: {
// Format: a typed value, a SILDeclRef, a BasicBlock ID for method, // Format: a typed value, a SILDeclRef, a BasicBlock ID for method,
// a BasicBlock ID for no method. Use SILOneTypeValuesLayout. // a BasicBlock ID for no method. Use SILOneTypeValuesLayout.

View File

@@ -136,6 +136,7 @@ namespace sil_block {
SIL_WITNESS_ASSOC_PROTOCOL, SIL_WITNESS_ASSOC_PROTOCOL,
SIL_WITNESS_ASSOC_ENTRY, SIL_WITNESS_ASSOC_ENTRY,
SIL_GENERIC_OUTER_PARAMS, SIL_GENERIC_OUTER_PARAMS,
SIL_INST_WITNESS_METHOD,
// We also share these layouts from the decls block. Their enumerators must // We also share these layouts from the decls block. Their enumerators must
// not overlap with ours. // not overlap with ours.
@@ -346,6 +347,20 @@ namespace sil_block {
SIL_GENERIC_OUTER_PARAMS, SIL_GENERIC_OUTER_PARAMS,
DeclIDField // The decl id of the outer param if any. 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<ValueIDField> // SILDeclRef
// may be trailed by an inline protocol conformance
>;
} }
} // end namespace serialization } // end namespace serialization

View File

@@ -293,6 +293,7 @@ void Serializer::writeBlockInfoBlock() {
BLOCK_RECORD(sil_block, SIL_WITNESS_ASSOC_PROTOCOL); BLOCK_RECORD(sil_block, SIL_WITNESS_ASSOC_PROTOCOL);
BLOCK_RECORD(sil_block, SIL_WITNESS_ASSOC_ENTRY); BLOCK_RECORD(sil_block, SIL_WITNESS_ASSOC_ENTRY);
BLOCK_RECORD(sil_block, SIL_GENERIC_OUTER_PARAMS); 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. // These layouts can exist in both decl blocks and sil blocks.
#define BLOCK_RECORD_WITH_NAMESPACE(K, X) emitRecordID(Out, X, #X, nameBuffer) #define BLOCK_RECORD_WITH_NAMESPACE(K, X) emitRecordID(Out, X, #X, nameBuffer)

View File

@@ -382,7 +382,7 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
for (auto conformance : conformancesToWrite) { for (auto conformance : conformancesToWrite) {
S.writeConformance(conformance->getProtocol(), conformance, nullptr, S.writeConformance(conformance->getProtocol(), conformance, nullptr,
SILAbbrCodes, /*writeIncomplete=*/true); SILAbbrCodes);
} }
break; break;
} }
@@ -1123,23 +1123,38 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
SILType Ty = AMI->getLookupType(); SILType Ty = AMI->getLookupType();
SILType Ty2 = AMI->getType(0); SILType Ty2 = AMI->getType(0);
SmallVector<ValueID, 7> ListOfValues; SmallVector<ValueID, 8> ListOfValues;
ListOfValues.push_back(AMI->isVolatile());
handleSILDeclRef(S, AMI->getMember(), ListOfValues); handleSILDeclRef(S, AMI->getMember(), ListOfValues);
ListOfValues.push_back(S.addTypeRef(Ty2.getSwiftRValueType()));
ListOfValues.push_back((unsigned)Ty2.getCategory());
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord, DeclID ConformanceProto;
SILAbbrCodes[SILOneTypeValuesLayout::Code], (unsigned)SI.getKind(), TypeID AdopterTy;
S.addTypeRef(Ty.getSwiftRValueType()), ModuleID ConformanceModule;
(unsigned)Ty.getCategory(), ListOfValues); bool WriteConformance = false;
if (AMI->getConformance()) if (auto *Conformance = AMI->getConformance()) {
S.writeConformance( ConformanceProto = S.addDeclRef(Conformance->getProtocol());
cast<ProtocolDecl>(AMI->getMember().getDecl()->getDeclContext()), 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(), AMI->getConformance(),
nullptr, nullptr,
SILAbbrCodes); SILAbbrCodes);
}
break; break;
} }
@@ -1525,6 +1540,7 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) {
registerSILAbbr<SILGenericOuterParamsLayout>(); registerSILAbbr<SILGenericOuterParamsLayout>();
registerSILAbbr<SILInstCastLayout>(); registerSILAbbr<SILInstCastLayout>();
registerSILAbbr<SILInstWitnessMethodLayout>();
// Register the abbreviation codes so these layouts can exist in both // Register the abbreviation codes so these layouts can exist in both
// decl blocks and sil blocks. // decl blocks and sil blocks.