Skip to content

Commit 88bc29a

Browse files
authored
Merge pull request #22775 from slavapestov/resilient-witness-table-cleanup
Resilient witness table emission cleanup
2 parents 780612c + 6ebd992 commit 88bc29a

File tree

7 files changed

+60
-58
lines changed

7 files changed

+60
-58
lines changed

include/swift/ABI/Metadata.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2039,7 +2039,8 @@ struct TargetGenericWitnessTable {
20392039
return WitnessTablePrivateSizeInWordsAndRequiresInstantiation >> 1;
20402040
}
20412041

2042-
/// Whether the witness table is known to require instantiation.
2042+
/// This bit doesn't really mean anything. Currently, the compiler always
2043+
/// sets it when emitting a generic witness table.
20432044
uint16_t requiresInstantiation() const {
20442045
return WitnessTablePrivateSizeInWordsAndRequiresInstantiation & 0x01;
20452046
}

lib/IRGen/ConformanceDescription.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,6 @@ class ConformanceDescription {
5151
/// Whether this witness table requires runtime specialization.
5252
const unsigned requiresSpecialization : 1;
5353

54-
/// Whether this witness table contains dependent associated type witnesses.
55-
const unsigned hasDependentAssociatedTypeWitnesses : 1;
56-
5754
/// The instantiation function, to be run at the end of witness table
5855
/// instantiation.
5956
llvm::Constant *instantiationFn = nullptr;
@@ -66,13 +63,11 @@ class ConformanceDescription {
6663
llvm::Constant *pattern,
6764
uint16_t witnessTableSize,
6865
uint16_t witnessTablePrivateSize,
69-
bool requiresSpecialization,
70-
bool hasDependentAssociatedTypeWitnesses)
66+
bool requiresSpecialization)
7167
: conformance(conformance), wtable(wtable), pattern(pattern),
7268
witnessTableSize(witnessTableSize),
7369
witnessTablePrivateSize(witnessTablePrivateSize),
74-
requiresSpecialization(requiresSpecialization),
75-
hasDependentAssociatedTypeWitnesses(hasDependentAssociatedTypeWitnesses)
70+
requiresSpecialization(requiresSpecialization)
7671
{
7772
}
7873
};

lib/IRGen/GenProto.cpp

