Skip to content

Commit 7a474ac

Browse files
committed
[SIL] Added on-stack pack metadata marker insts.
The new alloc_pack_metadata and dealloc_pack_metadata are inserted as part of IRGen lowering. The former indicates that the next instruction might result in on-stack pack metadata being emitted. The latter indicates that this is the position at which metadata emitted on behalf of its operand should be cleaned up.
1 parent 56439ea commit 7a474ac

21 files changed

+238
-3
lines changed

docs/SIL.rst

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3799,6 +3799,20 @@ address of the allocated memory.
37993799
on stack discipline. The corresponding stack deallocation instruction is
38003800
``dealloc_pack``.
38013801

3802+
alloc_pack_metadata
3803+
```````````````````
3804+
3805+
::
3806+
3807+
sil-instruction ::= 'alloc_pack_metadata' $()
3808+
3809+
Inserted as the last SIL lowering pass of IRGen, indicates that the next instruction
3810+
may have on-stack pack metadata allocated on its behalf.
3811+
3812+
Notionally, ``alloc_pack_metadata`` is a stack allocation instruction. See the
3813+
section above on stack discipline. The corresponding stack deallocation
3814+
instruction is ``dealloc_pack_metadata``.
3815+
38023816
alloc_ref
38033817
`````````
38043818
::
@@ -4056,6 +4070,23 @@ prior to being deallocated.
40564070
on Stack Discipline above. The operand must be an ``alloc_pack``
40574071
instruction.
40584072

4073+
dealloc_pack_metadata
4074+
`````````````````````
4075+
4076+
::
4077+
4078+
sil-instruction ::= 'dealloc_pack_metadata' sil-operand
4079+
4080+
dealloc_pack_metadata $0 : $*()
4081+
4082+
Inserted as the last SIL lowering pass of IRGen, indicates that the on-stack
4083+
pack metadata emitted on behalf of its operand (actually on behalf of the
4084+
instruction after its operand) must be cleaned up here.
4085+
4086+
``dealloc_pack_metadata`` is a stack deallocation instruction. See the section
4087+
on Stack Discipline above. The operand must be an ``alloc_pack_metadata``
4088+
instruction.
4089+
40594090
dealloc_box
40604091
```````````
40614092
::

include/swift/SIL/SILBuilder.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,15 @@ class SILBuilder {
436436
return insert(AllocPackInst::create(getSILDebugLocation(loc), packType,
437437
getFunction()));
438438
}
439+
AllocPackMetadataInst *
440+
createAllocPackMetadata(SILLocation loc,
441+
Optional<SILType> elementType = llvm::None) {
442+
return insert(new (getModule()) AllocPackMetadataInst(
443+
getSILDebugLocation(loc),
444+
elementType.value_or(
445+
SILType::getEmptyTupleType(getModule().getASTContext())
446+
.getAddressType())));
447+
}
439448

