Skip to content

Commit a354528

Browse files
Merge pull request #73155 from nate-chandler/lifetime-completion/20240419/1
[LifetimeCompletion] Don't destroy alloc_boxes.
2 parents 720ca4b + 6a01bf4 commit a354528

File tree

6 files changed

+139
-3
lines changed

6 files changed

+139
-3
lines changed

lib/SIL/Utils/OSSALifetimeCompletion.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ static SILInstruction *endOSSALifetime(SILValue value, SILBuilder &builder) {
6262
auto loc =
6363
RegularLocation::getAutoGeneratedLocation(builder.getInsertionPointLoc());
6464
if (value->getOwnershipKind() == OwnershipKind::Owned) {
65+
if (value->getType().is<SILBoxType>()) {
66+
return builder.createDeallocBox(loc, value);
67+
}
6568
return builder.createDestroyValue(loc, value);
6669
}
6770
return builder.createEndBorrow(loc, value);

lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2607,7 +2607,7 @@ void LifetimeChecker::processUninitializedRelease(SILInstruction *Release,
26072607
// If we see an alloc_box as the pointer, then we're deallocating a 'box' for
26082608
// self. Make sure that the box gets deallocated (not released) since the
26092609
// pointer it contains will be manually cleaned up.
2610-
auto *MUI = dyn_cast<MarkUninitializedInst>(Release->getOperand(0));
2610+
auto *MUI = dyn_cast<MarkUninitializedInst>(Pointer);
26112611

26122612
if (MUI && isa<AllocBoxInst>(MUI->getOperand())) {
26132613
Pointer = MUI->getSingleUserOfType<ProjectBoxInst>();
@@ -2642,6 +2642,12 @@ void LifetimeChecker::processUninitializedRelease(SILInstruction *Release,
26422642
}
26432643
}
26442644

2645+
// Cast back down from an upcast.
2646+
if (auto *UI = dyn_cast<UpcastInst>(Pointer)) {
2647+
Pointer =
2648+
B.createUncheckedRefCast(Loc, Pointer, UI->getOperand()->getType());
2649+
}
2650+
26452651
// We've already destroyed any instance variables initialized by this
26462652
// constructor, now destroy instance variables initialized by subclass
26472653
// constructors that delegated to us, and finally free the memory.

test/SILOptimizer/definite_init.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,15 @@ class AgainCheckCompilerInitAttr {
7676
whenever = 0
7777
} // expected-error {{return from initializer without initializing all stored properties}}
7878
}
79+
80+
class Super {
81+
init(_ i: Int) {}
82+
}
83+
84+
class Sub : Super {
85+
init() {
86+
super.init(try! get())
87+
}
88+
}
89+
90+
func get() throws -> Int { 0 }
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -definite-init -raw-sil-inst-lowering | %FileCheck %s
2+
3+
// These are all regression tests to ensure that the memory promotion pass
4+
// doesn't crash.
5+
6+
// REQUIRES: objc_interop
7+
8+
import Builtin
9+
import Swift
10+
import Foundation
11+
12+
sil @$ss30_diagnoseUnexpectedNilOptional14_filenameStart01_E6Length01_E7IsASCII5_line17_isImplicitUnwrapyBp_BwBi1_BwBi1_tF : $@convention(thin) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, Builtin.Word, Builtin.Int1) -> ()
13+
sil @superinit : $@convention(method) (@in Any, @owned Super) -> @owned Super
14+
sil [exact_self_class] [ossa] @$s4main5SuperCyACypcfC : $@convention(method) (@in Any, @thick Super.Type) -> @owned Super
15+
sil [ossa] @$s4main5SuperCfD : $@convention(method) (@owned Super) -> ()
16+
sil [ossa] @$s4main3SubCfD : $@convention(method) (@owned Sub) -> ()
17+
sil [exact_self_class] [ossa] @$s4main3SubCyACSo8NSStringCcfC : $@convention(method) (@owned NSString, @thick Sub.Type) -> @owned Sub
18+
19+
class Super {
20+
var t: Any
21+
init(_ t: Any) {
22+
self.t = t
23+
}
24+
}
25+
26+
class Sub : Super {
27+
init(_ i: NSString) {
28+
super.init(i.lowercased as NSString)
29+
}
30+
}
31+
32+
33+
// CHECK-LABEL: sil hidden [ossa] @cast_to_nsstring : {{.*}} {
34+
// CHECK: [[STACK:%[^,]+]] = alloc_stack
35+
// CHECK: [[SUB_1:%[^,]+]] = load [take] [[STACK]]
36+
// CHECK: [[SUPER_1:%[^,]+]] = upcast [[SUB_1]] : $Sub to $Super
37+
// CHECK: switch_enum
38+
// CHECK-SAME: case #Optional.none!enumelt: [[NONE:bb[0-9]+]]
39+
// CHECK: [[NONE]]:
40+
// CHECK: [[SUB_META_1:%[^,]+]] = metatype $@thick Sub.Type
41+
// CHECK: [[SUB_1:%[^,]+]] = unchecked_ref_cast [[SUPER_1]] : $Super to $Sub
42+
// CHECK: dealloc_partial_ref
43+
// CHECK-SAME: [[SUB_1]]
44+
// CHECK-SAME: [[SUB_META_1]]
45+
// CHECK: [[SUB_1:%[^,]+]] = load [take] [[STACK]]
46+
// CHECK: [[SUB_META_1:%[^,]+]] = metatype $@thick Sub.Type
47+
// CHECK: dealloc_partial_ref
48+
// CHECK-SAME: [[SUB_1]]
49+
// CHECK-SAME: [[SUB_META_1]]
50+
// CHECK-LABEL: } // end sil function 'cast_to_nsstring'
51+
sil hidden [ossa] @cast_to_nsstring : $@convention(method) (@owned NSString, @owned Sub) -> @owned Sub {
52+
bb0(%0 : @owned $NSString, %1 : @owned $Sub):
53+
%2 = alloc_stack [lexical] [var_decl] $Sub
54+
%3 = mark_uninitialized [derivedself] %2 : $*Sub
55+
store %1 to [init] %3 : $*Sub
56+
%6 = load [take] %3 : $*Sub
57+
%7 = upcast %6 : $Sub to $Super
58+
%8 = alloc_stack $Any
59+
%9 = objc_method %0 : $NSString, #NSString.lowercased!getter.foreign : (NSString) -> () -> String, $@convention(objc_method) (NSString) -> @autoreleased Optional<NSString>
60+
%10 = apply %9(%0) : $@convention(objc_method) (NSString) -> @autoreleased Optional<NSString>
61+
switch_enum %10 : $Optional<NSString>, case #Optional.some!enumelt: bb2, case #Optional.none!enumelt: bb1
62+
63+
bb1:
64+
destroy_value %7 : $Super
65+
%13 = string_literal utf8 "main/main.swift"
66+
%14 = integer_literal $Builtin.Word, 15
67+
%15 = integer_literal $Builtin.Int1, -1
68+
%16 = integer_literal $Builtin.Word, 14
69+
%17 = integer_literal $Builtin.Word, 18
70+
%18 = integer_literal $Builtin.Int1, -1
71+
%19 = function_ref @$ss30_diagnoseUnexpectedNilOptional14_filenameStart01_E6Length01_E7IsASCII5_line17_isImplicitUnwrapyBp_BwBi1_BwBi1_tF : $@convention(thin) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, Builtin.Word, Builtin.Int1) -> ()
72+
%20 = apply %19(%13, %14, %15, %16, %18) : $@convention(thin) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, Builtin.Word, Builtin.Int1) -> ()
73+
destroy_addr %3 : $*Sub
74+
destroy_value %0 : $NSString
75+
unreachable
76+
77+
bb2(%24 : @owned $NSString):
78+
%25 = init_existential_addr %8 : $*Any, $NSString
79+
store %24 to [init] %25 : $*NSString
80+
%27 = function_ref @superinit : $@convention(method) (@in Any, @owned Super) -> @owned Super
81+
%28 = apply %27(%8, %7) : $@convention(method) (@in Any, @owned Super) -> @owned Super
82+
dealloc_stack %8 : $*Any
83+
%30 = unchecked_ref_cast %28 : $Super to $Sub
84+
store %30 to [init] %3 : $*Sub
85+
%32 = load [copy] %3 : $*Sub
86+
destroy_value %0 : $NSString
87+
destroy_addr %3 : $*Sub
88+
dealloc_stack %2 : $*Sub
89+
return %32 : $Sub
90+
}
91+
92+
sil_vtable Super {
93+
#Super.init!allocator: (Super.Type) -> (Any) -> Super : @$s4main5SuperCyACypcfC
94+
#Super.deinit!deallocator: @$s4main5SuperCfD
95+
}
96+
97+
sil_vtable Sub {
98+
#Sub.init!allocator: (Sub.Type) -> (NSString) -> Sub : @$s4main3SubCyACSo8NSStringCcfC
99+
#Sub.deinit!deallocator: @$s4main3SubCfD
100+
}