Lines changed: 11 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -867,7 +867,6 @@ static bool hasDependentTypeWitness(
867867
static bool isDependentConformance(
868868
IRGenModule &IGM,
869869
const RootProtocolConformance *rootConformance,
870-
bool considerResilience,
871870
llvm::SmallPtrSet<const NormalProtocolConformance *, 4> &visited){
872871
// Self-conformances are never dependent.
873872
auto conformance = dyn_cast<NormalProtocolConformance>(rootConformance);
@@ -880,7 +879,7 @@ static bool isDependentConformance(
880879
return false;
881880

882881
// If the conformance is resilient, this is always true.
883-
if (considerResilience && IGM.isResilientConformance(conformance))
882+
if (IGM.isResilientConformance(conformance))
884883
return true;
885884

886885
// Check whether any of the conformances are dependent.
@@ -899,7 +898,6 @@ static bool isDependentConformance(
899898
isDependentConformance(IGM,
900899
assocConformance.getConcrete()
901900
->getRootConformance(),
902-
considerResilience,
903901
visited))
904902
return true;
905903
}
@@ -916,11 +914,9 @@ static bool isDependentConformance(
916914
/// Is there anything about the given conformance that requires witness
917915
/// tables to be dependently-generated?
918916
bool IRGenModule::isDependentConformance(
919-
const RootProtocolConformance *conformance,
920-
bool considerResilience) {
917+
const RootProtocolConformance *conformance) {
921918
llvm::SmallPtrSet<const NormalProtocolConformance *, 4> visited;
922-
return ::isDependentConformance(*this, conformance, considerResilience,
923-
visited);
919+
return ::isDependentConformance(*this, conformance, visited);
924920
}
925921

926922
static bool isSynthesizedNonUnique(const RootProtocolConformance *conformance) {
@@ -1140,7 +1136,6 @@ class AccessorConformanceInfo : public ConformanceInfo {
11401136
// offsets, with conditional conformances closest to 0.
11411137
unsigned NextPrivateDataIndex = 0;
11421138
bool ResilientConformance;
1143-
bool RequiresSpecialization = false;
11441139

11451140
const ProtocolInfo &PI;
11461141

@@ -1162,21 +1157,14 @@ class AccessorConformanceInfo : public ConformanceInfo {
11621157
PI(IGM.getProtocolInfo(SILWT->getConformance()->getProtocol(),
11631158
(ResilientConformance
11641159
? ProtocolInfoKind::RequirementSignature
1165-
: ProtocolInfoKind::Full))) {
1166-
// If the conformance is resilient, we require runtime instantiation.
1167-
if (ResilientConformance)
1168-
RequiresSpecialization = true;
1169-
}
1160+
: ProtocolInfoKind::Full))) {}
11701161

11711162
/// The number of entries in the witness table.
11721163
unsigned getTableSize() const { return TableSize; }
11731164

11741165
/// The number of private entries in the witness table.
11751166
unsigned getTablePrivateSize() const { return NextPrivateDataIndex; }
11761167

1177-
/// Whether this witness table must be specialized at runtime.
1178-
bool requiresSpecialization() const { return RequiresSpecialization; }
1179-
11801168
/// The top-level entry point.
11811169
void build();
11821170

@@ -1226,7 +1214,6 @@ class AccessorConformanceInfo : public ConformanceInfo {
12261214
}
12271215

12281216
// Otherwise, we'll need to derive it at instantiation time.
1229-
RequiresSpecialization = true;
12301217
SpecializedBaseConformances.push_back({Table.size(), &conf});
12311218
Table.addNullPointer(IGM.Int8PtrTy);
12321219
}
@@ -1293,8 +1280,6 @@ class AccessorConformanceInfo : public ConformanceInfo {
12931280
auto associate =
12941281
Conformance.getTypeWitness(requirement.getAssociation(), nullptr)
12951282
->getCanonicalType();
1296-
if (associate->hasTypeParameter())
1297-
RequiresSpecialization = true;
12981283
llvm::Constant *witness =
12991284
IGM.getAssociatedTypeWitness(associate, /*inProtocolContext=*/false);
13001285
Table.addBitCast(witness, IGM.Int8PtrTy);
@@ -1319,9 +1304,6 @@ class AccessorConformanceInfo : public ConformanceInfo {
13191304
requirement.getAssociation(),
13201305
requirement.getAssociatedRequirement());
13211306

1322-
if (requirement.getAssociation()->hasTypeParameter())
1323-
RequiresSpecialization = true;
1324-
13251307
#ifndef NDEBUG
13261308
assert(entry.getKind() == SILWitnessTable::AssociatedTypeProtocol
13271309
&& "sil witness table does not match protocol");
@@ -1372,7 +1354,6 @@ class AccessorConformanceInfo : public ConformanceInfo {
13721354

13731355
/// Allocate another word of private data storage in the conformance table.
13741356
unsigned getNextPrivateDataIndex() {
1375-
RequiresSpecialization = true;
13761357
return NextPrivateDataIndex++;
13771358
}
13781359

@@ -1911,7 +1892,7 @@ namespace {
19111892
// WitnessTablePrivateSizeInWordsAndRequiresInstantiation
19121893
B.addInt(IGM.Int16Ty,
19131894
(Description.witnessTablePrivateSize << 1) |
1914-
Description.hasDependentAssociatedTypeWitnesses);
1895+
Description.requiresSpecialization);
19151896
// Instantiation function
19161897
B.addRelativeAddressOrNull(Description.instantiationFn);
19171898
// Private data
@@ -2065,13 +2046,12 @@ IRGenModule::getConformanceInfo(const ProtocolDecl *protocol,
20652046

20662047
const ConformanceInfo *info;
20672048
// If the conformance is dependent in any way, we need to unique it.
2068-
// TODO: maybe this should apply whenever it's out of the module?
2069-
// TODO: actually enable this
2049+
//
20702050
// FIXME: Both implementations of ConformanceInfo are trivially-destructible,
20712051
// so in theory we could allocate them on a BumpPtrAllocator. But there's not
20722052
// a good one for us to use. (The ASTContext's outlives the IRGenModule in
20732053
// batch mode.)
2074-
if (isDependentConformance(rootConformance, /*considerResilience=*/true) ||
2054+
if (isDependentConformance(rootConformance) ||
20752055
// Foreign types need to go through the accessor to unique the witness
20762056
// table.
20772057
isSynthesizedNonUnique(rootConformance)) {
@@ -2143,13 +2123,13 @@ void IRGenModule::emitSILWitnessTable(SILWitnessTable *wt) {
21432123
// Produce the initializer value.
21442124
auto initializer = wtableContents.finishAndCreateFuture();
21452125

2126+
bool isDependent = isDependentConformance(conf);
2127+
21462128
llvm::GlobalVariable *global = nullptr;
21472129
unsigned tableSize;
21482130
if (!isResilientConformance(conf)) {
2149-
bool isDependent =
2150-
isDependentConformance(conf, /*considerResilience=*/false);
21512131
global = cast<llvm::GlobalVariable>(
2152-
isDependent
2132+
(isDependent && conf->getDeclContext()->isGenericContext())
21532133
? getAddrOfWitnessTablePattern(cast<NormalProtocolConformance>(conf),
21542134
initializer)
21552135
: getAddrOfWitnessTable(conf, initializer));
@@ -2165,10 +2145,7 @@ void IRGenModule::emitSILWitnessTable(SILWitnessTable *wt) {
21652145
// descriptor.
21662146
ConformanceDescription description(conf, wt, global, tableSize,
21672147
wtableBuilder.getTablePrivateSize(),
2168-
wtableBuilder.requiresSpecialization(),
2169-
isDependentConformance(
2170-
conf,
2171-
/*considerResilience=*/false));
2148+
isDependent);
21722149

21732150
// Build the instantiation function, we if need one.
21742151
description.instantiationFn = wtableBuilder.buildInstantiationFunction();

lib/IRGen/IRGenModule.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -794,8 +794,7 @@ class IRGenModule {
794794

795795
bool isResilientConformance(const NormalProtocolConformance *conformance);
796796
bool isResilientConformance(const RootProtocolConformance *root);
797-
bool isDependentConformance(const RootProtocolConformance *conformance,
798-
bool considerResilience);
797+
bool isDependentConformance(const RootProtocolConformance *conformance);
799798

800799
Alignment getCappedAlignment(Alignment alignment);
801800

test/IRGen/protocol_conformance_records.swift

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ public protocol Runcible {
2222
// -- witness table
2323
// CHECK-SAME: @"$s28protocol_conformance_records15NativeValueTypeVAA8RuncibleAAWP"
2424
// -- flags
25-
// CHECK-SAME: i32 0
26-
// CHECK-SAME: },
25+
// CHECK-SAME: i32 0 },
2726
public struct NativeValueType: Runcible {
2827
public func runce() {}
2928
}
@@ -36,8 +35,7 @@ public struct NativeValueType: Runcible {
3635
// -- witness table
3736
// CHECK-SAME: @"$s28protocol_conformance_records15NativeClassTypeCAA8RuncibleAAWP"
3837
// -- flags
39-
// CHECK-SAME: i32 0
40-
// CHECK-SAME: },
38+
// CHECK-SAME: i32 0 },
4139
public class NativeClassType: Runcible {
4240
public func runce() {}
4341
}
@@ -50,8 +48,7 @@ public class NativeClassType: Runcible {
5048
// -- witness table
5149
// CHECK-SAME: @"$s28protocol_conformance_records17NativeGenericTypeVyxGAA8RuncibleAAWP"
5250
// -- flags
53-
// CHECK-SAME: i32 0
54-
// CHECK-SAME: },
51+
// CHECK-SAME: i32 0 },
5552
public struct NativeGenericType<T>: Runcible {
5653
public func runce() {}
5754
}
@@ -87,6 +84,30 @@ extension Size: Runcible {
8784
public func runce() {}
8885
}
8986

87+
// A non-dependent type conforming to a protocol with associated conformances
88+
// does not require a generic witness table.
89+
public protocol Simple {}
90+
91+
public protocol AssociateConformance {
92+
associatedtype X : Simple
93+
}
94+
95+
public struct Other : Simple {}
96+
97+
public struct Concrete : AssociateConformance {
98+
public typealias X = Other
99+
}
100+
101+
// CHECK-LABEL: @"$s28protocol_conformance_records8ConcreteVAA20AssociateConformanceAAMc" ={{ dllexport | protected | }}constant
102+
// -- protocol descriptor
103+
// CHECK-SAME: @"$s28protocol_conformance_records20AssociateConformanceMp"
104+
// -- nominal type descriptor
105+
// CHECK-SAME: @"$s28protocol_conformance_records8ConcreteVMn"
106+
// -- witness table
107+
// CHECK-SAME: @"$s28protocol_conformance_records8ConcreteVAA20AssociateConformanceAAWP"
108+
// -- no flags are set, and no generic witness table follows
109+
// CHECK-SAME: i32 0 }
110+
90111
// CHECK-LABEL: @"\01l_protocols"
91112
// CHECK-SAME: @"$s28protocol_conformance_records8RuncibleMp"
92113
// CHECK-SAME: @"$s28protocol_conformance_records5SpoonMp"
@@ -136,7 +157,7 @@ extension Int : OtherResilientProtocol { }
136157
// -- witness table pattern
137158
// CHECK-SAME: @"$s28protocol_conformance_records9DependentVyxGAA9AssociateAAWp"
138159
// -- flags
139-
// CHECK-SAME: i32 0
160+
// CHECK-SAME: i32 131072,
140161
// -- number of words in witness table
141162
// CHECK-SAME: i16 2,
142163
// -- number of private words in witness table + bit for "needs instantiation"
@@ -151,5 +172,6 @@ extension Dependent : Associate {
151172
// CHECK-SAME: @"$s28protocol_conformance_records15NativeClassTypeCAA8RuncibleAAMc"
152173
// CHECK-SAME: @"$s28protocol_conformance_records17NativeGenericTypeVyxGAA8RuncibleAAMc"
153174
// CHECK-SAME: @"$s16resilient_struct4SizeV28protocol_conformance_records8RuncibleADMc"
175+
// CHECK-SAME: @"$s28protocol_conformance_records8ConcreteVAA20AssociateConformanceAAMc"
154176
// CHECK-SAME: @"$s28protocol_conformance_records17NativeGenericTypeVyxGAA5SpoonA2aERzlMc"
155-
// CHECK-SAME: @"$sSi18resilient_protocol22OtherResilientProtocol0B20_conformance_recordsMc"
177+
// CHECK-SAME: @"$sSi18resilient_protocol22OtherResilientProtocol0B20_conformance_recordsMc"

test/IRGen/protocol_resilience.sil

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ protocol InternalProtocol {
9797
// -- number of witness table entries
9898
// CHECK-SAME: i16 0,
9999

100-
// -- size of private area + 'requires instantiation' bit (not set)
101-
// CHECK-SAME: i16 0,
100+
// -- size of private area + 'requires instantiation' bit
101+
// CHECK-SAME: i16 1,
102102

103103
// -- instantiator function
104104
// CHECK-SAME: i32 0
@@ -127,8 +127,8 @@ protocol InternalProtocol {
127127
// -- number of witness table entries
128128
// CHECK-SAME: i16 0,
129129

130-
// -- size of private area + 'requires instantiation' bit (not set)
131-
// CHECK-SAME: i16 0,
130+
// -- size of private area + 'requires instantiation' bit
131+
// CHECK-SAME: i16 1,
132132

133133
// -- instantiator function
134134
// CHECK-SAME: i32 0

test/IRGen/protocol_resilience_descriptors.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,18 @@ public struct ConditionallyConforms<Element> { }
6060
public struct Y { }
6161

6262
// CHECK-USAGE-LABEL: @"$s31protocol_resilience_descriptors1YV010resilient_A022OtherResilientProtocolAAMc" =
63+
// -- flags: has generic witness table
6364
// CHECK-USAGE-SAME: i32 131072,
65+
// -- number of witness table entries
6466
// CHECK-USAGE-SAME: i16 0,
65-
// CHECK-USAGE-SAME: i16 0,
66-
// CHECK-USAGE-SAME: i32 0
67+
// -- size of private area + 'requires instantiation' bit
68+
// CHECK-USAGE-SAME: i16 1,
69+
// -- instantiator function
70+
// CHECK-USAGE-SAME: i32 0,
71+
// -- private data area
72+
// CHECK-USAGE-SAME: {{@[0-9]+}}
73+
// --
74+
// CHECK-USAGE-SAME: }
6775
extension Y: OtherResilientProtocol { }
6876

6977
// CHECK-USAGE: @"$s31protocol_resilience_descriptors29ConformsWithAssocRequirementsV010resilient_A008ProtocoleF12TypeDefaultsAAMc" =

0 commit comments

Comments
 (0)