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.
|
/// The module which contains the SILDefaultWitnessTable.
|
||||||
SILModule &Mod;
|
SILModule &Mod;
|
||||||
|
|
||||||
|
/// The linkage of the witness table.
|
||||||
|
SILLinkage Linkage;
|
||||||
|
|
||||||
/// The protocol declaration to which this default witness table applies.
|
/// The protocol declaration to which this default witness table applies.
|
||||||
const ProtocolDecl *Protocol;
|
const ProtocolDecl *Protocol;
|
||||||
|
|
||||||
@@ -90,24 +93,32 @@ private:
|
|||||||
bool IsDeclaration;
|
bool IsDeclaration;
|
||||||
|
|
||||||
/// Private constructor for making SILDefaultWitnessTable declarations.
|
/// 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.
|
/// Private constructor for making SILDefaultWitnessTable definitions.
|
||||||
SILDefaultWitnessTable(SILModule &M, const ProtocolDecl *Protocol,
|
SILDefaultWitnessTable(SILModule &M, SILLinkage Linkage,
|
||||||
|
const ProtocolDecl *Protocol,
|
||||||
ArrayRef<Entry> entries);
|
ArrayRef<Entry> entries);
|
||||||
|
|
||||||
void addDefaultWitnessTable();
|
void addDefaultWitnessTable();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Create a new SILDefaultWitnessTable declaration.
|
/// Create a new SILDefaultWitnessTable declaration.
|
||||||
static SILDefaultWitnessTable *create(SILModule &M,
|
static SILDefaultWitnessTable *create(SILModule &M, SILLinkage Linkage,
|
||||||
const ProtocolDecl *Protocol);
|
const ProtocolDecl *Protocol);
|
||||||
|
|
||||||
/// Create a new SILDefaultWitnessTable definition with the given entries.
|
/// Create a new SILDefaultWitnessTable definition with the given entries.
|
||||||
static SILDefaultWitnessTable *create(SILModule &M,
|
static SILDefaultWitnessTable *create(SILModule &M, SILLinkage Linkage,
|
||||||
const ProtocolDecl *Protocol,
|
const ProtocolDecl *Protocol,
|
||||||
ArrayRef<Entry> entries);
|
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);
|
void convertToDefinition(ArrayRef<Entry> entries);
|
||||||
|
|
||||||
~SILDefaultWitnessTable();
|
~SILDefaultWitnessTable();
|
||||||
|
|||||||
@@ -525,7 +525,8 @@ public:
|
|||||||
// Given a protocol, attempt to create a default witness table declaration
|
// Given a protocol, attempt to create a default witness table declaration
|
||||||
// for it.
|
// for it.
|
||||||
SILDefaultWitnessTable *
|
SILDefaultWitnessTable *
|
||||||
createDefaultWitnessTableDeclaration(const ProtocolDecl *Protocol);
|
createDefaultWitnessTableDeclaration(const ProtocolDecl *Protocol,
|
||||||
|
SILLinkage Linkage);
|
||||||
|
|
||||||
/// \brief Return the stage of processing this module is at.
|
/// \brief Return the stage of processing this module is at.
|
||||||
SILStage getStage() const { return Stage; }
|
SILStage getStage() const { return Stage; }
|
||||||
|
|||||||
@@ -4394,16 +4394,21 @@ bool Parser::parseSILWitnessTable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// decl-sil-default-witness ::= 'sil_default_witness_table'
|
/// 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
|
||||||
/// decl-sil-default-witness-body:
|
/// decl-sil-default-witness-body:
|
||||||
/// '{' sil-default-witness-entry* '}'
|
/// '{' sil-default-witness-entry* '}'
|
||||||
/// sil-default-witness-entry:
|
/// sil-default-witness-entry:
|
||||||
/// 'method' SILDeclRef ':' @SILFunctionName
|
/// 'method' SILDeclRef ':' @SILFunctionName
|
||||||
|
/// 'no_default'
|
||||||
bool Parser::parseSILDefaultWitnessTable() {
|
bool Parser::parseSILDefaultWitnessTable() {
|
||||||
consumeToken(tok::kw_sil_default_witness_table);
|
consumeToken(tok::kw_sil_default_witness_table);
|
||||||
SILParser WitnessState(*this);
|
SILParser WitnessState(*this);
|
||||||
|
|
||||||
|
// Parse the linkage.
|
||||||
|
Optional<SILLinkage> Linkage;
|
||||||
|
parseSILLinkage(Linkage, *this);
|
||||||
|
|
||||||
Scope S(this, ScopeKind::TopLevel);
|
Scope S(this, ScopeKind::TopLevel);
|
||||||
// We should use WitnessTableBody. This ensures that the generic params
|
// We should use WitnessTableBody. This ensures that the generic params
|
||||||
// are visible.
|
// are visible.
|
||||||
@@ -4465,7 +4470,11 @@ bool Parser::parseSILDefaultWitnessTable() {
|
|||||||
parseMatchingToken(tok::r_brace, RBraceLoc, diag::expected_sil_rbrace,
|
parseMatchingToken(tok::r_brace, RBraceLoc, diag::expected_sil_rbrace,
|
||||||
LBraceLoc);
|
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();
|
BodyScope.reset();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,13 +34,14 @@ void SILDefaultWitnessTable::addDefaultWitnessTable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SILDefaultWitnessTable *
|
SILDefaultWitnessTable *
|
||||||
SILDefaultWitnessTable::create(SILModule &M, const ProtocolDecl *Protocol,
|
SILDefaultWitnessTable::create(SILModule &M, SILLinkage Linkage,
|
||||||
|
const ProtocolDecl *Protocol,
|
||||||
ArrayRef<SILDefaultWitnessTable::Entry> entries){
|
ArrayRef<SILDefaultWitnessTable::Entry> entries){
|
||||||
// Allocate the witness table and initialize it.
|
// Allocate the witness table and initialize it.
|
||||||
void *buf = M.allocate(sizeof(SILDefaultWitnessTable),
|
void *buf = M.allocate(sizeof(SILDefaultWitnessTable),
|
||||||
alignof(SILDefaultWitnessTable));
|
alignof(SILDefaultWitnessTable));
|
||||||
SILDefaultWitnessTable *wt =
|
SILDefaultWitnessTable *wt =
|
||||||
::new (buf) SILDefaultWitnessTable(M, Protocol, entries);
|
::new (buf) SILDefaultWitnessTable(M, Linkage, Protocol, entries);
|
||||||
|
|
||||||
wt->addDefaultWitnessTable();
|
wt->addDefaultWitnessTable();
|
||||||
|
|
||||||
@@ -49,12 +50,13 @@ SILDefaultWitnessTable::create(SILModule &M, const ProtocolDecl *Protocol,
|
|||||||
}
|
}
|
||||||
|
|
||||||
SILDefaultWitnessTable *
|
SILDefaultWitnessTable *
|
||||||
SILDefaultWitnessTable::create(SILModule &M, const ProtocolDecl *Protocol) {
|
SILDefaultWitnessTable::create(SILModule &M, SILLinkage Linkage,
|
||||||
|
const ProtocolDecl *Protocol) {
|
||||||
// Allocate the witness table and initialize it.
|
// Allocate the witness table and initialize it.
|
||||||
void *buf = M.allocate(sizeof(SILDefaultWitnessTable),
|
void *buf = M.allocate(sizeof(SILDefaultWitnessTable),
|
||||||
alignof(SILDefaultWitnessTable));
|
alignof(SILDefaultWitnessTable));
|
||||||
SILDefaultWitnessTable *wt =
|
SILDefaultWitnessTable *wt =
|
||||||
::new (buf) SILDefaultWitnessTable(M, Protocol);
|
::new (buf) SILDefaultWitnessTable(M, Linkage, Protocol);
|
||||||
|
|
||||||
wt->addDefaultWitnessTable();
|
wt->addDefaultWitnessTable();
|
||||||
|
|
||||||
@@ -64,16 +66,20 @@ SILDefaultWitnessTable::create(SILModule &M, const ProtocolDecl *Protocol) {
|
|||||||
|
|
||||||
SILDefaultWitnessTable::
|
SILDefaultWitnessTable::
|
||||||
SILDefaultWitnessTable(SILModule &M,
|
SILDefaultWitnessTable(SILModule &M,
|
||||||
|
SILLinkage Linkage,
|
||||||
const ProtocolDecl *Protocol,
|
const ProtocolDecl *Protocol,
|
||||||
ArrayRef<Entry> entries)
|
ArrayRef<Entry> entries)
|
||||||
: Mod(M), Protocol(Protocol), Entries(), IsDeclaration(true) {
|
: Mod(M), Linkage(Linkage), Protocol(Protocol), Entries(),
|
||||||
|
IsDeclaration(true) {
|
||||||
|
|
||||||
convertToDefinition(entries);
|
convertToDefinition(entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
SILDefaultWitnessTable::SILDefaultWitnessTable(SILModule &M,
|
SILDefaultWitnessTable::SILDefaultWitnessTable(SILModule &M,
|
||||||
|
SILLinkage Linkage,
|
||||||
const ProtocolDecl *Protocol)
|
const ProtocolDecl *Protocol)
|
||||||
: Mod(M), Protocol(Protocol), Entries(), IsDeclaration(true) {}
|
: Mod(M), Linkage(Linkage), Protocol(Protocol), Entries(),
|
||||||
|
IsDeclaration(true) {}
|
||||||
|
|
||||||
void SILDefaultWitnessTable::
|
void SILDefaultWitnessTable::
|
||||||
convertToDefinition(ArrayRef<Entry> entries) {
|
convertToDefinition(ArrayRef<Entry> entries) {
|
||||||
|
|||||||
@@ -190,23 +190,17 @@ SILModule::lookUpDefaultWitnessTable(const ProtocolDecl *Protocol) {
|
|||||||
|
|
||||||
auto found = DefaultWitnessTableMap.find(Protocol);
|
auto found = DefaultWitnessTableMap.find(Protocol);
|
||||||
if (found == DefaultWitnessTableMap.end()) {
|
if (found == DefaultWitnessTableMap.end()) {
|
||||||
assert(Protocol->hasFixedLayout() &&
|
|
||||||
"Resilient protocol must have a default witness table");
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!Protocol->hasFixedLayout() &&
|
|
||||||
"Fixed-layout protocol cannot have a default witness table");
|
|
||||||
|
|
||||||
return found->second;
|
return found->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
SILDefaultWitnessTable *
|
SILDefaultWitnessTable *
|
||||||
SILModule::createDefaultWitnessTableDeclaration(const ProtocolDecl *Protocol) {
|
SILModule::createDefaultWitnessTableDeclaration(const ProtocolDecl *Protocol,
|
||||||
assert(!Protocol->hasFixedLayout() &&
|
SILLinkage Linkage) {
|
||||||
"Fixed-layout protocol cannot have a default witness table");
|
return SILDefaultWitnessTable::create(*this, Linkage, Protocol);
|
||||||
|
|
||||||
return SILDefaultWitnessTable::create(*this, Protocol);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SILFunction *SILModule::getOrCreateFunction(SILLocation loc,
|
SILFunction *SILModule::getOrCreateFunction(SILLocation loc,
|
||||||
|
|||||||
@@ -2117,9 +2117,10 @@ void SILWitnessTable::dump() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SILDefaultWitnessTable::print(llvm::raw_ostream &OS, bool Verbose) const {
|
void SILDefaultWitnessTable::print(llvm::raw_ostream &OS, bool Verbose) const {
|
||||||
// sil_default_witness_table <Protocol> <MinSize>
|
// sil_default_witness_table [<Linkage>] <Protocol> <MinSize>
|
||||||
OS << "sil_default_witness_table"
|
OS << "sil_default_witness_table ";
|
||||||
<< " " << getProtocol()->getName() << " {\n";
|
printLinkage(OS, getLinkage(), ForDefinition);
|
||||||
|
OS << getProtocol()->getName() << " {\n";
|
||||||
|
|
||||||
for (auto &witness : getEntries()) {
|
for (auto &witness : getEntries()) {
|
||||||
if (!witness.isValid()) {
|
if (!witness.isValid()) {
|
||||||
|
|||||||
@@ -3238,9 +3238,6 @@ void SILDefaultWitnessTable::verify(const SILModule &M) const {
|
|||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
assert(!isDeclaration() &&
|
assert(!isDeclaration() &&
|
||||||
"Default witness table declarations should not exist.");
|
"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() &&
|
assert(getProtocol()->getParentModule() == M.getSwiftModule() &&
|
||||||
"Default witness table declarations must appear in the same "
|
"Default witness table declarations must appear in the same "
|
||||||
"module as their protocol.");
|
"module as their protocol.");
|
||||||
@@ -3253,9 +3250,9 @@ void SILDefaultWitnessTable::verify(const SILModule &M) const {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
SILFunction *F = E.getWitness();
|
SILFunction *F = E.getWitness();
|
||||||
assert(!isLessVisibleThan(F->getLinkage(), SILLinkage::Public) &&
|
assert(!isLessVisibleThan(F->getLinkage(), getLinkage()) &&
|
||||||
"Default witness tables should not reference internal "
|
"Default witness tables should not reference "
|
||||||
"or private functions.");
|
"less visible functions.");
|
||||||
assert(F->getLoweredFunctionType()->getRepresentation() ==
|
assert(F->getLoweredFunctionType()->getRepresentation() ==
|
||||||
SILFunctionTypeRepresentation::WitnessMethod &&
|
SILFunctionTypeRepresentation::WitnessMethod &&
|
||||||
"Default witnesses must have witness_method representation.");
|
"Default witnesses must have witness_method representation.");
|
||||||
|
|||||||
@@ -1938,7 +1938,7 @@ void SILGenModule::emitDefaultWitnessTable(ProtocolDecl *protocol) {
|
|||||||
builder.visitProtocolDecl(protocol);
|
builder.visitProtocolDecl(protocol);
|
||||||
|
|
||||||
SILDefaultWitnessTable *defaultWitnesses =
|
SILDefaultWitnessTable *defaultWitnesses =
|
||||||
M.createDefaultWitnessTableDeclaration(protocol);
|
M.createDefaultWitnessTableDeclaration(protocol, linkage);
|
||||||
defaultWitnesses->convertToDefinition(builder.DefaultWitnesses);
|
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) -> ()
|
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-LABEL: sil_default_witness_table ResilientProtocol {
|
||||||
// CHECK: no_default
|
// CHECK: no_default
|
||||||
// CHECK: no_default
|
// CHECK: no_default
|
||||||
// CHECK: no_default
|
// CHECK: no_default
|
||||||
// CHECK: no_default
|
// CHECK: no_default
|
||||||
// CHECK: #ResilientProtocol.defaultC!1: @defaultC
|
// CHECK: method #ResilientProtocol.defaultC!1: @defaultC
|
||||||
// CHECK: #ResilientProtocol.defaultD!1: @defaultD
|
// CHECK: method #ResilientProtocol.defaultD!1: @defaultD
|
||||||
// CHECK: #ResilientProtocol.defaultE!1: @defaultE
|
// CHECK: method #ResilientProtocol.defaultE!1: @defaultE
|
||||||
// CHECK: }
|
// CHECK: }
|
||||||
|
|
||||||
sil_default_witness_table ResilientProtocol {
|
sil_default_witness_table ResilientProtocol {
|
||||||
@@ -53,3 +65,12 @@ sil_default_witness_table ResilientProtocol {
|
|||||||
method #ResilientProtocol.defaultD!1: @defaultD
|
method #ResilientProtocol.defaultD!1: @defaultD
|
||||||
method #ResilientProtocol.defaultE!1: @defaultE
|
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