mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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:
@@ -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();
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user