440449
AllocRefInst *createAllocRef(SILLocation Loc, SILType ObjectType,
441450
bool objc, bool canAllocOnStack,
@@ -2222,6 +2231,11 @@ class SILBuilder {
22222231
return insert(new (getModule())
22232232
DeallocPackInst(getSILDebugLocation(loc), operand));
22242233
}
2234+
DeallocPackMetadataInst *createDeallocPackMetadata(SILLocation loc,
2235+
SILValue alloc) {
2236+
return insert(new (getModule())
2237+
DeallocPackMetadataInst(getSILDebugLocation(loc), alloc));
2238+
}
22252239
DeallocStackRefInst *createDeallocStackRef(SILLocation Loc,
22262240
SILValue operand) {
22272241
return insert(new (getModule())

include/swift/SIL/SILCloner.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,14 @@ SILCloner<ImplClass>::visitAllocStackInst(AllocStackInst *Inst) {
892892
recordClonedInstruction(Inst, NewInst);
893893
}
894894

895+
template <typename ImplClass>
896+
void SILCloner<ImplClass>::visitAllocPackMetadataInst(
897+
AllocPackMetadataInst *Inst) {
898+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
899+
recordClonedInstruction(Inst, getBuilder().createAllocPackMetadata(
900+
getOpLocation(Inst->getLoc())));
901+
}
902+
895903
template<typename ImplClass>
896904
void
897905
SILCloner<ImplClass>::visitAllocPackInst(AllocPackInst *Inst) {
@@ -2856,6 +2864,15 @@ SILCloner<ImplClass>::visitDeallocPackInst(DeallocPackInst *Inst) {
28562864
getOpValue(Inst->getOperand())));
28572865
}
28582866

2867+
template <typename ImplClass>
2868+
void SILCloner<ImplClass>::visitDeallocPackMetadataInst(
2869+
DeallocPackMetadataInst *Inst) {
2870+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
2871+
recordClonedInstruction(
2872+
Inst, getBuilder().createDeallocPackMetadata(
2873+
getOpLocation(Inst->getLoc()), Inst->getOperand()));
2874+
}
2875+
28592876
template<typename ImplClass>
28602877
void
28612878
SILCloner<ImplClass>::visitDeallocRefInst(DeallocRefInst *Inst) {

include/swift/SIL/SILInstruction.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,10 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
821821
/// The first operand must be the allocating instruction.
822822
bool isDeallocatingStack() const;
823823

824+
/// Whether IRGen lowering of this instruction may result in emitting packs of
825+
/// metadata or witness tables.
826+
bool mayRequirePackMetadata() const;
827+
824828
/// Create a new copy of this instruction, which retains all of the operands
825829
/// and other information of this one. If an insertion point is specified,
826830
/// then the new instruction is inserted before the specified point, otherwise
@@ -2275,6 +2279,27 @@ class AllocPackInst final
22752279
}
22762280
};
22772281

2282+
/// AllocPackMetadataInst - Marker instruction indicating that the next
2283+
/// instruction might allocate on-stack pack metadata
2284+
/// during IRGen.
2285+
///
2286+
/// Only valid in lowered SIL.
2287+
class AllocPackMetadataInst final
2288+
: public NullaryInstructionWithTypeDependentOperandsBase<
2289+
SILInstructionKind::AllocPackMetadataInst, AllocPackMetadataInst,
2290+
AllocationInst> {
2291+
friend SILBuilder;
2292+
2293+
AllocPackMetadataInst(SILDebugLocation loc, SILType elementType)
2294+
: NullaryInstructionWithTypeDependentOperandsBase(
2295+
loc, {}, elementType.getAddressType()) {}
2296+
2297+
public:
2298+
/// The instruction which may trigger on-stack pack metadata when IRGen
2299+
/// lowering.
2300+
SILInstruction *getIntroducer() { return getNextInstruction(); }
2301+
};
2302+
22782303
/// The base class for AllocRefInst and AllocRefDynamicInst.
22792304
///
22802305
/// The first NumTailTypes operands are counts for the tail allocated
@@ -8685,6 +8710,27 @@ class DeallocPackInst :
86858710
: UnaryInstructionBase(debugLoc, operand) {}
86868711
};
86878712

8713+
/// DeallocPackMetadataInst - Deallocate stack memory allocated on behalf of the
8714+
/// operand by IRGen.
8715+
///
8716+
/// Only valid in lowered SIL.
8717+
class DeallocPackMetadataInst final
8718+
: public UnaryInstructionBase<SILInstructionKind::DeallocPackMetadataInst,
8719+
DeallocationInst> {
8720+
friend SILBuilder;
8721+
8722+
DeallocPackMetadataInst(SILDebugLocation debugLoc, SILValue alloc)
8723+
: UnaryInstructionBase(debugLoc, alloc) {}
8724+
8725+
public:
8726+
AllocPackMetadataInst *getAllocation() {
8727+
return cast<AllocPackMetadataInst>(getOperand().getDefiningInstruction());
8728+
}
8729+
/// The instruction which may trigger on-stack pack metadata when IRGen
8730+
/// lowering.
8731+
SILInstruction *getIntroducer() { return getAllocation()->getIntroducer(); }
8732+
};
8733+
86888734
/// Like DeallocStackInst, but for `alloc_ref [stack]`.
86898735
class DeallocStackRefInst
86908736
: public UnaryInstructionBase<SILInstructionKind::DeallocStackRefInst,

