SIL: Record whether vtable entries are inherited or overridden

Consider a class hierarchy like the following:

class Base {
  func m1() {}
  func m2() {}
}

class Derived : Base {
  override func m2() {}
  func m3() {}
}

The SIL vtable for 'Derived' now records that the entry for m1
is inherited, the entry for m2 is an override, and the entry
for m3 is a new entry:

sil_vtable Derived {
  #Base.m1!1: (Base) -> () -> () : _T01a4BaseC2m1yyF [inherited]
  #Base.m2!1: (Base) -> () -> () : _T01a7DerivedC2m2yyF [override]
  #Derived.m3!1: (Derived) -> () -> () : _T01a7DerivedC2m3yyF
}

This additional information will allow IRGen to emit the vtable
for Derived resiliently, without referencing the symbol for
the inherited method m1() directly.
This commit is contained in:
Slava Pestov
2017-08-14 17:57:17 -04:00
parent fd253dabaf
commit 556d35d9b1
17 changed files with 349 additions and 170 deletions

View File

@@ -74,6 +74,16 @@ fromStableSILLinkage(unsigned value) {
}
}
static Optional<SILVTable::Entry::Kind>
fromStableVTableEntryKind(unsigned value) {
switch (value) {
case SIL_VTABLE_ENTRY_NORMAL: return SILVTable::Entry::Kind::Normal;
case SIL_VTABLE_ENTRY_INHERITED: return SILVTable::Entry::Kind::Inherited;
case SIL_VTABLE_ENTRY_OVERRIDE: return SILVTable::Entry::Kind::Override;
default: return None;
}
}
/// Used to deserialize entries in the on-disk func hash table.
class SILDeserializer::FuncTableInfo {
public:
@@ -2441,9 +2451,10 @@ SILVTable *SILDeserializer::readVTable(DeclID VId) {
ArrayRef<uint64_t> ListOfValues;
DeclID NameID;
unsigned RawLinkage;
VTableEntryLayout::readRecord(scratch, NameID, RawLinkage, ListOfValues);
unsigned RawEntryKind;
VTableEntryLayout::readRecord(scratch, NameID, RawEntryKind, RawLinkage, ListOfValues);
Optional<SILLinkage> Linkage = fromStableSILLinkage(RawLinkage);
auto Linkage = fromStableSILLinkage(RawLinkage);
if (!Linkage) {
DEBUG(llvm::dbgs() << "invalid linkage code " << RawLinkage
<< " for VTable Entry\n");
@@ -2451,11 +2462,13 @@ SILVTable *SILDeserializer::readVTable(DeclID VId) {
return nullptr;
}
auto EntryKind = fromStableVTableEntryKind(RawEntryKind);
SILFunction *Func = getFuncForReference(MF->getIdentifier(NameID).str());
if (Func) {
unsigned NextValueIndex = 0;
vtableEntries.emplace_back(getSILDeclRef(MF, ListOfValues, NextValueIndex),
Func, Linkage.getValue());
Func, EntryKind.getValue(), Linkage.getValue());
}
// Fetch the next record.

View File

@@ -47,6 +47,13 @@ enum SILLinkageEncoding : uint8_t {
};
using SILLinkageField = BCFixed<3>;
enum SILVTableEntryKindEncoding : uint8_t {
SIL_VTABLE_ENTRY_NORMAL,
SIL_VTABLE_ENTRY_INHERITED,
SIL_VTABLE_ENTRY_OVERRIDE,
};
using SILVTableEntryKindField = BCFixed<2>;
enum CheckedCastKindEncoding : uint8_t {
SIL_CHECKED_CAST_ARCHETYPE_TO_ARCHETYPE,
SIL_CHECKED_CAST_ARCHETYPE_TO_CONCRETE,
@@ -185,6 +192,7 @@ namespace sil_block {
using VTableEntryLayout = BCRecordLayout<
SIL_VTABLE_ENTRY,
DeclIDField, // SILFunction name
SILVTableEntryKindField, // Kind
SILLinkageField, // Linkage
BCArray<ValueIDField> // SILDeclRef
>;

View File

@@ -74,6 +74,15 @@ static unsigned toStableSILLinkage(SILLinkage linkage) {
llvm_unreachable("bad linkage");
}
static unsigned toStableVTableEntryKind(SILVTable::Entry::Kind kind) {
switch (kind) {
case SILVTable::Entry::Kind::Normal: return SIL_VTABLE_ENTRY_NORMAL;
case SILVTable::Entry::Kind::Inherited: return SIL_VTABLE_ENTRY_INHERITED;
case SILVTable::Entry::Kind::Override: return SIL_VTABLE_ENTRY_OVERRIDE;
}
llvm_unreachable("bad vtable entry kind");
}
static unsigned toStableCastConsumptionKind(CastConsumptionKind kind) {
switch (kind) {
case CastConsumptionKind::TakeAlways:
@@ -2029,6 +2038,7 @@ void SILSerializer::writeSILVTable(const SILVTable &vt) {
SILAbbrCodes[VTableEntryLayout::Code],
// SILFunction name
S.addDeclBaseNameRef(Ctx.getIdentifier(entry.Implementation->getName())),
toStableVTableEntryKind(entry.TheKind),
toStableSILLinkage(entry.Linkage),
ListOfValues);
}