SILGen: Add linkage to SILDefaultWitnessTable

This is only used in the verifier, to ensure that default witness
thunks are suffiently visible.

Also this patch removes the asserts enforcing that only resilient
protocols have a default witness table. This will change in an
upcoming patch, and in this patch is necessary for the test to work.
This commit is contained in:
Slava Pestov
2016-03-17 01:31:13 -07:00
parent 25319d9d4b
commit b13457daaa
9 changed files with 75 additions and 35 deletions

View File

@@ -74,6 +74,9 @@ private:
/// The module which contains the SILDefaultWitnessTable.
SILModule &Mod;
/// The linkage of the witness table.
SILLinkage Linkage;
/// The protocol declaration to which this default witness table applies.
const ProtocolDecl *Protocol;
@@ -90,24 +93,32 @@ private:
bool IsDeclaration;
/// Private constructor for making SILDefaultWitnessTable declarations.
SILDefaultWitnessTable(SILModule &M, const ProtocolDecl *Protocol);
SILDefaultWitnessTable(SILModule &M, SILLinkage Linkage,
const ProtocolDecl *Protocol);
/// Private constructor for making SILDefaultWitnessTable definitions.
SILDefaultWitnessTable(SILModule &M, const ProtocolDecl *Protocol,
SILDefaultWitnessTable(SILModule &M, SILLinkage Linkage,
const ProtocolDecl *Protocol,
ArrayRef<Entry> entries);
void addDefaultWitnessTable();
public:
/// Create a new SILDefaultWitnessTable declaration.
static SILDefaultWitnessTable *create(SILModule &M,
static SILDefaultWitnessTable *create(SILModule &M, SILLinkage Linkage,
const ProtocolDecl *Protocol);
/// Create a new SILDefaultWitnessTable definition with the given entries.
static SILDefaultWitnessTable *create(SILModule &M,
static SILDefaultWitnessTable *create(SILModule &M, SILLinkage Linkage,
const ProtocolDecl *Protocol,
ArrayRef<Entry> entries);
/// Get the linkage of the default witness table.
SILLinkage getLinkage() const { return Linkage; }
/// Set the linkage of the default witness table.
void setLinkage(SILLinkage l) { Linkage = l; }
void convertToDefinition(ArrayRef<Entry> entries);
~SILDefaultWitnessTable();

View File

@@ -525,7 +525,8 @@ public:
// Given a protocol, attempt to create a default witness table declaration
// for it.
SILDefaultWitnessTable *
createDefaultWitnessTableDeclaration(const ProtocolDecl *Protocol);
createDefaultWitnessTableDeclaration(const ProtocolDecl *Protocol,
SILLinkage Linkage);
/// \brief Return the stage of processing this module is at.
SILStage getStage() const { return Stage; }

View File

@@ -4394,16 +4394,21 @@ bool Parser::parseSILWitnessTable() {
}
/// decl-sil-default-witness ::= 'sil_default_witness_table'
/// identifier minimum-witness-table-size
/// sil-linkage identifier
/// decl-sil-default-witness-body
/// decl-sil-default-witness-body:
/// '{' sil-default-witness-entry* '}'
/// sil-default-witness-entry:
/// 'method' SILDeclRef ':' @SILFunctionName
/// 'no_default'
bool Parser::parseSILDefaultWitnessTable() {
consumeToken(tok::kw_sil_default_witness_table);
SILParser WitnessState(*this);
// Parse the linkage.
Optional<SILLinkage> Linkage;
parseSILLinkage(Linkage, *this);
Scope S(this, ScopeKind::TopLevel);
// We should use WitnessTableBody. This ensures that the generic params
// are visible.
@@ -4465,7 +4470,11 @@ bool Parser::parseSILDefaultWitnessTable() {
parseMatchingToken(tok::r_brace, RBraceLoc, diag::expected_sil_rbrace,
LBraceLoc);
SILDefaultWitnessTable::create(*SIL->M, protocol, witnessEntries);
// Default to public linkage.
if (!Linkage)
Linkage = SILLinkage::Public;
SILDefaultWitnessTable::create(*SIL->M, *Linkage, protocol, witnessEntries);
BodyScope.reset();
return false;
}

View File

@@ -34,13 +34,14 @@ void SILDefaultWitnessTable::addDefaultWitnessTable() {
}
SILDefaultWitnessTable *
SILDefaultWitnessTable::create(SILModule &M, const ProtocolDecl *Protocol,
SILDefaultWitnessTable::create(SILModule &M, SILLinkage Linkage,
const ProtocolDecl *Protocol,
ArrayRef<SILDefaultWitnessTable::Entry> entries){
// Allocate the witness table and initialize it.
void *buf = M.allocate(sizeof(SILDefaultWitnessTable),
alignof(SILDefaultWitnessTable));
SILDefaultWitnessTable *wt =
::new (buf) SILDefaultWitnessTable(M, Protocol, entries);
::new (buf) SILDefaultWitnessTable(M, Linkage, Protocol, entries);
wt->addDefaultWitnessTable();
@@ -49,12 +50,13 @@ SILDefaultWitnessTable::create(SILModule &M, const ProtocolDecl *Protocol,
}
SILDefaultWitnessTable *
SILDefaultWitnessTable::create(SILModule &M, const ProtocolDecl *Protocol) {
SILDefaultWitnessTable::create(SILModule &M, SILLinkage Linkage,
const ProtocolDecl *Protocol) {
// Allocate the witness table and initialize it.
void *buf = M.allocate(sizeof(SILDefaultWitnessTable),
alignof(SILDefaultWitnessTable));
SILDefaultWitnessTable *wt =
::new (buf) SILDefaultWitnessTable(M, Protocol);
::new (buf) SILDefaultWitnessTable(M, Linkage, Protocol);
wt->addDefaultWitnessTable();
@@ -64,16 +66,20 @@ SILDefaultWitnessTable::create(SILModule &M, const ProtocolDecl *Protocol) {
SILDefaultWitnessTable::
SILDefaultWitnessTable(SILModule &M,
SILLinkage Linkage,
const ProtocolDecl *Protocol,
ArrayRef<Entry> entries)
: Mod(M), Protocol(Protocol), Entries(), IsDeclaration(true) {
: Mod(M), Linkage(Linkage), Protocol(Protocol), Entries(),
IsDeclaration(true) {
convertToDefinition(entries);
}
SILDefaultWitnessTable::SILDefaultWitnessTable(SILModule &M,
SILLinkage Linkage,
const ProtocolDecl *Protocol)
: Mod(M), Protocol(Protocol), Entries(), IsDeclaration(true) {}
: Mod(M), Linkage(Linkage), Protocol(Protocol), Entries(),
IsDeclaration(true) {}
void SILDefaultWitnessTable::
convertToDefinition(ArrayRef<Entry> entries) {

View File

@@ -190,23 +190,17 @@ SILModule::lookUpDefaultWitnessTable(const ProtocolDecl *Protocol) {
auto found = DefaultWitnessTableMap.find(Protocol);
if (found == DefaultWitnessTableMap.end()) {
assert(Protocol->hasFixedLayout() &&
"Resilient protocol must have a default witness table");
return nullptr;
}
assert(!Protocol->hasFixedLayout() &&
"Fixed-layout protocol cannot have a default witness table");
return found->second;
}
SILDefaultWitnessTable *
SILModule::createDefaultWitnessTableDeclaration(const ProtocolDecl *Protocol) {
assert(!Protocol->hasFixedLayout() &&
"Fixed-layout protocol cannot have a default witness table");
return SILDefaultWitnessTable::create(*this, Protocol);
SILModule::createDefaultWitnessTableDeclaration(const ProtocolDecl *Protocol,
SILLinkage Linkage) {
return SILDefaultWitnessTable::create(*this, Linkage, Protocol);
}
SILFunction *SILModule::getOrCreateFunction(SILLocation loc,

View File

@@ -2117,9 +2117,10 @@ void SILWitnessTable::dump() const {
}
void SILDefaultWitnessTable::print(llvm::raw_ostream &OS, bool Verbose) const {
// sil_default_witness_table <Protocol> <MinSize>
OS << "sil_default_witness_table"
<< " " << getProtocol()->getName() << " {\n";
// sil_default_witness_table [<Linkage>] <Protocol> <MinSize>
OS << "sil_default_witness_table ";
printLinkage(OS, getLinkage(), ForDefinition);
OS << getProtocol()->getName() << " {\n";
for (auto &witness : getEntries()) {
if (!witness.isValid()) {

View File

@@ -3238,9 +3238,6 @@ void SILDefaultWitnessTable::verify(const SILModule &M) const {
#ifndef NDEBUG
assert(!isDeclaration() &&
"Default witness table declarations should not exist.");
assert(!getProtocol()->hasFixedLayout() &&
"Default witness table declarations for fixed-layout protocols should "
"not exist.");
assert(getProtocol()->getParentModule() == M.getSwiftModule() &&
"Default witness table declarations must appear in the same "
"module as their protocol.");
@@ -3253,9 +3250,9 @@ void SILDefaultWitnessTable::verify(const SILModule &M) const {
continue;
SILFunction *F = E.getWitness();
assert(!isLessVisibleThan(F->getLinkage(), SILLinkage::Public) &&
"Default witness tables should not reference internal "
"or private functions.");
assert(!isLessVisibleThan(F->getLinkage(), getLinkage()) &&
"Default witness tables should not reference "
"less visible functions.");
assert(F->getLoweredFunctionType()->getRepresentation() ==
SILFunctionTypeRepresentation::WitnessMethod &&
"Default witnesses must have witness_method representation.");

View File

@@ -1938,7 +1938,7 @@ void SILGenModule::emitDefaultWitnessTable(ProtocolDecl *protocol) {
builder.visitProtocolDecl(protocol);
SILDefaultWitnessTable *defaultWitnesses =
M.createDefaultWitnessTableDeclaration(protocol);
M.createDefaultWitnessTableDeclaration(protocol, linkage);
defaultWitnesses->convertToDefinition(builder.DefaultWitnesses);
}

View File

@@ -34,14 +34,26 @@ bb0(%0 : $*Self):
sil public_external @defaultE : $@convention(witness_method) <Self where Self : ResilientProtocol> (@in_guaranteed Self) -> ()
protocol InternalProtocol {
func defaultF()
}
// CHECK-LABEL: sil hidden @defaultF
sil hidden @defaultF : $@convention(witness_method) <Self where Self : InternalProtocol> (@in_guaranteed Self) -> () {
bb0(%0 : $*Self):
%result = tuple ()
return %result : $()
}
// CHECK-LABEL: sil_default_witness_table ResilientProtocol {
// CHECK: no_default
// CHECK: no_default
// CHECK: no_default
// CHECK: no_default
// CHECK: #ResilientProtocol.defaultC!1: @defaultC
// CHECK: #ResilientProtocol.defaultD!1: @defaultD
// CHECK: #ResilientProtocol.defaultE!1: @defaultE
// CHECK: method #ResilientProtocol.defaultC!1: @defaultC
// CHECK: method #ResilientProtocol.defaultD!1: @defaultD
// CHECK: method #ResilientProtocol.defaultE!1: @defaultE
// CHECK: }
sil_default_witness_table ResilientProtocol {
@@ -53,3 +65,12 @@ sil_default_witness_table ResilientProtocol {
method #ResilientProtocol.defaultD!1: @defaultD
method #ResilientProtocol.defaultE!1: @defaultE
}
// CHECK-LABEL: sil_default_witness_table hidden InternalProtocol {
// CHECK: method #InternalProtocol.defaultF!1: @defaultF
// CHECK: }
sil_default_witness_table hidden InternalProtocol {
method #InternalProtocol.defaultF!1: @defaultF
}