include/swift/SIL/SILNodes.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,8 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
310310
AllocationInst, None, DoesNotRelease)
311311
SINGLE_VALUE_INST(AllocPackInst, alloc_pack,
312312
AllocationInst, None, DoesNotRelease)
313+
SINGLE_VALUE_INST(AllocPackMetadataInst, alloc_pack_metadata,
314+
AllocationInst, None, DoesNotRelease)
313315
SINGLE_VALUE_INST(AllocRefInst, alloc_ref,
314316
AllocationInst, None, DoesNotRelease)
315317
SINGLE_VALUE_INST(AllocRefDynamicInst, alloc_ref_dynamic,
@@ -727,6 +729,8 @@ ABSTRACT_INST(DeallocationInst, SILInstruction)
727729
DeallocationInst, MayHaveSideEffects, DoesNotRelease)
728730
NON_VALUE_INST(DeallocPackInst, dealloc_pack,
729731
DeallocationInst, MayHaveSideEffects, DoesNotRelease)
732+
NON_VALUE_INST(DeallocPackMetadataInst, dealloc_pack_metadata,
733+
DeallocationInst, MayHaveSideEffects, DoesNotRelease)
730734
NON_VALUE_INST(DeallocStackRefInst, dealloc_stack_ref,
731735
DeallocationInst, MayHaveSideEffects, DoesNotRelease)
732736
NON_VALUE_INST(DeallocRefInst, dealloc_ref,

lib/IRGen/IRGenSIL.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,6 +1175,7 @@ class IRGenSILFunction :
11751175
llvm::Value *addr);
11761176
void visitAllocStackInst(AllocStackInst *i);
11771177
void visitAllocPackInst(AllocPackInst *i);
1178+
void visitAllocPackMetadataInst(AllocPackMetadataInst *i);
11781179
void visitAllocRefInst(AllocRefInst *i);
11791180
void visitAllocRefDynamicInst(AllocRefDynamicInst *i);
11801181
void visitAllocBoxInst(AllocBoxInst *i);
@@ -1364,6 +1365,7 @@ class IRGenSILFunction :
13641365
void visitDeallocStackInst(DeallocStackInst *i);
13651366
void visitDeallocStackRefInst(DeallocStackRefInst *i);
13661367
void visitDeallocPackInst(DeallocPackInst *i);
1368+
void visitDeallocPackMetadataInst(DeallocPackMetadataInst *i);
13671369
void visitDeallocBoxInst(DeallocBoxInst *i);
13681370
void visitDeallocRefInst(DeallocRefInst *i);
13691371
void visitDeallocPartialRefInst(DeallocPartialRefInst *i);
@@ -5584,6 +5586,8 @@ void IRGenSILFunction::visitAllocPackInst(swift::AllocPackInst *i) {
55845586
setLoweredStackAddress(i, addr);
55855587
}
55865588

