mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
SIL Serialization: perform SIL linking right after SILGen.
Add a SILLinkage mode "Deserialized" to make sure IRGen will emit hidden symbols for deserialized SILFunction. Inside SIL linker, set Linkage to external if we only have a declaration for a callee function. Both sil block and decl block in a module can emit an array of substitutions. To share the serialization between SILSerializer and Serializer, we modify the interface to pass in the abbreviation codes to write functions and to pass in a cursor to read functions. We now correctly handle the serialization of Substitutions in SpecializeInst. For a deserialized SILFunction, we now temporarily set its SILLocation and DebugScope to an empty FileLocation. Once mandatory inliner sets the SILLocation to the location of ApplyInst, a null SILLocation and a null DebugScope may work for a deserialized SILFunction. Update testing cases to reflect that we are now inlining transparent functions from modules, or to disable SILDeserializer for now (I am not sure how to update those testing cases). Swift SVN r8582
This commit is contained in:
@@ -31,6 +31,7 @@ enum class SILLinkage : unsigned char {
|
||||
External,
|
||||
Thunk,
|
||||
Internal,
|
||||
Deserialized // Deserialized from a module.
|
||||
};
|
||||
|
||||
enum IsTransparent_t { IsNotTransparent, IsTransparent };
|
||||
|
||||
@@ -685,6 +685,12 @@ bool LinkEntity::isThunk() const {
|
||||
}
|
||||
}
|
||||
|
||||
bool LinkEntity::isDeserialized() const {
|
||||
if (getKind() == Kind::SILFunction)
|
||||
return getSILFunction()->getLinkage() == SILLinkage::Deserialized;
|
||||
return false;
|
||||
}
|
||||
|
||||
LinkInfo LinkInfo::get(IRGenModule &IGM, const LinkEntity &entity) {
|
||||
LinkInfo result;
|
||||
|
||||
@@ -704,6 +710,9 @@ LinkInfo LinkInfo::get(IRGenModule &IGM, const LinkEntity &entity) {
|
||||
// Clang thunks are linkonce_odr and hidden.
|
||||
result.Linkage = llvm::GlobalValue::LinkOnceODRLinkage;
|
||||
result.Visibility = llvm::GlobalValue::HiddenVisibility;
|
||||
} else if (entity.isDeserialized()) {
|
||||
result.Linkage = llvm::GlobalValue::LinkOnceODRLinkage;
|
||||
result.Visibility = llvm::GlobalValue::HiddenVisibility;
|
||||
} else {
|
||||
// Give everything else external linkage.
|
||||
result.Linkage = llvm::GlobalValue::ExternalLinkage;
|
||||
|
||||
@@ -397,6 +397,7 @@ public:
|
||||
void mangle(SmallVectorImpl<char> &buffer) const;
|
||||
bool isLocalLinkage() const;
|
||||
bool isThunk() const;
|
||||
bool isDeserialized() const;
|
||||
|
||||
ValueDecl *getDecl() const {
|
||||
assert(isDeclKind(getKind()));
|
||||
|
||||
@@ -493,6 +493,9 @@ static bool parseSILLinkage(SILLinkage &Result, Parser &P) {
|
||||
} else if (P.Tok.getText() == "thunk") {
|
||||
Result = SILLinkage::Thunk;
|
||||
P.consumeToken(tok::identifier);
|
||||
} else if (P.Tok.getText() == "deserialized") {
|
||||
Result = SILLinkage::Deserialized;
|
||||
P.consumeToken(tok::identifier);
|
||||
} else {
|
||||
P.diagnose(P.Tok, diag::expected_sil_linkage_or_function);
|
||||
return true;
|
||||
|
||||
@@ -1055,6 +1055,9 @@ void SILFunction::print(llvm::raw_ostream &OS, bool Verbose) const {
|
||||
break;
|
||||
case SILLinkage::External:
|
||||
break;
|
||||
case SILLinkage::Deserialized:
|
||||
OS << "deserialized ";
|
||||
break;
|
||||
}
|
||||
|
||||
printName(OS);
|
||||
|
||||
@@ -44,29 +44,41 @@ void swift::performSILLinking(SILModule *M) {
|
||||
|
||||
while (!Worklist.empty()) {
|
||||
auto Fn = Worklist.pop_back_val();
|
||||
|
||||
for (auto &BB : *Fn) {
|
||||
for (auto I = BB.begin(), E = BB.end(); I != E; I++) {
|
||||
// Handles ApplyInst only.
|
||||
auto *AI = dyn_cast<ApplyInst>(I);
|
||||
// When EnableLinkAll is true, we don't check whether it is transparent.
|
||||
if (!AI || (!EnableLinkAll && !AI->isTransparent()))
|
||||
SILFunction *CalleeFunction = nullptr;
|
||||
bool TryLinking = false;
|
||||
if (ApplyInst *AI = dyn_cast<ApplyInst>(I)) {
|
||||
SILValue Callee = AI->getCallee();
|
||||
// Handles FunctionRefInst only.
|
||||
if (FunctionRefInst *FRI = dyn_cast<FunctionRefInst>(Callee.getDef()))
|
||||
CalleeFunction = FRI->getFunction();
|
||||
|
||||
// When EnableLinkAll is true, we always link the Callee.
|
||||
TryLinking = EnableLinkAll ? true : AI->isTransparent();
|
||||
}
|
||||
else if (SpecializeInst *SI = dyn_cast<SpecializeInst>(I)) {
|
||||
SILValue Callee = SI->getOperand();
|
||||
// Handles FunctionRefInst only.
|
||||
if (FunctionRefInst *FRI = dyn_cast<FunctionRefInst>(Callee.getDef()))
|
||||
CalleeFunction = FRI->getFunction();
|
||||
}
|
||||
if (!CalleeFunction)
|
||||
continue;
|
||||
|
||||
SILValue Callee = AI->getCallee();
|
||||
// Handles FunctionRefInst only.
|
||||
FunctionRefInst *FRI = dyn_cast<FunctionRefInst>(Callee.getDef());
|
||||
if (!FRI)
|
||||
continue;
|
||||
|
||||
SILFunction *CalleeFunction = FRI->getFunction();
|
||||
if (CalleeFunction->empty()) {
|
||||
// Try to find the definition in a serialized module when callee is
|
||||
// currently empty and the ApplyInst is transparent.
|
||||
auto NewFn = SILLoader->lookupSILFunction(CalleeFunction);
|
||||
if (NewFn) {
|
||||
Worklist.push_back(NewFn);
|
||||
++NumFuncLinked;
|
||||
// currently empty.
|
||||
if (TryLinking) {
|
||||
if (auto NewFn = SILLoader->lookupSILFunction(CalleeFunction)) {
|
||||
Worklist.push_back(NewFn);
|
||||
++NumFuncLinked;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// FIXME: Make sure the declaration has external linkage?
|
||||
CalleeFunction->setLinkage(SILLinkage::External);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,10 +149,11 @@ Pattern *ModuleFile::maybeReadPattern() {
|
||||
ProtocolConformance *
|
||||
ModuleFile::readUnderlyingConformance(ProtocolDecl *proto,
|
||||
DeclID typeID,
|
||||
IdentifierID moduleID) {
|
||||
IdentifierID moduleID,
|
||||
llvm::BitstreamCursor &Cursor) {
|
||||
if (!moduleID) {
|
||||
// The underlying conformance is in the following record.
|
||||
return maybeReadConformance(getType(typeID))->second;
|
||||
return maybeReadConformance(getType(typeID), Cursor)->second;
|
||||
}
|
||||
|
||||
// Dig out the protocol conformance within the nominal declaration.
|
||||
@@ -187,17 +188,18 @@ ModuleFile::readUnderlyingConformance(ProtocolDecl *proto,
|
||||
llvm_unreachable("Unable to find underlying conformance");
|
||||
}
|
||||
|
||||
Optional<ConformancePair> ModuleFile::maybeReadConformance(Type conformingType){
|
||||
Optional<ConformancePair> ModuleFile::maybeReadConformance(Type conformingType,
|
||||
llvm::BitstreamCursor &Cursor){
|
||||
using namespace decls_block;
|
||||
|
||||
BCOffsetRAII lastRecordOffset(DeclTypeCursor);
|
||||
BCOffsetRAII lastRecordOffset(Cursor);
|
||||
SmallVector<uint64_t, 16> scratch;
|
||||
|
||||
auto next = DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
|
||||
auto next = Cursor.advance(AF_DontPopBlockAtEnd);
|
||||
if (next.Kind != llvm::BitstreamEntry::Record)
|
||||
return Nothing;
|
||||
|
||||
unsigned kind = DeclTypeCursor.readRecord(next.ID, scratch);
|
||||
unsigned kind = Cursor.readRecord(next.ID, scratch);
|
||||
switch (kind) {
|
||||
case NO_CONFORMANCE: {
|
||||
lastRecordOffset.reset();
|
||||
@@ -231,7 +233,7 @@ Optional<ConformancePair> ModuleFile::maybeReadConformance(Type conformingType){
|
||||
// Read the substitutions.
|
||||
SmallVector<Substitution, 4> substitutions;
|
||||
while (numSubstitutions--) {
|
||||
auto sub = maybeReadSubstitution();
|
||||
auto sub = maybeReadSubstitution(Cursor);
|
||||
assert(sub.hasValue() && "Missing substitution?");
|
||||
substitutions.push_back(*sub);
|
||||
}
|
||||
@@ -243,14 +245,14 @@ Optional<ConformancePair> ModuleFile::maybeReadConformance(Type conformingType){
|
||||
// FIXME: We don't actually want to allocate an archetype here; we just
|
||||
// want to get an access path within the protocol.
|
||||
auto first = cast<AssociatedTypeDecl>(getDecl(*rawIDIter++));
|
||||
auto second = maybeReadSubstitution();
|
||||
auto second = maybeReadSubstitution(Cursor);
|
||||
assert(second.hasValue());
|
||||
typeWitnesses[first] = *second;
|
||||
}
|
||||
assert(rawIDIter <= rawIDs.end() && "read too much");
|
||||
|
||||
ProtocolConformance *genericConformance
|
||||
= readUnderlyingConformance(proto, typeID, moduleID);
|
||||
= readUnderlyingConformance(proto, typeID, moduleID, Cursor);
|
||||
|
||||
// Reset the offset RAII to the end of the trailing records.
|
||||
lastRecordOffset.reset();
|
||||
@@ -276,7 +278,7 @@ Optional<ConformancePair> ModuleFile::maybeReadConformance(Type conformingType){
|
||||
auto proto = cast<ProtocolDecl>(getDecl(protoID));
|
||||
|
||||
ProtocolConformance *inheritedConformance
|
||||
= readUnderlyingConformance(proto, typeID, moduleID);
|
||||
= readUnderlyingConformance(proto, typeID, moduleID, Cursor);
|
||||
|
||||
// Reset the offset RAII to the end of the trailing records.
|
||||
lastRecordOffset.reset();
|
||||
@@ -305,7 +307,7 @@ Optional<ConformancePair> ModuleFile::maybeReadConformance(Type conformingType){
|
||||
InheritedConformanceMap inheritedConformances;
|
||||
|
||||
while (inheritedCount--) {
|
||||
auto inherited = maybeReadConformance(conformingType);
|
||||
auto inherited = maybeReadConformance(conformingType, Cursor);
|
||||
assert(inherited.hasValue());
|
||||
|
||||
inheritedConformances.insert(inherited.getValue());
|
||||
@@ -324,7 +326,7 @@ Optional<ConformancePair> ModuleFile::maybeReadConformance(Type conformingType){
|
||||
|
||||
SmallVector<Substitution, 8> substitutions;
|
||||
while (substitutionCount--) {
|
||||
auto sub = maybeReadSubstitution();
|
||||
auto sub = maybeReadSubstitution(Cursor);
|
||||
assert(sub.hasValue());
|
||||
substitutions.push_back(sub.getValue());
|
||||
}
|
||||
@@ -344,7 +346,7 @@ Optional<ConformancePair> ModuleFile::maybeReadConformance(Type conformingType){
|
||||
// FIXME: We don't actually want to allocate an archetype here; we just
|
||||
// want to get an access path within the protocol.
|
||||
auto first = cast<AssociatedTypeDecl>(getDecl(*rawIDIter++));
|
||||
auto second = maybeReadSubstitution();
|
||||
auto second = maybeReadSubstitution(Cursor);
|
||||
assert(second.hasValue());
|
||||
typeWitnesses[first] = *second;
|
||||
}
|
||||
@@ -387,17 +389,18 @@ void processConformances(ASTContext &ctx, T *decl,
|
||||
}
|
||||
|
||||
|
||||
Optional<Substitution> ModuleFile::maybeReadSubstitution() {
|
||||
BCOffsetRAII lastRecordOffset(DeclTypeCursor);
|
||||
Optional<Substitution> ModuleFile::maybeReadSubstitution(
|
||||
llvm::BitstreamCursor &Cursor) {
|
||||
BCOffsetRAII lastRecordOffset(Cursor);
|
||||
|
||||
auto entry = DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
|
||||
auto entry = Cursor.advance(AF_DontPopBlockAtEnd);
|
||||
if (entry.Kind != llvm::BitstreamEntry::Record)
|
||||
return Nothing;
|
||||
|
||||
StringRef blobData;
|
||||
SmallVector<uint64_t, 2> scratch;
|
||||
unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch,
|
||||
&blobData);
|
||||
unsigned recordID = Cursor.readRecord(entry.ID, scratch,
|
||||
&blobData);
|
||||
if (recordID != decls_block::BOUND_GENERIC_SUBSTITUTION)
|
||||
return Nothing;
|
||||
|
||||
@@ -416,7 +419,7 @@ Optional<Substitution> ModuleFile::maybeReadSubstitution() {
|
||||
|
||||
SmallVector<ProtocolConformance *, 16> conformanceBuf;
|
||||
while (numConformances--) {
|
||||
auto conformancePair = maybeReadConformance(replacementTy);
|
||||
auto conformancePair = maybeReadConformance(replacementTy, Cursor);
|
||||
assert(conformancePair.hasValue() && "Missing conformance");
|
||||
conformanceBuf.push_back(conformancePair->second);
|
||||
}
|
||||
@@ -689,7 +692,8 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext,
|
||||
alias->setImplicit();
|
||||
|
||||
SmallVector<ConformancePair, 16> conformances;
|
||||
while (auto conformance = maybeReadConformance(underlyingType.getType()))
|
||||
while (auto conformance = maybeReadConformance(underlyingType.getType(),
|
||||
DeclTypeCursor))
|
||||
conformances.push_back(*conformance);
|
||||
processConformances(ctx, alias, conformances);
|
||||
alias->setCheckedInheritanceClause();
|
||||
@@ -728,7 +732,8 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext,
|
||||
|
||||
SmallVector<ConformancePair, 16> conformances;
|
||||
while (auto conformance
|
||||
= maybeReadConformance(genericParam->getDeclaredType()))
|
||||
= maybeReadConformance(genericParam->getDeclaredType(),
|
||||
DeclTypeCursor))
|
||||
conformances.push_back(*conformance);
|
||||
processConformances(ctx, genericParam, conformances);
|
||||
genericParam->setCheckedInheritanceClause();
|
||||
@@ -765,7 +770,7 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext,
|
||||
|
||||
SmallVector<ConformancePair, 16> conformances;
|
||||
while (auto conformance
|
||||
= maybeReadConformance(assocType->getDeclaredType()))
|
||||
= maybeReadConformance(assocType->getDeclaredType(), DeclTypeCursor))
|
||||
conformances.push_back(*conformance);
|
||||
processConformances(ctx, assocType, conformances);
|
||||
assocType->setCheckedInheritanceClause();
|
||||
@@ -805,7 +810,7 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext,
|
||||
CanType canTy = theStruct->getDeclaredTypeInContext()->getCanonicalType();
|
||||
|
||||
SmallVector<ConformancePair, 16> conformances;
|
||||
while (auto conformance = maybeReadConformance(canTy))
|
||||
while (auto conformance = maybeReadConformance(canTy, DeclTypeCursor))
|
||||
conformances.push_back(*conformance);
|
||||
processConformances(ctx, theStruct, conformances);
|
||||
|
||||
@@ -1167,7 +1172,7 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext,
|
||||
CanType canTy = theClass->getDeclaredTypeInContext()->getCanonicalType();
|
||||
|
||||
SmallVector<ConformancePair, 16> conformances;
|
||||
while (auto conformance = maybeReadConformance(canTy))
|
||||
while (auto conformance = maybeReadConformance(canTy, DeclTypeCursor))
|
||||
conformances.push_back(*conformance);
|
||||
processConformances(ctx, theClass, conformances);
|
||||
|
||||
@@ -1216,7 +1221,7 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext,
|
||||
CanType canTy = theEnum->getDeclaredTypeInContext()->getCanonicalType();
|
||||
|
||||
SmallVector<ConformancePair, 16> conformances;
|
||||
while (auto conformance = maybeReadConformance(canTy))
|
||||
while (auto conformance = maybeReadConformance(canTy, DeclTypeCursor))
|
||||
conformances.push_back(*conformance);
|
||||
processConformances(ctx, theEnum, conformances);
|
||||
|
||||
@@ -1329,7 +1334,7 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext,
|
||||
CanType canBaseTy = baseTy.getType()->getCanonicalType();
|
||||
|
||||
SmallVector<ConformancePair, 16> conformances;
|
||||
while (auto conformance = maybeReadConformance(canBaseTy))
|
||||
while (auto conformance = maybeReadConformance(canBaseTy, DeclTypeCursor))
|
||||
conformances.push_back(*conformance);
|
||||
processConformances(ctx, extension, conformances);
|
||||
|
||||
@@ -1959,7 +1964,7 @@ Type ModuleFile::getType(TypeID TID) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
paramList = maybeReadGenericParams(nullptr);
|
||||
paramList = maybeReadGenericParams(ModuleContext);
|
||||
}
|
||||
assert(paramList && "missing generic params for polymorphic function");
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "SILFormat.h"
|
||||
#include "swift/SIL/SILArgument.h"
|
||||
#include "swift/SIL/SILBuilder.h"
|
||||
#include "swift/SIL/SILDebugScope.h"
|
||||
#include "swift/SIL/SILModule.h"
|
||||
#include "swift/Serialization/BCReadingExtras.h"
|
||||
|
||||
@@ -244,7 +245,12 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID, SILFunction *InFunc) {
|
||||
return nullptr;
|
||||
}
|
||||
auto Fn = InFunc;
|
||||
Fn->setLinkage((SILLinkage)Linkage);
|
||||
// FIXME: what should we set the linkage to?
|
||||
Fn->setLinkage(SILLinkage::Deserialized);
|
||||
// FIXME: use the correct SILLocation from module.
|
||||
SourceLoc Loc;
|
||||
Fn->setLocation(SILFileLocation(Loc));
|
||||
Fn->setDebugScope(new (SILMod) SILDebugScope(Fn->getLocation()));
|
||||
SILBasicBlock *CurrentBB = nullptr;
|
||||
|
||||
// Clear up at the beginning of each SILFunction.
|
||||
@@ -1147,16 +1153,16 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
|
||||
case ValueKind::SpecializeInst: {
|
||||
// Format: a typed value, a type, a list of substitutions (Archetype name,
|
||||
// Replacement type). Use SILOneTypeValuesLayout.
|
||||
assert(ListOfValues.size() >= 4 &&
|
||||
"Expect 4 or more numbers for SpecializeInst");
|
||||
assert(ListOfValues.size() == 5 && "Expect 5 numbers for SpecializeInst");
|
||||
unsigned NumSub = ListOfValues[4];
|
||||
// Read the substitutions.
|
||||
SmallVector<Substitution, 4> Substitutions;
|
||||
for (unsigned I = 4, E = ListOfValues.size(); I < E; I += 2) {
|
||||
Substitution Sub;
|
||||
Sub.Replacement = MF->getType(ListOfValues[I+1]);
|
||||
Sub.Archetype = cast<ArchetypeType>(
|
||||
MF->getType(ListOfValues[I]).getPointer());
|
||||
Substitutions.push_back(Sub);
|
||||
while (NumSub--) {
|
||||
auto sub = MF->maybeReadSubstitution(SILCursor);
|
||||
assert(sub.hasValue() && "Missing substitution?");
|
||||
Substitutions.push_back(*sub);
|
||||
}
|
||||
|
||||
auto ValTy = MF->getType(ListOfValues[0]);
|
||||
assert(ValTy->is<PolymorphicFunctionType>() &&
|
||||
"Should be a polymorphic function");
|
||||
|
||||
@@ -222,7 +222,8 @@ private:
|
||||
ProtocolConformance *
|
||||
readUnderlyingConformance(ProtocolDecl *proto,
|
||||
serialization::DeclID typeID,
|
||||
serialization::IdentifierID moduleID);
|
||||
serialization::IdentifierID moduleID,
|
||||
llvm::BitstreamCursor &Cursor);
|
||||
|
||||
/// Recursively reads a protocol conformance from \c DeclTypeCursor.
|
||||
///
|
||||
@@ -232,12 +233,7 @@ private:
|
||||
/// If the record at the cursor is not a protocol conformance, returns
|
||||
/// Nothing. Note that a null pointer is a valid conformance value.
|
||||
Optional<std::pair<ProtocolDecl *, ProtocolConformance *>>
|
||||
maybeReadConformance(Type conformingType);
|
||||
|
||||
/// Reads a substitution record from \c DeclTypeCursor.
|
||||
///
|
||||
/// If the record at the cursor is not a substitution, returns Nothing.
|
||||
Optional<Substitution> maybeReadSubstitution();
|
||||
maybeReadConformance(Type conformingType, llvm::BitstreamCursor &Cursor);
|
||||
|
||||
/// Reads a generic param list from \c DeclTypeCursor.
|
||||
///
|
||||
@@ -389,6 +385,11 @@ public:
|
||||
/// If the name matches the name of the current module, a shadowed module
|
||||
/// is loaded instead. An empty name represents the Builtin module.
|
||||
Module *getModule(Identifier name);
|
||||
|
||||
/// Reads a substitution record from \c DeclTypeCursor.
|
||||
///
|
||||
/// If the record at the cursor is not a substitution, returns Nothing.
|
||||
Optional<Substitution> maybeReadSubstitution(llvm::BitstreamCursor &Cursor);
|
||||
};
|
||||
|
||||
class SerializedModule : public LoadedModule {
|
||||
|
||||
@@ -577,11 +577,12 @@ Serializer::encodeUnderlyingConformance(const ProtocolConformance *conformance,
|
||||
void
|
||||
Serializer::writeConformance(const ProtocolDecl *protocol,
|
||||
const ProtocolConformance *conformance,
|
||||
const Decl *associatedDecl) {
|
||||
const Decl *associatedDecl,
|
||||
const std::array<unsigned, 256> &abbrCodes) {
|
||||
using namespace decls_block;
|
||||
|
||||
if (!conformance) {
|
||||
unsigned abbrCode = DeclTypeAbbrCodes[NoConformanceLayout::Code];
|
||||
unsigned abbrCode = abbrCodes[NoConformanceLayout::Code];
|
||||
NoConformanceLayout::emitRecord(Out, ScratchRecord, abbrCode,
|
||||
addDeclRef(protocol));
|
||||
return;
|
||||
@@ -621,7 +622,7 @@ Serializer::writeConformance(const ProtocolDecl *protocol,
|
||||
|
||||
unsigned numInheritedConformances = conf->getInheritedConformances().size();
|
||||
unsigned abbrCode
|
||||
= DeclTypeAbbrCodes[NormalProtocolConformanceLayout::Code];
|
||||
= abbrCodes[NormalProtocolConformanceLayout::Code];
|
||||
NormalProtocolConformanceLayout::emitRecord(Out, ScratchRecord, abbrCode,
|
||||
addDeclRef(protocol),
|
||||
numValueWitnesses,
|
||||
@@ -637,12 +638,14 @@ Serializer::writeConformance(const ProtocolDecl *protocol,
|
||||
inheritedProtos.push_back(inheritedMapping.first);
|
||||
inheritedConformance.push_back(inheritedMapping.second);
|
||||
}
|
||||
writeConformances(inheritedProtos, inheritedConformance, associatedDecl);
|
||||
writeConformances(inheritedProtos, inheritedConformance, associatedDecl,
|
||||
abbrCodes);
|
||||
for (auto valueMapping : conf->getWitnesses()) {
|
||||
writeSubstitutions(valueMapping.second.getSubstitutions());
|
||||
writeSubstitutions(valueMapping.second.getSubstitutions(),
|
||||
abbrCodes);
|
||||
}
|
||||
for (auto typeMapping : conf->getTypeWitnesses())
|
||||
writeSubstitutions(typeMapping.second);
|
||||
writeSubstitutions(typeMapping.second, abbrCodes);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -658,7 +661,7 @@ Serializer::writeConformance(const ProtocolDecl *protocol,
|
||||
}
|
||||
auto substitutions = conf->getGenericSubstitutions();
|
||||
unsigned abbrCode
|
||||
= DeclTypeAbbrCodes[SpecializedProtocolConformanceLayout::Code];
|
||||
= abbrCodes[SpecializedProtocolConformanceLayout::Code];
|
||||
DeclID typeID;
|
||||
IdentifierID moduleID;
|
||||
|
||||
@@ -674,12 +677,13 @@ Serializer::writeConformance(const ProtocolDecl *protocol,
|
||||
numTypeWitnesses,
|
||||
substitutions.size(),
|
||||
data);
|
||||
writeSubstitutions(substitutions);
|
||||
writeSubstitutions(substitutions, abbrCodes);
|
||||
for (auto typeMapping : conf->getTypeWitnesses())
|
||||
writeSubstitutions(typeMapping.second);
|
||||
writeSubstitutions(typeMapping.second, abbrCodes);
|
||||
|
||||
if (appendGenericConformance) {
|
||||
writeConformance(protocol, conf->getGenericConformance(), nullptr);
|
||||
writeConformance(protocol, conf->getGenericConformance(), nullptr,
|
||||
abbrCodes);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -687,7 +691,7 @@ Serializer::writeConformance(const ProtocolDecl *protocol,
|
||||
case ProtocolConformanceKind::Inherited: {
|
||||
auto conf = cast<InheritedProtocolConformance>(conformance);
|
||||
unsigned abbrCode
|
||||
= DeclTypeAbbrCodes[InheritedProtocolConformanceLayout::Code];
|
||||
= abbrCodes[InheritedProtocolConformanceLayout::Code];
|
||||
DeclID typeID;
|
||||
IdentifierID moduleID;
|
||||
|
||||
@@ -701,7 +705,8 @@ Serializer::writeConformance(const ProtocolDecl *protocol,
|
||||
typeID,
|
||||
moduleID);
|
||||
if (appendInheritedConformance) {
|
||||
writeConformance(protocol, conf->getInheritedConformance(), nullptr);
|
||||
writeConformance(protocol, conf->getInheritedConformance(), nullptr,
|
||||
abbrCodes);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -711,25 +716,29 @@ Serializer::writeConformance(const ProtocolDecl *protocol,
|
||||
void
|
||||
Serializer::writeConformances(ArrayRef<ProtocolDecl *> protocols,
|
||||
ArrayRef<ProtocolConformance *> conformances,
|
||||
const Decl *associatedDecl) {
|
||||
const Decl *associatedDecl,
|
||||
const std::array<unsigned, 256> &abbrCodes) {
|
||||
using namespace decls_block;
|
||||
|
||||
for_each(protocols, conformances,
|
||||
[&](const ProtocolDecl *proto, const ProtocolConformance *conf) {
|
||||
writeConformance(proto, conf, associatedDecl);
|
||||
writeConformance(proto, conf, associatedDecl, abbrCodes);
|
||||
});
|
||||
}
|
||||
|
||||
void Serializer::writeSubstitutions(ArrayRef<Substitution> substitutions) {
|
||||
/// Writes a list of generic substitutions.
|
||||
void Serializer::writeSubstitutions(ArrayRef<Substitution> substitutions,
|
||||
const std::array<unsigned, 256> &abbrCodes) {
|
||||
using namespace decls_block;
|
||||
auto abbrCode = DeclTypeAbbrCodes[BoundGenericSubstitutionLayout::Code];
|
||||
auto abbrCode = abbrCodes[BoundGenericSubstitutionLayout::Code];
|
||||
for (auto &sub : substitutions) {
|
||||
BoundGenericSubstitutionLayout::emitRecord(
|
||||
Out, ScratchRecord, abbrCode,
|
||||
addTypeRef(sub.Archetype),
|
||||
addTypeRef(sub.Replacement),
|
||||
sub.Archetype->getConformsTo().size());
|
||||
writeConformances(sub.Archetype->getConformsTo(), sub.Conformance);
|
||||
writeConformances(sub.Archetype->getConformsTo(), sub.Conformance, nullptr,
|
||||
abbrCodes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -886,7 +895,7 @@ void Serializer::writeDecl(const Decl *D) {
|
||||
extension->isImplicit());
|
||||
|
||||
writeConformances(extension->getProtocols(), extension->getConformances(),
|
||||
extension);
|
||||
extension, DeclTypeAbbrCodes);
|
||||
|
||||
bool isClassExtension = false;
|
||||
if (auto baseNominal = baseTy->getAnyNominal()) {
|
||||
@@ -980,7 +989,7 @@ void Serializer::writeDecl(const Decl *D) {
|
||||
typeAlias->isImplicit());
|
||||
|
||||
writeConformances(typeAlias->getProtocols(), typeAlias->getConformances(),
|
||||
typeAlias);
|
||||
typeAlias, DeclTypeAbbrCodes);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1005,7 +1014,7 @@ void Serializer::writeDecl(const Decl *D) {
|
||||
|
||||
writeConformances(genericParam->getProtocols(),
|
||||
genericParam->getConformances(),
|
||||
genericParam);
|
||||
genericParam, DeclTypeAbbrCodes);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1029,7 +1038,7 @@ void Serializer::writeDecl(const Decl *D) {
|
||||
|
||||
writeConformances(assocType->getProtocols(),
|
||||
assocType->getConformances(),
|
||||
assocType);
|
||||
assocType, DeclTypeAbbrCodes);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1049,7 +1058,7 @@ void Serializer::writeDecl(const Decl *D) {
|
||||
|
||||
writeGenericParams(theStruct->getGenericParams());
|
||||
writeConformances(theStruct->getProtocols(), theStruct->getConformances(),
|
||||
theStruct);
|
||||
theStruct, DeclTypeAbbrCodes);
|
||||
writeMembers(theStruct->getMembers(), false);
|
||||
break;
|
||||
}
|
||||
@@ -1070,7 +1079,7 @@ void Serializer::writeDecl(const Decl *D) {
|
||||
|
||||
writeGenericParams(theEnum->getGenericParams());
|
||||
writeConformances(theEnum->getProtocols(), theEnum->getConformances(),
|
||||
theEnum);
|
||||
theEnum, DeclTypeAbbrCodes);
|
||||
writeMembers(theEnum->getMembers(), false);
|
||||
break;
|
||||
}
|
||||
@@ -1094,7 +1103,7 @@ void Serializer::writeDecl(const Decl *D) {
|
||||
|
||||
writeGenericParams(theClass->getGenericParams());
|
||||
writeConformances(theClass->getProtocols(), theClass->getConformances(),
|
||||
theClass);
|
||||
theClass, DeclTypeAbbrCodes);
|
||||
writeMembers(theClass->getMembers(), true);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -172,9 +172,6 @@ private:
|
||||
/// Writes a generic parameter list.
|
||||
bool writeGenericParams(const GenericParamList *genericParams);
|
||||
|
||||
/// Writes a list of generic substitutions.
|
||||
void writeSubstitutions(ArrayRef<Substitution> substitutions);
|
||||
|
||||
/// Encode the underlying conformance of a generic or specialized
|
||||
/// conformance.
|
||||
///
|
||||
@@ -195,12 +192,14 @@ private:
|
||||
/// Writes a protocol conformance.
|
||||
void writeConformance(const ProtocolDecl *protocol,
|
||||
const ProtocolConformance *conformance,
|
||||
const Decl *associatedDecl);
|
||||
const Decl *associatedDecl,
|
||||
const std::array<unsigned, 256> &abbrCodes);
|
||||
|
||||
/// Writes a list of protocol conformances.
|
||||
void writeConformances(ArrayRef<ProtocolDecl *> protocols,
|
||||
ArrayRef<ProtocolConformance *> conformances,
|
||||
const Decl *associatedDecl = nullptr);
|
||||
const Decl *associatedDecl,
|
||||
const std::array<unsigned, 256> &abbrCodes);
|
||||
|
||||
/// Writes an array of members for a decl context.
|
||||
///
|
||||
@@ -291,6 +290,11 @@ public:
|
||||
/// \returns The ID for the identifier for the module's name, or 0 for the
|
||||
/// builtin module.
|
||||
IdentifierID addModuleRef(const Module *M);
|
||||
|
||||
/// Writes a list of generic substitutions. abbrCode is needed to support
|
||||
/// usage out of decl block.
|
||||
void writeSubstitutions(ArrayRef<Substitution> substitutions,
|
||||
const std::array<unsigned, 256> &abbrCodes);
|
||||
};
|
||||
} // end namespace serialization
|
||||
} // end namespace swift
|
||||
|
||||
@@ -1055,16 +1055,14 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
|
||||
ListOfValues.push_back((unsigned)SpI->getOperand().getType().getCategory());
|
||||
ListOfValues.push_back(addValueRef(SpI->getOperand()));
|
||||
ListOfValues.push_back(SpI->getOperand().getResultNumber());
|
||||
|
||||
for (auto Sub : SpI->getSubstitutions()) {
|
||||
ListOfValues.push_back(S.addTypeRef(Sub.Archetype));
|
||||
ListOfValues.push_back(S.addTypeRef(Sub.Replacement));
|
||||
}
|
||||
ListOfValues.push_back(SpI->getSubstitutions().size());
|
||||
|
||||
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
|
||||
SILAbbrCodes[SILOneTypeValuesLayout::Code], (unsigned)SI.getKind(),
|
||||
S.addTypeRef(SpI->getType().getSwiftRValueType()),
|
||||
(unsigned)SpI->getType().getCategory(), ListOfValues);
|
||||
|
||||
S.writeSubstitutions(SpI->getSubstitutions(), SILAbbrCodes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1105,7 +1103,7 @@ void SILSerializer::writeFuncTable() {
|
||||
|
||||
void SILSerializer::writeAllSILFunctions(const SILModule *M) {
|
||||
{
|
||||
BCBlockRAII subBlock(Out, SIL_BLOCK_ID, 4);
|
||||
BCBlockRAII subBlock(Out, SIL_BLOCK_ID, 5);
|
||||
registerSILAbbr<SILFunctionLayout>();
|
||||
registerSILAbbr<SILBasicBlockLayout>();
|
||||
registerSILAbbr<SILOneValueOneOperandLayout>();
|
||||
@@ -1117,6 +1115,16 @@ void SILSerializer::writeAllSILFunctions(const SILModule *M) {
|
||||
registerSILAbbr<SILInstApplyLayout>();
|
||||
registerSILAbbr<SILInstNoOperandLayout>();
|
||||
|
||||
// Register the abbreviation codes so these layouts can exist in both
|
||||
// decl blocks and sil blocks.
|
||||
// We have to make sure BOUND_GENERIC_SUBSTITUTION does not overlap with
|
||||
// SIL-specific records.
|
||||
registerSILAbbr<decls_block::BoundGenericSubstitutionLayout>();
|
||||
registerSILAbbr<decls_block::NoConformanceLayout>();
|
||||
registerSILAbbr<decls_block::NormalProtocolConformanceLayout>();
|
||||
registerSILAbbr<decls_block::SpecializedProtocolConformanceLayout>();
|
||||
registerSILAbbr<decls_block::InheritedProtocolConformanceLayout>();
|
||||
|
||||
// Go through all SILFunctions in M, and if it is transparent,
|
||||
// write out the SILFunction.
|
||||
if (M && (EnableSerialize || EnableSerializeAll)) {
|
||||
|
||||
Reference in New Issue
Block a user