test/SILOptimizer/ossa_lifetime_completion.sil

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ indirect enum IndirectEnumNontrivialPayload {
445445
// CHECK: cond_br undef, {{bb[0-9]+}}, [[BASIC_BLOCK4:bb[0-9]+]]
446446
// CHECK: [[BASIC_BLOCK4]]:
447447
// CHECK: end_borrow [[C]]
448-
// CHECK: destroy_value [[BOX]]
448+
// CHECK: dealloc_box [[BOX]]
449449
// CHECK: unreachable
450450
// CHECK-LABEL: } // end sil function 'project_box_owned'
451451
sil [ossa] @project_box_owned : $@convention(thin) (@owned IndirectEnumNontrivialPayload) -> () {
@@ -498,3 +498,18 @@ bb0:
498498
dealloc_stack %result_addr : $*()
499499
return %retval : $()
500500
}
501+
502+
// CHECK-LABEL: begin running test {{.*}} on alloc_box: ossa-lifetime-completion
503+
// CHECK-LABEL: sil [ossa] @alloc_box : {{.*}} {
504+
// CHECK: [[BOX:%[^,]+]] = alloc_box
505+
// CHECK: dealloc_box [[BOX]]
506+
// CHECK-LABEL: } // end sil function 'alloc_box'
507+
// CHECK-LABEL: end running test {{.*}} on alloc_box: ossa-lifetime-completion
508+
sil [ossa] @alloc_box : $@convention(thin) (@owned C) -> () {
509+
entry(%instance : @owned $C):
510+
%box = alloc_box ${ var C }
511+
specify_test "ossa-lifetime-completion %box"
512+
%addr = project_box %box : ${ var C }, 0
513+
store %instance to [init] %addr : $*C
514+
unreachable
515+
}

test/SILOptimizer/silgen_cleanup_complete_ossa.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ sil @unreachableHandler : $@convention(thin) () -> ()
3838
// CHECK: bb2:
3939
// CHECK: apply
4040
// CHECK: end_borrow [[BORROW]] : ${ var FakeOptional<Klass> }
41-
// CHECK: destroy_value [[BOX]] : ${ var FakeOptional<Klass> }
41+
// CHECK: dealloc_box [[BOX]] : ${ var FakeOptional<Klass> }
4242
// CHECK: unreachable
4343
sil [ossa] @testCompleteOSSALifetimes : $@convention(thin) (@owned FakeOptional<Klass>) -> () {
4444
bb0(%0 : @owned $FakeOptional<Klass>):

0 commit comments

Comments
 (0)