5589+
void IRGenSILFunction::visitAllocPackMetadataInst(AllocPackMetadataInst *i) {}
5590+
55875591
static void
55885592
buildTailArrays(IRGenSILFunction &IGF,
55895593
SmallVectorImpl<std::pair<SILType, llvm::Value *>> &TailArrays,
@@ -5689,6 +5693,10 @@ void IRGenSILFunction::visitDeallocPackInst(swift::DeallocPackInst *i) {
56895693
deallocatePack(*this, stackAddr, allocatedType);
56905694
}
56915695

5696+
void IRGenSILFunction::visitDeallocPackMetadataInst(
5697+
DeallocPackMetadataInst *i) {
5698+
}
5699+
56925700
void IRGenSILFunction::visitDeallocRefInst(swift::DeallocRefInst *i) {
56935701
// Lower the operand.
56945702
Explosion self = getLoweredExplosion(i->getOperand());

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ SHOULD_NEVER_VISIT_INST(AllocExistentialBox)
9999
SHOULD_NEVER_VISIT_INST(AllocGlobal)
100100
SHOULD_NEVER_VISIT_INST(AllocStack)
101101
SHOULD_NEVER_VISIT_INST(AllocPack)
102+
SHOULD_NEVER_VISIT_INST(AllocPackMetadata)
102103
SHOULD_NEVER_VISIT_INST(PackLength)
103104
SHOULD_NEVER_VISIT_INST(DifferentiabilityWitnessFunction)
104105
SHOULD_NEVER_VISIT_INST(FloatLiteral)
@@ -158,6 +159,7 @@ OPERAND_OWNERSHIP(TrivialUse, ExplicitCopyAddr)
158159
OPERAND_OWNERSHIP(TrivialUse, MarkUnresolvedMoveAddr)
159160
OPERAND_OWNERSHIP(TrivialUse, DeallocStack)
160161
OPERAND_OWNERSHIP(TrivialUse, DeallocPack)
162+
OPERAND_OWNERSHIP(TrivialUse, DeallocPackMetadata)
161163
OPERAND_OWNERSHIP(TrivialUse, DeinitExistentialAddr)
162164
OPERAND_OWNERSHIP(TrivialUse, DestroyAddr)
163165
OPERAND_OWNERSHIP(TrivialUse, EndAccess)

lib/SIL/IR/SILInstruction.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,7 +1247,8 @@ namespace {
12471247

12481248
bool SILInstruction::isAllocatingStack() const {
12491249
if (isa<AllocStackInst>(this) ||
1250-
isa<AllocPackInst>(this))
1250+
isa<AllocPackInst>(this) ||
1251+
isa<AllocPackMetadataInst>(this))
12511252
return true;
12521253

12531254
if (auto *ARI = dyn_cast<AllocRefInstBase>(this)) {
@@ -1278,7 +1279,8 @@ bool SILInstruction::isAllocatingStack() const {
12781279
bool SILInstruction::isDeallocatingStack() const {
12791280
if (isa<DeallocStackInst>(this) ||
12801281
isa<DeallocStackRefInst>(this) ||
1281-
isa<DeallocPackInst>(this))
1282+
isa<DeallocPackInst>(this) ||
1283+
isa<DeallocPackMetadataInst>(this))
12821284
return true;
12831285

12841286
if (auto *BI = dyn_cast<BuiltinInst>(this)) {
@@ -1290,6 +1292,24 @@ bool SILInstruction::isDeallocatingStack() const {
12901292
return false;
12911293
}
12921294

1295+
bool SILInstruction::mayRequirePackMetadata() const {
1296+
switch (getKind()) {
1297+
case SILInstructionKind::AllocPackInst:
1298+
case SILInstructionKind::PartialApplyInst:
1299+
case SILInstructionKind::ApplyInst:
1300+
case SILInstructionKind::BeginApplyInst:
1301+
case SILInstructionKind::TryApplyInst:
1302+
case SILInstructionKind::DebugValueInst:
1303+
case SILInstructionKind::MetatypeInst:
1304+
case SILInstructionKind::TuplePackElementAddrInst:
1305+
case SILInstructionKind::OpenPackElementInst:
1306+
case SILInstructionKind::ClassMethodInst:
1307+
case SILInstructionKind::WitnessMethodInst:
1308+
return true;
1309+
default:
1310+
return false;
1311+
}
1312+
}
12931313

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

lib/SIL/IR/SILPrinter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,6 +1424,9 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
14241424
void visitAllocPackInst(AllocPackInst *API) {
14251425
*this << API->getType().getObjectType();
14261426
}
1427+
void visitAllocPackMetadataInst(AllocPackMetadataInst *APMI) {
1428+
*this << APMI->getType().getObjectType();
1429+
}
14271430

14281431
void printAllocRefInstBase(AllocRefInstBase *ARI) {
14291432
if (ARI->isObjC())
@@ -2453,6 +2456,9 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
24532456
void visitDeallocPackInst(DeallocPackInst *DI) {
24542457
*this << getIDAndType(DI->getOperand());
24552458
}
2459+
void visitDeallocPackMetadataInst(DeallocPackMetadataInst *DPMI) {
2460+
*this << getIDAndType(DPMI->getOperand());
2461+
}
24562462
void visitDeallocStackRefInst(DeallocStackRefInst *ESRL) {
24572463
*this << getIDAndType(ESRL->getOperand());
24582464
}

lib/SIL/IR/ValueOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ CONSTANT_OWNERSHIP_INST(Owned, ObjCMetatypeToObject)
9494
CONSTANT_OWNERSHIP_INST(None, AddressToPointer)
9595
CONSTANT_OWNERSHIP_INST(None, AllocStack)
9696
CONSTANT_OWNERSHIP_INST(None, AllocPack)
97+
CONSTANT_OWNERSHIP_INST(None, AllocPackMetadata)
9798
CONSTANT_OWNERSHIP_INST(None, PackLength)
9899
CONSTANT_OWNERSHIP_INST(None, BeginAccess)
99100
CONSTANT_OWNERSHIP_INST(None, BindMemory)

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4770,6 +4770,14 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
47704770
ResultVal = B.createAllocPack(InstLoc, Ty);
47714771
break;
47724772
}
4773+
case SILInstructionKind::AllocPackMetadataInst: {
4774+
SILType Ty;
4775+
if (parseSILType(Ty))
4776+
return true;
4777+
4778+
ResultVal = B.createAllocPackMetadata(InstLoc, Ty);
4779+
break;
4780+
}
47734781
case SILInstructionKind::AllocStackInst: {
47744782
bool hasDynamicLifetime = false;
47754783
bool isLexical = false;
@@ -4898,6 +4906,11 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
48984906
return true;
48994907
ResultVal = B.createDeallocPack(InstLoc, Val);
49004908
break;
4909+
case SILInstructionKind::DeallocPackMetadataInst:
4910+
if (parseTypedValueRef(Val, B) || parseSILDebugLocation(InstLoc, B))
4911+
return true;
4912+
ResultVal = B.createDeallocPackMetadata(InstLoc, Val);
4913+
break;
49014914
case SILInstructionKind::DeallocRefInst: {
49024915
if (parseTypedValueRef(Val, B) || parseSILDebugLocation(InstLoc, B))
49034916
return true;

lib/SIL/Utils/InstructionUtils.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,9 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType)
484484
case SILInstructionKind::DeallocStackInst:
485485
case SILInstructionKind::DeallocStackRefInst:
486486
case SILInstructionKind::DeallocPackInst:
487+
// This instruction just destroys stack allocations where metadata pointers
488+
// have been stored.
489+
case SILInstructionKind::DeallocPackMetadataInst:
487490
case SILInstructionKind::AutoreleaseValueInst:
488491
case SILInstructionKind::BindMemoryInst:
489492
case SILInstructionKind::RebindMemoryInst:
@@ -631,6 +634,10 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType)
631634
case SILInstructionKind::AllocPackInst:
632635
// Just conservatively assume this has metadata impact.
633636
return RuntimeEffect::MetaData;
637+
case SILInstructionKind::AllocPackMetadataInst:
638+
// Currently this instruction has no effect but in the fullness of time it
639+
// will have a metadata effect.
640+
return RuntimeEffect::MetaData;
634641

635642
case SILInstructionKind::AllocStackInst:
636643
case SILInstructionKind::ProjectBoxInst:

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6026,6 +6026,19 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
60266026
"Result and operand must have the same type, today.");
60276027
}
60286028

6029+
void checkAllocPackMetadataInst(AllocPackMetadataInst *apmi) {
6030+
require(apmi->getIntroducer()->mayRequirePackMetadata(),
6031+
"Introduces instruction of kind which cannot emit on-stack pack "
6032+
"metadata");
6033+
}
6034+
6035+
void checkDeallocPackMetadataInst(DeallocPackMetadataInst *dpmi) {
6036+
auto *apmi = dpmi->getOperand()->getDefiningInstruction();
6037+
require(apmi, "Must have instruction operand.");
6038+
require(isa<AllocPackMetadataInst>(apmi),
6039+
"Must have alloc_pack_metadata operand");
6040+
}
6041+
60296042
void verifyEpilogBlocks(SILFunction *F) {
60306043
bool FoundReturnBlock = false;
60316044
bool FoundThrowBlock = false;

lib/SILOptimizer/UtilityPasses/SerializeSILPass.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ static bool hasOpaqueArchetype(TypeExpansionContext context,
149149
switch (inst.getKind()) {
150150
case SILInstructionKind::AllocStackInst:
151151
case SILInstructionKind::AllocPackInst:
152+
case SILInstructionKind::AllocPackMetadataInst:
152153
case SILInstructionKind::AllocRefInst:
153154
case SILInstructionKind::AllocRefDynamicInst:
154155
case SILInstructionKind::AllocBoxInst:
@@ -281,6 +282,7 @@ static bool hasOpaqueArchetype(TypeExpansionContext context,
281282
case SILInstructionKind::DeallocStackInst:
282283
case SILInstructionKind::DeallocStackRefInst:
283284
case SILInstructionKind::DeallocPackInst:
285+
case SILInstructionKind::DeallocPackMetadataInst:
284286
case SILInstructionKind::DeallocRefInst:
285287
case SILInstructionKind::DeallocPartialRefInst:
286288
case SILInstructionKind::DeallocBoxInst:

0 commit comments

Comments
 (0)