Files
swift-mirror/test/SIL/memory_lifetime.sil
2024-04-03 10:30:55 -07:00

809 lines
26 KiB
Plaintext

// RUN: %target-sil-opt -o /dev/null %s
// REQUIRES: asserts
// REQUIRES: swift_in_compiler
sil_stage canonical
import Builtin
import Swift
import SwiftShims
// A non-trivial type
class T {
init()
}
struct Inner {
var a: T
var b: T
}
struct Outer {
var x: T
var y: Inner
var z: T
var i: Int
}
struct Mixed {
var t: T
var i: Int
}
enum KlassOrBool {
case value(T)
case bool(Bool)
}
sil [ossa] @test_struct : $@convention(thin) (@in Outer) -> @owned T {
bb0(%0 : $*Outer):
%1 = struct_element_addr %0 : $*Outer, #Outer.y
%2 = struct_element_addr %0 : $*Outer, #Outer.x
%10 = struct_element_addr %0 : $*Outer, #Outer.z
%3 = load [copy] %2 : $*T
br bb1
bb1:
cond_br undef, bb2, bb6
bb2:
cond_br undef, bb3, bb4
bb3:
%4 = struct_element_addr %1 : $*Inner, #Inner.a
%5 = copy_value %3 : $T
store %5 to [assign] %4 : $*T
br bb5
bb4:
%6 = struct_element_addr %0 : $*Outer, #Outer.y
%7 = struct_element_addr %6 : $*Inner, #Inner.b
destroy_addr %7 : $*T
%8 = copy_value %3 : $T
store %8 to [init] %7 : $*T
br bb5
bb5:
br bb1
bb6:
destroy_addr %1 : $*Inner
destroy_addr %2 : $*T
destroy_addr %10 : $*T
return %3 : $T
}
sil [ossa] @test_struct2 : $@convention(thin) (@in Outer, @owned T) -> () {
bb0(%0 : $*Outer, %1 : @owned $T):
%2 = struct_element_addr %0 : $*Outer, #Outer.x
store %1 to [assign] %2 : $*T
destroy_addr %0 : $*Outer
%3 = tuple ()
return %3 : $()
}
sil @throwing_func : $@convention(thin) () -> (@out T, @error Error)
sil [ossa] @test_try_apply : $@convention(thin) () -> (@out T, @error Error) {
bb0(%0 : $*T):
%1 = function_ref @throwing_func : $@convention(thin) () -> (@out T, @error Error)
try_apply %1(%0) : $@convention(thin) () -> (@out T, @error Error), normal bb1, error bb2
bb1(%2 : $()):
%3 = tuple ()
return %3 : $()
bb2(%4 : @owned $Error):
throw %4 : $Error
}
sil [ossa] @test_alloc_stack_simple : $@convention(thin) (@in_guaranteed T) -> () {
bb0(%0 : $*T):
%2 = alloc_stack $T
copy_addr %0 to [init] %2 : $*T
br bb1
bb1:
destroy_addr %2 : $*T
dealloc_stack %2 : $*T
%r = tuple ()
return %r : $()
}
sil [ossa] @test_alloc_stack_nested : $@convention(thin) (@in_guaranteed T) -> () {
bb0(%0 : $*T):
%1 = alloc_stack $T
copy_addr %0 to [init] %1 : $*T
%2 = alloc_stack $T
copy_addr %0 to [init] %2 : $*T
destroy_addr %2 : $*T
dealloc_stack %2 : $*T
cond_br undef, bb1, bb2
bb1:
%3 = alloc_stack $T
%4 = alloc_stack $T
copy_addr %0 to [init] %3 : $*T
copy_addr %0 to [init] %4 : $*T
destroy_addr %3 : $*T
destroy_addr %4 : $*T
dealloc_stack %4 : $*T
dealloc_stack %3 : $*T
br bb3
bb2:
br bb3
bb3:
destroy_addr %1 : $*T
dealloc_stack %1 : $*T
%r = tuple ()
return %r : $()
}
sil [ossa] @test_unreachable_block : $@convention(thin) (@owned T) -> () {
bb0(%0 : @owned $T):
%2 = alloc_stack $T
store %0 to [init] %2 : $*T
br bb2
bb1:
br bb2
bb2:
destroy_addr %2 : $*T
dealloc_stack %2 : $*T
%r = tuple ()
return %r : $()
}
sil [ossa] @test_mixed_cfg_merge : $@convention(thin) (@owned T, Int) -> () {
bb0(%0 : @owned $T, %1 : $Int):
%2 = alloc_stack $Mixed
%3 = struct_element_addr %2 : $*Mixed, #Mixed.t
%4 = struct_element_addr %2 : $*Mixed, #Mixed.i
store %0 to [init] %3 : $*T
cond_br undef, bb1, bb2
bb1:
store %1 to [trivial] %4 : $*Int
br bb3
bb2:
br bb3
bb3:
destroy_addr %2 : $*Mixed
dealloc_stack %2 : $*Mixed
%r = tuple ()
return %r : $()
}
sil [ossa] @test_many_locations_in_block : $@convention(thin) <A, B, C, D, E, G, H, I> (@in_guaranteed A, @in_guaranteed B, @in_guaranteed C, @in_guaranteed D, @in_guaranteed E, @in_guaranteed G, @in_guaranteed H, @in_guaranteed I) -> (@out A, @out B, @out C, @out D, @out E, @out G, @out H, @out I) {
bb0(%0 : $*A, %1 : $*B, %2 : $*C, %3 : $*D, %4 : $*E, %5 : $*G, %6 : $*H, %7 : $*I, %9 : $*A, %10 : $*B, %11 : $*C, %12 : $*D, %13 : $*E, %14 : $*G, %15 : $*H, %16 : $*I):
%18 = alloc_stack $(A, B, C, D, E, G, H, I), let, name "a", argno 1
%19 = tuple_element_addr %18 : $*(A, B, C, D, E, G, H, I), 0
copy_addr %9 to [init] %19 : $*A
%21 = tuple_element_addr %18 : $*(A, B, C, D, E, G, H, I), 1
copy_addr %10 to [init] %21 : $*B
%23 = tuple_element_addr %18 : $*(A, B, C, D, E, G, H, I), 2
copy_addr %11 to [init] %23 : $*C
%25 = tuple_element_addr %18 : $*(A, B, C, D, E, G, H, I), 3
copy_addr %12 to [init] %25 : $*D
%27 = tuple_element_addr %18 : $*(A, B, C, D, E, G, H, I), 4
copy_addr %13 to [init] %27 : $*E
%29 = tuple_element_addr %18 : $*(A, B, C, D, E, G, H, I), 5
copy_addr %14 to [init] %29 : $*G
%31 = tuple_element_addr %18 : $*(A, B, C, D, E, G, H, I), 6
copy_addr %15 to [init] %31 : $*H
%33 = tuple_element_addr %18 : $*(A, B, C, D, E, G, H, I), 7
copy_addr %16 to [init] %33 : $*I
%41 = alloc_stack $(A, B, C, D, E, G, H, I)
copy_addr %18 to [init] %41 : $*(A, B, C, D, E, G, H, I)
%43 = tuple_element_addr %41 : $*(A, B, C, D, E, G, H, I), 0
%44 = tuple_element_addr %41 : $*(A, B, C, D, E, G, H, I), 1
%45 = tuple_element_addr %41 : $*(A, B, C, D, E, G, H, I), 2
%46 = tuple_element_addr %41 : $*(A, B, C, D, E, G, H, I), 3
%47 = tuple_element_addr %41 : $*(A, B, C, D, E, G, H, I), 4
%48 = tuple_element_addr %41 : $*(A, B, C, D, E, G, H, I), 5
%49 = tuple_element_addr %41 : $*(A, B, C, D, E, G, H, I), 6
%50 = tuple_element_addr %41 : $*(A, B, C, D, E, G, H, I), 7
copy_addr [take] %43 to [init] %0 : $*A
%52 = alloc_stack $(A, B, C, D, E, G, H, I)
copy_addr %18 to [init] %52 : $*(A, B, C, D, E, G, H, I)
%54 = tuple_element_addr %52 : $*(A, B, C, D, E, G, H, I), 0
%55 = tuple_element_addr %52 : $*(A, B, C, D, E, G, H, I), 1
%56 = tuple_element_addr %52 : $*(A, B, C, D, E, G, H, I), 2
%57 = tuple_element_addr %52 : $*(A, B, C, D, E, G, H, I), 3
%58 = tuple_element_addr %52 : $*(A, B, C, D, E, G, H, I), 4
%59 = tuple_element_addr %52 : $*(A, B, C, D, E, G, H, I), 5
%60 = tuple_element_addr %52 : $*(A, B, C, D, E, G, H, I), 6
%61 = tuple_element_addr %52 : $*(A, B, C, D, E, G, H, I), 7
copy_addr [take] %55 to [init] %1 : $*B
%63 = alloc_stack $(A, B, C, D, E, G, H, I)
copy_addr %18 to [init] %63 : $*(A, B, C, D, E, G, H, I)
%65 = tuple_element_addr %63 : $*(A, B, C, D, E, G, H, I), 0
%66 = tuple_element_addr %63 : $*(A, B, C, D, E, G, H, I), 1
%67 = tuple_element_addr %63 : $*(A, B, C, D, E, G, H, I), 2
%68 = tuple_element_addr %63 : $*(A, B, C, D, E, G, H, I), 3
%69 = tuple_element_addr %63 : $*(A, B, C, D, E, G, H, I), 4
%70 = tuple_element_addr %63 : $*(A, B, C, D, E, G, H, I), 5
%71 = tuple_element_addr %63 : $*(A, B, C, D, E, G, H, I), 6
%72 = tuple_element_addr %63 : $*(A, B, C, D, E, G, H, I), 7
copy_addr [take] %67 to [init] %2 : $*C
%74 = alloc_stack $(A, B, C, D, E, G, H, I)
copy_addr %18 to [init] %74 : $*(A, B, C, D, E, G, H, I)
%76 = tuple_element_addr %74 : $*(A, B, C, D, E, G, H, I), 0
%77 = tuple_element_addr %74 : $*(A, B, C, D, E, G, H, I), 1
%78 = tuple_element_addr %74 : $*(A, B, C, D, E, G, H, I), 2
%79 = tuple_element_addr %74 : $*(A, B, C, D, E, G, H, I), 3
%80 = tuple_element_addr %74 : $*(A, B, C, D, E, G, H, I), 4
%81 = tuple_element_addr %74 : $*(A, B, C, D, E, G, H, I), 5
%82 = tuple_element_addr %74 : $*(A, B, C, D, E, G, H, I), 6
%83 = tuple_element_addr %74 : $*(A, B, C, D, E, G, H, I), 7
copy_addr [take] %79 to [init] %3 : $*D
%85 = alloc_stack $(A, B, C, D, E, G, H, I)
copy_addr %18 to [init] %85 : $*(A, B, C, D, E, G, H, I)
%87 = tuple_element_addr %85 : $*(A, B, C, D, E, G, H, I), 0
%88 = tuple_element_addr %85 : $*(A, B, C, D, E, G, H, I), 1
%89 = tuple_element_addr %85 : $*(A, B, C, D, E, G, H, I), 2
%90 = tuple_element_addr %85 : $*(A, B, C, D, E, G, H, I), 3
%91 = tuple_element_addr %85 : $*(A, B, C, D, E, G, H, I), 4
%92 = tuple_element_addr %85 : $*(A, B, C, D, E, G, H, I), 5
%93 = tuple_element_addr %85 : $*(A, B, C, D, E, G, H, I), 6
%94 = tuple_element_addr %85 : $*(A, B, C, D, E, G, H, I), 7
copy_addr [take] %91 to [init] %4 : $*E
%96 = alloc_stack $(A, B, C, D, E, G, H, I)
copy_addr %18 to [init] %96 : $*(A, B, C, D, E, G, H, I)
%98 = tuple_element_addr %96 : $*(A, B, C, D, E, G, H, I), 0
%99 = tuple_element_addr %96 : $*(A, B, C, D, E, G, H, I), 1
%100 = tuple_element_addr %96 : $*(A, B, C, D, E, G, H, I), 2
%101 = tuple_element_addr %96 : $*(A, B, C, D, E, G, H, I), 3
%102 = tuple_element_addr %96 : $*(A, B, C, D, E, G, H, I), 4
%103 = tuple_element_addr %96 : $*(A, B, C, D, E, G, H, I), 5
%104 = tuple_element_addr %96 : $*(A, B, C, D, E, G, H, I), 6
%105 = tuple_element_addr %96 : $*(A, B, C, D, E, G, H, I), 7
copy_addr [take] %103 to [init] %5 : $*G
%107 = alloc_stack $(A, B, C, D, E, G, H, I)
copy_addr %18 to [init] %107 : $*(A, B, C, D, E, G, H, I)
%109 = tuple_element_addr %107 : $*(A, B, C, D, E, G, H, I), 0
%110 = tuple_element_addr %107 : $*(A, B, C, D, E, G, H, I), 1
%111 = tuple_element_addr %107 : $*(A, B, C, D, E, G, H, I), 2
%112 = tuple_element_addr %107 : $*(A, B, C, D, E, G, H, I), 3
%113 = tuple_element_addr %107 : $*(A, B, C, D, E, G, H, I), 4
%114 = tuple_element_addr %107 : $*(A, B, C, D, E, G, H, I), 5
%115 = tuple_element_addr %107 : $*(A, B, C, D, E, G, H, I), 6
%116 = tuple_element_addr %107 : $*(A, B, C, D, E, G, H, I), 7
copy_addr [take] %115 to [init] %6 : $*H
%118 = alloc_stack $(A, B, C, D, E, G, H, I)
copy_addr %18 to [init] %118 : $*(A, B, C, D, E, G, H, I)
%120 = tuple_element_addr %118 : $*(A, B, C, D, E, G, H, I), 0
%121 = tuple_element_addr %118 : $*(A, B, C, D, E, G, H, I), 1
%122 = tuple_element_addr %118 : $*(A, B, C, D, E, G, H, I), 2
%123 = tuple_element_addr %118 : $*(A, B, C, D, E, G, H, I), 3
%124 = tuple_element_addr %118 : $*(A, B, C, D, E, G, H, I), 4
%125 = tuple_element_addr %118 : $*(A, B, C, D, E, G, H, I), 5
%126 = tuple_element_addr %118 : $*(A, B, C, D, E, G, H, I), 6
%127 = tuple_element_addr %118 : $*(A, B, C, D, E, G, H, I), 7
copy_addr [take] %127 to [init] %7 : $*I
destroy_addr %126 : $*H
destroy_addr %125 : $*G
destroy_addr %124 : $*E
destroy_addr %123 : $*D
destroy_addr %122 : $*C
destroy_addr %121 : $*B
destroy_addr %120 : $*A
dealloc_stack %118 : $*(A, B, C, D, E, G, H, I)
destroy_addr %116 : $*I
destroy_addr %114 : $*G
destroy_addr %113 : $*E
destroy_addr %112 : $*D
destroy_addr %111 : $*C
destroy_addr %110 : $*B
destroy_addr %109 : $*A
dealloc_stack %107 : $*(A, B, C, D, E, G, H, I)
destroy_addr %105 : $*I
destroy_addr %104 : $*H
destroy_addr %102 : $*E
destroy_addr %101 : $*D
destroy_addr %100 : $*C
destroy_addr %99 : $*B
destroy_addr %98 : $*A
dealloc_stack %96 : $*(A, B, C, D, E, G, H, I)
destroy_addr %94 : $*I
destroy_addr %93 : $*H
destroy_addr %92 : $*G
destroy_addr %90 : $*D
destroy_addr %89 : $*C
destroy_addr %88 : $*B
destroy_addr %87 : $*A
dealloc_stack %85 : $*(A, B, C, D, E, G, H, I)
destroy_addr %83 : $*I
destroy_addr %82 : $*H
destroy_addr %81 : $*G
destroy_addr %80 : $*E
destroy_addr %78 : $*C
destroy_addr %77 : $*B
destroy_addr %76 : $*A
dealloc_stack %74 : $*(A, B, C, D, E, G, H, I)
destroy_addr %72 : $*I
destroy_addr %71 : $*H
destroy_addr %70 : $*G
destroy_addr %69 : $*E
destroy_addr %68 : $*D
destroy_addr %66 : $*B
destroy_addr %65 : $*A
dealloc_stack %63 : $*(A, B, C, D, E, G, H, I)
destroy_addr %61 : $*I
destroy_addr %60 : $*H
destroy_addr %59 : $*G
destroy_addr %58 : $*E
destroy_addr %57 : $*D
destroy_addr %56 : $*C
destroy_addr %54 : $*A
dealloc_stack %52 : $*(A, B, C, D, E, G, H, I)
destroy_addr %50 : $*I
destroy_addr %49 : $*H
destroy_addr %48 : $*G
destroy_addr %47 : $*E
destroy_addr %46 : $*D
destroy_addr %45 : $*C
destroy_addr %44 : $*B
dealloc_stack %41 : $*(A, B, C, D, E, G, H, I)
destroy_addr %18 : $*(A, B, C, D, E, G, H, I)
dealloc_stack %18 : $*(A, B, C, D, E, G, H, I)
%196 = tuple ()
return %196 : $()
}
sil @getInner : $@convention(thin) () -> (@owned T, @error Error)
sil [ossa] @test_mismatch_at_unreachable : $@convention(thin) () -> @owned Inner {
bb0:
%1 = alloc_stack $Inner, var, name "self"
%3 = function_ref @getInner : $@convention(thin) () -> (@owned T, @error Error)
try_apply %3() : $@convention(thin) () -> (@owned T, @error Error), normal bb1, error bb5
bb1(%5 : @owned $T):
%7 = struct_element_addr %1 : $*Inner, #Inner.a
store %5 to [init] %7 : $*T
%11 = function_ref @getInner : $@convention(thin) () -> (@owned T, @error Error)
try_apply %11() : $@convention(thin) () -> (@owned T, @error Error), normal bb2, error bb6
bb2(%13 : @owned $T):
%15 = struct_element_addr %1 : $*Inner, #Inner.b
store %13 to [init] %15 : $*T
br bb3
bb3:
%19 = load [take] %1 : $*Inner
dealloc_stack %1 : $*Inner
return %19 : $Inner
// An inconsistent state is allowed at unreachable blocks.
bb4(%23 : @owned $Error):
unreachable
bb5(%43 : @owned $Error):
br bb4(%43 : $Error)
bb6(%45 : @owned $Error):
br bb4(%45 : $Error)
}
sil [ossa] @test_memory_lifetime_select_enum : $@convention(thin) (@in_guaranteed Optional<T>) -> () {
bb0(%0 : $*Optional<T>):
%2 = integer_literal $Builtin.Int1, 0
%3 = integer_literal $Builtin.Int1, 1
%4 = select_enum_addr %0 : $*Optional<T>, case #Optional.none!enumelt: %2, case #Optional.some!enumelt: %3 : $Builtin.Int1
cond_br %4, bb1, bb2
bb1:
br bb3
bb2:
br bb3
bb3:
%9999 = tuple()
return %9999 : $()
}
sil [ossa] @test_switch_enum_addr : $@convention(thin) (@in Optional<T>) -> () {
bb0(%0 : $*Optional<T>):
switch_enum_addr %0 : $*Optional<T>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
bb1:
%2 = unchecked_take_enum_data_addr %0 : $*Optional<T>, #Optional.some!enumelt
destroy_addr %2 : $*T
br bb3
bb2:
br bb3
bb3:
%r = tuple ()
return %r : $()
}
sil [ossa] @test_switch_enum : $@convention(thin) (@in Optional<T>) -> () {
bb0(%0 : $*Optional<T>):
%1 = load_borrow %0 : $*Optional<T>
switch_enum %1 : $Optional<T>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
bb1(%3 : @guaranteed $T):
end_borrow %1 : $Optional<T>
%2 = unchecked_take_enum_data_addr %0 : $*Optional<T>, #Optional.some!enumelt
destroy_addr %2 : $*T
br bb3
bb2:
end_borrow %1 : $Optional<T>
br bb3
bb3:
%r = tuple ()
return %r : $()
}
sil [ossa] @test_init_enum : $@convention(thin) (@in_guaranteed T) -> @out Optional<T> {
bb0(%0 : $*Optional<T>, %1 : $*T):
cond_br undef, bb1, bb2
bb1:
inject_enum_addr %0 : $*Optional<T>, #Optional.none!enumelt
br bb3
bb2:
%5 = init_enum_data_addr %0 : $*Optional<T>, #Optional.some!enumelt
copy_addr %1 to [init] %5 : $*T
inject_enum_addr %0 : $*Optional<T>, #Optional.some!enumelt
br bb3
bb3:
%r = tuple ()
return %r : $()
}
sil [ossa] @test_store_to_enum : $@convention(thin) (@owned T) -> () {
bb0(%0 : @owned $T):
%1 = alloc_stack $Optional<T>
%2 = enum $Optional<T>, #Optional.some!enumelt, %0 : $T
store %2 to [init] %1 : $*Optional<T>
destroy_addr %1 : $*Optional<T>
%3 = enum $Optional<T>, #Optional.none!enumelt
store %3 to [trivial] %1 : $*Optional<T>
dealloc_stack %1 : $*Optional<T>
%r = tuple ()
return %r : $()
}
sil [ossa] @test_store_enum_tuple : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = enum $Optional<T>, #Optional.none!enumelt
%3 = tuple (%0 : $Int, %2 : $Optional<T>)
%8 = alloc_stack $(Int, Optional<T>)
store %3 to [trivial] %8 : $*(Int, Optional<T>)
dealloc_stack %8 : $*(Int, Optional<T>)
%13 = tuple ()
return %13 : $()
}
sil [ossa] @test_select_enum_addr : $@convention(thin) (@in_guaranteed Optional<T>) -> Builtin.Int1 {
bb0(%0 : $*Optional<T>):
%1 = integer_literal $Builtin.Int1, -1
%2 = integer_literal $Builtin.Int1, 0
%3 = select_enum_addr %0 : $*Optional<T>, case #Optional.some!enumelt: %1, case #Optional.none!enumelt: %2 : $Builtin.Int1
return %3 : $Builtin.Int1
}
sil [ossa] @closure : $@convention(thin) (@in_guaranteed T) -> ()
sil [ossa] @test_non_escaping_closure : $@convention(thin) (@in_guaranteed T) -> () {
bb0(%0 : $*T):
%func = function_ref @closure : $@convention(thin) (@in_guaranteed T) -> ()
%pa = partial_apply [callee_guaranteed] [on_stack] %func(%0) : $@convention(thin) (@in_guaranteed T) -> ()
destroy_value %pa : $@noescape @callee_guaranteed () -> ()
%res = tuple ()
return %res : $()
}
sil [ossa] @test_escaping_closure : $@convention(thin) (@in T) -> () {
bb0(%0 : $*T):
%func = function_ref @closure : $@convention(thin) (@in_guaranteed T) -> ()
%pa = partial_apply %func(%0) : $@convention(thin) (@in_guaranteed T) -> ()
destroy_value %pa : $@callee_owned () -> ()
%res = tuple ()
return %res : $()
}
sil [ossa] @test_store_borrow : $@convention(thin) (@guaranteed T) -> () {
bb0(%0 : @guaranteed $T):
%s = alloc_stack $T
%sb = store_borrow %0 to %s : $*T
end_borrow %sb : $*T
dealloc_stack %s : $*T
%res = tuple ()
return %res : $()
}
sil [ossa] @test_cast_br_take_always : $@convention(thin) <U, V> (@in U) -> () {
bb0(%0 : $*U):
%s = alloc_stack $V
checked_cast_addr_br take_always U in %0 : $*U to V in %s : $*V, bb1, bb2
bb1:
destroy_addr %s : $*V
br bb3
bb2:
br bb3
bb3:
dealloc_stack %s : $*V
%res = tuple ()
return %res : $()
}
sil [ossa] @test_cast_br_take_on_success : $@convention(thin) <U, V> (@in U) -> () {
bb0(%0 : $*U):
%s = alloc_stack $V
checked_cast_addr_br take_on_success U in %0 : $*U to V in %s : $*V, bb1, bb2
bb1:
destroy_addr %s : $*V
br bb3
bb2:
destroy_addr %0 : $*U
br bb3
bb3:
dealloc_stack %s : $*V
%res = tuple ()
return %res : $()
}
sil [ossa] @test_cast_br_copy_on_success : $@convention(thin) <U, V> (@in U) -> () {
bb0(%0 : $*U):
%s = alloc_stack $V
checked_cast_addr_br copy_on_success U in %0 : $*U to V in %s : $*V, bb1, bb2
bb1:
destroy_addr %0 : $*U
destroy_addr %s : $*V
br bb3
bb2:
destroy_addr %0 : $*U
br bb3
bb3:
dealloc_stack %s : $*V
%res = tuple ()
return %res : $()
}
sil [ossa] @test_unconditional_checked_cast : $@convention(thin) <U, V> (@in U) -> () {
bb0(%0 : $*U):
%s = alloc_stack $V
unconditional_checked_cast_addr U in %0 : $*U to V in %s : $*V
destroy_addr %s : $*V
dealloc_stack %s : $*V
%5 = tuple ()
return %5 : $()
}
sil [ossa] @test_unchecked_ref_cast : $@convention(thin) <U : AnyObject, V : AnyObject> (@in U) -> () {
bb0(%0 : $*U):
%s = alloc_stack $V
unchecked_ref_cast_addr U in %0 : $*U to V in %s : $*V
destroy_addr %s : $*V
dealloc_stack %s : $*V
%5 = tuple ()
return %5 : $()
}
protocol P {}
sil [ossa] @test_existentials : $@convention(thin) <U: P> (@in_guaranteed U) -> () {
bb0(%0 : $*U):
%s = alloc_stack $P
%i = init_existential_addr %s : $*P, $U
copy_addr %0 to [init] %i : $*U
%o = open_existential_addr immutable_access %s : $*P to $*@opened("5B62392E-7C62-11EB-BF90-D0817AD9985D", P) Self
%s2 = alloc_stack $@opened("5B62392E-7C62-11EB-BF90-D0817AD9985D", P) Self
copy_addr %o to [init] %s2 : $*@opened("5B62392E-7C62-11EB-BF90-D0817AD9985D", P) Self
destroy_addr %s2 : $*@opened("5B62392E-7C62-11EB-BF90-D0817AD9985D", P) Self
dealloc_stack %s2 : $*@opened("5B62392E-7C62-11EB-BF90-D0817AD9985D", P) Self
destroy_addr %s : $*P
dealloc_stack %s : $*P
%5 = tuple ()
return %5 : $()
}
sil [ossa] @test_init_two_existentials : $@convention(thin) <U: P, V: P> (@in_guaranteed U, @in_guaranteed V) -> () {
bb0(%0 : $*U, %1 : $*V):
%s = alloc_stack $P
%t = init_existential_addr %s : $*P, $U
copy_addr %0 to [init] %t : $*U
destroy_addr %s : $*P
%v = init_existential_addr %s : $*P, $V
copy_addr %1 to [init] %v : $*V
destroy_addr %s : $*P
dealloc_stack %s : $*P
%5 = tuple ()
return %5 : $()
}
sil [ossa] @test_existential_metatype : $@convention(thin) (@in_guaranteed P) -> () {
bb0(%0 : $*P):
%714 = existential_metatype $@thick P.Type, %0 : $*P
%5 = tuple ()
return %5 : $()
}
sil [ossa] @test_value_metatype : $@convention(thin) <U> (@in_guaranteed U) -> () {
bb0(%0 : $*U):
%1 = value_metatype $@thick U.Type, %0 : $*U
%5 = tuple ()
return %5 : $()
}
sil [ossa] @test_is_unique : $@convention(thin) (@in T) -> () {
bb0(%0 : $*T):
%1 = is_unique %0 : $*T
destroy_addr %0 : $*T
%5 = tuple ()
return %5 : $()
}
sil [ossa] @test_fix_lifetime : $@convention(thin) (@in_guaranteed T) -> () {
bb0(%0 : $*T):
fix_lifetime %0 : $*T
%5 = tuple ()
return %5 : $()
}
sil [ossa] @test_ignore_empty_types : $@convention(thin) (Int, @guaranteed @callee_guaranteed (@in_guaranteed (Int, ((), ()))) -> Int) -> Int {
bb0(%0 : $Int, %1 : @guaranteed $@callee_guaranteed (@in_guaranteed (Int, ((), ()))) -> Int):
%2 = alloc_stack $(Int, ((), ()))
%3 = tuple_element_addr %2 : $*(Int, ((), ())), 0
store %0 to [trivial] %3 : $*Int
%5 = apply %1(%2) : $@callee_guaranteed (@in_guaranteed (Int, ((), ()))) -> Int
dealloc_stack %2 : $*(Int, ((), ()))
return %5 : $Int
}
enum Result<T1, T2>{
case success(T1)
case failure(T2)
}
sil @try_get_error : $@convention(thin) () -> @error Error
sil [ossa] @test_init_enum_empty_case : $@convention(thin) () -> @error Error {
bb0:
%0 = alloc_stack $Result<(), Error>
%1 = function_ref @try_get_error : $@convention(thin) () -> @error Error
try_apply %1() : $@convention(thin) () -> @error Error, normal bb1, error bb2
bb1(%3 : $()):
inject_enum_addr %0 : $*Result<(), Error>, #Result.success!enumelt
br bb3
bb2(%6 : @owned $Error):
%7 = init_enum_data_addr %0 : $*Result<(), Error>, #Result.failure!enumelt
store %6 to [init] %7 : $*Error
inject_enum_addr %0 : $*Result<(), Error>, #Result.failure!enumelt
br bb3
bb3:
%11 = load [take] %0 : $*Result<(), Error>
destroy_value %11 : $Result<(), Error>
dealloc_stack %0 : $*Result<(), Error>
%14 = tuple ()
return %14 : $()
}
sil [ossa] @begin_apply_in_destroy : $@convention(thin) () -> () {
entry:
(%instance, %token) = begin_apply undef<Inner>() : $@yield_once @convention(thin) <U> () -> @yields @in U
destroy_addr %instance : $*Inner
end_apply %token as $()
%retval = tuple ()
return %retval : $()
}
sil [ossa] @begin_apply_in_constant_destroy : $@convention(thin) () -> () {
entry:
(%instance, %token) = begin_apply undef<Inner>() : $@yield_once @convention(thin) <U> () -> @yields @in_constant U
destroy_addr %instance : $*Inner
end_apply %token as $()
%retval = tuple ()
return %retval : $()
}
sil [ossa] @begin_apply_in_guaranteed_no_destroy : $@convention(thin) () -> () {
entry:
(%instance, %token) = begin_apply undef<Inner>() : $@yield_once @convention(thin) <U> () -> @yields @in_guaranteed U
end_apply %token as $()
%retval = tuple ()
return %retval : $()
}
sil @read_inner_b : $@convention(thin) (@in_guaranteed Inner) -> () {
[%0: read s1]
}
sil [ossa] @test_partial_read_in_argument : $@convention(thin) (@in Inner) -> () {
bb0(%0: $*Inner):
%1 = struct_element_addr %0 : $*Inner, #Inner.a
destroy_addr %1 : $*T
%3 = function_ref @read_inner_b : $@convention(thin) (@in_guaranteed Inner) -> ()
%4 = apply %3(%0) : $@convention(thin) (@in_guaranteed Inner) -> ()
%5 = struct_element_addr %0 : $*Inner, #Inner.b
destroy_addr %5 : $*T
%r = tuple ()
return %r : $()
}
sil [ossa] @test : $@convention(thin) (@guaranteed KlassOrBool) -> () {
bb0(%0 : @guaranteed $KlassOrBool):
%1 = alloc_stack $KlassOrBool
%2 = copy_value %0 : $KlassOrBool
store %2 to [init] %1 : $*KlassOrBool
%4 = load_borrow %1 : $*KlassOrBool
switch_enum %4 : $KlassOrBool, case #KlassOrBool.bool!enumelt: bb1, case #KlassOrBool.value!enumelt: bb2
bb1(%6 : $Bool):
end_borrow %4 : $KlassOrBool
%8 = alloc_stack $KlassOrBool
%9 = load [copy] %1 : $*KlassOrBool
store %9 to [init] %8 : $*KlassOrBool
%11 = load_borrow %8 : $*KlassOrBool
%12 = unchecked_enum_data %11 : $KlassOrBool, #KlassOrBool.bool!enumelt
end_borrow %11 : $KlassOrBool
dealloc_stack %8 : $*KlassOrBool
br bb3
bb2(%16 : @guaranteed $T):
end_borrow %4 : $KlassOrBool
%18 = load [take] %1 : $*KlassOrBool
destroy_value %18 : $KlassOrBool
br bb3
bb3:
dealloc_stack %1 : $*KlassOrBool
%22 = tuple ()
return %22 : $()
}
sil @$testTrivialThinToThickClosure : $@convention(thin) @substituted <τ_0_0> () -> @out τ_0_0 for <Int>
sil @$testTrivialThinToThickApply : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
// Test alloc_stack of a non-trivial (thick) function.
// Initialize by storing a thin function, which as ownership .none.
// Deallocation does not require a destroy_adr.
sil [ossa] @testTrivialThinToThick : $@convention(thin) () -> () {
bb0:
%0 = function_ref @$testTrivialThinToThickClosure : $@convention(thin) @substituted <τ_0_0> () -> @out τ_0_0 for <Int>
%1 = thin_to_thick_function %0 : $@convention(thin) @substituted <τ_0_0> () -> @out τ_0_0 for <Int> to $@callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <Int>
%2 = alloc_stack $@callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <Int>
store %1 to [trivial] %2 : $*@callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <Int>
%4 = function_ref @$testTrivialThinToThickApply : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
%5 = apply %4<() -> Int>(%2) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
dealloc_stack %2 : $*@callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <Int>
%7 = tuple ()
return %7 : $()
}
sil [ossa] @test_init_enum_switch_value : $@convention(thin) (@in_guaranteed Optional<T>, @in_guaranteed T) -> () {
bb0(%0 : $*Optional<T>, %1 : $*T):
%stk = alloc_stack $Optional<T>
%2 = init_enum_data_addr %stk : $*Optional<T>, #Optional.some!enumelt
copy_addr %1 to [init] %2 : $*T
inject_enum_addr %stk : $*Optional<T>, #Optional.some!enumelt
%one = integer_literal $Builtin.Word, 1
%two = integer_literal $Builtin.Word, 2
switch_value %one : $Builtin.Word, case %one: bb1, case %two: bb2
bb1:
destroy_addr %stk : $*Optional<T>
dealloc_stack %stk : $*Optional<T>
br bb3
bb2:
dealloc_stack %stk : $*Optional<T>
br bb3
bb3:
%r = tuple ()
return %r : $()
}