mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
It is necessary for opaque values where for casts that will newly start out as checked_cast_brs and be lowered to checked_cast_addr_brs, since the latter has the source formal type, IRGen relies on being able to access it, and there's no way in general to obtain the source formal type from the source lowered type.
130 lines
4.2 KiB
Plaintext
130 lines
4.2 KiB
Plaintext
// RUN: %target-sil-opt -enable-sil-verify-all %s -devirtualizer -dce | %FileCheck %s
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
class Bar {
|
|
init()
|
|
func ping()
|
|
}
|
|
|
|
class Foo : Bar {
|
|
override init()
|
|
override func ping()
|
|
}
|
|
|
|
sil_global @x : $Bar
|
|
|
|
// CHECK-LABEL: sil [ossa] @function_with_cm_with_cast
|
|
// CHECK: [[SELF:%.*]] = alloc_ref $Foo
|
|
// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
|
|
// CHECK: [[CAST_1_SELF:%.*]] = upcast [[SELF_COPY]]
|
|
// CHECK: [[CAST_2_SELF:%.*]] = unconditional_checked_cast [[CAST_1_SELF]]
|
|
// CHECK: destroy_value [[SELF]]
|
|
// CHECK: [[CAST_3_SELF:%.*]] = upcast [[CAST_2_SELF]]
|
|
// CHECK-NOT: class_method
|
|
// CHECK: [[REF:%.*]] = function_ref @_TFC4main3Foo4pingfS0_FT_T_
|
|
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[CAST_3_SELF]]
|
|
// CHECK: [[SELF:%.*]] = unchecked_ref_cast [[BORROWED_SELF]]
|
|
// CHECK: apply [[REF]]([[SELF]])
|
|
// CHECK: return
|
|
sil [ossa] @function_with_cm_with_cast : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = global_addr @x : $*Bar // users: %7, %8
|
|
%1 = alloc_ref $Foo // users: %5, %3, %2
|
|
%2 = copy_value %1 : $Foo // id: %2
|
|
%3 = upcast %2 : $Foo to $Bar // user: %4
|
|
%4 = unconditional_checked_cast %3 : $Bar to Foo // user: %6
|
|
destroy_value %1 : $Foo // id: %5
|
|
%6 = upcast %4 : $Foo to $Bar // user: %7
|
|
%10 = class_method %6 : $Bar, #Bar.ping : (Bar) -> () -> (), $@convention(method) (@guaranteed Bar) -> () // user: %11
|
|
%11 = apply %10(%6) : $@convention(method) (@guaranteed Bar) -> ()
|
|
destroy_value %6 : $Bar
|
|
%12 = tuple () // user: %13
|
|
return %12 : $() // id: %13
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @function_with_cm_with_dynamic_type_known_from_checked_cast_br :
|
|
// CHECK-NOT: class_method
|
|
// CHECK: bb4([[SELF:%.*]] : @owned $Bar):
|
|
// CHECK: [[REF:%.*]] = function_ref @_TFC4main3Bar4pingfS0_FT_T_
|
|
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
|
|
// CHECK: apply [[REF]]([[BORROWED_SELF]])
|
|
// CHECK: } // end sil function 'function_with_cm_with_dynamic_type_known_from_checked_cast_br'
|
|
sil [ossa] @function_with_cm_with_dynamic_type_known_from_checked_cast_br : $@convention(thin) (@owned Bar) -> () {
|
|
bb0(%0 : @owned $Bar):
|
|
checked_cast_br [exact] Bar in %0 : $Bar to Bar, bb1, bb5
|
|
|
|
bb1(%1 : @owned $Bar):
|
|
br bb2(%1 : $Bar)
|
|
|
|
bb2(%2 : @owned $Bar):
|
|
br bb3(%2 : $Bar)
|
|
|
|
bb3(%3 : @owned $Bar):
|
|
br bb4(%3 : $Bar)
|
|
|
|
bb4(%4 : @owned $Bar):
|
|
// Devirtualizer should be able to figure out that the exact dynamic type of %1 is Bar.
|
|
%5 = class_method %4 : $Bar, #Bar.ping : (Bar) -> () -> (), $@convention(method) (@guaranteed Bar) -> ()
|
|
%6 = apply %5(%4) : $@convention(method) (@guaranteed Bar) -> ()
|
|
destroy_value %4 : $Bar
|
|
br bb6
|
|
|
|
bb5(%7 : @owned $Bar):
|
|
destroy_value %7 : $Bar
|
|
br bb6
|
|
|
|
bb6:
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @function_with_cm_with_dynamic_type_known_from_incoming_bb_args :
|
|
// CHECK-NOT: class_method
|
|
// CHECK: bb3([[SELF:%.*]] : @owned $Bar):
|
|
// CHECK: [[REF:%.*]] = function_ref @_TFC4main3Bar4pingfS0_FT_T_
|
|
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
|
|
// CHECK: apply [[REF]]([[BORROWED_SELF]])
|
|
// CHECK: } // end sil function 'function_with_cm_with_dynamic_type_known_from_incoming_bb_args'
|
|
sil [ossa] @function_with_cm_with_dynamic_type_known_from_incoming_bb_args : $@convention(thin) (Builtin.Int1) -> () {
|
|
bb0(%0 : $Builtin.Int1):
|
|
cond_br %0, bb1, bb2
|
|
|
|
bb1:
|
|
%1 = alloc_ref $Bar
|
|
br bb3(%1 : $Bar)
|
|
|
|
bb2:
|
|
%2 = alloc_ref $Bar
|
|
br bb3(%2 : $Bar)
|
|
|
|
bb3(%4 : @owned $Bar):
|
|
// Devirtualizer should be able to figure out that the exact dynamic type of %4 is Bar.
|
|
%5 = class_method %4 : $Bar, #Bar.ping : (Bar) -> () -> (), $@convention(method) (@guaranteed Bar) -> ()
|
|
%6 = apply %5(%4) : $@convention(method) (@guaranteed Bar) -> ()
|
|
br bb4
|
|
|
|
bb4:
|
|
destroy_value %4 : $Bar
|
|
%7 = tuple ()
|
|
return %7 : $()
|
|
}
|
|
|
|
|
|
sil @_TFC4main3Bar4pingfS0_FT_T_ : $@convention(method) (@guaranteed Bar) -> ()
|
|
sil @_TFC4main3Foo4pingfS0_FT_T_ : $@convention(method) (@guaranteed Foo) -> ()
|
|
|
|
sil_vtable Bar {
|
|
#Bar.ping: @_TFC4main3Bar4pingfS0_FT_T_
|
|
}
|
|
|
|
sil_vtable Foo {
|
|
#Bar.ping: @_TFC4main3Foo4pingfS0_FT_T_ [override]
|
|
}
|
|
|
|
|
|
|