mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
introduce a common superclass, SILNode. This is in preparation for allowing instructions to have multiple results. It is also a somewhat more elegant representation for instructions that have zero results. Instructions that are known to have exactly one result inherit from a class, SingleValueInstruction, that subclasses both ValueBase and SILInstruction. Some care must be taken when working with SILNode pointers and testing for equality; please see the comment on SILNode for more information. A number of SIL passes needed to be updated in order to handle this new distinction between SIL values and SIL instructions. Note that the SIL parser is now stricter about not trying to assign a result value from an instruction (like 'return' or 'strong_retain') that does not produce any.
253 lines
9.7 KiB
Plaintext
253 lines
9.7 KiB
Plaintext
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -sil-combine -simplify-cfg | %FileCheck %s
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
// CHECK-LABEL: sil @convert_inject_enum_addr_select_enum_addr_into_cond_br : $@convention(thin) (@in Int, @inout _Stdout) -> ()
|
|
// CHECK: init_existential_addr
|
|
// CHECK: inject_enum_addr
|
|
// CHECK-NOT: select_enum_addr
|
|
// CHECK-NOT: bb1
|
|
// CHECK: unchecked_take_enum_data_addr
|
|
// CHECK: return
|
|
sil @convert_inject_enum_addr_select_enum_addr_into_cond_br : $@convention(thin) (@in Int, @inout _Stdout) -> () {
|
|
bb0(%0 : $*Int, %1 : $*_Stdout):
|
|
%2 = alloc_stack $CustomStringConvertible
|
|
%3 = alloc_stack $Optional<CustomStringConvertible>
|
|
%4 = init_enum_data_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
|
|
%5 = alloc_stack $Int
|
|
%6 = load %0 : $*Int
|
|
store %6 to %5 : $*Int
|
|
unconditional_checked_cast_addr Int in %5 : $*Int to CustomStringConvertible in %4 : $*CustomStringConvertible
|
|
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
|
|
dealloc_stack %5 : $*Int
|
|
%11 = integer_literal $Builtin.Int1, -1
|
|
%12 = integer_literal $Builtin.Int1, 0
|
|
%13 = select_enum_addr %3 : $*Optional<CustomStringConvertible>, case #Optional.some!enumelt.1: %11, case #Optional.none!enumelt: %12 : $Builtin.Int1
|
|
cond_br %13, bb2, bb1
|
|
|
|
bb1:
|
|
%15 = tuple ()
|
|
dealloc_stack %3 : $*Optional<CustomStringConvertible>
|
|
dealloc_stack %2 : $*CustomStringConvertible
|
|
return %15 : $()
|
|
|
|
bb2:
|
|
%19 = unchecked_take_enum_data_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
|
|
copy_addr [take] %19 to [initialization] %2 : $*CustomStringConvertible
|
|
br bb1
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: sil @convert_inject_enum_addr_switch_enum_addr_into_cond_br : $@convention(thin) (@in Int, @inout _Stdout) -> ()
|
|
// CHECK: init_existential_addr
|
|
// CHECK: inject_enum_addr
|
|
// CHECK-NOT: switch_enum_addr
|
|
// CHECK-NOT: bb1
|
|
// CHECK: unchecked_take_enum_data_addr
|
|
// CHECK: return
|
|
sil @convert_inject_enum_addr_switch_enum_addr_into_cond_br : $@convention(thin) (@in Int, @inout _Stdout) -> () {
|
|
bb0(%0 : $*Int, %1 : $*_Stdout):
|
|
%2 = alloc_stack $CustomStringConvertible
|
|
%3 = alloc_stack $Optional<CustomStringConvertible>
|
|
%4 = init_enum_data_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
|
|
%5 = alloc_stack $Int
|
|
%6 = load %0 : $*Int
|
|
store %6 to %5 : $*Int
|
|
unconditional_checked_cast_addr Int in %5 : $*Int to CustomStringConvertible in %4 : $*CustomStringConvertible
|
|
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
|
|
dealloc_stack %5 : $*Int
|
|
switch_enum_addr %3 : $*Optional<CustomStringConvertible>, case #Optional.some!enumelt.1: bb3, case #Optional.none!enumelt: bb2
|
|
|
|
bb1:
|
|
%15 = tuple ()
|
|
dealloc_stack %3 : $*Optional<CustomStringConvertible>
|
|
dealloc_stack %2 : $*CustomStringConvertible
|
|
return %15 : $()
|
|
|
|
bb2:
|
|
br bb1
|
|
|
|
bb3:
|
|
%19 = unchecked_take_enum_data_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
|
|
copy_addr [take] %19 to [initialization] %2 : $*CustomStringConvertible
|
|
br bb1
|
|
}
|
|
|
|
|
|
// Check that a checked_cast_addr_br converting a known type into a protocol type
|
|
// is performed at the compile-time if protocol conformances are statically known.
|
|
//
|
|
// CHECK-LABEL: sil @convert_checked_cast_addr_br_into_unconditional_checked_cast_addr_cond_br : $@convention(thin) (@in Int, @inout _Stdout) -> ()
|
|
// CHECK: store
|
|
// CHECK-NOT: checked_cast_addr_br
|
|
// CHECK-NOT: bb1
|
|
// CHECK: inject_enum_addr %{{.*}} : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
|
|
// CHECK: dealloc_stack
|
|
// CHECK: return
|
|
sil @convert_checked_cast_addr_br_into_unconditional_checked_cast_addr_cond_br : $@convention(thin) (@in Int, @inout _Stdout) -> () {
|
|
bb0(%0 : $*Int, %1 : $*_Stdout):
|
|
%2 = alloc_stack $CustomStringConvertible
|
|
%3 = alloc_stack $Optional<CustomStringConvertible>
|
|
%4 = init_enum_data_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
|
|
%5 = alloc_stack $Int
|
|
%6 = load %0 : $*Int
|
|
store %6 to %5 : $*Int
|
|
checked_cast_addr_br take_always Int in %5 : $*Int to CustomStringConvertible in %4 : $*CustomStringConvertible, bb1, bb22
|
|
|
|
bb1:
|
|
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
|
|
br bb2
|
|
|
|
bb2:
|
|
dealloc_stack %5 : $*Int
|
|
dealloc_stack %3 : $*Optional<CustomStringConvertible>
|
|
%12 = integer_literal $Builtin.Int1, -1
|
|
%13 = integer_literal $Builtin.Int1, 0
|
|
%26 = tuple ()
|
|
dealloc_stack %2 : $*CustomStringConvertible
|
|
return %26 : $()
|
|
|
|
bb22:
|
|
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.none!enumelt
|
|
br bb2
|
|
}
|
|
|
|
|
|
class A {
|
|
|
|
}
|
|
|
|
private final class B {
|
|
}
|
|
|
|
public class C {
|
|
}
|
|
|
|
// D cannot be extended elsewhere, but C can!
|
|
private class D : C {
|
|
}
|
|
|
|
// Check that a checked_cast_addr_br converting a known type into a protocol type
|
|
// is performed at the compile-time if protocol conformances are statically known.
|
|
// In a negative case, take care that check for internal types are not folded (unless
|
|
// a whole module optimization is used), because an extension implementing a conformance
|
|
// could be defined elsewhere.
|
|
//
|
|
// CHECK-LABEL: sil @convert_checked_cast_addr_br_with_internal_type : $@convention(thin) (@in A, @inout _Stdout) -> ()
|
|
// CHECK: checked_cast_addr_br
|
|
// CHECK: inject_enum_addr %{{.*}} : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
|
|
// CHECK: dealloc_stack
|
|
// CHECK: return
|
|
// CHECK: inject_enum_addr %{{.*}} : $*Optional<CustomStringConvertible>, #Optional.none!enumelt
|
|
// CHECK: }
|
|
sil @convert_checked_cast_addr_br_with_internal_type : $@convention(thin) (@in A, @inout _Stdout) -> () {
|
|
bb0(%0 : $*A, %1 : $*_Stdout):
|
|
%2 = alloc_stack $CustomStringConvertible
|
|
%3 = alloc_stack $Optional<CustomStringConvertible>
|
|
%4 = init_enum_data_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
|
|
%5 = alloc_stack $A
|
|
%6 = load %0 : $*A
|
|
store %6 to %5 : $*A
|
|
checked_cast_addr_br take_always A in %5 : $*A to CustomStringConvertible in %4 : $*CustomStringConvertible, bb1, bb22
|
|
|
|
bb1:
|
|
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
|
|
br bb2
|
|
|
|
bb2:
|
|
dealloc_stack %5 : $*A
|
|
dealloc_stack %3 : $*Optional<CustomStringConvertible>
|
|
%12 = integer_literal $Builtin.Int1, -1
|
|
%13 = integer_literal $Builtin.Int1, 0
|
|
%26 = tuple ()
|
|
dealloc_stack %2 : $*CustomStringConvertible
|
|
return %26 : $()
|
|
|
|
bb22:
|
|
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.none!enumelt
|
|
br bb2
|
|
}
|
|
|
|
// Check that a checked_cast_addr_br converting a known type into a protocol type
|
|
// is performed at the compile-time if protocol conformances are statically known.
|
|
// In a negative case, if the source type is private, it is safe to fold the check,
|
|
// because a conformance for this type cannot be defined elsewhere.
|
|
//
|
|
// CHECK-LABEL: sil @convert_checked_cast_addr_br_with_private_type : $@convention(thin) (@in B, @inout _Stdout) -> ()
|
|
// CHECK: store
|
|
// CHECK-NOT: checked_cast_addr_br
|
|
// CHECK-NOT: bb1
|
|
// CHECK: inject_enum_addr %{{.*}} : $*Optional<CustomStringConvertible>, #Optional.none!enumelt
|
|
// CHECK: dealloc_stack
|
|
// CHECK: return
|
|
sil @convert_checked_cast_addr_br_with_private_type : $@convention(thin) (@in B, @inout _Stdout) -> () {
|
|
bb0(%0 : $*B, %1 : $*_Stdout):
|
|
%2 = alloc_stack $CustomStringConvertible
|
|
%3 = alloc_stack $Optional<CustomStringConvertible>
|
|
%4 = init_enum_data_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
|
|
%5 = alloc_stack $B
|
|
%6 = load %0 : $*B
|
|
store %6 to %5 : $*B
|
|
checked_cast_addr_br take_always B in %5 : $*B to CustomStringConvertible in %4 : $*CustomStringConvertible, bb1, bb22
|
|
|
|
bb1:
|
|
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
|
|
br bb2
|
|
|
|
bb2:
|
|
dealloc_stack %5 : $*B
|
|
dealloc_stack %3 : $*Optional<CustomStringConvertible>
|
|
%12 = integer_literal $Builtin.Int1, -1
|
|
%13 = integer_literal $Builtin.Int1, 0
|
|
%26 = tuple ()
|
|
dealloc_stack %2 : $*CustomStringConvertible
|
|
return %26 : $()
|
|
|
|
bb22:
|
|
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.none!enumelt
|
|
br bb2
|
|
}
|
|
|
|
// Check that a checked_cast_addr_br converting a known type into a protocol type
|
|
// is performed at the compile-time if protocol conformances are statically known.
|
|
// In a negative case, take care that cast for private types are not folded if one
|
|
// of its superclasses could have a conformance extension defined elsewhere.
|
|
//
|
|
// CHECK-LABEL: sil @convert_checked_cast_addr_br_with_non_private_superclass : $@convention(thin) (@in D, @inout _Stdout) -> ()
|
|
// CHECK: checked_cast_addr_br
|
|
// CHECK: inject_enum_addr %{{.*}} : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
|
|
// CHECK: dealloc_stack
|
|
// CHECK: return
|
|
// CHECK: inject_enum_addr %{{.*}} : $*Optional<CustomStringConvertible>, #Optional.none!enumelt
|
|
// CHECK: }
|
|
sil @convert_checked_cast_addr_br_with_non_private_superclass : $@convention(thin) (@in D, @inout _Stdout) -> () {
|
|
bb0(%0 : $*D, %1 : $*_Stdout):
|
|
%2 = alloc_stack $CustomStringConvertible
|
|
%3 = alloc_stack $Optional<CustomStringConvertible>
|
|
%4 = init_enum_data_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
|
|
%5 = alloc_stack $D
|
|
%6 = load %0 : $*D
|
|
store %6 to %5 : $*D
|
|
checked_cast_addr_br take_always D in %5 : $*D to CustomStringConvertible in %4 : $*CustomStringConvertible, bb1, bb22
|
|
|
|
bb1:
|
|
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
|
|
br bb2
|
|
|
|
bb2:
|
|
dealloc_stack %5 : $*D
|
|
dealloc_stack %3 : $*Optional<CustomStringConvertible>
|
|
%12 = integer_literal $Builtin.Int1, -1
|
|
%13 = integer_literal $Builtin.Int1, 0
|
|
%26 = tuple ()
|
|
dealloc_stack %2 : $*CustomStringConvertible
|
|
return %26 : $()
|
|
|
|
bb22:
|
|
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.none!enumelt
|
|
br bb2
|
|
}
|