mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
823 lines
29 KiB
Plaintext
823 lines
29 KiB
Plaintext
// RUN: %target-sil-opt -sil-print-types -inline -verify %s | %FileCheck %s
|
|
// RUN: %target-sil-opt -sil-print-types -mandatory-inlining -verify %s | %FileCheck %s
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
sil @marker : $(Builtin.Int32) -> ()
|
|
|
|
class SomeClass {}
|
|
sil_vtable SomeClass {}
|
|
|
|
class SomeSubclass : SomeClass {}
|
|
sil_vtable SomeSubclass {}
|
|
|
|
// This is designed to be formally indirect.
|
|
struct Indirect<T: AnyObject> {
|
|
var x: Any
|
|
var y: T
|
|
}
|
|
|
|
sil @make_indirect : $<T: SomeClass> () -> (@out Indirect<T>)
|
|
|
|
sil [transparent] [ossa] @test_one_yield : $@yield_once <C: SomeClass> () -> (@yields @in Indirect<C>) {
|
|
entry:
|
|
%marker = function_ref @marker : $@convention(thin) (Builtin.Int32) -> ()
|
|
%1000 = integer_literal $Builtin.Int32, 1000
|
|
apply %marker(%1000) : $@convention(thin) (Builtin.Int32) -> ()
|
|
%temp = alloc_stack $Indirect<C>
|
|
%make = function_ref @make_indirect : $@convention(thin) <T: SomeClass> () -> (@out Indirect<T>)
|
|
apply %make<C>(%temp) : $@convention(thin) <T: SomeClass> () -> (@out Indirect<T>)
|
|
yield %temp : $*Indirect<C>, resume resume, unwind unwind
|
|
|
|
resume:
|
|
%2000 = integer_literal $Builtin.Int32, 2000
|
|
apply %marker(%2000) : $@convention(thin) (Builtin.Int32) -> ()
|
|
dealloc_stack %temp : $*Indirect<C>
|
|
%ret = tuple ()
|
|
return %ret : $()
|
|
|
|
unwind:
|
|
%3000 = integer_literal $Builtin.Int32, 3000
|
|
apply %marker(%3000) : $@convention(thin) (Builtin.Int32) -> ()
|
|
dealloc_stack %temp : $*Indirect<C>
|
|
unwind
|
|
}
|
|
|
|
sil [ossa] @getSomeClass : $@convention(thin) () -> @owned SomeClass
|
|
|
|
sil [transparent] [ossa] @yield_owned_as_guaranteed : $@yield_once @convention(thin) () -> @yields @guaranteed SomeClass {
|
|
%getSomeClass = function_ref @getSomeClass : $@convention(thin) () -> @owned SomeClass
|
|
%SomeClass = apply %getSomeClass() : $@convention(thin) () -> @owned SomeClass
|
|
yield %SomeClass : $SomeClass, resume bb1, unwind bb2
|
|
|
|
bb1:
|
|
destroy_value %SomeClass : $SomeClass
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
|
|
bb2:
|
|
destroy_value %SomeClass : $SomeClass
|
|
unwind
|
|
}
|
|
|
|
sil [transparent] [ossa] @test_unreachable : $@yield_once <C: SomeClass> () -> (@yields @in Indirect<C>) {
|
|
entry:
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_simple_call
|
|
// CHECK: bb0(%0 : $Builtin.Int1):
|
|
// CHECK: [[MARKER:%.*]] = function_ref @marker
|
|
// CHECK: [[MARKER2:%.*]] = function_ref @marker
|
|
// CHECK: [[I:%.*]] = integer_literal $Builtin.Int32, 1000
|
|
// CHECK: apply [[MARKER2]]([[I]]) : $@convention(thin) (Builtin.Int32) -> ()
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $Indirect<SomeSubclass>
|
|
// CHECK: [[MK_IND:%.*]] = function_ref @make_indirect
|
|
// CHECK: apply [[MK_IND]]<SomeSubclass>([[TEMP]])
|
|
// CHECK: destroy_addr [[TEMP]] : $*Indirect<SomeSubclass>
|
|
// CHECK: cond_br %0, bb1, bb2
|
|
|
|
// CHECK: bb1:
|
|
// CHECK: [[I4:%.*]] = integer_literal $Builtin.Int32, 10
|
|
// CHECK: apply [[MARKER]]([[I4]])
|
|
// CHECK: [[I2:%.*]] = integer_literal $Builtin.Int32, 2000
|
|
// CHECK: apply [[MARKER2]]([[I2]])
|
|
// CHECK: dealloc_stack [[TEMP]] : $*Indirect<SomeSubclass>
|
|
// CHECK: [[I5:%.*]] = integer_literal $Builtin.Int32, 20
|
|
// CHECK: apply [[MARKER]]([[I5]])
|
|
// CHECK: br bb3
|
|
|
|
// CHECK: bb2:
|
|
// CHECK: [[I6:%.*]] = integer_literal $Builtin.Int32, 11
|
|
// CHECK: apply [[MARKER]]([[I6]])
|
|
// CHECK: [[I3:%.*]] = integer_literal $Builtin.Int32, 3000
|
|
// CHECK: apply [[MARKER2]]([[I3]])
|
|
// CHECK: dealloc_stack [[TEMP]] : $*Indirect<SomeSubclass>
|
|
// CHECK: [[I7:%.*]] = integer_literal $Builtin.Int32, 21
|
|
// CHECK: [[MARKER]]([[I7]])
|
|
// CHECK: br bb3
|
|
|
|
// CHECK:bb3:
|
|
// CHECK: return
|
|
// CHECK:}
|
|
|
|
sil @test_simple_call : $(Builtin.Int1) -> () {
|
|
entry(%flag : $Builtin.Int1):
|
|
%marker = function_ref @marker : $@convention(thin) (Builtin.Int32) -> ()
|
|
%0 = function_ref @test_one_yield : $@convention(thin) @yield_once <T: SomeClass> () -> (@yields @in Indirect<T>)
|
|
(%value, %token) = begin_apply %0<SomeSubclass>() : $@convention(thin) @yield_once <T: SomeClass> () -> (@yields @in Indirect<T>)
|
|
destroy_addr %value : $*Indirect<SomeSubclass>
|
|
cond_br %flag, yes, no
|
|
|
|
yes:
|
|
%10 = integer_literal $Builtin.Int32, 10
|
|
apply %marker(%10) : $@convention(thin) (Builtin.Int32) -> ()
|
|
end_apply %token as $()
|
|
%20 = integer_literal $Builtin.Int32, 20
|
|
apply %marker(%20) : $@convention(thin) (Builtin.Int32) -> ()
|
|
br cont
|
|
|
|
no:
|
|
%11 = integer_literal $Builtin.Int32, 11
|
|
apply %marker(%11) : $@convention(thin) (Builtin.Int32) -> ()
|
|
abort_apply %token
|
|
%21 = integer_literal $Builtin.Int32, 21
|
|
apply %marker(%21) : $@convention(thin) (Builtin.Int32) -> ()
|
|
br cont
|
|
|
|
cont:
|
|
%ret = tuple ()
|
|
return %ret : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_unreachable_call :
|
|
// CHECK: bb0(%0 : $Builtin.Int1):
|
|
// CHECK: [[MARKER:%.*]] = function_ref @marker
|
|
// CHECK: unreachable
|
|
// CHECK: } // end sil function 'test_unreachable_call'
|
|
sil @test_unreachable_call : $(Builtin.Int1) -> () {
|
|
entry(%flag : $Builtin.Int1):
|
|
%marker = function_ref @marker : $@convention(thin) (Builtin.Int32) -> ()
|
|
%0 = function_ref @test_unreachable : $@convention(thin) @yield_once <T: SomeClass> () -> (@yields @in Indirect<T>)
|
|
(%value, %token) = begin_apply %0<SomeSubclass>() : $@convention(thin) @yield_once <T: SomeClass> () -> (@yields @in Indirect<T>)
|
|
destroy_addr %value : $*Indirect<SomeSubclass>
|
|
cond_br %flag, yes, no
|
|
|
|
yes:
|
|
%10 = integer_literal $Builtin.Int32, 10
|
|
apply %marker(%10) : $@convention(thin) (Builtin.Int32) -> ()
|
|
end_apply %token as $()
|
|
%20 = integer_literal $Builtin.Int32, 20
|
|
apply %marker(%20) : $@convention(thin) (Builtin.Int32) -> ()
|
|
br cont
|
|
|
|
no:
|
|
%11 = integer_literal $Builtin.Int32, 11
|
|
apply %marker(%11) : $@convention(thin) (Builtin.Int32) -> ()
|
|
abort_apply %token
|
|
%21 = integer_literal $Builtin.Int32, 21
|
|
apply %marker(%21) : $@convention(thin) (Builtin.Int32) -> ()
|
|
br cont
|
|
|
|
cont:
|
|
%ret = tuple ()
|
|
return %ret : $()
|
|
}
|
|
|
|
sil [transparent] [ossa] @test_two_yield : $@yield_once <C: SomeClass> (Builtin.Int1) -> (@yields @in Indirect<C>, @yields Builtin.Int64) {
|
|
entry(%0 : $Builtin.Int1):
|
|
%marker = function_ref @marker : $@convention(thin) (Builtin.Int32) -> ()
|
|
%1000 = integer_literal $Builtin.Int32, 1000
|
|
apply %marker(%1000) : $@convention(thin) (Builtin.Int32) -> ()
|
|
%temp = alloc_stack $Indirect<C>
|
|
%make = function_ref @make_indirect : $@convention(thin) <T: SomeClass> () -> (@out Indirect<T>)
|
|
cond_br %0, yield1, yield2
|
|
|
|
yield1:
|
|
apply %make<C>(%temp) : $@convention(thin) <T: SomeClass> () -> (@out Indirect<T>)
|
|
%res = integer_literal $Builtin.Int64, 31
|
|
yield (%temp : $*Indirect<C>, %res: $Builtin.Int64), resume resume1, unwind unwind1
|
|
|
|
yield2:
|
|
apply %make<C>(%temp) : $@convention(thin) <T: SomeClass> () -> (@out Indirect<T>)
|
|
%res2 = integer_literal $Builtin.Int64, 32
|
|
yield (%temp : $*Indirect<C>, %res2: $Builtin.Int64), resume resume2, unwind unwind2
|
|
|
|
resume1:
|
|
br resume
|
|
resume2:
|
|
br resume
|
|
|
|
resume:
|
|
%2000 = integer_literal $Builtin.Int32, 2000
|
|
apply %marker(%2000) : $@convention(thin) (Builtin.Int32) -> ()
|
|
dealloc_stack %temp : $*Indirect<C>
|
|
%ret = tuple ()
|
|
return %ret : $()
|
|
|
|
unwind1:
|
|
br unwind
|
|
unwind2:
|
|
br unwind
|
|
|
|
unwind:
|
|
%3000 = integer_literal $Builtin.Int32, 3000
|
|
apply %marker(%3000) : $@convention(thin) (Builtin.Int32) -> ()
|
|
dealloc_stack %temp : $*Indirect<C>
|
|
unwind
|
|
}
|
|
|
|
// We don't support inlining functions with multiple yields yet.
|
|
// CHECK-LABEL: sil @test_simple_call_two_yields : $@convention(thin) (Builtin.Int1, Builtin.Int1) -> () {
|
|
// CHECK: bb0(%0 : $Builtin.Int1, %1 : $Builtin.Int1):
|
|
// CHECK: begin_apply
|
|
// CHECK: return
|
|
|
|
sil @test_simple_call_two_yields : $(Builtin.Int1, Builtin.Int1) -> () {
|
|
entry(%flag : $Builtin.Int1, %flag2 : $Builtin.Int1):
|
|
%marker = function_ref @marker : $@convention(thin) (Builtin.Int32) -> ()
|
|
%0 = function_ref @test_two_yield : $@convention(thin) @yield_once <T: SomeClass> (Builtin.Int1) -> (@yields @in Indirect<T>, @yields Builtin.Int64)
|
|
(%value, %value2, %token) = begin_apply %0<SomeSubclass>(%flag) : $@convention(thin) @yield_once <T: SomeClass> (Builtin.Int1) -> (@yields @in Indirect<T>, @yields Builtin.Int64)
|
|
destroy_addr %value : $*Indirect<SomeSubclass>
|
|
cond_br %flag2, yes, no
|
|
|
|
yes:
|
|
end_apply %token as $()
|
|
br cont
|
|
|
|
no:
|
|
abort_apply %token
|
|
br cont
|
|
|
|
cont:
|
|
%ret = tuple ()
|
|
return %ret : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_simple_call_yield_owned : $@convention(thin) (Builtin.Int1, @owned SomeClass) -> () {
|
|
// CHECK: bb0(%0 : $Builtin.Int1, %1 : @owned $SomeClass):
|
|
// CHECK-NEXT: // function_ref
|
|
// CHECK-NEXT: %2 = function_ref @marker
|
|
// CHECK-NEXT: %3 = integer_literal $Builtin.Int32, 1000
|
|
// CHECK-NEXT: %4 = apply %2(%3)
|
|
// CHECK-NEXT: destroy_value %1
|
|
// CHECK-NEXT: cond_br %0, bb1, bb2
|
|
// CHECK: bb1:
|
|
// CHECK-NEXT: [[T0:%.*]] = integer_literal $Builtin.Int32, 2000
|
|
// CHECK-NEXT: apply %2([[T0]])
|
|
// CHECK-NEXT: tuple ()
|
|
// CHECK-NEXT: br bb3
|
|
// CHECK: bb2:
|
|
// CHECK-NEXT: [[T1:%.*]] = integer_literal $Builtin.Int32, 3000
|
|
// CHECK-NEXT: apply %2([[T1]])
|
|
// CHECK-NEXT: br bb3
|
|
// CHECK: bb3:
|
|
// CHECK-NEXT: [[T0:%.*]] = tuple ()
|
|
// CHECK-NEXT: return [[T0]] : $()
|
|
|
|
sil [transparent] [ossa] @yield_owned : $@yield_once(@owned SomeClass) -> (@yields @owned SomeClass) {
|
|
entry(%0 : @owned $SomeClass):
|
|
%marker = function_ref @marker : $@convention(thin) (Builtin.Int32) -> ()
|
|
%1000 = integer_literal $Builtin.Int32, 1000
|
|
apply %marker(%1000) : $@convention(thin) (Builtin.Int32) -> ()
|
|
yield %0 : $SomeClass, resume resume, unwind unwind
|
|
|
|
resume:
|
|
%2000 = integer_literal $Builtin.Int32, 2000
|
|
apply %marker(%2000) : $@convention(thin) (Builtin.Int32) -> ()
|
|
%ret = tuple ()
|
|
return %ret : $()
|
|
|
|
unwind:
|
|
%3000 = integer_literal $Builtin.Int32, 3000
|
|
apply %marker(%3000) : $@convention(thin) (Builtin.Int32) -> ()
|
|
unwind
|
|
}
|
|
|
|
sil [ossa] @test_simple_call_yield_owned : $(Builtin.Int1, @owned SomeClass) -> () {
|
|
entry(%flag : $Builtin.Int1, %c: @owned $SomeClass):
|
|
%0 = function_ref @yield_owned : $@convention(thin) @yield_once(@owned SomeClass) -> (@yields @owned SomeClass)
|
|
(%value, %token) = begin_apply %0(%c) : $@convention(thin) @yield_once(@owned SomeClass) -> (@yields @owned SomeClass)
|
|
destroy_value %value : $SomeClass
|
|
cond_br %flag, yes, no
|
|
|
|
yes:
|
|
end_apply %token as $()
|
|
br cont
|
|
|
|
no:
|
|
abort_apply %token
|
|
br cont
|
|
|
|
cont:
|
|
%ret = tuple ()
|
|
return %ret : $()
|
|
}
|
|
|
|
sil @use : $@convention(thin) (@in Builtin.Int8) -> ()
|
|
|
|
sil [transparent] [ossa] [ossa] @yield_inout : $@yield_once() -> (@yields @inout Builtin.Int8) {
|
|
entry:
|
|
%addr = alloc_stack $Builtin.Int8
|
|
%8 = integer_literal $Builtin.Int8, 8
|
|
store %8 to [trivial] %addr : $*Builtin.Int8
|
|
yield %addr : $*Builtin.Int8, resume resume, unwind unwind
|
|
|
|
resume:
|
|
%use = function_ref @use : $@convention(thin) (@in Builtin.Int8) -> ()
|
|
apply %use(%addr) : $@convention(thin) (@in Builtin.Int8) -> ()
|
|
dealloc_stack %addr: $*Builtin.Int8
|
|
%ret = tuple ()
|
|
return %ret : $()
|
|
|
|
unwind:
|
|
%3000 = integer_literal $Builtin.Int32, 3000
|
|
%marker = function_ref @marker : $@convention(thin) (Builtin.Int32) -> ()
|
|
apply %marker(%3000) : $@convention(thin) (Builtin.Int32) -> ()
|
|
dealloc_stack %addr: $*Builtin.Int8
|
|
unwind
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_simple_call_yield_inout : $@convention(thin) (Builtin.Int1) -> () {
|
|
// CHECK: bb0(%0 : $Builtin.Int1):
|
|
// CHECK-NEXT: %1 = alloc_stack $Builtin.Int8
|
|
// CHECK-NEXT: %2 = integer_literal $Builtin.Int8, 8
|
|
// CHECK-NEXT: store %2 to [trivial] %1 : $*Builtin.Int8
|
|
// CHECK-NEXT: cond_br %0, bb1, bb2
|
|
|
|
// CHECK: bb1:
|
|
// CHECK-NEXT: [[T0:%.*]] = integer_literal $Builtin.Int8, 8
|
|
// CHECK-NEXT: store [[T0]] to [trivial] %1 : $*Builtin.Int8
|
|
// CHECK-NEXT: // function_ref
|
|
// CHECK-NEXT: [[USE:%.*]] = function_ref @use : $@convention(thin) (@in Builtin.Int8) -> ()
|
|
// CHECK-NEXT: apply [[USE]](%1) : $@convention(thin) (@in Builtin.Int8) -> ()
|
|
// CHECK-NEXT: dealloc_stack %1 : $*Builtin.Int8
|
|
// CHECK-NEXT: tuple ()
|
|
// CHECK-NEXT: br bb3
|
|
|
|
// CHECK: bb2:
|
|
// CHECK-NEXT: [[T0:%.*]] = integer_literal $Builtin.Int32, 3000
|
|
// CHECK-NEXT: // function_ref
|
|
// CHECK-NEXT: [[MARKER:%.*]] = function_ref @marker : $@convention(thin) (Builtin.Int32) -> ()
|
|
// CHECK-NEXT: apply [[MARKER]]([[T0]]) : $@convention(thin) (Builtin.Int32) -> ()
|
|
// CHECK-NEXT: dealloc_stack %1 : $*Builtin.Int8
|
|
// CHECK-NEXT: br bb3
|
|
|
|
// CHECK: bb3:
|
|
// CHECK-NEXT: [[T0:%.*]] = tuple ()
|
|
// CHECK-NEXT: return [[T0]] : $()
|
|
// CHECK: }
|
|
|
|
sil [ossa] @test_simple_call_yield_inout : $(Builtin.Int1) -> () {
|
|
entry(%flag : $Builtin.Int1):
|
|
%0 = function_ref @yield_inout : $@convention(thin) @yield_once() -> (@yields @inout Builtin.Int8)
|
|
(%addr, %token) = begin_apply %0() : $@convention(thin) @yield_once() -> (@yields @inout Builtin.Int8)
|
|
cond_br %flag, yes, no
|
|
|
|
yes:
|
|
%8 = integer_literal $Builtin.Int8, 8
|
|
store %8 to [trivial] %addr : $*Builtin.Int8
|
|
end_apply %token as $()
|
|
br cont
|
|
|
|
no:
|
|
abort_apply %token
|
|
br cont
|
|
|
|
cont:
|
|
%ret = tuple ()
|
|
return %ret : $()
|
|
}
|
|
|
|
sil [transparent] [ossa] [ossa] @yield_inout_result : $@yield_once() -> (@yields @inout Builtin.Int8, Builtin.Int32) {
|
|
entry:
|
|
%addr = alloc_stack $Builtin.Int8
|
|
%8 = integer_literal $Builtin.Int8, 8
|
|
store %8 to [trivial] %addr : $*Builtin.Int8
|
|
yield %addr : $*Builtin.Int8, resume resume, unwind unwind
|
|
|
|
resume:
|
|
%use = function_ref @use : $@convention(thin) (@in Builtin.Int8) -> ()
|
|
apply %use(%addr) : $@convention(thin) (@in Builtin.Int8) -> ()
|
|
dealloc_stack %addr: $*Builtin.Int8
|
|
%42 = integer_literal $Builtin.Int32, 42
|
|
return %42 : $Builtin.Int32
|
|
|
|
unwind:
|
|
%3000 = integer_literal $Builtin.Int32, 3000
|
|
%marker = function_ref @marker : $@convention(thin) (Builtin.Int32) -> ()
|
|
apply %marker(%3000) : $@convention(thin) (Builtin.Int32) -> ()
|
|
dealloc_stack %addr: $*Builtin.Int8
|
|
unwind
|
|
}
|
|
|
|
sil [ossa] @test_simple_call_yield_inout_result : $(Builtin.Int1) -> Builtin.Int32 {
|
|
entry(%flag : $Builtin.Int1):
|
|
%0 = function_ref @yield_inout_result : $@convention(thin) @yield_once() -> (@yields @inout Builtin.Int8, Builtin.Int32)
|
|
(%addr, %token) = begin_apply %0() : $@convention(thin) @yield_once() -> (@yields @inout Builtin.Int8, Builtin.Int32)
|
|
cond_br %flag, yes, no
|
|
|
|
yes:
|
|
%8 = integer_literal $Builtin.Int8, 8
|
|
store %8 to [trivial] %addr : $*Builtin.Int8
|
|
%42 = end_apply %token as $Builtin.Int32
|
|
br cont(%42 : $Builtin.Int32)
|
|
|
|
no:
|
|
abort_apply %token
|
|
%0val = integer_literal $Builtin.Int32, 0
|
|
br cont(%0val : $Builtin.Int32)
|
|
|
|
cont(%ret : $Builtin.Int32):
|
|
return %ret : $Builtin.Int32
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_simple_call_yield_inout_result : $@convention(thin) (Builtin.Int1) -> Builtin.Int32 {
|
|
// CHECK: bb0(%0 : $Builtin.Int1):
|
|
// CHECK-NEXT: %1 = alloc_stack $Builtin.Int8
|
|
// CHECK-NEXT: %2 = integer_literal $Builtin.Int8, 8
|
|
// CHECK-NEXT: store %2 to [trivial] %1 : $*Builtin.Int8
|
|
// CHECK-NEXT: cond_br %0, bb1, bb2
|
|
|
|
// CHECK: bb1:
|
|
// CHECK-NEXT: [[T0:%.*]] = integer_literal $Builtin.Int8, 8
|
|
// CHECK-NEXT: store [[T0]] to [trivial] %1 : $*Builtin.Int8
|
|
// CHECK-NEXT: // function_ref
|
|
// CHECK-NEXT: [[USE:%.*]] = function_ref @use : $@convention(thin) (@in Builtin.Int8) -> ()
|
|
// CHECK-NEXT: apply [[USE]](%1) : $@convention(thin) (@in Builtin.Int8) -> ()
|
|
// CHECK-NEXT: dealloc_stack %1 : $*Builtin.Int8
|
|
// CHECK-NEXT: [[NORMAL_RES:%.*]] = integer_literal $Builtin.Int32, 42
|
|
// CHECK-NEXT: br bb3([[NORMAL_RES]] : $Builtin.Int32)
|
|
|
|
// CHECK: bb2:
|
|
// CHECK-NEXT: [[T0:%.*]] = integer_literal $Builtin.Int32, 3000
|
|
// CHECK-NEXT: // function_ref
|
|
// CHECK-NEXT: [[MARKER:%.*]] = function_ref @marker : $@convention(thin) (Builtin.Int32) -> ()
|
|
// CHECK-NEXT: apply [[MARKER]]([[T0]]) : $@convention(thin) (Builtin.Int32) -> ()
|
|
// CHECK-NEXT: dealloc_stack %1 : $*Builtin.Int8
|
|
// CHECK-NEXT: [[UNWIND_RES:%.*]] = integer_literal $Builtin.Int32, 0
|
|
// CHECK-NEXT: br bb3([[UNWIND_RES]] : $Builtin.Int32)
|
|
|
|
// CHECK: bb3([[RES:%.*]] : $Builtin.Int32):
|
|
// CHECK-NEXT: return [[RES]] : $Builtin.Int32
|
|
// CHECK: }
|
|
|
|
// We can't inline yet if there are multiple ends.
|
|
// CHECK-LABEL: sil [ossa] @test_multi_end_yield_inout : $@convention(thin) (Builtin.Int1) -> () {
|
|
// CHECK: [[T0:%.*]] = function_ref @yield_inout
|
|
// CHECK: begin_apply [[T0]]
|
|
sil [ossa] @test_multi_end_yield_inout : $(Builtin.Int1) -> () {
|
|
entry(%flag : $Builtin.Int1):
|
|
%0 = function_ref @yield_inout : $@convention(thin) @yield_once() -> (@yields @inout Builtin.Int8)
|
|
(%addr, %token) = begin_apply %0() : $@convention(thin) @yield_once() -> (@yields @inout Builtin.Int8)
|
|
cond_br %flag, yes, no
|
|
|
|
yes:
|
|
end_apply %token as $()
|
|
br cont
|
|
|
|
no:
|
|
end_apply %token as $()
|
|
br cont
|
|
|
|
cont:
|
|
%ret = tuple ()
|
|
return %ret : $()
|
|
}
|
|
|
|
// We can't inline yet if there are multiple aborts.
|
|
// CHECK-LABEL: sil [ossa] @test_multi_abort_yield_inout : $@convention(thin) (Builtin.Int1) -> () {
|
|
// CHECK: [[T0:%.*]] = function_ref @yield_inout
|
|
// CHECK: begin_apply [[T0]]
|
|
sil [ossa] @test_multi_abort_yield_inout : $(Builtin.Int1) -> () {
|
|
entry(%flag : $Builtin.Int1):
|
|
%0 = function_ref @yield_inout : $@convention(thin) @yield_once() -> (@yields @inout Builtin.Int8)
|
|
(%addr, %token) = begin_apply %0() : $@convention(thin) @yield_once() -> (@yields @inout Builtin.Int8)
|
|
cond_br %flag, yes, no
|
|
|
|
yes:
|
|
abort_apply %token
|
|
br cont
|
|
|
|
no:
|
|
abort_apply %token
|
|
br cont
|
|
|
|
cont:
|
|
%ret = tuple ()
|
|
return %ret : $()
|
|
}
|
|
|
|
sil [transparent] [ossa] @no_yields : $@yield_once () -> (@yields @inout Builtin.Int8) {
|
|
entry:
|
|
%3000 = integer_literal $Builtin.Int32, 3000
|
|
%marker = function_ref @marker : $@convention(thin) (Builtin.Int32) -> ()
|
|
apply %marker(%3000) : $@convention(thin) (Builtin.Int32) -> ()
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_simple_call_no_yields : $@convention(thin) () -> () {
|
|
// CHECK: bb0:
|
|
// CHECK-NEXT: [[T0:%.*]] = integer_literal $Builtin.Int32, 3000
|
|
// CHECK-NEXT: // function_ref
|
|
// CHECK-NEXT: [[MARKER:%.*]] = function_ref @marker : $@convention(thin) (Builtin.Int32) -> ()
|
|
// CHECK-NEXT: apply [[MARKER]]([[T0]]) : $@convention(thin) (Builtin.Int32) -> ()
|
|
// CHECK-NEXT: unreachable
|
|
// CHECK: }
|
|
sil [ossa] @test_simple_call_no_yields : $() -> () {
|
|
entry:
|
|
%0 = function_ref @no_yields : $@convention(thin) @yield_once () -> (@yields @inout Builtin.Int8)
|
|
(%addr, %token) = begin_apply %0() : $@convention(thin) @yield_once () -> (@yields @inout Builtin.Int8)
|
|
%use = function_ref @use : $@convention(thin) (@in Builtin.Int8) -> ()
|
|
apply %use(%addr) : $@convention(thin) (@in Builtin.Int8) -> ()
|
|
end_apply %token as $()
|
|
%ret = tuple ()
|
|
return %ret : $()
|
|
}
|
|
|
|
sil [transparent] [ossa] @stack_overlap : $@convention(thin) @yield_once () -> (@yields @inout Builtin.Int32) {
|
|
entry:
|
|
%marker = function_ref @marker : $@convention(thin) (Builtin.Int32) -> ()
|
|
%temp = alloc_stack $Builtin.Int32
|
|
%1000 = integer_literal $Builtin.Int32, 1000
|
|
store %1000 to [trivial] %temp : $*Builtin.Int32
|
|
%2000 = integer_literal $Builtin.Int32, 2000
|
|
apply %marker(%2000) : $@convention(thin) (Builtin.Int32) -> ()
|
|
yield %temp : $*Builtin.Int32, resume resume, unwind unwind
|
|
|
|
resume:
|
|
%3000 = integer_literal $Builtin.Int32, 3000
|
|
apply %marker(%3000) : $@convention(thin) (Builtin.Int32) -> ()
|
|
dealloc_stack %temp : $*Builtin.Int32
|
|
%4000 = integer_literal $Builtin.Int32, 4000
|
|
apply %marker(%4000) : $@convention(thin) (Builtin.Int32) -> ()
|
|
%ret = tuple ()
|
|
return %ret : $()
|
|
|
|
unwind:
|
|
dealloc_stack %temp : $*Builtin.Int32
|
|
unwind
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_stack_overlap_dealloc
|
|
// CHECK: bb0:
|
|
// CHECK-NEXT: [[A16:%.*]] = alloc_stack $Builtin.Int16
|
|
// CHECK-NEXT: // function_ref
|
|
// CHECK-NEXT: [[MARKER:%.*]] = function_ref @marker
|
|
// CHECK-NEXT: [[A32:%.*]] = alloc_stack $Builtin.Int32
|
|
// CHECK-NEXT: [[I1000:%.*]] = integer_literal $Builtin.Int32, 1000
|
|
// CHECK-NEXT: store [[I1000]] to [trivial] [[A32]]
|
|
// CHECK-NEXT: [[I2000:%.*]] = integer_literal $Builtin.Int32, 2000
|
|
// CHECK-NEXT: apply [[MARKER]]([[I2000]])
|
|
// CHECK-NEXT: [[I3000:%.*]] = integer_literal $Builtin.Int32, 3000
|
|
// CHECK-NEXT: apply [[MARKER]]([[I3000]])
|
|
// CHECK-NEXT: dealloc_stack [[A32]] : $*Builtin.Int32
|
|
// Note that this has been delayed to follow stack discipline.
|
|
// CHECK-NEXT: dealloc_stack [[A16]] : $*Builtin.Int16
|
|
// CHECK-NEXT: [[I4000:%.*]] = integer_literal $Builtin.Int32, 4000
|
|
// CHECK-NEXT: apply [[MARKER]]([[I4000]])
|
|
// CHECK-NEXT: tuple ()
|
|
// CHECK-NEXT: [[RET:%.*]] = tuple ()
|
|
// CHECK-NEXT: return [[RET]] : $()
|
|
// CHECK-LABEL: // end sil function 'test_stack_overlap_dealloc'
|
|
sil [ossa] @test_stack_overlap_dealloc : $() -> () {
|
|
bb0:
|
|
%stack = alloc_stack $Builtin.Int16
|
|
%0 = function_ref @stack_overlap : $@convention(thin) @yield_once () -> (@yields @inout Builtin.Int32)
|
|
(%value, %token) = begin_apply %0() : $@convention(thin) @yield_once () -> (@yields @inout Builtin.Int32)
|
|
dealloc_stack %stack : $*Builtin.Int16
|
|
end_apply %token as $()
|
|
%ret = tuple ()
|
|
return %ret : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_stack_overlap_alloc
|
|
// CHECK: bb0:
|
|
// CHECK-NEXT: // function_ref
|
|
// CHECK-NEXT: [[MARKER:%.*]] = function_ref @marker
|
|
// CHECK-NEXT: [[A32:%.*]] = alloc_stack $Builtin.Int32
|
|
// CHECK-NEXT: [[I1000:%.*]] = integer_literal $Builtin.Int32, 1000
|
|
// CHECK-NEXT: store [[I1000]] to [trivial] [[A32]]
|
|
// CHECK-NEXT: [[I2000:%.*]] = integer_literal $Builtin.Int32, 2000
|
|
// CHECK-NEXT: apply [[MARKER]]([[I2000]])
|
|
// CHECK-NEXT: [[A16:%.*]] = alloc_stack $Builtin.Int16
|
|
// CHECK-NEXT: [[I3000:%.*]] = integer_literal $Builtin.Int32, 3000
|
|
// CHECK-NEXT: apply [[MARKER]]([[I3000]])
|
|
// CHECK-NEXT: [[I4000:%.*]] = integer_literal $Builtin.Int32, 4000
|
|
// CHECK-NEXT: apply [[MARKER]]([[I4000]])
|
|
// CHECK-NEXT: tuple ()
|
|
// CHECK-NEXT: dealloc_stack [[A16]] : $*Builtin.Int16
|
|
// Note that this has been delayed to follow stack discipline.
|
|
// CHECK-NEXT: dealloc_stack [[A32]] : $*Builtin.Int32
|
|
// CHECK-NEXT: [[RET:%.*]] = tuple ()
|
|
// CHECK-NEXT: return [[RET]] : $()
|
|
// CHECK-LABEL: // end sil function 'test_stack_overlap_alloc'
|
|
sil [ossa] @test_stack_overlap_alloc : $() -> () {
|
|
bb0:
|
|
%0 = function_ref @stack_overlap : $@convention(thin) @yield_once () -> (@yields @inout Builtin.Int32)
|
|
(%value, %token) = begin_apply %0() : $@convention(thin) @yield_once () -> (@yields @inout Builtin.Int32)
|
|
%stack = alloc_stack $Builtin.Int16
|
|
end_apply %token as $()
|
|
dealloc_stack %stack : $*Builtin.Int16
|
|
%ret = tuple ()
|
|
return %ret : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_stack_overlap_unreachable
|
|
// CHECK: bb0:
|
|
// CHECK: [[A16:%.*]] = alloc_stack $Builtin.Int16
|
|
// CHECK: [[A32:%.*]] = alloc_stack $Builtin.Int32
|
|
// CHECK: bb1:
|
|
// CHECK: unreachable
|
|
// CHECK: bb2:
|
|
// CHECK: dealloc_stack [[A32]] : $*Builtin.Int32
|
|
// CHECK: dealloc_stack [[A16]] : $*Builtin.Int16
|
|
// CHECK: return
|
|
// CHECK-LABEL: // end sil function 'test_stack_overlap_unreachable'
|
|
sil [ossa] @test_stack_overlap_unreachable : $() -> () {
|
|
bb0:
|
|
%stack = alloc_stack $Builtin.Int16
|
|
%0 = function_ref @stack_overlap : $@convention(thin) @yield_once () -> (@yields @inout Builtin.Int32)
|
|
(%value, %token) = begin_apply %0() : $@convention(thin) @yield_once () -> (@yields @inout Builtin.Int32)
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
dealloc_stack %stack : $*Builtin.Int16
|
|
unreachable
|
|
|
|
bb2:
|
|
end_apply %token as $()
|
|
dealloc_stack %stack : $*Builtin.Int16
|
|
%ret = tuple ()
|
|
return %ret : $()
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_store_borrow_owned_as_guaranteed_yield : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}:
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $SomeClass
|
|
// CHECK: [[INSTANCE:%[^,]+]] = apply
|
|
// CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [[INSTANCE]]
|
|
// CHECK: [[BORROW:%[^,]+]] = store_borrow [[LIFETIME]] to [[ADDR]]
|
|
// CHECK: yield [[BORROW]] {{.*}}, resume [[BB_RESUME:bb[0-9]+]], unwind [[BB_UNWIND:bb[0-9]+]]
|
|
// CHECK: [[BB_RESUME]]:
|
|
// CHECK: end_borrow [[BORROW]]
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK: end_borrow [[LIFETIME]]
|
|
// CHECK: destroy_value [[INSTANCE]]
|
|
// CHECK: tuple ()
|
|
// CHECK: [[RETVAL:%[^,]+]] = tuple ()
|
|
// CHECK: return [[RETVAL]]
|
|
// CHECK: [[BB_UNWIND]]:
|
|
// CHECK: end_borrow [[BORROW]]
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK: end_borrow [[LIFETIME]]
|
|
// CHECK: destroy_value [[INSTANCE]]
|
|
// CHECK: unwind
|
|
// CHECK-LABEL: } // end sil function 'test_store_borrow_owned_as_guaranteed_yield'
|
|
sil [ossa] @test_store_borrow_owned_as_guaranteed_yield : $@yield_once @convention(thin) @substituted <T> () -> @yields @in_guaranteed T for <SomeClass> {
|
|
entry:
|
|
%addr = alloc_stack $SomeClass
|
|
%callee = function_ref @yield_owned_as_guaranteed : $@yield_once @convention(thin) () -> @yields @guaranteed SomeClass
|
|
(%instance, %token) = begin_apply %callee() : $@yield_once @convention(thin) () -> @yields @guaranteed SomeClass
|
|
%borrow = store_borrow %instance to %addr : $*SomeClass
|
|
yield %borrow : $*SomeClass, resume bb_resume, unwind bb_unwind
|
|
|
|
bb_resume:
|
|
end_borrow %borrow : $*SomeClass
|
|
dealloc_stack %addr : $*SomeClass
|
|
end_apply %token as $()
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
|
|
bb_unwind:
|
|
end_borrow %borrow : $*SomeClass
|
|
dealloc_stack %addr : $*SomeClass
|
|
abort_apply %token
|
|
unwind
|
|
|
|
}
|
|
|
|
sil [ossa] [transparent] @simplest_in_guaranteed : $@yield_once @convention(thin) () -> @yields @in_guaranteed () {
|
|
entry:
|
|
%tuple = tuple ()
|
|
%addr = alloc_stack $()
|
|
store %tuple to [trivial] %addr : $*()
|
|
yield %addr : $*(), resume resume_block, unwind unwind_block
|
|
|
|
resume_block:
|
|
dealloc_stack %addr : $*()
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
|
|
unwind_block:
|
|
dealloc_stack %addr : $*()
|
|
unwind
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @ends_1 : {{.*}} {
|
|
// CHECK: [[VOID:%[^,]+]] = tuple ()
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $()
|
|
// CHECK: store [[VOID]] to [trivial] [[ADDR]]
|
|
// CHECK: cond_br undef, [[GOOD:bb[0-9]+]], [[BAD:bb[0-9]+]]
|
|
// CHECK: [[GOOD]]:
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK: br [[EXIT:bb[0-9]+]]
|
|
// CHECK: [[BAD]]:
|
|
// CHECK: cond_br undef, [[NORMAL_BAD:bb[0-9]+]], [[REALLY_BAD:bb[0-9]+]]
|
|
// CHECK: [[NORMAL_BAD]]:
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK: br [[EXIT]]
|
|
// CHECK: [[REALLY_BAD]]:
|
|
// CHECK: unreachable
|
|
// CHECK: [[EXIT]]:
|
|
// CHECK-LABEL: } // end sil function 'ends_1'
|
|
sil [ossa] @ends_1 : $@convention(thin) () -> () {
|
|
entry:
|
|
%simplest = function_ref @simplest_in_guaranteed : $@yield_once @convention(thin) () -> @yields @in_guaranteed ()
|
|
(%_, %token) = begin_apply %simplest() : $@yield_once @convention(thin) () -> @yields @in_guaranteed ()
|
|
cond_br undef, good, bad
|
|
|
|
good:
|
|
end_apply %token as $()
|
|
br exit
|
|
|
|
bad:
|
|
cond_br undef, normal_bad, really_bad
|
|
|
|
normal_bad:
|
|
abort_apply %token
|
|
br exit
|
|
|
|
really_bad:
|
|
end_borrow %token : $Builtin.SILToken
|
|
unreachable
|
|
|
|
exit:
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// Test handling for multiple end_borrows of a token.
|
|
// CHECK-LABEL: sil [ossa] @ends_2 : {{.*}} {
|
|
// CHECK: [[VOID:%[^,]+]] = tuple ()
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $()
|
|
// CHECK: store [[VOID]] to [trivial] [[ADDR]] : $*()
|
|
// CHECK: cond_br undef, [[GOOD:bb[0-9]+]], [[BAD:bb[0-9]+]]
|
|
// CHECK: [[GOOD]]:
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK: br [[EXIT:bb[0-9]+]]
|
|
// CHECK: [[BAD]]:
|
|
// CHECK: cond_br undef, [[NORMAL_BAD:bb[0-9]+]], [[REALLY_BAD:bb[0-9]+]]
|
|
// CHECK: [[NORMAL_BAD]]:
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK: br [[EXIT]]
|
|
// CHECK: [[REALLY_BAD]]:
|
|
// CHECK: cond_br undef, [[BAD_NEWS_BUNNIES:bb[0-9]+]], [[BAD_NEWS_BEARS:bb[0-9]+]]
|
|
// CHECK: [[BAD_NEWS_BUNNIES]]:
|
|
// CHECK: unreachable
|
|
// CHECK: [[BAD_NEWS_BEARS]]:
|
|
// CHECK: unreachable
|
|
// CHECK: [[EXIT]]:
|
|
// CHECK-LABEL: } // end sil function 'ends_2'
|
|
sil [ossa] @ends_2 : $@convention(thin) () -> () {
|
|
entry:
|
|
%simplest = function_ref @simplest_in_guaranteed : $@yield_once @convention(thin) () -> @yields @in_guaranteed ()
|
|
(%_, %token) = begin_apply %simplest() : $@yield_once @convention(thin) () -> @yields @in_guaranteed ()
|
|
cond_br undef, good, bad
|
|
|
|
good:
|
|
end_apply %token as $()
|
|
br exit
|
|
|
|
bad:
|
|
cond_br undef, normal_bad, really_bad
|
|
|
|
normal_bad:
|
|
abort_apply %token
|
|
br exit
|
|
|
|
really_bad:
|
|
cond_br undef, bad_news_bunnies, bad_news_bears
|
|
|
|
bad_news_bunnies:
|
|
end_borrow %token : $Builtin.SILToken
|
|
unreachable
|
|
|
|
bad_news_bears:
|
|
end_borrow %token : $Builtin.SILToken
|
|
unreachable
|
|
|
|
exit:
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
sil [transparent] [ossa] @simplest_yield_once_2 : $@yield_once_2 @convention(thin) () -> @yields @in_guaranteed () {
|
|
%addr = alloc_stack $()
|
|
yield %addr : $*(), resume resume_block, unwind unwind_block
|
|
|
|
unwind_block:
|
|
dealloc_stack %addr : $*()
|
|
unwind
|
|
|
|
resume_block:
|
|
dealloc_stack %addr : $*()
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @simplest_begin_apply_yield_once_2 : {{.*}} {
|
|
// CHECK-NOT: begin_apply
|
|
// CHECK-LABEL: } // end sil function 'simplest_begin_apply_yield_once_2'
|
|
sil [ossa] @simplest_begin_apply_yield_once_2 : $@convention(thin) () -> () {
|
|
%callee = function_ref @simplest_yield_once_2 : $@yield_once_2 @convention(thin) () -> @yields @in_guaranteed ()
|
|
(%addr, %token, %allocation) = begin_apply %callee() : $@yield_once_2 @convention(thin) () -> @yields @in_guaranteed ()
|
|
end_apply %token as $()
|
|
dealloc_stack %allocation : $*Builtin.SILToken
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|