Skip to content

Commit 2975584

Browse files
committed
[sil] Add basic SIL support for alloc_stack [non_nested].
This means I just added the flag and added support for cloning/printing/serializing the bit on alloc_stack.
1 parent 26627d7 commit 2975584

File tree

13 files changed

+120
-10
lines changed

13 files changed

+120
-10
lines changed

include/swift/SIL/SILCloner.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,7 @@ SILCloner<ImplClass>::visitAllocStackInst(AllocStackInst *Inst) {
10621062
true
10631063
#endif
10641064
);
1065+
NewInst->setStackAllocationIsNested(Inst->isStackAllocationNested());
10651066
recordClonedInstruction(Inst, NewInst);
10661067
}
10671068

include/swift/SIL/SILInstruction.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,24 @@ class SILPrintContext;
141141

142142
template <typename ImplClass> class SILClonerWithScopes;
143143

144+
/// An enum that describes whether or not a stack allocation may violate the
145+
/// stack discipline of swift.
146+
///
147+
/// DISCUSSION: In swift, we require that all allocations on the stack be
148+
/// strictly allocated in a LIFO order... that is the last stack allocation
149+
/// created must be the first stack allocation destroyed. In some cases, we
150+
/// cannot guarantee that behavior. In such cases we may need to use other
151+
/// strategies that do not involve stack memory (e.x.: using heap memory
152+
/// although we do not require heap memory to be used).
153+
enum StackAllocationIsNested_t : bool {
154+
/// The instruction may not obey the LIFO rule of stack allocation.
155+
StackAllocationIsNotNested = false,
156+
157+
/// The instruction obeys the LIFO rule of stack allocation and can allocate
158+
/// memory on the stack normally.
159+
StackAllocationIsNested = true,
160+
};
161+
144162
enum class MemoryBehavior {
145163
None,
146164
/// The instruction may read memory.
@@ -858,6 +876,15 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
858876
/// The stack allocation produced by the instruction, if any.
859877
SILValue getStackAllocation() const;
860878

879+
/// Returns the kind of stack memory that should be allocated. There are
880+
/// certain (unfortunate) situations in which "stack" allocations may become
881+
/// unnested and must use alternative allocation strategies. Rather than
882+
/// requiring all of these to explicitly use heap allocation, which may be
883+
/// to be significantly less efficient (e.g. )
884+
StackAllocationIsNested_t isStackAllocationNested() const;
885+
886+
void setStackAllocationIsNested(StackAllocationIsNested_t isNested);
887+
861888
/// Returns true if this is the deallocation of a stack allocating instruction.
862889
/// The first operand must be the allocating instruction.
863890
bool isDeallocatingStack() const;
@@ -2055,6 +2082,24 @@ class AllocStackInst final
20552082
}
20562083
}
20572084

2085+
StackAllocationIsNested_t isStackAllocationNested() const {
2086+
if (sharedUInt8().AllocStackInst.isNested) {
2087+
return StackAllocationIsNested;
2088+
}
2089+
return StackAllocationIsNotNested;
2090+
}
2091+
2092+
void setStackAllocationIsNested(StackAllocationIsNested_t isNested) {
2093+
switch (isNested) {
2094+
case StackAllocationIsNotNested:
2095+
sharedUInt8().AllocStackInst.isNested = false;
2096+
break;
2097+
case StackAllocationIsNested:
2098+
sharedUInt8().AllocStackInst.isNested = true;
2099+
break;
2100+
}
2101+
}
2102+
20582103
void markUsesMoveableValueDebugInfo() {
20592104
sharedUInt8().AllocStackInst.usesMoveableValueDebugInfo =
20602105
(bool)UsesMoveableValueDebugInfo;

include/swift/SIL/SILNode.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,8 @@ class alignas(8) SILNode :
229229
lexical : 1,
230230
fromVarDecl : 1,
231231
usesMoveableValueDebugInfo : 1,
232-
hasInvalidatedVarInfo : 1);
232+
hasInvalidatedVarInfo : 1,
233+
isNested : 1);
233234

