Files
swift-mirror/test/SIL/memory_lifetime.sil
Erik Eckstein 535a58e3fb SIL: assume a read-effect for unused indirect arguments
Even if an indirect argument is unused, pretend that the function reads from it.
If the unused argument is passed to another generic function and that function is specialized,
the argument may be re-abstracted and the specializer inserts a load from the indirect argument.
Therefore we must be prepared that unused indirect argument might get loaded from at some time.

Fixes a compiler crash
rdar://168623362
2026-01-23 15:58:23 +01:00

888 lines
28 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)
}
struct IntPair {
var a: Int
var b: Int
}
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_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):
destroy_value [dead_end] %23
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_init_enum2 : $@convention(thin) (@inout Optional<T>, @in T) -> () {
bb0(%0 : $*Optional<T>, %1 : $*T):
%11 = init_enum_data_addr %0, #Optional.some!enumelt
destroy_addr %0
copy_addr [take] %1 to [init] %11
inject_enum_addr %0, #Optional.some!enumelt
%121 = tuple ()
return %121
}
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_store_borrow_nested : $@convention(thin) (@guaranteed Inner) -> () {
bb0(%0 : @guaranteed $Inner):
%s = alloc_stack $Inner
%sb = store_borrow %0 to %s
%elem = struct_element_addr %sb, #Inner.a
end_borrow %sb
dealloc_stack %s
%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 [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 : $()
}
sil [ossa] @mark_dependence : $@convention(method) (@owned T, @owned Inner) -> @owned Inner {
bb0(%0 : @owned $T, %1 : @owned $Inner):
%2 = alloc_stack $T
store %0 to [init] %2
%4 = alloc_stack $Inner
store %1 to [init] %4
%6 = mark_dependence %4 on %2
%7 = begin_access [modify] [dynamic] %6
%8 = load [take] %7
end_access %7
dealloc_stack %4
destroy_addr %2
dealloc_stack %2
return %8
}
sil [ossa] @mark_dependence_addr : $@convention(method) (@owned T, @owned Inner) -> @owned Inner {
bb0(%0 : @owned $T, %1 : @owned $Inner):
%2 = alloc_stack $T
store %0 to [init] %2
%4 = alloc_stack $Inner
store %1 to [init] %4
mark_dependence_addr %4 on %2
%7 = begin_access [modify] [dynamic] %4
%8 = load [take] %7
end_access %7
dealloc_stack %4
destroy_addr %2
dealloc_stack %2
return %8
}
sil @initfn : $@convention(thin) () -> @out T
sil [ossa] @inject_enum_case : $@convention(thin) () -> () {
bb0:
%0 = alloc_stack $Optional<T>
%1 = function_ref @initfn : $@convention(thin) () -> @out T
%2 = init_enum_data_addr %0, #Optional.some!enumelt
%3 = apply %1(%2) : $@convention(thin) () -> @out T
inject_enum_addr %0, #Optional.some!enumelt
destroy_addr %0
dealloc_stack %0
%10 = tuple ()
return %10
}
sil [ossa] @storage_leaked_into_dead_ends : $@convention(thin) () -> () {
%t = apply undef() : $@convention(thin) () -> (@owned T)
%t_addr = alloc_stack $T
store %t to [init] %t_addr
dealloc_stack %t_addr
unreachable
}
sil [ossa] @read_a : $@convention(thin) (@inout IntPair) -> () {
[%0: read s0.v**]
}
sil [ossa] @callee_reads_unknown_subfield : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%1 = alloc_stack $IntPair
%2 = struct_element_addr %1, #IntPair.a
store %0 to [trivial] %2
%4 = function_ref @read_a : $@convention(thin) (@inout IntPair) -> ()
%5 = apply %4(%1) : $@convention(thin) (@inout IntPair) -> ()
dealloc_stack %1
%7 = tuple ()
return %7
}
sil [ossa] @callee_reads_known_subfield : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%1 = alloc_stack $IntPair
%2 = struct_element_addr %1, #IntPair.a
%3 = struct_element_addr %1, #IntPair.b
store %0 to [trivial] %2
%4 = function_ref @read_a : $@convention(thin) (@inout IntPair) -> ()
%5 = apply %4(%1) : $@convention(thin) (@inout IntPair) -> ()
dealloc_stack %1
%7 = tuple ()
return %7
}