Skip to content

Commit 75b2707

Browse files
committed
[TypeLowering] Added hasPack field.
Record whether any sort of pack was seen when visiting the type.
1 parent 2bc509a commit 75b2707

File tree

5 files changed

+150
-7
lines changed

5 files changed

+150
-7
lines changed

include/swift/SIL/SILType.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,9 @@ class SILType {
395395
/// Whether the type contains any flavor of pack.
396396
bool hasAnyPack() const { return getASTType()->hasAnyPack(); }
397397

398+
/// Whether the type's layout is known to include some flavor of pack.
399+
bool isOrContainsPack(const SILFunction &F) const;
400+
398401
/// True if the type is an empty tuple or an empty struct or a tuple or
399402
/// struct containing only empty types.
400403
bool isEmpty(const SILFunction &F) const;

include/swift/SIL/TypeLowering.h

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,12 @@ enum IsLexical_t : bool {
176176
IsLexical = true,
177177
};
178178

179+
/// Does this type contain any pack-like thing.
180+
enum HasPack_t : bool {
181+
HasNoPack = false,
182+
HasPack = true,
183+
};
184+
179185
/// Extended type information used by SIL.
180186
class TypeLowering {
181187
public:
@@ -192,10 +198,12 @@ class TypeLowering {
192198
InfiniteFlag = 1 << 5,
193199
HasRawPointerFlag = 1 << 6,
194200
LexicalFlag = 1 << 7,
201+
HasPackFlag = 1 << 8,
195202
};
196203
// clang-format on
197204

198-
uint8_t Flags;
205+
uint16_t Flags;
206+
199207
public:
200208
/// Construct a default RecursiveProperties, which corresponds to
201209
/// a trivial, loadable, fixed-layout type.
@@ -207,14 +215,15 @@ class TypeLowering {
207215
IsTypeExpansionSensitive_t isTypeExpansionSensitive =
208216
IsNotTypeExpansionSensitive,
209217
HasRawPointer_t hasRawPointer = DoesNotHaveRawPointer,
210-
IsLexical_t isLexical = IsNotLexical)
218+
IsLexical_t isLexical = IsNotLexical, HasPack_t hasPack = HasNoPack)
211219
: Flags((isTrivial ? 0U : NonTrivialFlag) |
212220
(isFixedABI ? 0U : NonFixedABIFlag) |
213221
(isAddressOnly ? AddressOnlyFlag : 0U) |
214222
(isResilient ? ResilientFlag : 0U) |
215223
(isTypeExpansionSensitive ? TypeExpansionSensitiveFlag : 0U) |
216224
(hasRawPointer ? HasRawPointerFlag : 0U) |
217-
(isLexical ? LexicalFlag : 0U)) {}
225+
(isLexical ? LexicalFlag : 0U) |
226+
(hasPack ? HasPackFlag : 0U)) {}
218227

