Skip to content

Commit 6f86052

Browse files
committed
Fix unidentified LifetimeDependence.Scope initialization.
Fixes rdar://149226564 (Compiler crash with non-escapable storing another non-escapable and having a deinit)
1 parent 62454f4 commit 6f86052

File tree

3 files changed

+64
-1
lines changed

3 files changed

+64
-1
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/LifetimeDependenceUtils.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,10 @@ extension LifetimeDependence.Scope {
279279
case let .box(projectBox):
280280
// Note: the box may be in a borrow scope.
281281
self.init(base: projectBox.operand.value, context)
282-
case .stack, .class, .tail, .pointer, .index, .unidentified:
282+
case .stack, .class, .tail, .pointer, .index:
283283
self = .unknown(accessBase.address!)
284+
case .unidentified:
285+
self = .unknown(address)
284286
case .global:
285287
// TODO: When AccessBase directly stores GlobalAccessBase, we don't need a check here and don't need to pass
286288
// 'address' in to this function.

SwiftCompilerSources/Sources/SIL/Utilities/AccessUtils.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ public enum AccessBase : CustomStringConvertible, Hashable {
8989

9090
/// The access base is some SIL pattern which does not fit into any other case.
9191
/// This should be a very rare situation.
92+
///
93+
/// TODO: unidentified should preserve its base address value, but AccessBase must be Hashable.
9294
case unidentified
9395

9496
public init(baseAddress: Value) {

test/SILOptimizer/lifetime_dependence/scope_fixup.sil

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,22 @@ struct A {
4747
init()
4848
}
4949

50+
struct B: ~Copyable, ~Escapable {
51+
let ne: NE
52+
53+
deinit
54+
}
55+
5056
struct Holder {
5157
var object: AnyObject
5258
}
5359

5460
@_addressableForDependencies
5561
struct AddressableForDeps {}
5662

63+
sil @getNEPointerToA : $@convention(thin) (@guaranteed NE) -> UnsafePointer<A>
64+
sil @useA : $@convention(thin) (A) -> ()
65+
5766
sil @getPtr : $@convention(thin) () -> @out UnsafeRawPointer
5867
sil @getSpan : $@convention(thin) (@in_guaranteed AnyObject) -> @lifetime(borrow 0) @out NE
5968

@@ -380,3 +389,53 @@ bb0:
380389
%99 = tuple ()
381390
return %99
382391
}
392+
393+
// =============================================================================
394+
// Reduced bugs
395+
// =============================================================================
396+
397+
// rdar149226564 (Compiler crash with non-escapable storing another non-escapable and having a deinit)
398+
//
399+
// Test that initializing LifetimeDependence.Scope from an unidentified enclosing access scope does not
400+
// unwrap nil.
401+
//
402+
// TODO: the mark_dependence should redirect to the drop_deinit, not the struct_element_addr, but AccessBase does not
403+
// currently preserve the address of an unidentified base.
404+
//
405+
// CHECK-LABEL: sil hidden [ossa] @testUnidentified : $@convention(method) (@owned B) -> () {
406+
// CHECK: [[DD:%.*]] = drop_deinit
407+
// CHECK: [[SE:%.*]] = struct_element_addr [[DD]], #B.ne
408+
// CHECK: [[LB:%.*]] = load_borrow
409+
// CHECK: apply %{{.*}} : $@convention(thin) (@guaranteed NE) -> UnsafePointer<A>
410+
// CHECK: mark_dependence [unresolved] %{{.*}} on [[SE]]
411+
// CHECK-LABEL: } // end sil function 'testUnidentified'
412+
sil hidden [ossa] @testUnidentified : $@convention(method) (@owned B) -> () {
413+
bb0(%0 : @owned $B):
414+
%1 = alloc_stack $B, let, name "self", argno 1
415+
%2 = mark_unresolved_non_copyable_value [consumable_and_assignable] %1
416+
store %0 to [init] %2
417+
%4 = drop_deinit %2
418+
debug_value %4, let, name "self", argno 1, expr op_deref
419+
%6 = struct_element_addr %4, #B.ne
420+
%7 = load_borrow %6
421+
422+
%8 = function_ref @getNEPointerToA : $@convention(thin) (@guaranteed NE) -> UnsafePointer<A>
423+
%9 = apply %8(%7) : $@convention(thin) (@guaranteed NE) -> UnsafePointer<A>
424+
%10 = struct_extract %9, #UnsafePointer._rawValue
425+
%11 = pointer_to_address %10 to [strict] $*A
426+
%12 = mark_dependence [unresolved] %11 on %7
427+
%13 = begin_access [read] [unsafe] %12
428+
%14 = load [trivial] %13
429+
end_access %13
430+
431+
%16 = function_ref @useA : $@convention(thin) (A) -> ()
432+
%17 = apply %16(%14) : $@convention(thin) (A) -> ()
433+
end_borrow %7
434+
%19 = struct_element_addr %4, #B.ne
435+
%20 = begin_access [deinit] [static] %19
436+
destroy_addr %20
437+
end_access %20
438+
dealloc_stack %1
439+
%24 = tuple ()
440+
return %24
441+
}

0 commit comments

Comments
 (0)