Skip to content

Commit 17fa484

Browse files
committed
SILGen. Fix temporary LValue cleanup.
Use the LValue formal evaluation scope to destroy temporary lvalues that aren't part of the expression's resulting value. Disable an old hack that destroyed call site arguments after the call. This is the first step in cleanup up LValue materialization.
1 parent 73bf2df commit 17fa484

9 files changed

+31
-39
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,25 +1615,6 @@ static SILValue emitRawApply(SILGenFunction &SGF,
16151615
normalBB, errorBB);
16161616
SGF.B.emitBlock(normalBB);
16171617
}
1618-
1619-
// Given any guaranteed arguments that are not being passed at +0, insert the
1620-
// decrement here instead of at the end of scope. Guaranteed just means that
1621-
// we guarantee the lifetime of the object for the duration of the call.
1622-
// Be sure to use a CleanupLocation so that unreachable code diagnostics don't
1623-
// trigger.
1624-
for (auto i : indices(args)) {
1625-
if (!inputParams[i].isGuaranteed() || args[i].isPlusZeroRValueOrTrivial())
1626-
continue;
1627-
1628-
SILValue argValue = args[i].forward(SGF);
1629-
SILType argType = argValue->getType();
1630-
CleanupLocation cleanupLoc = CleanupLocation::get(loc);
1631-
if (!argType.isAddress())
1632-
SGF.getTypeLowering(argType).emitDestroyRValue(SGF.B, cleanupLoc, argValue);
1633-
else
1634-
SGF.getTypeLowering(argType).emitDestroyAddress(SGF.B, cleanupLoc, argValue);
1635-
}
1636-
16371618
return result;
16381619
}
16391620

lib/SILGen/SILGenLValue.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2104,7 +2104,20 @@ static ManagedValue visitRecNonInOutBase(SILGenLValue &SGL, Expr *e,
21042104
ctx = SGFContext::AllowGuaranteedPlusZero;
21052105
}
21062106

2107-
return SGF.emitRValueAsSingleValue(e, ctx);
2107+
ManagedValue mv = SGF.emitRValueAsSingleValue(e, ctx);
2108+
if (mv.isPlusZeroRValueOrTrivial())
2109+
return mv;
2110+
2111+
// Any temporaries needed to materialize the lvalue must be destroyed when
2112+
// at the end of the lvalue's formal evaluation scope.
2113+
// e.g. for foo(self.bar)
2114+
// %self = load [copy] %ptr_self
2115+
// %rvalue = barGetter(%self)
2116+
// destroy_value %self // self must be released before calling foo.
2117+
// foo(%rvalue)
2118+
SILValue value = mv.forward(SGF);
2119+
return SGF.emitFormalAccessManagedRValueWithCleanup(CleanupLocation(e),
2120+
value);
21082121
}
21092122