219228
constexpr bool operator==(RecursiveProperties p) const {
220229
return Flags == p.Flags;
@@ -236,7 +245,7 @@ class TypeLowering {
236245

237246
static constexpr RecursiveProperties forOpaque() {
238247
return {IsNotTrivial, IsNotFixedABI, IsAddressOnly, IsNotResilient,
239-
IsNotTypeExpansionSensitive, DoesNotHaveRawPointer, IsLexical};
248+
IsNotTypeExpansionSensitive, DoesNotHaveRawPointer, IsLexical, HasNoPack};
240249
}
241250

242251
static constexpr RecursiveProperties forResilient() {
@@ -272,6 +281,9 @@ class TypeLowering {
272281
IsLexical_t isLexical() const {
273282
return IsLexical_t((Flags & LexicalFlag) != 0);
274283
}
284+
HasPack_t isOrContainsPack() const {
285+
return HasPack_t((Flags & HasPackFlag) != 0);
286+
}
275287

276288
void setNonTrivial() { Flags |= NonTrivialFlag; }
277289
void setNonFixedABI() { Flags |= NonFixedABIFlag; }
@@ -285,6 +297,7 @@ class TypeLowering {
285297
void setLexical(IsLexical_t isLexical) {
286298
Flags = (Flags & ~LexicalFlag) | (isLexical ? LexicalFlag : 0);
287299
}
300+
void setHasPack() { Flags |= HasPackFlag; }
288301
};
289302

290303
private:
@@ -395,6 +408,11 @@ class TypeLowering {
395408
return Properties.isLexical();
396409
}
397410

411+
/// Does this type feature a pack at some level of its type tree.
412+
bool isOrContainsPack() const {
413+
return Properties.isOrContainsPack();
414+
}
415+
398416
ResilienceExpansion getResilienceExpansion() const {
399417
return expansionContext.getResilienceExpansion();
400418
}

lib/SIL/IR/SILType.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ bool SILType::isNonTrivialOrContainsRawPointer(const SILFunction *f) const {
128128
return result;
129129
}
130130

131+
bool SILType::isOrContainsPack(const SILFunction &F) const {
132+
auto contextType = hasTypeParameter() ? F.mapTypeIntoContext(*this) : *this;
133+
return F.getTypeLowering(contextType).isOrContainsPack();
134+
}
135+
131136
bool SILType::isEmpty(const SILFunction &F) const {
132137
// Infinite types are never empty.
133138
if (F.getTypeLowering(*this).getRecursiveProperties().isInfinite()) {

lib/SIL/IR/TypeLowering.cpp

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "swift/AST/TypeDifferenceVisitor.h"
3232
#include "swift/AST/Types.h"
3333
#include "swift/ClangImporter/ClangModule.h"
34+
#include "swift/SIL/AbstractionPatternGenerators.h"
3435
#include "swift/SIL/PrettyStackTrace.h"
3536
#include "swift/SIL/SILArgument.h"
3637
#include "swift/SIL/SILBuilder.h"
@@ -261,6 +262,13 @@ namespace {
261262
return props;
262263
}
263264

265+
RecursiveProperties mergeHasPack(HasPack_t hasPack,
266+
RecursiveProperties props) {
267+
if (hasPack == HasPack)
268+
props.setHasPack();
269+
return props;
270+
}
271+
264272
RecursiveProperties applyLifetimeAnnotation(LifetimeAnnotation annotation,
265273
RecursiveProperties props) {
266274
switch (annotation) {
@@ -333,7 +341,8 @@ namespace {
333341
IsAddressOnly, IsNotResilient,
334342
isSensitive,
335343
DoesNotHaveRawPointer,
336-
IsLexical});
344+
IsLexical,
345+
HasPack});
337346
}
338347

339348
RetTy visitSILPackType(CanSILPackType type,
@@ -343,7 +352,8 @@ namespace {
343352
IsAddressOnly, IsNotResilient,
344353
isSensitive,
345354
DoesNotHaveRawPointer,
346-
IsLexical});
355+
IsLexical,
356+
HasPack});
347357
}
348358

349359
RetTy visitPackExpansionType(CanPackExpansionType type,
@@ -355,6 +365,7 @@ namespace {
355365
type.getPatternType(),
356366
TC, Expansion));
357367
props = mergeIsTypeExpansionSensitive(isSensitive, props);
368+
props.setHasPack();
358369
return asImpl().handleAddressOnly(type, props);
359370
}
360371

