Skip to content

Commit c84a14f

Browse files
committed
IRGen: Conditional conformances for variadic types
1 parent 90faaee commit c84a14f

File tree

6 files changed

+109
-37
lines changed

6 files changed

+109
-37
lines changed

lib/IRGen/Fulfillment.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,22 @@ bool FulfillmentMap::searchConformance(
228228

229229
SILWitnessTable::enumerateWitnessTableConditionalConformances(
230230
conformance, [&](unsigned index, CanType type, ProtocolDecl *protocol) {
231+
Optional<unsigned> packExpansionComponent;
232+
233+
if (auto packType = dyn_cast<PackType>(type)) {
234+
auto param =
235+
getSingletonPackExpansionParameter(packType, interestingKeys,
236+
packExpansionComponent);
237+
if (!param)
238+
return /*finished?*/ false;
239+
type = param;
240+
}
241+
231242
MetadataPath conditionalPath = path;
232243
conditionalPath.addConditionalConformanceComponent(index);
244+
if (packExpansionComponent)
245+
conditionalPath.addPackExpansionPatternComponent(*packExpansionComponent);
246+
233247
hadFulfillment |=
234248
searchWitnessTable(IGM, type, protocol, sourceIndex,
235249
std::move(conditionalPath), interestingKeys);

lib/IRGen/GenMeta.cpp

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -566,21 +566,7 @@ namespace {
566566
B.addInt(IGM.Int16Ty, shapes.size());
567567

568568
// Emit each GenericPackShapeDescriptor collected previously.
569-
for (const auto &packArg : packArgs) {
570-
// Kind
571-
B.addInt(IGM.Int16Ty, uint16_t(packArg.Kind));
572-
573-
// Index
574-
B.addInt(IGM.Int16Ty, packArg.Index);
575-
576-
// ShapeClass
577-
auto found = std::find(shapes.begin(), shapes.end(), packArg.ReducedShape);
578-
assert(found != shapes.end());
579-
B.addInt(IGM.Int16Ty, found - shapes.begin());
580-
581-
// Unused
582-
B.addInt(IGM.Int16Ty, 0);
583-
}
569+
irgen::addGenericPackShapeDescriptors(IGM, B, shapes, packArgs);
584570
}
585571

586572
uint8_t getVersion() {
@@ -6580,6 +6566,27 @@ GenericArgumentMetadata irgen::addGenericRequirements(
65806566
return metadata;
65816567
}
65826568

6569+
void irgen::addGenericPackShapeDescriptors(IRGenModule &IGM,
6570+
ConstantStructBuilder &B,
6571+
ArrayRef<CanType> shapes,
6572+
ArrayRef<GenericPackArgument> packArgs) {
6573+
for (const auto &packArg : packArgs) {
6574+
// Kind
6575+
B.addInt(IGM.Int16Ty, uint16_t(packArg.Kind));
6576+
6577+
// Index
6578+
B.addInt(IGM.Int16Ty, packArg.Index);
6579+
6580+
// ShapeClass
6581+
auto found = std::find(shapes.begin(), shapes.end(), packArg.ReducedShape);
6582+
assert(found != shapes.end());
6583+
B.addInt(IGM.Int16Ty, found - shapes.begin());
6584+
6585+
// Unused
6586+
B.addInt(IGM.Int16Ty, 0);
6587+
}
6588+
}
6589+
65836590
//===----------------------------------------------------------------------===//
65846591
// Other metadata.
65856592
//===----------------------------------------------------------------------===//

lib/IRGen/GenMeta.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,15 @@ namespace irgen {
239239
GenericSignature sig,
240240
ArrayRef<Requirement> requirements);
241241

242+
/// Add generic pack shape descriptors to the given constant struct builder.
243+
///
244+
/// These appear in generic type metadata, and conformance descriptors with
245+
/// conditional pack requirements.
246+
void addGenericPackShapeDescriptors(IRGenModule &IGM,
247+
ConstantStructBuilder &B,
248+
ArrayRef<CanType> shapes,
249+
ArrayRef<GenericPackArgument> packArgs);
250+
242251
llvm::GlobalValue *emitAsyncFunctionPointer(IRGenModule &IGM,
243252
llvm::Function *function,
244253
LinkEntity entity,

lib/IRGen/GenProto.cpp

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1942,6 +1942,10 @@ namespace {
19421942
ConformanceDescription Description;
19431943
ConformanceFlags Flags;
19441944

1945+
using PlaceholderPosition =
1946+
ConstantAggregateBuilderBase::PlaceholderPosition;
1947+
Optional<PlaceholderPosition> FlagsPP;
1948+
19451949
public:
19461950
ProtocolConformanceDescriptorBuilder(
19471951
IRGenModule &IGM,
@@ -1960,6 +1964,11 @@ namespace {
19601964
addResilientWitnesses();
19611965
addGenericWitnessTable();
19621966

1967+
// We fill the flags last, since we continue filling them in
1968+
// after the call to addFlags() deposits the placeholder.
1969+
B.fillPlaceholderWithInt(*FlagsPP, IGM.Int32Ty,
1970+
Flags.getIntValue());
1971+
19631972
B.suggestType(IGM.ProtocolConformanceDescriptorTy);
19641973
}
19651974

@@ -1981,13 +1990,6 @@ namespace {
19811990
}
19821991

19831992
void addWitnessTable() {
1984-
// Note the number of conditional requirements.
1985-
unsigned numConditional = 0;
1986-
if (auto normal = dyn_cast<NormalProtocolConformance>(Conformance)) {
1987-
numConditional = normal->getConditionalRequirements().size();
1988-
}
1989-
Flags = Flags.withNumConditionalRequirements(numConditional);
1990-
19911993
// Relative reference to the witness table.
19921994
B.addRelativeAddressOrNull(Description.pattern);
19931995
}
@@ -2001,13 +2003,9 @@ namespace {
20012003
Flags = Flags.withIsRetroactive(false)
20022004
.withIsSynthesizedNonUnique(false);
20032005
}
2004-
Flags = Flags.withHasResilientWitnesses(
2005-
!Description.resilientWitnesses.empty());
2006-
Flags =
2007-
Flags.withHasGenericWitnessTable(Description.requiresSpecialization);
20082006

2009-
// Add the flags.
2010-
B.addInt32(Flags.getIntValue());
2007+
// Add a placeholder for the flags.
2008+
FlagsPP = B.addPlaceholderWithSize(IGM.Int32Ty);
20112009
}
20122010

20132011
void addContext() {
@@ -2025,19 +2023,42 @@ namespace {
20252023

20262024
void addConditionalRequirements() {
20272025
auto normal = dyn_cast<NormalProtocolConformance>(Conformance);
2028-
if (!normal || normal->getConditionalRequirements().empty())
2026+
if (!normal)
20292027
return;
20302028

2031-
auto nominal = normal->getType()->getAnyNominal();
2032-
irgen::addGenericRequirements(IGM, B,
2033-
nominal->getGenericSignatureOfContext(),
2034-
normal->getConditionalRequirements());
2029+
auto condReqs = normal->getConditionalRequirements();
2030+
if (condReqs.empty())
2031+
return;
2032+
2033+
Flags = Flags.withNumConditionalRequirements(condReqs.size());
2034+
2035+
auto nominal = normal->getDeclContext()->getSelfNominalTypeDecl();
2036+
auto sig = nominal->getGenericSignatureOfContext();
2037+
auto metadata = irgen::addGenericRequirements(IGM, B, sig, condReqs);
2038+
2039+
Flags = Flags.withNumConditionalPackDescriptors(
2040+
metadata.GenericPackArguments.size());
2041+
2042+
// Collect the shape classes from the nominal type's generic signature.
2043+
sig->forEachParam([&](GenericTypeParamType *param, bool canonical) {
2044+
if (canonical && param->isParameterPack()) {
2045+
auto reducedShape = sig->getReducedShape(param)->getCanonicalType();
2046+
if (reducedShape->isEqual(param))
2047+
metadata.ShapeClasses.push_back(reducedShape);
2048+
}
2049+
});
2050+
2051+
irgen::addGenericPackShapeDescriptors(
2052+
IGM, B, metadata.ShapeClasses,
2053+
metadata.GenericPackArguments);
20352054
}
20362055

20372056
void addResilientWitnesses() {
20382057
if (Description.resilientWitnesses.empty())
20392058
return;
20402059

2060+
Flags = Flags.withHasResilientWitnesses(true);
2061+
20412062
// TargetResilientWitnessesHeader
20422063
ArrayRef<llvm::Constant *> witnesses = Description.resilientWitnesses;
20432064
B.addInt32(witnesses.size());
@@ -2098,6 +2119,8 @@ namespace {
20982119
if (!Description.requiresSpecialization)
20992120
return;
21002121

2122+
Flags = Flags.withHasGenericWitnessTable(true);
2123+
21012124
// WitnessTableSizeInWords
21022125
B.addInt(IGM.Int16Ty, Description.witnessTableSize);
21032126
// WitnessTablePrivateSizeInWordsAndRequiresInstantiation

lib/IRGen/LocalTypeData.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -473,18 +473,24 @@ void IRGenFunction::bindLocalTypeDataFromSelfWitnessTable(
473473
SILWitnessTable::enumerateWitnessTableConditionalConformances(
474474
conformance,
475475
[&](unsigned index, CanType type, ProtocolDecl *proto) {
476-
auto archetype = getTypeInContext(type);
477-
if (isa<ArchetypeType>(archetype)) {
476+
if (auto packType = dyn_cast<PackType>(type)) {
477+
if (auto expansion = packType.unwrapSingletonPackExpansion())
478+
type = expansion.getPatternType();
479+
}
480+
481+
type = getTypeInContext(type);
482+
483+
if (isa<ArchetypeType>(type)) {
478484
WitnessIndex wIndex(privateWitnessTableIndexToTableOffset(index),
479485
/*prefix*/ false);
480486

481487
auto table = loadConditionalConformance(*this ,selfTable,
482488
wIndex.forProtocolWitnessTable());
483489
table = Builder.CreateBitCast(table, IGM.WitnessTablePtrTy);
484-
setProtocolWitnessTableName(IGM, table, archetype, proto);
490+
setProtocolWitnessTableName(IGM, table, type, proto);
485491

486492
setUnscopedLocalTypeData(
487-
archetype,
493+
type,
488494
LocalTypeDataKind::forAbstractProtocolWitnessTable(proto),
489495
table);
490496
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %target-swift-frontend -emit-ir %s -disable-availability-checking | %FileCheck %s
2+
3+
protocol P {
4+
static func foobar()
5+
}
6+
7+
struct G<each T> {}
8+
9+
extension G: P where repeat each T: P {
10+
static func foobar() {}
11+
}
12+
13+
// CHECK-LABEL: define internal swiftcc void @"$s41variadic_generic_conditional_conformances1GVyxxQp_QPGAA1PA2aEP6foobaryyFZTW"(ptr swiftself %0, ptr %Self, ptr %SelfWitnessTable)

0 commit comments

Comments
 (0)