Skip to content

Commit bb24b8c

Browse files
Merge pull request #70720 from nate-chandler/rdar119829826
[IRGen] Pack metadata may be allocated based on type layouts.
2 parents 8d9f04b + 73d68a3 commit bb24b8c

File tree

10 files changed

+272
-20
lines changed

10 files changed

+272
-20
lines changed

include/swift/SIL/SILInstruction.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -853,7 +853,7 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
853853

854854
/// Whether IRGen lowering of this instruction may result in emitting packs of
855855
/// metadata or witness tables.
856-
bool mayRequirePackMetadata() const;
856+
bool mayRequirePackMetadata(SILFunction const &F) const;
857857

858858
/// Create a new copy of this instruction, which retains all of the operands
859859
/// and other information of this one. If an insertion point is specified,

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/IRGen/PackMetadataMarkerInserter.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,9 @@ Inserter::shouldInsertMarkersForInstruction(SILInstruction *inst) {
9494
LLVM_FALLTHROUGH;
9595
}
9696
default:
97-
return inst->mayRequirePackMetadata() ? FindResult::Some : FindResult::None;
97+
return inst->mayRequirePackMetadata(*inst->getFunction())
98+
? FindResult::Some
99+
: FindResult::None;
98100
}
99101
}
100102

lib/SIL/IR/SILInstruction.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,7 +1301,11 @@ bool SILInstruction::isDeallocatingStack() const {
13011301
return false;
13021302
}
13031303

1304-
bool SILInstruction::mayRequirePackMetadata() const {
1304+
static bool typeOrLayoutInvolvesPack(SILType ty, SILFunction const &F) {
1305+
return ty.hasAnyPack() || ty.isOrContainsPack(F);
1306+
}
1307+
1308+
bool SILInstruction::mayRequirePackMetadata(SILFunction const &F) const {
13051309
switch (getKind()) {
13061310
case SILInstructionKind::AllocPackInst:
13071311
case SILInstructionKind::TuplePackElementAddrInst:
@@ -1313,11 +1317,11 @@ bool SILInstruction::mayRequirePackMetadata() const {
13131317
case SILInstructionKind::TryApplyInst: {
13141318
// Check the function type for packs.
13151319
auto apply = ApplySite::isa(const_cast<SILInstruction *>(this));
1316-
if (apply.getCallee()->getType().hasAnyPack())
1320+
if (typeOrLayoutInvolvesPack(apply.getCallee()->getType(), F))
13171321
return true;
13181322
// Check the substituted types for packs.
13191323
for (auto ty : apply.getSubstitutionMap().getReplacementTypes()) {
1320-
if (ty->hasAnyPack())
1324+
if (typeOrLayoutInvolvesPack(F.getTypeLowering(ty).getLoweredType(), F))
13211325
return true;
13221326
}
13231327
return false;
@@ -1328,20 +1332,20 @@ bool SILInstruction::mayRequirePackMetadata() const {
13281332
case SILInstructionKind::DestroyValueInst:
13291333
// Unary instructions.
13301334
{
1331-
return getOperand(0)->getType().hasAnyPack();
1335+
return typeOrLayoutInvolvesPack(getOperand(0)->getType(), F);
13321336
}
13331337
case SILInstructionKind::AllocStackInst: {
13341338
auto *asi = cast<AllocStackInst>(this);
1335-
return asi->getType().hasAnyPack();
1339+
return typeOrLayoutInvolvesPack(asi->getType(), F);
13361340
}
13371341
case SILInstructionKind::MetatypeInst: {
13381342
auto *mi = cast<MetatypeInst>(this);
1339-
return mi->getType().hasAnyPack();
1343+
return typeOrLayoutInvolvesPack(mi->getType(), F);
13401344
}
13411345
case SILInstructionKind::WitnessMethodInst: {
13421346
auto *wmi = cast<WitnessMethodInst>(this);
13431347
auto ty = wmi->getLookupType();
1344-
return ty->hasAnyPack();
1348+
return typeOrLayoutInvolvesPack(F.getTypeLowering(ty).getLoweredType(), F);
13451349
}
13461350
default:
13471351
// Instructions that deallocate stack must not result in pack metadata
@@ -1359,15 +1363,15 @@ bool SILInstruction::mayRequirePackMetadata() const {
13591363
// Check results and operands for packs. If a pack appears, lowering the
13601364
// instruction might result in pack metadata emission.
13611365
for (auto result : getResults()) {
1362-
if (result->getType().hasAnyPack())
1366+
if (typeOrLayoutInvolvesPack(result->getType(), F))
13631367
return true;
13641368
}
13651369
for (auto operandTy : getOperandTypes()) {
1366-
if (operandTy.hasAnyPack())
1370+
if (typeOrLayoutInvolvesPack(operandTy, F))
13671371
return true;
13681372
}
13691373
for (auto &tdo : getTypeDependentOperands()) {
1370-
if (tdo.get()->getType().hasAnyPack())
1374+
if (typeOrLayoutInvolvesPack(tdo.get()->getType(), F))
13711375
return true;
13721376
}
13731377

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

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6270,7 +6270,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
62706270
}
62716271

62726272
void checkAllocPackMetadataInst(AllocPackMetadataInst *apmi) {
6273-
require(apmi->getIntroducer()->mayRequirePackMetadata(),
6273+
require(apmi->getIntroducer()->mayRequirePackMetadata(*apmi->getFunction()),
62746274
"Introduces instruction of kind which cannot emit on-stack pack "
62756275
"metadata");
62766276
require(F.getModule().getStage() == SILStage::Lowered,

0 commit comments

Comments
 (0)