Skip to content

Commit b017761

Browse files
authored
Merge pull request #20034 from DougGregor/conformance-requires-instantiation
2 parents 14d4235 + 0e817b4 commit b017761

File tree

7 files changed

+60
-27
lines changed

7 files changed

+60
-27
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2009,7 +2009,11 @@ llvm::Function *IRGenModule::getAddrOfSILFunction(SILFunction *f,
20092009

20102010
static llvm::GlobalVariable *createGOTEquivalent(IRGenModule &IGM,
20112011
llvm::Constant *global,
2012-
StringRef globalName) {
2012+
LinkEntity entity) {
2013+
// Determine the name of this entity.
2014+
llvm::SmallString<64> globalName;
2015+
entity.mangle(globalName);
2016+
20132017
if (IGM.Triple.getObjectFormat() == llvm::Triple::COFF) {
20142018
if (cast<llvm::GlobalValue>(global)->hasDLLImportStorageClass()) {
20152019
llvm::GlobalVariable *GV =
@@ -2178,7 +2182,7 @@ IRGenModule::getAddrOfLLVMVariable(LinkEntity entity,
21782182

21792183
// Make a new GOT equivalent referring to the new variable with its
21802184
// definition type.
2181-
auto newGOTEquiv = createGOTEquivalent(*this, var, var->getName());
2185+
auto newGOTEquiv = createGOTEquivalent(*this, var, entity);
21822186
auto castGOTEquiv = llvm::ConstantExpr::getBitCast(newGOTEquiv,
21832187
existingGOTEquiv->getType());
21842188
existingGOTEquiv->replaceAllUsesWith(castGOTEquiv);
@@ -2256,9 +2260,7 @@ IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity,
22562260
auto global = cast<llvm::GlobalValue>(entry);
22572261
// Use it as the initializer for an anonymous constant. LLVM can treat this as
22582262
// equivalent to the global's GOT entry.
2259-
llvm::SmallString<64> name;
2260-
entity.mangle(name);
2261-
auto gotEquivalent = createGOTEquivalent(*this, global, name);
2263+
auto gotEquivalent = createGOTEquivalent(*this, global, entity);
22622264
gotEntry = gotEquivalent;
22632265
return {gotEquivalent, ConstantReference::Indirect};
22642266
};

lib/IRGen/GenProto.cpp

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,31 @@ static bool isResilientConformance(const NormalProtocolConformance *conformance)
961961
return true;
962962
}
963963

964+
/// Whether this protocol conformance has a dependent type witness.
965+
static bool hasDependentTypeWitness(
966+
const NormalProtocolConformance *conformance) {
967+
auto DC = conformance->getDeclContext();
968+
// If the conforming type isn't dependent, the below check is never true.
969+
if (!DC->isGenericContext())
970+
return false;
971+
972+
// Check whether any of the associated types are dependent.
973+
if (conformance->forEachTypeWitness(nullptr,
974+
[&](AssociatedTypeDecl *requirement, Type type,
975+
TypeDecl *explicitDecl) -> bool {
976+
// Skip associated types that don't have witness table entries.
977+
if (!requirement->getOverriddenDecls().empty())
978+
return false;
979+
980+
// RESILIENCE: this could be an opaque conformance
981+
return type->hasTypeParameter();
982+
})) {
983+
return true;
984+
}
985+
986+
return false;
987+
}
988+
964989
/// Is there anything about the given conformance that requires witness
965990
/// tables to be dependently-generated?
966991
bool irgen::isDependentConformance(const NormalProtocolConformance *conformance) {
@@ -984,20 +1009,8 @@ bool irgen::isDependentConformance(const NormalProtocolConformance *conformance)
9841009
return true;
9851010
}
9861011

987-
auto DC = conformance->getDeclContext();
988-
// If the conforming type isn't dependent, the below check is never true.
989-
if (!DC->isGenericContext())
990-
return false;
991-
992-
// Check whether any of the associated types are dependent.
993-
if (conformance->forEachTypeWitness(nullptr,
994-
[&](AssociatedTypeDecl *requirement, Type type,
995-
TypeDecl *explicitDecl) -> bool {
996-
// RESILIENCE: this could be an opaque conformance
997-
return type->hasTypeParameter();
998-
})) {
1012+
if (hasDependentTypeWitness(conformance))
9991013
return true;
1000-
}
10011014

10021015
// Check if there are any conditional conformances. Other forms of conditional
10031016
// requirements don't exist in the witness table.
@@ -2184,7 +2197,7 @@ namespace {
21842197
// WitnessTablePrivateSizeInWordsAndRequiresInstantiation
21852198
B.addInt(IGM.Int16Ty,
21862199
(Description.witnessTablePrivateSize << 1) |
2187-
Description.requiresSpecialization);
2200+
Description.hasDependentAssociatedTypeWitnesses);
21882201
// RelativePointer<WitnessTable>
21892202
B.addRelativeAddress(Description.pattern);
21902203
// Instantiation function
@@ -2413,7 +2426,8 @@ void IRGenModule::emitSILWitnessTable(SILWitnessTable *wt) {
24132426
ConformanceDescription description(conf, wt, global,
24142427
wtableBuilder.getTableSize(),
24152428
wtableBuilder.getTablePrivateSize(),
2416-
wtableBuilder.requiresSpecialization());
2429+
wtableBuilder.requiresSpecialization(),
2430+
hasDependentTypeWitness(conf));
24172431

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

lib/IRGen/IRGenModule.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,9 @@ struct ConformanceDescription {
470470
/// Whether this witness table requires runtime specialization.
471471
const unsigned requiresSpecialization : 1;
472472

473+
/// Whether this witness table contains dependent associated type witnesses.
474+
const unsigned hasDependentAssociatedTypeWitnesses : 1;
475+
473476
/// The instantiation function, to be run at the end of witness table
474477
/// instantiation.
475478
llvm::Constant *instantiationFn = nullptr;
@@ -482,11 +485,15 @@ struct ConformanceDescription {
482485
llvm::Constant *pattern,
483486
uint16_t witnessTableSize,
484487
uint16_t witnessTablePrivateSize,
485-
bool requiresSpecialization)
488+
bool requiresSpecialization,
489+
bool hasDependentAssociatedTypeWitnesses)
486490
: conformance(conformance), wtable(wtable), pattern(pattern),
487491
witnessTableSize(witnessTableSize),
488492
witnessTablePrivateSize(witnessTablePrivateSize),
489-
requiresSpecialization(requiresSpecialization) { }
493+
requiresSpecialization(requiresSpecialization),
494+
hasDependentAssociatedTypeWitnesses(hasDependentAssociatedTypeWitnesses)
495+
{
496+
}
490497
};
491498

492499
/// IRGenModule - Primary class for emitting IR for global declarations.

test/IRGen/associated_type_witness.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ struct UsesVoid : HasSimpleAssoc {
167167
// Protocol conformance descriptor for GenericComputed : DerivedFromSimpleAssoc.
168168
// GLOBAL-LABEL: @"$s23associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAMc" = hidden constant
169169
// GLOBAL-SAME: i16 2,
170-
// GLOBAL-SAME: i16 1,
170+
// GLOBAL-SAME: i16 0,
171171

172172
// Relative reference to witness table template
173173
// GLOBAL-SAME: i32 trunc (i64 sub (i64 ptrtoint ([2 x i8*]* @"$s23associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWp" to i64

test/IRGen/protocol_conformance_records.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ extension Int : OtherResilientProtocol { }
137137
// CHECK-SAME: @"$s28protocol_conformance_records9DependentVyxGAA9AssociateAAWa"
138138
// -- flags
139139
// CHECK-SAME: i32 1
140+
// -- number of words in witness table
141+
// CHECK-SAME: i16 2,
142+
// -- number of private words in witness table + bit for "needs instantiation"
143+
// CHECK-SAME: i16 1
140144
// CHECK-SAME: }
141145
extension Dependent : Associate {
142146
public typealias X = (T, T)

test/IRGen/protocol_resilience.sil

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ protocol InternalProtocol {
106106
// -- number of witness table entries
107107
// CHECK-SAME: i16 1,
108108

109-
// -- size of private area + 'needs instantiation' bit
110-
// CHECK-SAME: i16 1,
109+
// -- size of private area + 'requires instantiation' bit (not set)
110+
// CHECK-SAME: i16 0,
111111

112112
// -- the template
113113
// CHECK-SAME: @"$s19protocol_resilience23ResilientConformingTypeV010resilient_A005OtherC8ProtocolAAWp"
@@ -139,8 +139,8 @@ protocol InternalProtocol {
139139
// -- number of witness table entries
140140
// CHECK-SAME: i16 1,
141141

142-
// -- size of private area + 'needs instantiation' bit
143-
// CHECK-SAME: i16 1,
142+
// -- size of private area + 'requires instantiation' bit (not set)
143+
// CHECK-SAME: i16 0,
144144

145145
// -- the template
146146
// CHECK-SAME: @"$s19protocol_resilience24ConformsWithRequirementsV010resilient_A008ProtocoldE0AAWp"

test/IRGen/protocol_resilience_descriptors.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ public protocol P { }
5656
public struct ConditionallyConforms<Element> { }
5757
public struct Y { }
5858

59+
// CHECK-USAGE-LABEL: @"$s31protocol_resilience_descriptors1YV010resilient_A022OtherResilientProtocolAAMc" =
60+
// CHECK-USAGE-SAME: i32 131073,
61+
// CHECK-USAGE-SAME: i16 1,
62+
// CHECK-USAGE-SAME: i16 0
63+
extension Y: OtherResilientProtocol { }
64+
5965
// CHECK-USAGE: @"$s31protocol_resilience_descriptors29ConformsWithAssocRequirementsV010resilient_A008ProtocoleF12TypeDefaultsAAMc" =
6066
// CHECK-USAGE-SAME: $s18resilient_protocol29ProtocolWithAssocTypeDefaultsP2T2AC_AA014OtherResilientC0Tn
6167
// CHECK-USAGE-SAME: $s31protocol_resilience_descriptors29ConformsWithAssocRequirementsV010resilient_A008ProtocoleF12TypeDefaultsAA2T2AdEP_AD014OtherResilientI0PWT

0 commit comments

Comments
 (0)