Skip to content

Commit 30a3e75

Browse files
committed
IRGen: Fix dependent witness table linkage
Witness tables for conformances that require runtime instantiation should not be public, because it is an error to directly reference such a symbol from outside the module. Use a different mangling for witness table patterns and give them non-public linkage.
1 parent d1da8f3 commit 30a3e75

15 files changed

+81
-20
lines changed

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ NODE(ProtocolListWithAnyObject)
145145
NODE(ProtocolWitness)
146146
NODE(ProtocolWitnessTable)
147147
NODE(ProtocolWitnessTableAccessor)
148+
NODE(ProtocolWitnessTablePattern)
148149
NODE(QualifiedArchetype)
149150
NODE(ReabstractionThunk)
150151
NODE(ReabstractionThunkHelper)

include/swift/IRGen/Linking.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,10 @@ class LinkEntity {
199199
/// ProtocolConformance*.
200200
DirectProtocolWitnessTable,
201201

202+
/// A protocol witness table pattern. The secondary pointer is a
203+
/// ProtocolConformance*.
204+
ProtocolWitnessTablePattern,
205+
202206
/// A witness accessor function. The secondary pointer is a
203207
/// ProtocolConformance*.
204208
ProtocolWitnessTableAccessFunction,
@@ -615,6 +619,13 @@ class LinkEntity {
615619
return entity;
616620
}
617621

622+
static LinkEntity
623+
forProtocolWitnessTablePattern(const ProtocolConformance *C) {
624+
LinkEntity entity;
625+
entity.setForProtocolConformance(Kind::ProtocolWitnessTablePattern, C);
626+
return entity;
627+
}
628+
618629
static LinkEntity
619630
forProtocolWitnessTableAccessFunction(const ProtocolConformance *C) {
620631
LinkEntity entity;

lib/Demangling/Demangler.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2072,6 +2072,9 @@ NodePointer Demangler::demangleWitness() {
20722072
case 'P':
20732073
return createWithChild(Node::Kind::ProtocolWitnessTable,
20742074
popProtocolConformance());
2075+
case 'p':
2076+
return createWithChild(Node::Kind::ProtocolWitnessTablePattern,
2077+
popProtocolConformance());
20752078
case 'G':
20762079
return createWithChild(Node::Kind::GenericProtocolWitnessTable,
20772080
popProtocolConformance());

lib/Demangling/NodePrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ class NodePrinter {
403403
case Node::Kind::ProtocolWitness:
404404
case Node::Kind::ProtocolWitnessTable:
405405
case Node::Kind::ProtocolWitnessTableAccessor:
406+
case Node::Kind::ProtocolWitnessTablePattern:
406407
case Node::Kind::ReabstractionThunk:
407408
case Node::Kind::ReabstractionThunkHelper:
408409
case Node::Kind::RelatedEntityDeclName:
@@ -1303,6 +1304,10 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
13031304
Printer << "protocol witness table for ";
13041305
print(Node->getFirstChild());
13051306
return nullptr;
1307+
case Node::Kind::ProtocolWitnessTablePattern:
1308+
Printer << "protocol witness table pattern for ";
1309+
print(Node->getFirstChild());
1310+
return nullptr;
13061311
case Node::Kind::GenericProtocolWitnessTable:
13071312
Printer << "generic protocol witness table for ";
13081313
print(Node->getFirstChild());

lib/Demangling/OldRemangler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,10 @@ void Remangler::mangleProtocolRequirementArray(Node *node) {
760760
unreachable("todo");
761761
}
762762

763+
void Remangler::mangleProtocolWitnessTablePattern(Node *node) {
764+
unreachable("todo");
765+
}
766+
763767
void Remangler::mangleProtocolConformanceDescriptor(Node *node) {
764768
Out << "Mc";
765769
mangleProtocolConformance(node->begin()[0]);

lib/Demangling/Remangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1562,6 +1562,11 @@ void Remangler::mangleProtocolWitnessTable(Node *node) {
15621562
Buffer << "WP";
15631563
}
15641564

1565+
void Remangler::mangleProtocolWitnessTablePattern(Node *node) {
1566+
mangleSingleChildNode(node);
1567+
Buffer << "Wp";
1568+
}
1569+
15651570
void Remangler::mangleProtocolWitnessTableAccessor(Node *node) {
15661571
mangleSingleChildNode(node);
15671572
Buffer << "Wa";

lib/IRGen/GenDecl.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,6 +1567,11 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
15671567
case Kind::ProtocolConformanceDescriptor:
15681568
return getLinkageAsConformance();
15691569

1570+
case Kind::ProtocolWitnessTablePattern:
1571+
if (getLinkageAsConformance() == SILLinkage::Shared)
1572+
return SILLinkage::Shared;
1573+
return SILLinkage::Private;
1574+
15701575
case Kind::ProtocolWitnessTableLazyAccessFunction:
15711576
case Kind::ProtocolWitnessTableLazyCacheVariable: {
15721577
auto *nominal = getType().getAnyNominal();
@@ -1663,7 +1668,6 @@ bool LinkEntity::isAvailableExternally(IRGenModule &IGM) const {
16631668
case Kind::PropertyDescriptor:
16641669
case Kind::NominalTypeDescriptor:
16651670
case Kind::ProtocolDescriptor:
1666-
case Kind::ProtocolRequirementArray:
16671671
return ::isAvailableExternally(IGM, getDecl());
16681672

16691673
case Kind::EnumCase:
@@ -1673,6 +1677,8 @@ bool LinkEntity::isAvailableExternally(IRGenModule &IGM) const {
16731677
case Kind::ProtocolConformanceDescriptor:
16741678
return ::isAvailableExternally(IGM, getProtocolConformance()->getDeclContext());
16751679

1680+
case Kind::ProtocolWitnessTablePattern:
1681+
case Kind::ProtocolRequirementArray:
16761682
case Kind::ObjCClassRef:
16771683
case Kind::ModuleDescriptor:
16781684
case Kind::ExtensionDescriptor:
@@ -4125,10 +4131,7 @@ IRGenModule::getAddrOfWitnessTableLazyCacheVariable(
41254131

41264132
/// Look up the address of a witness table.
41274133
///
4128-
/// TODO: This needs to take a flag for the access mode of the witness table,
4129-
/// which may be direct, lazy, or a runtime instantiation template.
4130-
/// TODO: Use name from witness table here to lookup witness table instead of
4131-
/// recomputing it.
4134+
/// This can only be used with non-dependent conformances.
41324135
llvm::Constant*
41334136
IRGenModule::getAddrOfWitnessTable(const NormalProtocolConformance *conf,
41344137
ConstantInit definition) {
@@ -4139,6 +4142,20 @@ IRGenModule::getAddrOfWitnessTable(const NormalProtocolConformance *conf,
41394142
WitnessTableTy, DebugTypeInfo());
41404143
}
41414144

4145+
/// Look up the address of a witness table pattern.
4146+
///
4147+
/// This can only be used with dependent conformances from inside the
4148+
/// defining module.
4149+
llvm::Constant*
4150+
IRGenModule::getAddrOfWitnessTablePattern(const NormalProtocolConformance *conf,
4151+
ConstantInit definition) {
4152+
IRGen.addLazyWitnessTable(conf);
4153+
4154+
auto entity = LinkEntity::forProtocolWitnessTablePattern(conf);
4155+
return getAddrOfLLVMVariable(entity, getPointerAlignment(), definition,
4156+
WitnessTableTy, DebugTypeInfo());
4157+
}
4158+
41424159
llvm::Function *
41434160
IRGenModule::getAddrOfAssociatedTypeMetadataAccessFunction(
41444161
const NormalProtocolConformance *conformance,

lib/IRGen/GenProto.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2069,6 +2069,8 @@ void IRGenModule::emitSILWitnessTable(SILWitnessTable *wt) {
20692069
if (isAvailableExternally(wt->getLinkage()))
20702070
return;
20712071

2072+
auto *conf = wt->getConformance();
2073+
20722074
// Build the witnesses.
20732075
ConstantInitBuilder builder(*this);
20742076
auto wtableContents = builder.beginArray(Int8PtrTy);
@@ -2083,23 +2085,26 @@ void IRGenModule::emitSILWitnessTable(SILWitnessTable *wt) {
20832085
// Produce the initializer value.
20842086
auto initializer = wtableContents.finishAndCreateFuture();
20852087

2088+
bool isDependent = isDependentConformance(*this, conf,
2089+
ResilienceExpansion::Maximal);
20862090
auto global = cast<llvm::GlobalVariable>(
2087-
getAddrOfWitnessTable(wt->getConformance(), initializer));
2091+
isDependent
2092+
? getAddrOfWitnessTablePattern(conf, initializer)
2093+
: getAddrOfWitnessTable(conf, initializer));
20882094
global->setConstant(true);
20892095
global->setAlignment(getWitnessTableAlignment().getValue());
20902096

2091-
// FIXME: resilience; this should use the conformance's publishing scope.
2097+
// Always emit an accessor function.
20922098
wtableBuilder.buildAccessFunction(global);
20932099

20942100
// Behavior conformances can't be reflected.
2095-
if (wt->getConformance()->isBehaviorConformance())
2101+
if (conf->isBehaviorConformance())
20962102
return;
20972103

2098-
NormalProtocolConformance *Conf = wt->getConformance();
2099-
addProtocolConformance(Conf);
2104+
addProtocolConformance(conf);
21002105

21012106
// Trigger the lazy emission of the foreign type metadata.
2102-
CanType conformingType = Conf->getType()->getCanonicalType();
2107+
CanType conformingType = conf->getType()->getCanonicalType();
21032108
if (requiresForeignTypeMetadata(conformingType))
21042109
(void)getAddrOfForeignTypeMetadataCandidate(conformingType);
21052110
}

lib/IRGen/IRGenMangler.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,10 @@ class IRGenMangler : public Mangle::ASTMangler {
161161
return mangleConformanceSymbol(Type(), C, "WP");
162162
}
163163

164+
std::string mangleProtocolWitnessTablePattern(const ProtocolConformance *C) {
165+
return mangleConformanceSymbol(Type(), C, "Wp");
166+
}
167+
164168
std::string mangleGenericProtocolWitnessTableCache(
165169
const ProtocolConformance *C) {
166170
return mangleConformanceSymbol(Type(), C, "WG");

lib/IRGen/IRGenModule.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1201,7 +1201,10 @@ private: \
12011201
CanType conformingType,
12021202
ForDefinition_t forDefinition);
12031203
llvm::Constant *getAddrOfWitnessTable(const NormalProtocolConformance *C,
1204-
ConstantInit definition = ConstantInit());
1204+
ConstantInit definition = ConstantInit());
1205+
llvm::Constant *getAddrOfWitnessTablePattern(const NormalProtocolConformance *C,
1206+
ConstantInit definition = ConstantInit());
1207+
12051208
llvm::Constant *
12061209
getAddrOfGenericWitnessTableCache(const NormalProtocolConformance *C,
12071210
ForDefinition_t forDefinition);

lib/IRGen/Linking.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ std::string LinkEntity::mangleAsString() const {
170170
return mangler.mangleProtocolWitnessTableAccessFunction(
171171
getProtocolConformance());
172172

173+
case Kind::ProtocolWitnessTablePattern:
174+
return mangler.mangleProtocolWitnessTablePattern(getProtocolConformance());
175+
173176
case Kind::ProtocolWitnessTableLazyAccessFunction:
174177
return mangler.mangleProtocolWitnessTableLazyAccessFunction(getType(),
175178
getProtocolConformance());

test/IRGen/associated_type_witness.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ struct GenericWithUniversal<T> : Assocked {
5151
}
5252

5353
// Witness table for Fulfilled : Assocked.
54-
// GLOBAL-LABEL: @"$S23associated_type_witness9FulfilledVyxGAA8AssockedAAWP" = hidden constant [4 x i8*] [
54+
// GLOBAL-LABEL: @"$S23associated_type_witness9FulfilledVyxGAA8AssockedAAWp" = internal constant [4 x i8*] [
5555
// GLOBAL-SAME: @"$S23associated_type_witness9FulfilledVyxGAA8AssockedAAMc"
5656
// GLOBAL-SAME: i8* bitcast (%swift.metadata_response (i64, %swift.type*, i8**)* @"$S23associated_type_witness9FulfilledVyxGAA8AssockedAA5AssocWt" to i8*)
5757
// GLOBAL-SAME: i8* bitcast (i8** (%swift.type*, %swift.type*, i8**)* @"$S23associated_type_witness9FulfilledVyxGAA8AssockedAA5Assoc_AA1PPWT" to i8*)
@@ -90,7 +90,7 @@ struct Fulfilled<T : P & Q> : Assocked {
9090
struct Pair<T, U> : P, Q {}
9191

9292
// Generic witness table pattern for Computed : Assocked.
93-
// GLOBAL-LABEL: @"$S23associated_type_witness8ComputedVyxq_GAA8AssockedAAWP" = hidden constant [4 x i8*] [
93+
// GLOBAL-LABEL: @"$S23associated_type_witness8ComputedVyxq_GAA8AssockedAAWp" = internal constant [4 x i8*] [
9494
// GLOBAL-SAME: @"$S23associated_type_witness8ComputedVyxq_GAA8AssockedAAMc"
9595
// GLOBAL-SAME: i8* bitcast (%swift.metadata_response (i64, %swift.type*, i8**)* @"$S23associated_type_witness8ComputedVyxq_GAA8AssockedAA5AssocWt" to i8*)
9696
// GLOBAL-SAME: i8* bitcast (i8** (%swift.type*, %swift.type*, i8**)* @"$S23associated_type_witness8ComputedVyxq_GAA8AssockedAA5Assoc_AA1PPWT" to i8*)
@@ -104,7 +104,7 @@ struct Pair<T, U> : P, Q {}
104104
// GLOBAL-SAME: i32 trunc (i64 sub (i64 ptrtoint (%swift.protocol* @"$S23associated_type_witness8AssockedMp" to i64), i64 ptrtoint (i32* getelementptr inbounds (%swift.generic_witness_table_cache, %swift.generic_witness_table_cache* @"$S23associated_type_witness8ComputedVyxq_GAA8AssockedAAWG", i32 0, i32 2) to i64)) to i32
105105

106106
// Relative reference to witness table template
107-
// GLOBAL-SAME: i32 trunc (i64 sub (i64 ptrtoint ([4 x i8*]* @"$S23associated_type_witness8ComputedVyxq_GAA8AssockedAAWP" to i64), i64 ptrtoint (i32* getelementptr inbounds (%swift.generic_witness_table_cache, %swift.generic_witness_table_cache* @"$S23associated_type_witness8ComputedVyxq_GAA8AssockedAAWG", i32 0, i32 3) to i64)) to i32
107+
// GLOBAL-SAME: i32 trunc (i64 sub (i64 ptrtoint ([4 x i8*]* @"$S23associated_type_witness8ComputedVyxq_GAA8AssockedAAWp" to i64), i64 ptrtoint (i32* getelementptr inbounds (%swift.generic_witness_table_cache, %swift.generic_witness_table_cache* @"$S23associated_type_witness8ComputedVyxq_GAA8AssockedAAWG", i32 0, i32 3) to i64)) to i32
108108

109109
// No instantiator function
110110
// GLOBAL-SAME: i32 0,
@@ -162,7 +162,7 @@ protocol DerivedFromSimpleAssoc : HasSimpleAssoc {}
162162

163163

164164
// Generic witness table pattern for GenericComputed : DerivedFromSimpleAssoc.
165-
// GLOBAL-LABEL: @"$S23associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWP" = hidden constant [2 x i8*]
165+
// GLOBAL-LABEL: @"$S23associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWp" = internal constant [2 x i8*]
166166
// GLOBAL-SAME: @"$S23associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAMc"
167167
// GLOBAL-SAME: i8* null
168168

@@ -173,7 +173,7 @@ protocol DerivedFromSimpleAssoc : HasSimpleAssoc {}
173173
// Relative reference to protocol
174174
// GLOBAL-SAME: i32 trunc (i64 sub (i64 ptrtoint (%swift.protocol* @"$S23associated_type_witness22DerivedFromSimpleAssocMp" to i64
175175
// Relative reference to witness table template
176-
// GLOBAL-SAME: i32 trunc (i64 sub (i64 ptrtoint ([2 x i8*]* @"$S23associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWP" to i64
176+
// GLOBAL-SAME: i32 trunc (i64 sub (i64 ptrtoint ([2 x i8*]* @"$S23associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWp" to i64
177177
// Relative reference to instantiator function
178178
// GLOBAL-SAME: i32 trunc (i64 sub (i64 ptrtoint (void (i8**, %swift.type*, i8**)* @"$S23associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWI" to i64), i64 ptrtoint (i32* getelementptr inbounds (%swift.generic_witness_table_cache, %swift.generic_witness_table_cache* @"$S23associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWG", i32 0, i32 4) to i64)) to i32)
179179
// GLOBAL-SAME: i32 trunc (i64 sub (i64 ptrtoint ([16 x i8*]* @1 to i64), i64 ptrtoint (i32* getelementptr inbounds (%swift.generic_witness_table_cache, %swift.generic_witness_table_cache* @"$S23associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWG", i32 0, i32 5) to i64)) to i32)

test/IRGen/newtype.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Newtype
99
// REQUIRES: objc_interop
1010

1111
// Witness table for synthesized ClosedEnums : _ObjectiveCBridgeable.
12-
// CHECK: @"$SSo13SNTClosedEnumas21_ObjectiveCBridgeableSCWP" = linkonce_odr
12+
// CHECK: @"$SSo13SNTClosedEnumas21_ObjectiveCBridgeableSCWp" = linkonce_odr
1313

1414
// CHECK-LABEL: define swiftcc %TSo8NSStringC* @"$S7newtype14getErrorDomainSo08SNTErrorD0ayF"()
1515
public func getErrorDomain() -> ErrorDomain {

test/IRGen/objc_extensions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ extension NSDogcow {
179179
@NSManaged var woof: Int
180180
}
181181

182-
// CHECK: @"$SSo8NSObjectC15objc_extensionsE8SomeEnum33_1F05E59585E0BB585FCA206FBFF1A92DLLOs9EquatableACWP" =
182+
// CHECK: @"$SSo8NSObjectC15objc_extensionsE8SomeEnum33_1F05E59585E0BB585FCA206FBFF1A92DLLOs9EquatableACWp" =
183183

184184
class SwiftSubGizmo : SwiftBaseGizmo {
185185

test/IRGen/objc_ns_enum.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import gizmo
1111
// CHECK: @"$SSo16NSRuncingOptionsVWV" = linkonce_odr hidden constant
1212
// CHECK: @"$SSo16NSRuncingOptionsVMn" = linkonce_odr hidden constant
1313
// CHECK: @"$SSo16NSRuncingOptionsVN" = linkonce_odr hidden global
14-
// CHECK: @"$SSo28NeverActuallyMentionedByNameVs9EquatableSCWP" = linkonce_odr hidden constant
14+
// CHECK: @"$SSo28NeverActuallyMentionedByNameVs9EquatableSCWp" = linkonce_odr hidden constant
1515

1616
// CHECK-LABEL: define{{( protected)?}} i32 @main
1717
// CHECK: call swiftcc %swift.metadata_response @"$SSo16NSRuncingOptionsVMa"(i64 0)

0 commit comments

Comments
 (0)