@@ -2252,6 +2263,7 @@ namespace {
22522263
IsTypeExpansionSensitive_t isSensitive) {
22532264
RecursiveProperties properties;
22542265
properties.setAddressOnly();
2266+
properties.setHasPack();
22552267
for (auto i : indices(packType.getElementTypes())) {
22562268
auto &eltLowering =
22572269
TC.getTypeLowering(packType->getSILElementType(i),
@@ -2268,6 +2280,7 @@ namespace {
22682280
IsTypeExpansionSensitive_t isSensitive) {
22692281
RecursiveProperties properties;
22702282
properties.setAddressOnly();
2283+
properties.setHasPack();
22712284
auto &patternLowering =
22722285
TC.getTypeLowering(origType.getPackExpansionPatternType(),
22732286
packExpansionType.getPatternType(),
@@ -2362,7 +2375,19 @@ namespace {
23622375
properties.setNonTrivial();
23632376
properties.setLexical(IsLexical);
23642377
}
2365-
2378+
2379+
// [is_or_contains_pack_unsubstituted] Visit the fields of the
2380+
// unsubstituted type to find pack types which would be substituted away.
2381+
for (auto field : D->getStoredProperties()) {
2382+
auto fieldInterfaceTy = field->getInterfaceType()->getCanonicalType();
2383+
auto origFieldType = AbstractionPattern(
2384+
D->getGenericSignature().getCanonicalSignature(), fieldInterfaceTy);
2385+
auto fieldProperties =
2386+
classifyType(origFieldType, fieldInterfaceTy, TC, Expansion);
2387+
properties =
2388+
mergeHasPack(fieldProperties.isOrContainsPack(), properties);
2389+
}
2390+
23662391
// If the type has raw storage, it is move-only and address-only.
23672392
if (D->getAttrs().hasAttribute<RawLayoutAttr>()) {
23682393
properties.setAddressOnly();
@@ -2442,6 +2467,19 @@ namespace {
24422467
if (handleResilience(enumType, D, properties))
24432468
return handleAddressOnly(enumType, properties);
24442469

2470+
// [is_or_contains_pack_unsubstituted] Visit the elements of the
2471+
// unsubstituted type to find pack types which would be substituted away.
2472+
for (auto elt : D->getAllElements()) {
2473+
if (!elt->hasAssociatedValues())
2474+
continue;
2475+
auto eltInterfaceTy = elt->getInterfaceType()->getCanonicalType();
2476+
auto origEltType = AbstractionPattern(
2477+
D->getGenericSignature().getCanonicalSignature(), eltInterfaceTy);
2478+
auto eltProperties =
2479+
classifyType(origEltType, eltInterfaceTy, TC, Expansion);
2480+
properties = mergeHasPack(eltProperties.isOrContainsPack(), properties);
2481+
}
2482+
24452483
// If the whole enum is indirect, we lower it as if all payload
24462484
// cases were indirect. This means a fixed-layout indirect enum
24472485
// is always loadable and nontrivial. A resilient indirect enum
@@ -4646,6 +4684,7 @@ void TypeLowering::print(llvm::raw_ostream &os) const {
46464684
<< "isOrContainsRawPointer: " << BOOL(Properties.isOrContainsRawPointer())
46474685
<< ".\n"
46484686
<< "isLexical: " << BOOL(Properties.isLexical()) << ".\n"
4687+
<< "isOrContainsPack: " << BOOL(Properties.isOrContainsPack()) << ".\n"
46494688
<< "\n";
46504689
}
46514690

test/SIL/type_lowering_unit.sil

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,81 @@ bb0(%0 : @owned $S):
1616
%retval = tuple ()
1717
return %retval : $()
1818
}
19+
20+
// CHECK-LABEL: begin {{.*}} print-type-lowering with: @argument[0]
21+
// CHECK: isOrContainsPack: true
22+
// CHECK-LABEL: end {{.*}} print-type-lowering with: @argument[0]
23+
sil @pack_argument : $@convention(thin) <each T> (@pack_guaranteed Pack{repeat each T}) -> () {
24+
bb0(%0 : $*Pack{repeat each T}):
25+
specify_test "print-type-lowering @argument[0]"
26+
%retval = tuple ()
27+
return %retval : $()
28+
}
29+
30+
public struct VG<each T> {
31+
var value: (repeat each T)
32+
}
33+
34+
public struct VGS<T> {
35+
let g: VG<T>
36+
}
37+
38+
public enum VGE<T> {
39+
case one(VG<T>)
40+
case two(VG<T, T>, VG<T>)
41+
case three(VG<T, T, T>)
42+
}
43+
44+
// CHECK-LABEL: begin {{.*}} pack_field: print-type-lowering with: %instance
45+
// CHECK: isOrContainsPack: true
46+
// CHECK-LABEL: end {{.*}} pack_field: print-type-lowering with: %instance
47+
sil @pack_field : $@convention(thin) <T> (@in_guaranteed VGS<T>) -> () {
48+
entry(%instance : $*VGS<T>):
49+
specify_test "print-type-lowering %instance"
50+
%retval = tuple ()
51+
return %retval : $()
52+
}
53+
54+
// CHECK-LABEL: begin {{.*}} pack_element: print-type-lowering with: %instance
55+
// CHECK: isOrContainsPack: true
56+
// CHECK-LABEL: end {{.*}} pack_element: print-type-lowering with: %instance
57+
sil @pack_element : $@convention(thin) <T> (@in_guaranteed VGE<T>) -> () {
58+
entry(%instance : $*VGE<T>):
59+
specify_test "print-type-lowering %instance"
60+
%retval = tuple ()
61+
return %retval : $()
62+
}
63+
64+
public struct G<T> {
65+
var value: (T, T)
66+
}
67+
68+
public struct GS<T> {
69+
let g: G<T>
70+
}
71+
72+
public enum GE<T> {
73+
case one(G<T>)
74+
case two(G<T>, G<T>)
75+
case three(G<T>)
76+
}
77+
78+
// CHECK-LABEL: begin {{.*}} nonpack_field: print-type-lowering with: %instance
79+
// CHECK: isOrContainsPack: false
80+
// CHECK-LABEL: end {{.*}} nonpack_field: print-type-lowering with: %instance
81+
sil @nonpack_field : $@convention(thin) <T> (@in_guaranteed GS<T>) -> () {
82+
entry(%instance : $*GS<T>):
83+
specify_test "print-type-lowering %instance"
84+
%retval = tuple ()
85+
return %retval : $()
86+
}
87+
88+
// CHECK-LABEL: begin {{.*}} nonpack_element: print-type-lowering with: %instance
89+
// CHECK: isOrContainsPack: false
90+
// CHECK-LABEL: end {{.*}} nonpack_element: print-type-lowering with: %instance
91+
sil @nonpack_element : $@convention(thin) <T> (@in_guaranteed GE<T>) -> () {
92+
entry(%instance : $*GE<T>):
93+
specify_test "print-type-lowering %instance"
94+
%retval = tuple ()
95+
return %retval : $()
96+
}

0 commit comments

Comments
 (0)