mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
* Allow normal function results of @yield_once coroutines * Address review comments * Workaround LLVM coroutine codegen problem: it assumes that unwind path never returns. This is not true to Swift coroutines as unwind path should end with error result.
626 lines
29 KiB
Plaintext
626 lines
29 KiB
Plaintext
// RUN: %target-sil-opt -enable-sil-verify-all %s -mandatory-inlining | %FileCheck %s
|
|
|
|
sil_stage raw
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
class C {
|
|
var i: Builtin.Int64
|
|
init(i: Builtin.Int64)
|
|
}
|
|
|
|
private class C2 {
|
|
var i: Builtin.Int64 { get set }
|
|
init(i: Builtin.Int64)
|
|
}
|
|
|
|
class Klass {}
|
|
|
|
class AnotherKlass {}
|
|
|
|
sil [transparent] [ossa] @calleeWithGuaranteed : $@convention(thin) (@guaranteed C) -> Builtin.Int64 {
|
|
bb(%0 : @guaranteed $C):
|
|
%1 = ref_element_addr %0 : $C, #C.i
|
|
%2 = load [trivial] %1 : $*Builtin.Int64
|
|
return %2 : $Builtin.Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @callerWithOwned : $@convention(thin) (@owned C) -> Builtin.Int64 {
|
|
// CHECK: bb0(%0 : @owned $C):
|
|
// CHECK: [[BORROW:%.*]] = begin_borrow %0 : $C
|
|
// CHECK: [[ADDR:%.*]] = ref_element_addr [[BORROW]] : $C, #C.i
|
|
// CHECK: [[VAL:%.*]] = load [trivial] [[ADDR]] : $*Builtin.Int64
|
|
// CHECK: end_borrow [[BORROW]] : $C
|
|
// CHECK: destroy_value %0 : $C
|
|
// CHECK: return [[VAL]] : $Builtin.Int64
|
|
// CHECK-LABEL: } // end sil function 'callerWithOwned'
|
|
sil [ossa] @callerWithOwned : $@convention(thin) (@owned C) -> Builtin.Int64 {
|
|
bb(%0 : @owned $C):
|
|
%fn = function_ref @calleeWithGuaranteed : $@convention(thin) (@guaranteed C) -> Builtin.Int64
|
|
%call = apply %fn(%0) : $@convention(thin) (@guaranteed C) -> Builtin.Int64
|
|
destroy_value %0 : $C
|
|
return %call : $Builtin.Int64
|
|
}
|
|
|
|
struct MyError : Error {}
|
|
|
|
sil [transparent] [ossa] @calleeWithGuaranteedThrows : $@convention(thin) (@guaranteed C) -> (Builtin.Int64, @error Error) {
|
|
bb(%0 : @guaranteed $C):
|
|
%1 = ref_element_addr %0 : $C, #C.i
|
|
%2 = load [trivial] %1 : $*Builtin.Int64
|
|
%3 = integer_literal $Builtin.Int64, 0
|
|
%5 = builtin "cmp_eq_Int64"(%2 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int1
|
|
cond_br %5, bb1, bb2
|
|
|
|
bb1:
|
|
%6 = alloc_existential_box $Error, $MyError
|
|
throw %6 : $Error
|
|
|
|
bb2:
|
|
return %2 : $Builtin.Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @callerWithThrow : $@convention(thin) (@owned C) -> (Builtin.Int64, @error any Error) {
|
|
// CHECK: bb0(%0 : @owned $C):
|
|
// CHECK: [[BORROW:%.*]] = begin_borrow %0 : $C
|
|
// CHECK: [[ADDR:%.*]] = ref_element_addr [[BORROW]] : $C, #C.i
|
|
// CHECK: [[VAL:%.*]] = load [trivial] [[ADDR]] : $*Builtin.Int64
|
|
// CHECK: bb{{.*}}:
|
|
// CHECK: [[ERR:%.*]] = alloc_existential_box $any Error, $MyError
|
|
// CHECK: end_borrow [[BORROW]] : $C
|
|
// CHECK: destroy_value %0 : $C
|
|
// CHECK: throw [[ERR]] : $any Error
|
|
// CHECK: bb{{.*}}:
|
|
// CHECK: end_borrow [[BORROW]] : $C
|
|
// CHECK: destroy_value %0 : $C
|
|
// CHECK: return [[VAL]] : $Builtin.Int64
|
|
// CHECK-LABEL: } // end sil function 'callerWithThrow'
|
|
sil [ossa] @callerWithThrow : $@convention(thin) (@owned C) -> (Builtin.Int64, @error Error) {
|
|
bb(%0 : @owned $C):
|
|
%fn = function_ref @calleeWithGuaranteedThrows : $@convention(thin) (@guaranteed C) -> (Builtin.Int64, @error Error)
|
|
try_apply %fn(%0) : $@convention(thin) (@guaranteed C) -> (Builtin.Int64, @error Error), normal bb1, error bb2
|
|
|
|
bb1(%4 : $Builtin.Int64):
|
|
destroy_value %0 : $C
|
|
return %4 : $Builtin.Int64
|
|
|
|
bb2(%5 : @owned $Error):
|
|
destroy_value %0 : $C
|
|
throw %5 : $Error
|
|
}
|
|
|
|
// Partial Apply copy_value, begin_borrow
|
|
|
|
sil @nativeobject_plus : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
sil @partial_apply_user : $@convention(thin) (@owned @callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject) -> ()
|
|
sil @partial_apply_user_guaranteed : $@convention(thin) (@guaranteed @callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject) -> ()
|
|
|
|
sil [ossa] [transparent] @test_partial_nativeobject_baz : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : @owned $Builtin.NativeObject, %1 : @owned $Builtin.NativeObject):
|
|
%6 = function_ref @nativeobject_plus : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
%7 = apply %6(%0, %1) : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
return %7 : $Builtin.NativeObject
|
|
}
|
|
|
|
sil [ossa] [transparent] @test_partial_nativeobject_bar : $@convention(thin) (@owned @callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : @owned $@callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject, %1 : @owned $Builtin.NativeObject):
|
|
%7 = apply %0(%1) : $@callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
return %7 : $Builtin.NativeObject
|
|
}
|
|
|
|
sil [ossa] [transparent] @test_partial_nativeobject_bar_guaranteed : $@convention(thin) (@guaranteed @callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : @guaranteed $@callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject, %1 : @owned $Builtin.NativeObject):
|
|
%7 = apply %0(%1) : $@callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
return %7 : $Builtin.NativeObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [transparent] [ossa] @test_partial_nativeobject_foo : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
// CHECK: bb0([[ARG:%.*]] : @owned $Builtin.NativeObject):
|
|
// CHECK: [[FN:%.*]] = function_ref @test_partial_nativeobject_baz :
|
|
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
|
|
// CHECK: [[ARG_COPY_2:%.*]] = copy_value [[ARG_COPY]]
|
|
// CHECK: [[PAI:%.*]] = partial_apply [[FN]]([[ARG_COPY]])
|
|
// CHECK: [[ARG_COPY_3:%.*]] = copy_value [[ARG]]
|
|
// CHECK: [[MOVE_ARG_COPY_3:%[^,]+]] = move_value [lexical] [[ARG_COPY_3]]
|
|
// CHECK: [[MOVE_ARG_COPY_2:%[^,]+]] = move_value [lexical] [[ARG_COPY_2]]
|
|
// CHECK: [[FN2:%.*]] = function_ref @nativeobject_plus :
|
|
// CHECK: [[RESULT:%.*]] = apply [[FN2]]([[MOVE_ARG_COPY_3]], [[MOVE_ARG_COPY_2]])
|
|
// CHECK: [[PAI_COPY:%.*]] = copy_value [[PAI]]
|
|
// CHECK: [[OPAQUE_FN:%.*]] = function_ref @partial_apply_user
|
|
// CHECK: apply [[OPAQUE_FN]]([[PAI_COPY]])
|
|
// CHECK: destroy_value [[PAI]]
|
|
// CHECK: destroy_value [[ARG]]
|
|
// CHECK: return [[RESULT]]
|
|
// CHECK: } // end sil function 'test_partial_nativeobject_foo'
|
|
sil [transparent] [ossa] @test_partial_nativeobject_foo : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%2 = function_ref @test_partial_nativeobject_bar : $@convention(thin) (@owned @callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
%3 = function_ref @test_partial_nativeobject_baz : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
br bb1
|
|
|
|
bb1:
|
|
%0copy1 = copy_value %0 : $Builtin.NativeObject
|
|
%5 = partial_apply %3(%0copy1) : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
br bb2
|
|
|
|
bb2:
|
|
%0copy2 = copy_value %0 : $Builtin.NativeObject
|
|
%5copy1 = copy_value %5 : $@callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
%13 = apply %2(%5copy1, %0copy2) : $@convention(thin) (@owned @callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
br bb3
|
|
|
|
bb3:
|
|
%5copy2 = copy_value %5 : $@callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
%15 = function_ref @partial_apply_user : $@convention(thin) (@owned @callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject) -> ()
|
|
apply %15(%5copy2) : $@convention(thin) (@owned @callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject) -> ()
|
|
destroy_value %5 : $@callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
destroy_value %0 : $Builtin.NativeObject
|
|
return %13 : $Builtin.NativeObject
|
|
}
|
|
|
|
// Make sure we do not eliminate the actual closure but do the inlining.
|
|
//
|
|
// CHECK-LABEL: sil [transparent] [ossa] @test_partial_nativeobject_foo_guaranteed_explicit_borrow : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
// CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed]
|
|
// CHECK: [[NATIVEOBJECT_PLUS_FUNC:%.*]] = function_ref @nativeobject_plus : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
// CHECK-NEXT: apply [[NATIVEOBJECT_PLUS_FUNC]](
|
|
// CHECK: } // end sil function 'test_partial_nativeobject_foo_guaranteed_explicit_borrow'
|
|
sil [transparent] [ossa] @test_partial_nativeobject_foo_guaranteed_explicit_borrow : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%2 = function_ref @test_partial_nativeobject_bar_guaranteed : $@convention(thin) (@guaranteed @callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
%3 = function_ref @test_partial_nativeobject_baz : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
br bb1
|
|
|
|
bb1:
|
|
%0copy1 = copy_value %0 : $Builtin.NativeObject
|
|
%5 = partial_apply [callee_guaranteed] %3(%0copy1) : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
%6 = begin_borrow %5 : $@callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
br bb2
|
|
|
|
bb2:
|
|
%0copy2 = copy_value %0 : $Builtin.NativeObject
|
|
%13 = apply %2(%6, %0copy2) : $@convention(thin) (@guaranteed @callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
end_borrow %6 : $@callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
br bb3
|
|
|
|
bb3:
|
|
%15 = function_ref @partial_apply_user_guaranteed : $@convention(thin) (@guaranteed @callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject) -> ()
|
|
apply %15(%5) : $@convention(thin) (@guaranteed @callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject) -> ()
|
|
destroy_value %5 : $@callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
destroy_value %0 : $Builtin.NativeObject
|
|
return %13 : $Builtin.NativeObject
|
|
}
|
|
|
|
// Make sure we do the inlining and delete the closure.
|
|
// CHECK-LABEL: sil [transparent] [ossa] @test_partial_nativeobject_foo_guaranteed_explicit_borrow_dead_pa : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
// CHECK-NOT: partial_apply
|
|
// CHECK: [[NATIVEOBJECT_PLUS_FUNC:%.*]] = function_ref @nativeobject_plus : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
// CHECK-NEXT: apply [[NATIVEOBJECT_PLUS_FUNC]](
|
|
// CHECK-NOT: partial_apply
|
|
// CHECK: } // end sil function 'test_partial_nativeobject_foo_guaranteed_explicit_borrow_dead_pa'
|
|
sil [transparent] [ossa] @test_partial_nativeobject_foo_guaranteed_explicit_borrow_dead_pa : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%2 = function_ref @test_partial_nativeobject_bar_guaranteed : $@convention(thin) (@guaranteed @callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
%3 = function_ref @test_partial_nativeobject_baz : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
br bb1
|
|
|
|
bb1:
|
|
%0copy1 = copy_value %0 : $Builtin.NativeObject
|
|
%5 = partial_apply [callee_guaranteed] %3(%0copy1) : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
%6 = begin_borrow %5 : $@callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
br bb2
|
|
|
|
bb2:
|
|
%0copy2 = copy_value %0 : $Builtin.NativeObject
|
|
%13 = apply %2(%6, %0copy2) : $@convention(thin) (@guaranteed @callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
end_borrow %6 : $@callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
br bb3
|
|
|
|
bb3:
|
|
destroy_value %5 : $@callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
destroy_value %0 : $Builtin.NativeObject
|
|
return %13 : $Builtin.NativeObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [transparent] [ossa] @test_partial_nativeobject_foo_guaranteed_implicit_borrow : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
// We shouldn't delete the PAI here.
|
|
// CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed]
|
|
// CHECK: [[NATIVEOBJECT_PLUS_FUNC:%.*]] = function_ref @nativeobject_plus : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
// CHECK: apply [[NATIVEOBJECT_PLUS_FUNC]](
|
|
// CHECK: } // end sil function 'test_partial_nativeobject_foo_guaranteed_implicit_borrow'
|
|
sil [transparent] [ossa] @test_partial_nativeobject_foo_guaranteed_implicit_borrow : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%2 = function_ref @test_partial_nativeobject_bar_guaranteed : $@convention(thin) (@guaranteed @callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
%3 = function_ref @test_partial_nativeobject_baz : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
br bb1
|
|
|
|
bb1:
|
|
%0copy1 = copy_value %0 : $Builtin.NativeObject
|
|
%5 = partial_apply [callee_guaranteed] %3(%0copy1) : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
br bb2
|
|
|
|
bb2:
|
|
%0copy2 = copy_value %0 : $Builtin.NativeObject
|
|
%13 = apply %2(%5, %0copy2) : $@convention(thin) (@guaranteed @callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
br bb3
|
|
|
|
bb3:
|
|
%15 = function_ref @partial_apply_user_guaranteed : $@convention(thin) (@guaranteed @callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject) -> ()
|
|
apply %15(%5) : $@convention(thin) (@guaranteed @callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject) -> ()
|
|
destroy_value %5 : $@callee_guaranteed (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject
|
|
destroy_value %0 : $Builtin.NativeObject
|
|
return %13 : $Builtin.NativeObject
|
|
}
|
|
|
|
sil [transparent] [ossa] @term_ossa_checked_cast_addr_br_takealways_callee : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%1 = alloc_stack $Builtin.NativeObject
|
|
%2 = alloc_stack $Klass
|
|
store %0 to [init] %1 : $*Builtin.NativeObject
|
|
checked_cast_addr_br take_always Builtin.NativeObject in %1 : $*Builtin.NativeObject to Klass in %2 : $*Klass, bb1, bb2
|
|
|
|
bb1:
|
|
destroy_addr %2 : $*Klass
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
dealloc_stack %2 : $*Klass
|
|
dealloc_stack %1 : $*Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
sil [transparent] [ossa] @term_ossa_checked_cast_addr_br_takealways_callee2 : $@convention(thin) (@in @thick Klass.Type) -> () {
|
|
bb0(%0 : $*@thick Klass.Type):
|
|
%2 = alloc_stack $AnotherKlass
|
|
checked_cast_addr_br take_always Klass in %0 : $*@thick Klass.Type to Klass in %2 : $*AnotherKlass, bb1, bb2
|
|
|
|
bb1:
|
|
destroy_addr %2 : $*AnotherKlass
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
dealloc_stack %2 : $*AnotherKlass
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @term_nonossa_checked_cast_addr_br_takealways_caller : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] :
|
|
// CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[ARG]]
|
|
// CHECK-NEXT: [[ARG_MOVE:%[^,]+]] = move_value [lexical] [[ARG_COPY]] : $Builtin.NativeObject
|
|
// CHECK-NEXT: [[SRC_ADDR:%.*]] = alloc_stack $Builtin.NativeObject
|
|
// CHECK-NEXT: [[DEST_ADDR:%.*]] = alloc_stack $Klass
|
|
// CHECK-NEXT: store [[ARG_MOVE]] to [init] [[SRC_ADDR]]
|
|
// CHECK-NEXT: [[RELOADED_ARG:%.*]] = load [take] [[SRC_ADDR]]
|
|
// CHECK-NEXT: checked_cast_br Builtin.NativeObject in [[RELOADED_ARG]] : $Builtin.NativeObject to Klass, [[SUCCESS_BB:bb[0-9]+]], [[FAILURE_BB:bb[0-9]+]]
|
|
//
|
|
// ==> On success, we store the value into dest. The destroy is not from the
|
|
// ==> optimizer, but from the code.
|
|
// CHECK: [[SUCCESS_BB]]([[CAST_VALUE:%.*]] :
|
|
// CHECK-NEXT: store [[CAST_VALUE]] to [init] [[DEST_ADDR]]
|
|
// CHECK-NEXT: destroy_addr [[DEST_ADDR]]
|
|
// CHECK-NEXT: br [[CONT_BB:bb[0-9]+]]
|
|
//
|
|
// ==> take_always implies we destroy in failure
|
|
// CHECK: [[FAILURE_BB]]([[FAILURE_ARG:%.*]] :
|
|
// CHECK-NEXT: destroy_value [[FAILURE_ARG]]
|
|
// CHECK-NEXT: br [[CONT_BB]]
|
|
//
|
|
// CHECK: [[CONT_BB]]:
|
|
// CHECK: destroy_value [[ARG]]
|
|
// CHECK: } // end sil function 'term_nonossa_checked_cast_addr_br_takealways_caller'
|
|
sil [ossa] @term_nonossa_checked_cast_addr_br_takealways_caller : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%3 = function_ref @term_ossa_checked_cast_addr_br_takealways_callee : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
%1 = copy_value %0 : $Builtin.NativeObject
|
|
apply %3(%1) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
destroy_value %0 : $Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
sil [ossa] @get_klass_type : $@convention(thin) () -> @out @thick Klass.Type
|
|
|
|
// CHECK-LABEL: sil [ossa] @term_nonossa_checked_cast_addr_br_takealways_caller2 :
|
|
// CHECK: checked_cast_br Klass in {{.*}} : $@thick Klass.Type to Klass, [[SUCCESS_BB:bb[0-9]+]], [[FAILURE_BB:bb[0-9]+]], forwarding: @owned
|
|
// CHECK: [[SUCCESS_BB]]({{.*}}@owned $AnotherKlass):
|
|
// CHECK: [[FAILURE_BB]]([[FAILURE_ARG:%.*]] :
|
|
// CHECK: } // end sil function 'term_nonossa_checked_cast_addr_br_takealways_caller2'
|
|
sil [ossa] @term_nonossa_checked_cast_addr_br_takealways_caller2 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%res = alloc_stack $@thick Klass.Type
|
|
%2 = function_ref @get_klass_type : $@convention(thin) () -> @out @thick Klass.Type
|
|
apply %2(%res) : $@convention(thin) () -> @out @thick Klass.Type
|
|
%3 = function_ref @term_ossa_checked_cast_addr_br_takealways_callee2 : $@convention(thin) (@in @thick Klass.Type) -> ()
|
|
apply %3(%res) : $@convention(thin) (@in @thick Klass.Type) -> ()
|
|
dealloc_stack %res : $*@thick Klass.Type
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
sil [transparent] [ossa] @term_ossa_checked_cast_addr_br_takeonsuccess_callee : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%1 = alloc_stack $Builtin.NativeObject
|
|
%2 = alloc_stack $Klass
|
|
store %0 to [init] %1 : $*Builtin.NativeObject
|
|
checked_cast_addr_br take_on_success Builtin.NativeObject in %1 : $*Builtin.NativeObject to Klass in %2 : $*Klass, bb1, bb2
|
|
|
|
bb1:
|
|
destroy_addr %2 : $*Klass
|
|
br bb3
|
|
|
|
bb2:
|
|
destroy_addr %1 : $*Builtin.NativeObject
|
|
br bb3
|
|
|
|
bb3:
|
|
dealloc_stack %2 : $*Klass
|
|
dealloc_stack %1 : $*Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @checked_cast_addr_br_takeonsuccess_caller : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] :
|
|
// CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[ARG]]
|
|
// CHECK-NEXT: [[ARG_MOVE:%[^,]+]] = move_value [lexical] [[ARG_COPY]] : $Builtin.NativeObject
|
|
// CHECK-NEXT: [[SRC_ADDR:%.*]] = alloc_stack $Builtin.NativeObject
|
|
// CHECK-NEXT: [[DEST_ADDR:%.*]] = alloc_stack $Klass
|
|
// CHECK-NEXT: store [[ARG_MOVE]] to [init] [[SRC_ADDR]]
|
|
// CHECK-NEXT: [[RELOADED_ARG:%.*]] = load [take] [[SRC_ADDR]]
|
|
// CHECK-NEXT: checked_cast_br Builtin.NativeObject in [[RELOADED_ARG]] : $Builtin.NativeObject to Klass, [[SUCCESS_BB:bb[0-9]+]], [[FAILURE_BB:bb[0-9]+]]
|
|
//
|
|
// CHECK: [[SUCCESS_BB]]([[CAST_VALUE:%.*]] :
|
|
// ==> On success, we store into dest and destroy dest.
|
|
// CHECK-NEXT: store [[CAST_VALUE]] to [init] [[DEST_ADDR]]
|
|
// CHECK-NEXT: destroy_addr [[DEST_ADDR]]
|
|
// CHECK-NEXT: br [[CONT_BB:bb[0-9]+]]
|
|
//
|
|
// ==> Since we are doing a take on success and we failed... store the original
|
|
// ==> value back into the memory slot.
|
|
// CHECK: [[FAILURE_BB]]([[FAIL_ARG:%.*]] :
|
|
// CHECK-NEXT: store [[FAIL_ARG]] to [init] [[SRC_ADDR]]
|
|
// CHECK-NEXT: destroy_addr [[SRC_ADDR]]
|
|
// CHECK-NEXT: br [[CONT_BB]]
|
|
//
|
|
// CHECK: } // end sil function 'checked_cast_addr_br_takeonsuccess_caller'
|
|
sil [ossa] @checked_cast_addr_br_takeonsuccess_caller : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%2 = function_ref @term_ossa_checked_cast_addr_br_takeonsuccess_callee : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
%1 = copy_value %0 : $Builtin.NativeObject
|
|
apply %2(%1) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
destroy_value %0 : $Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
sil [transparent] [ossa] @term_ossa_checked_cast_addr_br_copyonsuccess_callee : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%1 = alloc_stack $Builtin.NativeObject
|
|
%2 = alloc_stack $Klass
|
|
store %0 to [init] %1 : $*Builtin.NativeObject
|
|
checked_cast_addr_br copy_on_success Builtin.NativeObject in %1 : $*Builtin.NativeObject to Klass in %2 : $*Klass, bb1, bb2
|
|
|
|
bb1:
|
|
destroy_addr %2 : $*Klass
|
|
destroy_addr %1 : $*Builtin.NativeObject
|
|
br bb3
|
|
|
|
bb2:
|
|
destroy_addr %1 : $*Builtin.NativeObject
|
|
br bb3
|
|
|
|
bb3:
|
|
dealloc_stack %2 : $*Klass
|
|
dealloc_stack %1 : $*Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @checked_cast_addr_br_copyonsuccess_caller : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] :
|
|
// CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[ARG]]
|
|
// CHECK-NEXT: [[ARG_MOVE:%[^,]+]] = move_value [lexical] [[ARG_COPY]]
|
|
// CHECK-NEXT: [[SRC_ADDR:%.*]] = alloc_stack $Builtin.NativeObject
|
|
// CHECK-NEXT: [[DEST_ADDR:%.*]] = alloc_stack $Klass
|
|
// CHECK-NEXT: store [[ARG_MOVE]] to [init] [[SRC_ADDR]]
|
|
// CHECK-NEXT: [[RELOADED_ARG:%.*]] = load_borrow [[SRC_ADDR]]
|
|
// CHECK-NEXT: checked_cast_br Builtin.NativeObject in [[RELOADED_ARG]] : $Builtin.NativeObject to Klass, [[SUCCESS_BB:bb[0-9]+]], [[FAILURE_BB:bb[0-9]+]]
|
|
//
|
|
// CHECK: [[SUCCESS_BB]]([[CAST_VALUE:%.*]] : @guaranteed
|
|
// CHECK-NEXT: [[CAST_VALUE_COPY:%.*]] = copy_value [[CAST_VALUE]]
|
|
// CHECK-NEXT: end_borrow [[RELOADED_ARG]]
|
|
// CHECK-NEXT: store [[CAST_VALUE_COPY]] to [init] [[DEST_ADDR]]
|
|
// CHECK-NEXT: destroy_addr [[DEST_ADDR]]
|
|
// CHECK-NEXT: destroy_addr [[SRC_ADDR]]
|
|
// CHECK-NEXT: br [[CONT_BB:bb[0-9]+]]
|
|
//
|
|
// CHECK: [[FAILURE_BB]]([[FAILURE_BORROWED_ARG:%.*]] :
|
|
// CHECK-NEXT: end_borrow [[RELOADED_ARG]]
|
|
// CHECK-NEXT: destroy_addr [[SRC_ADDR]]
|
|
// CHECK-NEXT: br [[CONT_BB]]
|
|
//
|
|
// CHECK: } // end sil function 'checked_cast_addr_br_copyonsuccess_caller'
|
|
sil [ossa] @checked_cast_addr_br_copyonsuccess_caller : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%1 = function_ref @term_ossa_checked_cast_addr_br_copyonsuccess_callee : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
%2 = copy_value %0 : $Builtin.NativeObject
|
|
apply %1(%2) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
destroy_value %0 : $Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
///////////////////////
|
|
// Begin Apply Tests //
|
|
///////////////////////
|
|
|
|
// Make sure that we do not violate any ownership invariants after inlining this
|
|
// code.
|
|
|
|
sil @get_hidden_int_field_of_klass : $@convention(method) (@guaranteed Klass) -> Builtin.Int32
|
|
sil @int_klass_pair_user : $@convention(method) (Builtin.Int32, @guaranteed Klass) -> ()
|
|
|
|
sil [transparent] [ossa] @begin_apply_callee : $@yield_once @convention(method) (@guaranteed Klass) -> @yields @inout Builtin.Int32 {
|
|
bb0(%0 : @guaranteed $Klass):
|
|
%2 = alloc_stack $Builtin.Int32
|
|
%3 = function_ref @get_hidden_int_field_of_klass : $@convention(method) (@guaranteed Klass) -> Builtin.Int32
|
|
%4 = apply %3(%0) : $@convention(method) (@guaranteed Klass) -> Builtin.Int32
|
|
store %4 to [trivial] %2 : $*Builtin.Int32
|
|
yield %2 : $*Builtin.Int32, resume bb1, unwind bb2
|
|
|
|
bb1:
|
|
%7 = load [trivial] %2 : $*Builtin.Int32
|
|
%8 = function_ref @int_klass_pair_user : $@convention(method) (Builtin.Int32, @guaranteed Klass) -> ()
|
|
%9 = apply %8(%7, %0) : $@convention(method) (Builtin.Int32, @guaranteed Klass) -> ()
|
|
dealloc_stack %2 : $*Builtin.Int32
|
|
%11 = tuple ()
|
|
return %11 : $()
|
|
|
|
bb2:
|
|
%13 = load [trivial] %2 : $*Builtin.Int32
|
|
%14 = function_ref @int_klass_pair_user : $@convention(method) (Builtin.Int32, @guaranteed Klass) -> ()
|
|
%15 = apply %14(%13, %0) : $@convention(method) (Builtin.Int32, @guaranteed Klass) -> ()
|
|
dealloc_stack %2 : $*Builtin.Int32
|
|
unwind
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @begin_apply_caller : $@convention(method) (@guaranteed Klass) -> @error any Error {
|
|
// CHECK-NOT: begin_apply
|
|
// CHECK: } // end sil function 'begin_apply_caller'
|
|
sil [ossa] @begin_apply_caller : $@convention(method) (@guaranteed Klass) -> @error Error {
|
|
bb0(%0 : @guaranteed $Klass):
|
|
%6 = copy_value %0 : $Klass
|
|
%12 = function_ref @begin_apply_callee : $@yield_once @convention(method) (@guaranteed Klass) -> @yields @inout Builtin.Int32
|
|
(%13, %14) = begin_apply %12(%6) : $@yield_once @convention(method) (@guaranteed Klass) -> @yields @inout Builtin.Int32
|
|
end_apply %14 as $()
|
|
destroy_value %6 : $Klass
|
|
%19 = tuple ()
|
|
return %19 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @begin_apply_caller_2 : $@convention(method) (@guaranteed Klass) -> @error any Error {
|
|
// CHECK-NOT: begin_apply
|
|
// CHECK: } // end sil function 'begin_apply_caller_2'
|
|
sil [ossa] @begin_apply_caller_2 : $@convention(method) (@guaranteed Klass) -> @error Error {
|
|
bb0(%0 : @guaranteed $Klass):
|
|
%6 = copy_value %0 : $Klass
|
|
%12 = function_ref @begin_apply_callee : $@yield_once @convention(method) (@guaranteed Klass) -> @yields @inout Builtin.Int32
|
|
(%13, %14) = begin_apply %12(%6) : $@yield_once @convention(method) (@guaranteed Klass) -> @yields @inout Builtin.Int32
|
|
abort_apply %14
|
|
destroy_value %6 : $Klass
|
|
%19 = tuple ()
|
|
return %19 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @begin_apply_caller_3 : $@convention(method) (@guaranteed Klass) -> @error any Error {
|
|
// CHECK-NOT: begin_apply
|
|
// CHECK: } // end sil function 'begin_apply_caller_3'
|
|
sil [ossa] @begin_apply_caller_3 : $@convention(method) (@guaranteed Klass) -> @error Error {
|
|
bb0(%0 : @guaranteed $Klass):
|
|
%6 = copy_value %0 : $Klass
|
|
%12 = function_ref @begin_apply_callee : $@yield_once @convention(method) (@guaranteed Klass) -> @yields @inout Builtin.Int32
|
|
(%13, %14) = begin_apply %12(%6) : $@yield_once @convention(method) (@guaranteed Klass) -> @yields @inout Builtin.Int32
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
end_apply %14 as $()
|
|
br bb3
|
|
|
|
bb2:
|
|
abort_apply %14
|
|
br bb3
|
|
|
|
bb3:
|
|
destroy_value %6 : $Klass
|
|
%19 = tuple ()
|
|
return %19 : $()
|
|
}
|
|
|
|
sil [ossa] [transparent] @devirt_callee : $@yield_once @convention(method) (@guaranteed C) -> @yields @inout Builtin.Int64 {
|
|
bb0(%0 : @guaranteed $C):
|
|
%1 = alloc_stack $Builtin.Int64
|
|
%1a = integer_literal $Builtin.Int64, 0
|
|
store %1a to [trivial] %1 : $*Builtin.Int64
|
|
yield %1 : $*Builtin.Int64, resume bb1, unwind bb2
|
|
|
|
bb1:
|
|
dealloc_stack %1 : $*Builtin.Int64
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
|
|
bb2:
|
|
dealloc_stack %1 : $*Builtin.Int64
|
|
unwind
|
|
}
|
|
|
|
// Just make sure we actually inlined the begin_apply. We just want to make sure
|
|
// we are not breaking ownership invariants by not properly borrowing %0.
|
|
// CHECK-LABEL: sil [ossa] @begin_apply_devirt_caller : $@convention(method) (@owned C2) -> @error any Error {
|
|
// CHECK-NOT: begin_apply
|
|
// CHECK: } // end sil function 'begin_apply_devirt_caller'
|
|
sil [ossa] @begin_apply_devirt_caller : $@convention(method) (@owned C2) -> @error Error {
|
|
bb0(%0 : @owned $C2):
|
|
%1 = class_method %0 : $C2, #C2.i!modify : (C2) -> () -> (), $@yield_once @convention(method) (@guaranteed C2) -> @yields @inout Builtin.Int64
|
|
(%mem, %tok) = begin_apply %1(%0) : $@yield_once @convention(method) (@guaranteed C2) -> @yields @inout Builtin.Int64
|
|
br bb1
|
|
|
|
bb1:
|
|
end_apply %tok as $()
|
|
destroy_value %0 : $C2
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @begin_apply_devirt_caller_2 : $@convention(method) (@owned C2) -> @error any Error {
|
|
// CHECK-NOT: begin_apply
|
|
// CHECK: } // end sil function 'begin_apply_devirt_caller_2'
|
|
sil [ossa] @begin_apply_devirt_caller_2 : $@convention(method) (@owned C2) -> @error Error {
|
|
bb0(%0 : @owned $C2):
|
|
%1 = class_method %0 : $C2, #C2.i!modify : (C2) -> () -> (), $@yield_once @convention(method) (@guaranteed C2) -> @yields @inout Builtin.Int64
|
|
(%mem, %tok) = begin_apply %1(%0) : $@yield_once @convention(method) (@guaranteed C2) -> @yields @inout Builtin.Int64
|
|
br bb1
|
|
|
|
bb1:
|
|
abort_apply %tok
|
|
destroy_value %0 : $C2
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @begin_apply_devirt_caller_3 : $@convention(method) (@owned C2) -> @error any Error {
|
|
// CHECK-NOT: begin_apply
|
|
// CHECK: } // end sil function 'begin_apply_devirt_caller_3'
|
|
sil [ossa] @begin_apply_devirt_caller_3 : $@convention(method) (@owned C2) -> @error Error {
|
|
bb0(%0 : @owned $C2):
|
|
%1 = class_method %0 : $C2, #C2.i!modify : (C2) -> () -> (), $@yield_once @convention(method) (@guaranteed C2) -> @yields @inout Builtin.Int64
|
|
(%mem, %tok) = begin_apply %1(%0) : $@yield_once @convention(method) (@guaranteed C2) -> @yields @inout Builtin.Int64
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
end_apply %tok as $()
|
|
br bb3
|
|
|
|
bb2:
|
|
abort_apply %tok
|
|
br bb3
|
|
|
|
bb3:
|
|
destroy_value %0 : $C2
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
|
|
sil_vtable C2 {
|
|
#C2.i!modify: (C2) -> () -> () : @devirt_callee
|
|
}
|