Skip to content

Commit f0b811c

Browse files
committed
SIL: add the end_init_let_ref instruction
This instructions marks the point where all let-fields of a class are initialized. This is important to ensure the correctness of ``ref_element_addr [immutable]`` for let-fields, because in the initializer of a class, its let-fields are not immutable, yet.
1 parent e5eb15d commit f0b811c

File tree

27 files changed

+112
-7
lines changed

27 files changed

+112
-7
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/StripObjectHeaders.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ private struct IsBareObjectWalker : ValueDefUseWalker {
5555
is BranchInst, is CondBranchInst, is SwitchEnumInst,
5656
is UpcastInst, is UncheckedRefCastInst,
5757
is BeginDeallocRefInst,
58+
is EndInitLetRefInst,
5859
is EndCOWMutationInst:
5960
return walkDownDefault(value: operand, path: path)
6061
default:

SwiftCompilerSources/Sources/Optimizer/Utilities/AccessUtils.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ extension Value {
545545
while true {
546546
switch value {
547547
case is BeginBorrowInst, is CopyValueInst, is MoveValueInst,
548+
is EndInitLetRefInst,
548549
is BeginDeallocRefInst,
549550
is UpcastInst, is UncheckedRefCastInst, is EndCOWMutationInst:
550551
value = (value as! Instruction).operands[0].value

SwiftCompilerSources/Sources/Optimizer/Utilities/WalkUtils.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ extension ValueDefUseWalker {
349349
return unmatchedPath(value: operand, path: path)
350350
}
351351
case is BeginBorrowInst, is CopyValueInst, is MoveValueInst,
352-
is UpcastInst, is UncheckedRefCastInst, is EndCOWMutationInst,
352+
is UpcastInst, is UncheckedRefCastInst, is EndCOWMutationInst, is EndInitLetRefInst,
353353
is RefToBridgeObjectInst, is BridgeObjectToRefInst, is MarkUnresolvedNonCopyableValueInst:
354354
return walkDownUses(ofValue: (instruction as! SingleValueInstruction), path: path)
355355
case let beginDealloc as BeginDeallocRefInst:
@@ -660,7 +660,7 @@ extension ValueUseDefWalker {
660660
case let oer as OpenExistentialRefInst:
661661
return walkUp(value: oer.existential, path: path.push(.existential, index: 0))
662662
case is BeginBorrowInst, is CopyValueInst, is MoveValueInst,
663-
is UpcastInst, is UncheckedRefCastInst, is EndCOWMutationInst,
663+
is UpcastInst, is UncheckedRefCastInst, is EndCOWMutationInst, is EndInitLetRefInst,
664664
is BeginDeallocRefInst,
665665
is RefToBridgeObjectInst, is BridgeObjectToRefInst, is MarkUnresolvedNonCopyableValueInst:
666666
return walkUp(value: (def as! Instruction).operands[0].value, path: path)

SwiftCompilerSources/Sources/SIL/Builder.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,11 @@ public struct Builder {
123123
return notifyNew(beginDealloc.getAs(BeginDeallocRefInst.self))
124124
}
125125

126+
public func createEndInitLetRef(operand: Value) -> EndInitLetRefInst {
127+
let endInit = bridged.createEndInitLetRef(operand.bridged)
128+
return notifyNew(endInit.getAs(EndInitLetRefInst.self))
129+
}
130+
126131
@discardableResult
127132
public func createStrongRetain(operand: Value) -> StrongRetainInst {
128133
let retain = bridged.createStrongRetain(operand.bridged)

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,8 @@ final public class BeginDeallocRefInst : SingleValueInstruction {
309309
public var allocation: AllocRefInstBase { operands[1].value as! AllocRefInstBase }
310310
}
311311

312+
final public class EndInitLetRefInst : SingleValueInstruction, UnaryInstruction {}
313+
312314
public class RefCountingInst : Instruction, UnaryInstruction {
313315
public var isAtomic: Bool { bridged.RefCountingInst_getIsAtomic() }
314316
}

SwiftCompilerSources/Sources/SIL/Registration.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public func registerSILClasses() {
5151
register(DebugStepInst.self)
5252
register(UnconditionalCheckedCastAddrInst.self)
5353
register(BeginDeallocRefInst.self)
54+
register(EndInitLetRefInst.self)
5455
register(EndApplyInst.self)
5556
register(AbortApplyInst.self)
5657
register(StrongRetainInst.self)

docs/SIL.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5131,6 +5131,21 @@ implications and it's purpose is purly to enforce that the object allocation
51315131
is present in the same function and trivially visible from the
51325132
``begin_dealloc_ref`` instruction.
51335133

5134+
end_init_let_ref
5135+
````````````````
5136+
::
5137+
5138+
%1 = end_init_let_ref %0 : $T
5139+
// $T must be a reference type.
5140+
5141+
Marks the point where all let-fields of a class are initialized.
5142+
5143+
Returns the reference operand. Technically, the returned reference is the same
5144+
as the operand. But it's important that optimizations see the result as a
5145+
different SSA value than the operand. This is important to ensure the
5146+
correctness of ``ref_element_addr [immutable]`` for let-fields, because in the
5147+
initializer of a class, its let-fields are not immutable, yet.
5148+
51345149
strong_copy_unowned_value
51355150
`````````````````````````
51365151
::
@@ -6574,6 +6589,10 @@ is null.
65746589
The ``immutable`` attribute specifies that all loads of the same instance
65756590
variable from the same class reference operand are guaranteed to yield the
65766591
same value.
6592+
The ``immutable`` attribute is used to reference COW buffer elements after an
6593+
``end_cow_mutation`` and before a ``begin_cow_mutation``.
6594+
The attribute is also used for let-fields of a class after an
6595+
``end_init_let_ref`` and before a ``begin_dealloc_ref``.
65776596

65786597
ref_tail_addr
65796598
`````````````

include/swift/SIL/SILBridging.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,6 +1142,11 @@ struct BridgedBuilder{
11421142
return {builder().createBeginDeallocRef(regularLoc(), reference.getSILValue(), allocation.getSILValue())};
11431143
}
11441144

1145+
SWIFT_IMPORT_UNSAFE
1146+
BridgedInstruction createEndInitLetRef(BridgedValue op) const {
1147+
return {builder().createEndInitLetRef(regularLoc(), op.getSILValue())};
1148+
}
1149+
11451150
SWIFT_IMPORT_UNSAFE
11461151
BridgedInstruction createStrongRetain(BridgedValue op) const {
11471152
auto b = builder();

include/swift/SIL/SILBuilder.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,6 +1599,12 @@ class SILBuilder {
15991599
getSILDebugLocation(Loc), reference, allocation));
16001600
}
16011601

1602+
EndInitLetRefInst *createEndInitLetRef(SILLocation Loc,
1603+
SILValue operand) {
1604+
return insert(new (getModule()) EndInitLetRefInst(
1605+
getSILDebugLocation(Loc), operand));
1606+
}
1607+
16021608
ObjectInst *createObject(SILLocation Loc, SILType Ty,
16031609
ArrayRef<SILValue> Elements,
16041610
unsigned NumBaseElements) {

include/swift/SIL/SILCloner.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2130,6 +2130,15 @@ SILCloner<ImplClass>::visitBeginDeallocRefInst(BeginDeallocRefInst *Inst) {
21302130
getOpValue(Inst->getAllocation())));
21312131
}
21322132

2133+
template<typename ImplClass>
2134+
void
2135+
SILCloner<ImplClass>::visitEndInitLetRefInst(EndInitLetRefInst *Inst) {
2136+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
2137+
recordClonedInstruction(
2138+
Inst, getBuilder().createEndInitLetRef(getOpLocation(Inst->getLoc()),
2139+
getOpValue(Inst->getOperand())));
2140+
}
2141+
21332142
template<typename ImplClass>
21342143
void
21352144
SILCloner<ImplClass>::visitObjectInst(ObjectInst *Inst) {

0 commit comments

Comments
 (0)