Skip to content

Commit 030f2b8

Browse files
authored
Merge pull request swiftlang#75050 from atrick/vardecl_lifetime
[SILGen] Create SIL variable declaration scopes for trivial values.
2 parents d281fb8 + 9b055ae commit 030f2b8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+571
-261
lines changed

include/swift/SIL/SILBuilder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1459,7 +1459,7 @@ class SILBuilder {
14591459
HasPointerEscape_t hasPointerEscape = DoesNotHavePointerEscape,
14601460
IsFromVarDecl_t fromVarDecl = IsNotFromVarDecl) {
14611461
assert(getFunction().hasOwnership());
1462-
assert(!operand->getType().isTrivial(getFunction()) &&
1462+
assert(fromVarDecl || !operand->getType().isTrivial(getFunction()) &&
14631463
"Should not be passing trivial values to this api. Use instead "
14641464
"emitMoveValueOperation");
14651465
return insert(new (getModule())

include/swift/SIL/SILInstruction.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1978,6 +1978,7 @@ enum HasPointerEscape_t : bool {
19781978
HasPointerEscape = true,
19791979
};
19801980

1981+
// See SILValue::isFromVarDecl()
19811982
enum IsFromVarDecl_t : bool {
19821983
IsNotFromVarDecl = false,
19831984
IsFromVarDecl = true,

include/swift/SIL/SILValue.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,9 @@ class ValueBase : public SILNode, public SILAllocated<ValueBase> {
609609
/// (it has a debug_value [trace] user).
610610
bool hasDebugTrace() const;
611611

612+
/// Does this SILValue begin a VarDecl scope? Only true in OSSA.
613+
bool isFromVarDecl();
614+
612615
static bool classof(SILNodePointer node) {
613616
return node->getKind() >= SILNodeKind::First_ValueBase &&
614617
node->getKind() <= SILNodeKind::Last_ValueBase;

include/swift/SILOptimizer/Utils/StackNesting.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,11 @@ class StackNesting {
160160
/// Returns the stack allocation instruction for a stack deallocation
161161
/// instruction.
162162
SILInstruction *getAllocForDealloc(SILInstruction *Dealloc) const {
163-
return Dealloc->getOperand(0)->getDefiningInstruction();
163+
SILValue op = Dealloc->getOperand(0);
164+
while (auto *mvi = dyn_cast<MoveValueInst>(op)) {
165+
op = mvi->getOperand();
166+
}
167+
return op->getDefiningInstruction();
164168
}
165169

166170
/// Insert deallocations at block boundaries.

lib/SIL/IR/SILValue.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,16 @@ bool ValueBase::hasDebugTrace() const {
209209
return false;
210210
}
211211

212+
bool ValueBase::isFromVarDecl() {
213+
if (auto *mvi = dyn_cast<MoveValueInst>(this)) {
214+
return mvi->isFromVarDecl();
215+
}
216+
if (auto *bbi = dyn_cast<BeginBorrowInst>(this)) {
217+
return bbi->isFromVarDecl();
218+
}
219+
return false;
220+
}
221+
212222
SILBasicBlock *SILNode::getParentBlock() const {
213223
if (auto *Inst = dyn_cast<SILInstruction>(this))
214224
return Inst->getParent();

lib/SIL/IR/TypeLowering.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,6 +1061,15 @@ namespace {
10611061

10621062
void emitDestroyValue(SILBuilder &B, SILLocation loc,
10631063
SILValue value) const override {
1064+
if (B.getFunction().hasOwnership()
1065+
&& B.getModule().getStage() == SILStage::Raw
1066+
&& value->isFromVarDecl()) {
1067+
// Do not use destroy_value for trivial values. The lifetime introducer
1068+
// may be implicitly copied and used outside of its original scope,
1069+
// which violates the invariants of destroy_value.
1070+
B.createExtendLifetime(loc, value);
1071+
return;
1072+
}
10641073
// Trivial
10651074
}
10661075
};

lib/SIL/IR/ValueOwnership.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ CONSTANT_OWNERSHIP_INST(Owned, CopyBlock)
8585
CONSTANT_OWNERSHIP_INST(Owned, CopyBlockWithoutEscaping)
8686
CONSTANT_OWNERSHIP_INST(Owned, CopyValue)
8787
CONSTANT_OWNERSHIP_INST(Owned, ExplicitCopyValue)
88-
CONSTANT_OWNERSHIP_INST(Owned, MoveValue)
8988
CONSTANT_OWNERSHIP_INST(Owned, EndCOWMutation)
9089
CONSTANT_OWNERSHIP_INST(Owned, EndInitLetRef)
9190
CONSTANT_OWNERSHIP_INST(Owned, BeginDeallocRef)
@@ -212,7 +211,9 @@ CONSTANT_OR_NONE_OWNERSHIP_INST(Guaranteed, OpenExistentialBoxValue)
212211
// value).
213212
CONSTANT_OR_NONE_OWNERSHIP_INST(Owned, MarkUninitialized)
214213

215-
// unchecked_bitwise_cast is a bitwise copy. It produces a trivial or unowned
214+
// In raw SIL, a MoveValue delimits the scope of trivial variables.
215+
CONSTANT_OR_NONE_OWNERSHIP_INST(Owned, MoveValue)
216+
216217
// result.
217218
//
218219
// If the operand is nontrivial and the result is trivial, then it is the

lib/SIL/Verifier/SILOwnershipVerifier.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -607,8 +607,8 @@ bool SILValueOwnershipChecker::checkYieldWithoutLifetimeEndingUses(
607607

608608
bool SILValueOwnershipChecker::checkValueWithoutLifetimeEndingUses(
609609
ArrayRef<Operand *> regularUses, ArrayRef<Operand *> extendLifetimeUses) {
610-
if (extendLifetimeUses.size()) {
611-
}
610+
if (value->getOwnershipKind() == OwnershipKind::None)
611+
return true;
612612

613613
LLVM_DEBUG(llvm::dbgs() << "No lifetime ending users?! Bailing early.\n");
614614
if (auto *arg = dyn_cast<SILFunctionArgument>(value)) {

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2702,13 +2702,18 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
27022702
}
27032703

27042704
void checkExtendLifetimeInst(ExtendLifetimeInst *I) {
2705-
require(!I->getOperand()->getType().isTrivial(*I->getFunction()),
2706-
"Source value should be non-trivial");
27072705
require(F.hasOwnership(),
27082706
"extend_lifetime is only valid in functions with qualified "
27092707
"ownership");
2708+
// In Raw SIL, extend_lifetime marks the end of variable scopes.
2709+
if (F.getModule().getStage() == SILStage::Raw)
2710+
return;
2711+
2712+
require(!I->getOperand()->getType().isTrivial(*I->getFunction()),
2713+
"Source value should be non-trivial after diagnostics");
27102714
require(getDeadEndBlocks().isDeadEnd(I->getParent()),
2711-
"extend_lifetime in non-dead-end!?");
2715+
"extend_lifetime in non-dead-end after diagnostics");
2716+
27122717
auto value = I->getOperand();
27132718
LinearLiveness linearLiveness(value,
27142719
LinearLiveness::DoNotIncludeExtensions);
@@ -3403,7 +3408,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
34033408
void checkDestroyValueInst(DestroyValueInst *I) {
34043409
require(I->getOperand()->getType().isObject(),
34053410
"Source value should be an object value");
3406-
require(!I->getOperand()->getType().isTrivial(*I->getFunction()),
3411+
require(!I->getOperand()->getType().isTrivial(*I->getFunction())
3412+
|| I->getOperand()->isFromVarDecl(),
34073413
"Source value should be non-trivial");
34083414
require(!fnConv.useLoweredAddresses() || F.hasOwnership(),
34093415
"destroy_value is only valid in functions with qualified "
@@ -6779,6 +6785,9 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
67796785

67806786
} else if (i.isDeallocatingStack()) {
67816787
SILValue op = i.getOperand(0);
6788+
while (auto *mvi = dyn_cast<MoveValueInst>(op)) {
6789+
op = mvi->getOperand();
6790+
}
67826791
require(!state.Stack.empty(),
67836792
"stack dealloc with empty stack");
67846793
if (op != state.Stack.back()) {

0 commit comments

Comments
 (0)