234235
SHARED_FIELD(AllocBoxInst, uint8_t
235236
dynamicLifetime : 1,

lib/SIL/IR/SILInstruction.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,6 +1339,27 @@ SILValue SILInstruction::getStackAllocation() const {
13391339
return cast<SingleValueInstruction>(this);
13401340
}
13411341

1342+
StackAllocationIsNested_t SILInstruction::isStackAllocationNested() const {
1343+
assert(isAllocatingStack());
1344+
if (auto ASI = dyn_cast<AllocStackInst>(this)) {
1345+
return ASI->isStackAllocationNested();
1346+
} else {
1347+
// TODO: implement for all remaining allocations
1348+
return StackAllocationIsNested;
1349+
}
1350+
}
1351+
1352+
void SILInstruction::setStackAllocationIsNested(
1353+
StackAllocationIsNested_t nested) {
1354+
assert(isAllocatingStack());
1355+
if (auto ASI = dyn_cast<AllocStackInst>(this)) {
1356+
assert(nested == StackAllocationIsNested);
1357+
ASI->setStackAllocationIsNested(nested);
1358+
} else if (!nested) {
1359+
llvm_unreachable("unimplemented");
1360+
}
1361+
}
1362+
13421363
bool SILInstruction::isDeallocatingStack() const {
13431364
// NOTE: If you're adding a new kind of deallocating instruction,
13441365
// there are several places scattered around the SIL optimizer which

lib/SIL/IR/SILInstructions.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ AllocStackInst::AllocStackInst(
231231
sharedUInt8().AllocStackInst.fromVarDecl = (bool)isFromVarDecl;
232232
sharedUInt8().AllocStackInst.usesMoveableValueDebugInfo =
233233
(bool)usesMoveableValueDebugInfo || elementType.isMoveOnly();
234+
setStackAllocationIsNested(StackAllocationIsNested);
234235
sharedUInt32().AllocStackInst.numOperands = TypeDependentOperands.size();
235236

236237
// VarInfo must be initialized after

lib/SIL/IR/SILPrinter.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,7 +1568,17 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
15681568
printDebugInfoExpression(Var->DIExpr);
15691569
}
15701570

1571+
template <class T>
1572+
void printNonNested(T *inst) {
1573+
static_assert(&T::isStackAllocationNested !=
1574+
&SILInstruction::isStackAllocationNested,
1575+
"Type doesn't override isStackAllocationNested");
1576+
if (inst->isStackAllocationNested() == StackAllocationIsNotNested)
1577+
*this << "[non_nested] ";
1578+
}
1579+
15711580
void visitAllocStackInst(AllocStackInst *AVI) {
1581+
printNonNested(AVI);
15721582
if (AVI->hasDynamicLifetime())
15731583
*this << "[dynamic_lifetime] ";
15741584
if (AVI->isLexical())

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4994,6 +4994,7 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
49944994
auto isFromVarDecl = IsNotFromVarDecl;
49954995
UsesMoveableValueDebugInfo_t usesMoveableValueDebugInfo =
49964996
DoesNotUseMoveableValueDebugInfo;
4997+
auto isNested = StackAllocationIsNested;
49974998

49984999
StringRef attributeName;
49995000
SourceLoc attributeLoc;
@@ -5006,6 +5007,8 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
50065007
isFromVarDecl = IsFromVarDecl;
50075008
else if (attributeName == "moveable_value_debuginfo")
50085009
usesMoveableValueDebugInfo = UsesMoveableValueDebugInfo;
5010+
else if (attributeName == "non_nested")
5011+
isNested = StackAllocationIsNotNested;
50095012
else {
50105013
P.diagnose(attributeLoc, diag::sil_invalid_attribute_for_instruction,
50115014
attributeName, "alloc_stack");
@@ -5025,14 +5028,16 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
50255028
usesMoveableValueDebugInfo = UsesMoveableValueDebugInfo;
50265029

50275030
// It doesn't make sense to attach a debug var info if the name is empty
5031+
AllocStackInst *ASI;
50285032
if (VarInfo.Name.size())
5029-
ResultVal = B.createAllocStack(InstLoc, Ty, VarInfo, hasDynamicLifetime,
5030-
isLexical, isFromVarDecl,
5031-
usesMoveableValueDebugInfo);
5033+
ASI = B.createAllocStack(InstLoc, Ty, VarInfo, hasDynamicLifetime,
5034+
isLexical, isFromVarDecl,
5035+
usesMoveableValueDebugInfo);
50325036
else
5033-
ResultVal =
5034-
B.createAllocStack(InstLoc, Ty, {}, hasDynamicLifetime, isLexical,
5035-
isFromVarDecl, usesMoveableValueDebugInfo);
5037+
ASI = B.createAllocStack(InstLoc, Ty, {}, hasDynamicLifetime, isLexical,
5038+
isFromVarDecl, usesMoveableValueDebugInfo);
5039+
ASI->setStackAllocationIsNested(isNested);
5040+
ResultVal = ASI;
50365041
break;
50375042
}
50385043
case SILInstructionKind::MetatypeInst: {

lib/Serialization/DeserializeSIL.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1818,9 +1818,12 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn,
18181818
auto isLexical = IsLexical_t((Attr >> 1) & 0x1);
18191819
auto isFromVarDecl = IsFromVarDecl_t((Attr >> 2) & 0x1);
18201820
auto wasMoved = UsesMoveableValueDebugInfo_t((Attr >> 3) & 0x1);
1821-
ResultInst = Builder.createAllocStack(
1821+
auto isNested = StackAllocationIsNested_t((Attr >> 4) & 0x1);
1822+
auto ASI = Builder.createAllocStack(
18221823
Loc, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn),
18231824
std::nullopt, hasDynamicLifetime, isLexical, isFromVarDecl, wasMoved);
1825+
ASI->setStackAllocationIsNested(isNested);
1826+
ResultInst = ASI;
18241827
break;
18251828
}
18261829
case SILInstructionKind::AllocPackInst: {

lib/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR = 974; // remove 'isCallerIsolated' bit from ParamDecl
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 975; // Expand one type layout
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///

lib/Serialization/SILFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ namespace sil_block {
542542

543543
// SIL instructions with one type. (alloc_stack)
544544
using SILOneTypeLayout = BCRecordLayout<SIL_ONE_TYPE, SILInstOpCodeField,
545-
BCFixed<4>, // Optional attributes
545+
BCFixed<5>, // Optional attributes
546546
TypeIDField, SILTypeCategoryField>;
547547

548548
// SIL instructions with one typed valueref. (dealloc_stack, return)

0 commit comments

Comments
 (0)