21102123
LValue SILGenLValue::visitRec(Expr *e, AccessKind accessKind,

test/SILGen/borrow.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ func useD(_ d: D) {}
2323
// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[OFFSET]] : $*D
2424
// CHECK: [[LOADED_VALUE:%.*]] = load [copy] [[ACCESS]]
2525
// CHECK: end_borrow [[BORROWED_CLASS]] from [[CLASS]]
26+
// CHECK: destroy_value [[CLASS]]
2627
// CHECK: [[FUNC:%.*]] = function_ref @_T06borrow4useD{{.*}} : $@convention(thin) (@owned D) -> ()
2728
// CHECK: apply [[FUNC]]([[LOADED_VALUE]])
28-
// CHECK: destroy_value [[CLASS]]
2929
// CHECK: destroy_value [[BOX]]
3030
// CHECK: } // end sil function '_T06borrow44lvalueBorrowShouldBeAtEndOfFormalAccessScope{{.*}}'
3131
func lvalueBorrowShouldBeAtEndOfFormalAccessScope() {

test/SILGen/class_bound_protocols.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,7 @@ func takesInheritsMutatingMethod(x: inout InheritsMutatingMethod,
204204
//
205205
// CHECK-NEXT: [[METHOD:%.*]] = witness_method $@opened("{{.*}}") InheritsMutatingMethod, #HasMutatingMethod.mutatingCounter!getter.1 : <Self where Self : HasMutatingMethod> (Self) -> () -> Value, [[X_PAYLOAD]] : $@opened("{{.*}}") InheritsMutatingMethod : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (@in_guaranteed τ_0_0) -> Value
206206
// CHECK-NEXT: [[RESULT_VALUE:%.*]] = apply [[METHOD]]<@opened("{{.*}}") InheritsMutatingMethod>([[TEMPORARY_2]]) : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (@in_guaranteed τ_0_0) -> Value
207-
// CHECK-NEXT: [[X_VALUE:%.*]] = load [take] [[TEMPORARY_2]] : $*@opened("{{.*}}") InheritsMutatingMethod
208-
// CHECK-NEXT: destroy_value [[X_VALUE]] : $@opened("{{.*}}") InheritsMutatingMethod
207+
// CHECK-NEXT: destroy_addr [[TEMPORARY_2]] : $*@opened("{{.*}}") InheritsMutatingMethod
209208
// CHECK-NEXT: dealloc_stack [[TEMPORARY_2]]
210209
// CHECK-NEXT: end_access [[X_ADDR]] : $*InheritsMutatingMethod
211210
// CHECK-NEXT: assign [[RESULT_VALUE]] to [[RESULT]] : $*Value

test/SILGen/objc_ownership_conventions.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,9 @@ func test10(_ g: Gizmo) -> AnyClass {
147147
// CHECK: [[SOME_BB]]([[OBJC:%.*]] : @trivial $@objc_metatype AnyObject.Type):
148148
// CHECK-NEXT: [[THICK:%.*]] = objc_to_thick_metatype [[OBJC]]
149149
// CHECK: [[T0:%.*]] = enum $Optional<@thick AnyObject.Type>, #Optional.some!enumelt.1, [[THICK]]
150-
// CHECK: bb5([[RES:%.*]] : @trivial $@thick AnyObject.Type):
150+
// CHECK: bb{{.*}}(%{{.*}} : @trivial $Optional<@thick AnyObject.Type>):
151151
// CHECK: destroy_value [[NS_G_COPY]] : $NSObject
152+
// CHECK: bb{{.*}}([[RES:%.*]] : @trivial $@thick AnyObject.Type):
152153
// CHECK: destroy_value [[G]] : $Gizmo
153154
// CHECK-NEXT: return [[RES]] : $@thick AnyObject.Type
154155
return g.classProp
@@ -167,10 +168,11 @@ func test11(_ g: Gizmo) -> AnyClass {
167168
// CHECK: [[SOME_BB]]([[OBJC:%.*]] : @trivial $@objc_metatype NSAnsing.Type):
168169
// CHECK-NEXT: [[THICK:%.*]] = objc_to_thick_metatype [[OBJC]]
169170
// CHECK: [[T0:%.*]] = enum $Optional<@thick NSAnsing.Type>, #Optional.some!enumelt.1, [[THICK]]
170-
// CHECK: bb5([[RES:%.*]] : @trivial $@thick NSAnsing.Type):
171+
// CHECK: bb{{.*}}(%{{.*}} : @trivial $Optional<@thick NSAnsing.Type>):
172+
// CHECK: destroy_value [[NS_G_COPY]] : $NSObject
173+
// CHECK: bb{{.*}}([[RES:%.*]] : @trivial $@thick NSAnsing.Type):
171174
// CHECK: [[OPENED:%.*]] = open_existential_metatype [[RES]]
172175
// CHECK: [[RES_ANY:%.*]] = init_existential_metatype [[OPENED]]
173-
// CHECK: destroy_value [[NS_G_COPY]] : $NSObject
174176
// CHECK: destroy_value [[G]] : $Gizmo
175177
// CHECK-NEXT: return [[RES_ANY]] : $@thick AnyObject.Type
176178
return g.qualifiedClassProp

test/SILGen/properties.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,15 +1186,16 @@ protocol NonmutatingProtocol {
11861186
// CHECK-NEXT: [[C_FIELD_BOX:%.*]] = alloc_stack $NonmutatingProtocol
11871187
// CHECK-NEXT: [[GETTER:%.*]] = class_method [[C]] : $ReferenceType, #ReferenceType.p!getter.1 : (ReferenceType) -> () -> NonmutatingProtocol, $@convention(method) (@guaranteed ReferenceType) -> @out NonmutatingProtocol
11881188
// CHECK-NEXT: apply [[GETTER]]([[C_FIELD_BOX]], [[C]]) : $@convention(method) (@guaranteed ReferenceType) -> @out NonmutatingProtocol
1189-
// CHECK-NEXT: destroy_value [[C]] : $ReferenceType
1189+
11901190
// CHECK-NEXT: [[C_FIELD_PAYLOAD:%.*]] = open_existential_addr immutable_access [[C_FIELD_BOX]] : $*NonmutatingProtocol to $*@opened("{{.*}}") NonmutatingProtocol
11911191
// CHECK-NEXT: [[C_FIELD_COPY:%.*]] = alloc_stack $@opened("{{.*}}") NonmutatingProtocol
11921192
// CHECK-NEXT: copy_addr [[C_FIELD_PAYLOAD]] to [initialization] [[C_FIELD_COPY]] : $*@opened("{{.*}}") NonmutatingProtocol
11931193
// CHECK-NEXT: destroy_addr [[C_FIELD_BOX]] : $*NonmutatingProtocol
1194+
// CHECK-NEXT: destroy_value [[C]] : $ReferenceType
11941195
// CHECK-NEXT: [[GETTER:%.*]] = witness_method $@opened("{{.*}}") NonmutatingProtocol, #NonmutatingProtocol.x!getter.1 : <Self where Self : NonmutatingProtocol> (Self) -> () -> Int, [[C_FIELD_PAYLOAD]] : $*@opened("{{.*}}") NonmutatingProtocol : $@convention(witness_method: NonmutatingProtocol) <τ_0_0 where τ_0_0 : NonmutatingProtocol> (@in_guaranteed τ_0_0) -> Int
11951196
// CHECK-NEXT: [[RESULT_VALUE:%.*]] = apply [[GETTER]]<@opened("{{.*}}") NonmutatingProtocol>([[C_FIELD_COPY]]) : $@convention(witness_method: NonmutatingProtocol) <τ_0_0 where τ_0_0 : NonmutatingProtocol> (@in_guaranteed τ_0_0) -> Int
1196-
// CHECK-NEXT: destroy_addr [[C_FIELD_COPY]] : $*@opened("{{.*}}") NonmutatingProtocol
11971197
// CHECK-NEXT: assign [[RESULT_VALUE]] to [[UNINIT]] : $*Int
1198+
// CHECK-NEXT: destroy_addr [[C_FIELD_COPY]] : $*@opened("{{.*}}") NonmutatingProtocol
11981199
// CHECK-NEXT: dealloc_stack [[C_FIELD_COPY]] : $*@opened("{{.*}}") NonmutatingProtocol
11991200
// CHECK-NEXT: dealloc_stack [[C_FIELD_BOX]] : $*NonmutatingProtocol
12001201
// CHECK-NEXT: dealloc_stack [[RESULT]] : $*Int

test/SILGen/protocol_class_refinement.swift

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ func getObjectUID<T: ObjectUID>(x: T) -> (Int, Int, Int, Int) {
3737
// CHECK: store [[X]] to [init] [[X_TMP]]
3838
// CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
3939
// CHECK: [[UID:%.*]] = apply [[GET_UID]]<T>([[X_TMP]])
40-
// CHECK: [[X2:%.*]] = load [take] [[X_TMP]]
41-
// CHECK: destroy_value [[X2]]
40+
// CHECK: destroy_addr [[X_TMP]]
4241
// -- call set x.clsid
4342
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]] : $*T
4443
// CHECK: [[SET_CLSID:%.*]] = witness_method $T, #UID.clsid!setter.1
@@ -52,8 +51,7 @@ func getObjectUID<T: ObjectUID>(x: T) -> (Int, Int, Int, Int) {
5251
// CHECK: store [[X]] to [init] [[X_TMP]]
5352
// CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
5453
// CHECK: [[UID:%.*]] = apply [[GET_UID]]<T>([[X_TMP]])
55-
// CHECK: [[X2:%.*]] = load [take] [[X_TMP]]
56-
// CHECK: destroy_value [[X2]]
54+
// CHECK: destroy_addr [[X_TMP]]
5755
// -- call nextCLSID from protocol ext
5856
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]] : $*T
5957
// CHECK: [[SET_NEXTCLSID:%.*]] = function_ref @_T025protocol_class_refinement3UIDPAAE9nextCLSIDSivs
@@ -71,8 +69,7 @@ func getObjectUID<T: ObjectUID>(x: T) -> (Int, Int, Int, Int) {
7169

7270
// CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
7371
// CHECK: [[UID:%.*]] = apply [[GET_UID]]<T>([[X_TMP]])
74-
// CHECK: [[X2:%.*]] = load [take] [[X_TMP]]
75-
// CHECK: destroy_value [[X2]]
72+
// CHECK: destroy_addr [[X_TMP]]
7673
// -- call secondNextCLSID from class-constrained protocol ext
7774
// CHECK: [[SET_SECONDNEXT:%.*]] = function_ref @_T025protocol_class_refinement9ObjectUIDPAAE15secondNextCLSIDSivs
7875
// CHECK: apply [[SET_SECONDNEXT]]<T>([[UID]], [[BORROWED_X1]])
@@ -96,8 +93,7 @@ func getBaseObjectUID<T: UID where T: Base>(x: T) -> (Int, Int, Int) {
9693
// CHECK: store [[X]] to [init] [[X_TMP]]
9794
// CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
9895
// CHECK: [[UID:%.*]] = apply [[GET_UID]]<T>([[X_TMP]])
99-
// CHECK: [[X2:%.*]] = load [take] [[X_TMP]]
100-
// CHECK: destroy_value [[X2]]
96+
// CHECK: destroy_addr [[X_TMP]]
10197
// -- call set x.clsid
10298
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]] : $*T
10399
// CHECK: [[SET_CLSID:%.*]] = witness_method $T, #UID.clsid!setter.1
@@ -111,8 +107,7 @@ func getBaseObjectUID<T: UID where T: Base>(x: T) -> (Int, Int, Int) {
111107
// CHECK: store [[X]] to [init] [[X_TMP]]
112108
// CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
113109
// CHECK: [[UID:%.*]] = apply [[GET_UID]]<T>([[X_TMP]])
114-
// CHECK: [[X2:%.*]] = load [take] [[X_TMP]]
115-
// CHECK: destroy_value [[X2]]
110+
// CHECK: destroy_addr [[X_TMP]]
116111
// -- call nextCLSID from protocol ext
117112
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]] : $*T
118113
// CHECK: [[SET_NEXTCLSID:%.*]] = function_ref @_T025protocol_class_refinement3UIDPAAE9nextCLSIDSivs

test/SILGen/protocol_extensions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -509,8 +509,8 @@ func testExistentials1(_ p1: P1, b: Bool, i: Int64) {
509509
// CHECK: copy_addr [[POPENED]] to [initialization] [[POPENED_COPY:%.*]] :
510510
// CHECK: [[GETTER:%[0-9]+]] = function_ref @_T019protocol_extensions2P1PAAEySbs5Int64Vcig
511511
// CHECK: apply [[GETTER]]<@opened([[UUID]]) P1>([[I]], [[POPENED_COPY]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (Int64, @in_guaranteed τ_0_0) -> Bool
512-
// CHECK: destroy_addr [[POPENED_COPY]]
513512
// CHECK: store{{.*}} : $*Bool
513+
// CHECK: destroy_addr [[POPENED_COPY]]
514514
// CHECK: dealloc_stack [[POPENED_COPY]]
515515
var b2 = p1[i]
516516

test/SILGen/protocols.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ func testExistentialPropertyRead<T: ExistentialProperty>(_ t: inout T) {
386386
// CHECK-NEXT: copy_addr [[OPEN]] to [initialization] [[T0]]
387387
// CHECK-NEXT: [[B_GETTER:%.*]] = witness_method $[[P_OPENED]], #PropertyWithGetterSetter.b!getter.1
388388
// CHECK-NEXT: apply [[B_GETTER]]<[[P_OPENED]]>([[T0]])
389+
// CHECK-NEXT: debug_value
389390
// CHECK-NEXT: destroy_addr [[T0]]
390391
// CHECK-NOT: witness_method
391392
// CHECK: return

0 commit comments

Comments
 (0)