mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Type annotations for instruction operands are omitted, e.g. ``` %3 = struct $S(%1, %2) ``` Operand types are redundant anyway and were only used for sanity checking in the SIL parser. But: operand types _are_ printed if the definition of the operand value was not printed yet. This happens: * if the block with the definition appears after the block where the operand's instruction is located * if a block or instruction is printed in isolation, e.g. in a debugger The old behavior can be restored with `-Xllvm -sil-print-types`. This option is added to many existing test files which check for operand types in their check-lines.
418 lines
20 KiB
Plaintext
418 lines
20 KiB
Plaintext
// RUN: %target-sil-opt -sil-print-types -enable-sil-verify-all %s -update-borrowed-from -simplify-cfg | %FileCheck %s
|
|
|
|
// REQUIRES: swift_in_compiler
|
|
|
|
// Declare this SIL to be canonical because some tests break raw SIL
|
|
// conventions. e.g. address-type block args. -enforce-exclusivity=none is also
|
|
// required to allow address-type block args in canonical SIL.
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
public class EE {
|
|
init()
|
|
}
|
|
|
|
public class BB {
|
|
init()
|
|
}
|
|
|
|
public class CC : BB {
|
|
@inline(never) init(e: EE)
|
|
override init()
|
|
}
|
|
|
|
public protocol PP {
|
|
var prop1: BB? { get }
|
|
}
|
|
|
|
public class DD : PP {
|
|
public var prop1: BB? { get }
|
|
init()
|
|
}
|
|
|
|
class B {}
|
|
class E : B {}
|
|
|
|
sil [ossa] @unknown : $@convention(thin) () -> ()
|
|
|
|
sil [ossa] @adder : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
|
|
sil [ossa] @rethrow_function : $@convention(thin) (@owned @callee_owned (Int) -> (Int, @error Error)) -> (Int, @error Error)
|
|
sil [ossa] @non_throwing_closure : $@convention(thin) (Int) -> Int
|
|
|
|
sil [ossa] @rethrowGuaranteed : $@convention(thin) (@guaranteed (Optional<B>, B)) -> Int
|
|
sil [ossa] @rethrowOwned : $@convention(thin) (@owned (Optional<B>, B)) -> Int
|
|
|
|
// CHECK-LABEL: sil [ossa] @replace_try_apply_with_apply
|
|
// CHECK: [[R:%[0-9]+]] = apply [nothrow] %1(%{{[0-9]+}}) : $@convention(thin) (@owned @callee_owned (Int) -> (Int, @error any Error)) -> (Int, @error any Error)
|
|
// CHECK-NEXT: dealloc_stack
|
|
// CHECK-NEXT: return [[R]] : $Int
|
|
sil [ossa] @replace_try_apply_with_apply : $@convention(thin) () -> Int {
|
|
bb0:
|
|
%as = alloc_stack $Builtin.Int32
|
|
%0 = function_ref @rethrow_function : $@convention(thin) (@owned @callee_owned (Int) -> (Int, @error Error)) -> (Int, @error Error)
|
|
%1 = function_ref @non_throwing_closure : $@convention(thin) (Int) -> Int
|
|
%2 = thin_to_thick_function %1 : $@convention(thin) (Int) -> Int to $@callee_owned (Int) -> Int
|
|
%3 = convert_function %2 : $@callee_owned (Int) -> Int to $@callee_owned (Int) -> (Int, @error Error)
|
|
try_apply %0(%3) : $@convention(thin) (@owned @callee_owned (Int) -> (Int, @error Error)) -> (Int, @error Error), normal bb1, error bb2
|
|
|
|
bb1(%5 : $Int):
|
|
dealloc_stack %as: $*Builtin.Int32
|
|
return %5 : $Int
|
|
|
|
bb2(%8 : @owned $Error):
|
|
dealloc_stack %as: $*Builtin.Int32
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @replace_try_apply_with_apply_cast_return_type : $@convention(method) (@guaranteed DD) -> @owned Optional<BB>
|
|
// CHECK: bb0
|
|
// CHECK: [[INIT:%.*]] = apply %{{.*}}
|
|
// CHECK: [[COPY:%.*]] = copy_value [[INIT]] : $@callee_owned (@owned EE) -> @owned CC
|
|
// CHECK: [[CVT:%.*]] = convert_function [[INIT]]
|
|
// CHECK-NOT: try_apply
|
|
// CHECK: destroy_value [[CVT]] : $@callee_owned (@owned EE) -> (@owned Optional<BB>, @error any Error)
|
|
// CHECK: apply [[COPY]]
|
|
// Check that return value is properly casted
|
|
// CHECK-NEXT: enum $Optional<CC>, #Optional.some!enumelt, %{{.*}} : $CC
|
|
// CHECK-NEXT: upcast %{{.*}} : $Optional<CC> to $Optional<BB>
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @replace_try_apply_with_apply_cast_return_type: $@convention(method) (@guaranteed DD) -> @owned Optional<BB> {
|
|
bb0(%0 : @guaranteed $DD):
|
|
%1 = alloc_ref $EE
|
|
debug_value %1 : $EE
|
|
%3 = function_ref @initCC : $@convention(thin) (@thick CC.Type) -> @owned @callee_owned (@owned EE) -> @owned CC
|
|
%4 = metatype $@thick CC.Type
|
|
%5 = apply %3(%4) : $@convention(thin) (@thick CC.Type) -> @owned @callee_owned (@owned EE) -> @owned CC
|
|
%6 = convert_function %5 : $@callee_owned (@owned EE) -> @owned CC to $@callee_owned (@owned EE) -> (@owned Optional<BB>, @error Error)
|
|
try_apply %6(%1) : $@callee_owned (@owned EE) -> (@owned Optional<BB>, @error Error), normal bb1, error bb2
|
|
|
|
bb1(%8 : @owned $Optional<BB>):
|
|
return %8 : $Optional<BB>
|
|
|
|
bb2(%10 : @owned $Error):
|
|
unreachable
|
|
}
|
|
|
|
// Check that we don't crash on this, because we perform casting
|
|
// if the argument types of the converted function types do not match.
|
|
// CHECK-LABEL: try_apply_with_apply_of_cast_argument
|
|
// CHECK-NOT: try_apply {{%[0-9]+}}
|
|
// CHECK: convert_function
|
|
// CHECK: upcast
|
|
// CHECK: apply
|
|
// CHECK-NOT: try_apply
|
|
// CHECK: return
|
|
sil [ossa] @try_apply_with_apply_of_cast_argument: $@convention(method) (@owned CC) -> @owned BB {
|
|
bb0(%0 : @owned $CC):
|
|
%3 = function_ref @takeBB : $@convention(thin) (@owned BB) -> @owned BB
|
|
%6 = convert_function %3 : $@convention(thin) (@owned BB) -> @owned BB to $@convention(thin) (@owned CC) -> (@owned BB, @error Error)
|
|
try_apply %6(%0) : $@convention(thin) (@owned CC) -> (@owned BB, @error Error), normal bb1, error bb2
|
|
|
|
bb1(%8 : @owned $BB):
|
|
return %8 : $BB
|
|
|
|
bb2(%10 : @owned $Error):
|
|
// Prevent that the conversion is done because the error block is empty and unreachable.
|
|
%12 = function_ref @unknown : $@convention(thin) () -> ()
|
|
apply %12() : $@convention(thin) () -> ()
|
|
unreachable
|
|
}
|
|
|
|
sil [noinline] @initCC : $@convention(thin) (@thick CC.Type) -> @owned @callee_owned (@owned EE) -> @owned CC
|
|
|
|
sil [noinline] @takeBB : $@convention(thin) (@owned BB) -> @owned BB
|
|
|
|
// Check that we don't crash on this.
|
|
// The compiler should be able to cast between the labeled and unlabeled return tuple types.
|
|
// CHECK-LABEL: @try_apply_with_convert_function_returning_casted_tuple
|
|
// CHECK: [[T0:%.*]] = apply {{%[0-9]+}}
|
|
// CHECK: return [[T0]]
|
|
sil [ossa] @try_apply_with_convert_function_returning_casted_tuple: $@convention(thin) () -> (Int32, Int32) {
|
|
bb0:
|
|
%3 = function_ref @returnTuple : $@convention(thin) () -> (Int32, Int32)
|
|
%6 = convert_function %3 : $@convention(thin) () -> (Int32, Int32) to $@convention(thin) () -> (Int32, Int32, @error Error)
|
|
try_apply %6() : $@convention(thin) () -> (Int32, Int32, @error Error), normal bb1, error bb2
|
|
|
|
bb1(%8 : $(Int32, Int32)):
|
|
return %8 : $(Int32, Int32)
|
|
|
|
bb2(%10 : @owned $Error):
|
|
// Prevent that the conversion is done because the error block is empty and unreachable.
|
|
%12 = function_ref @unknown : $@convention(thin) () -> ()
|
|
apply %12() : $@convention(thin) () -> ()
|
|
unreachable
|
|
}
|
|
|
|
sil [noinline] @returnTuple: $@convention(thin) () -> (Int32, Int32)
|
|
|
|
public class AAA {
|
|
}
|
|
|
|
public class BBB : AAA {
|
|
}
|
|
|
|
@inline(never) func returnUnlabeledTuple(b: BBB) -> (BBB, BBB)
|
|
|
|
func testit(f: (BBB) throws -> (AAA, AAA), _ b: BBB) throws -> (AAA, AAA)
|
|
|
|
func callit(b: BBB) throws -> (AAA, AAA)
|
|
|
|
sil [ossa] [noinline] @returnUnlabeledTupleOfClasses : $@convention(thin) (@owned BBB) -> @owned (BBB, BBB) {
|
|
bb0(%0 : @owned $BBB):
|
|
debug_value %0 : $BBB
|
|
%0a = copy_value %0 : $BBB
|
|
%3 = tuple (%0a : $BBB, %0 : $BBB)
|
|
return %3 : $(BBB, BBB)
|
|
}
|
|
|
|
sil [ossa] @testFunctorReturningUnlabeledTuple : $@convention(thin) (@owned @callee_owned (@owned BBB) -> (@owned (AAA, AAA), @error Error), @owned BBB) -> (@owned (AAA, AAA), @error Error) {
|
|
bb0(%0 : @owned $@callee_owned (@owned BBB) -> (@owned (AAA, AAA), @error Error), %1 : @owned $BBB):
|
|
debug_value %0 : $@callee_owned (@owned BBB) -> (@owned (AAA, AAA), @error Error)
|
|
debug_value %1 : $BBB
|
|
%0a = copy_value %0 : $@callee_owned (@owned BBB) -> (@owned (AAA, AAA), @error Error)
|
|
%1a = copy_value %1 : $BBB
|
|
try_apply %0a(%1a) : $@callee_owned (@owned BBB) -> (@owned (AAA, AAA), @error Error), normal bb1, error bb2
|
|
|
|
bb1(%7 : @owned $(AAA, AAA)):
|
|
(%8, %9) = destructure_tuple %7 : $(AAA, AAA)
|
|
%10 = tuple (%8 : $AAA, %9 : $AAA)
|
|
destroy_value %1 : $BBB
|
|
destroy_value %0 : $@callee_owned (@owned BBB) -> (@owned (AAA, AAA), @error Error)
|
|
return %10 : $(AAA, AAA)
|
|
|
|
bb2(%14 : @owned $Error):
|
|
destroy_value %1 : $BBB
|
|
destroy_value %0 : $@callee_owned (@owned BBB) -> (@owned (AAA, AAA), @error Error)
|
|
throw %14 : $Error
|
|
}
|
|
|
|
|
|
// Check that we don't crash on this. Currently we just do not optimize try_apply if
|
|
// we cannot cast the actual return type into expected return type.
|
|
// TODO: Change the checks when we support more complex casts of return types.
|
|
// CHECK-LABEL: @testCallingFunctionWithFunctorReturningUnlabeledTuple
|
|
// CHECK: try_apply {{%[0-9]+}}
|
|
// CHECK: return
|
|
sil [ossa] @testCallingFunctionWithFunctorReturningUnlabeledTuple : $@convention(thin) (@owned BBB) -> (@owned (AAA, AAA), @error Error) {
|
|
bb0(%0 : @owned $BBB):
|
|
debug_value %0 : $BBB
|
|
|
|
%2 = function_ref @testFunctorReturningUnlabeledTuple : $@convention(thin) (@owned @callee_owned (@owned BBB) -> (@owned (AAA, AAA), @error Error), @owned BBB) -> (@owned (AAA, AAA), @error Error)
|
|
|
|
%3 = function_ref @returnUnlabeledTupleOfClasses : $@convention(thin) (@owned BBB) -> @owned (BBB, BBB)
|
|
%4 = thin_to_thick_function %3 : $@convention(thin) (@owned BBB) -> @owned (BBB, BBB) to $@callee_owned (@owned BBB) -> @owned (BBB, BBB)
|
|
%5 = convert_function %4 : $@callee_owned (@owned BBB) -> @owned (BBB, BBB) to $@callee_owned (@owned BBB) -> (@owned (AAA, AAA), @error Error)
|
|
%0a = copy_value %0 : $BBB
|
|
try_apply %2(%5, %0a) : $@convention(thin) (@owned @callee_owned (@owned BBB) -> (@owned (AAA, AAA), @error Error), @owned BBB) -> (@owned (AAA, AAA), @error Error), normal bb1, error bb2
|
|
|
|
bb1(%8 : @owned $(AAA, AAA)):
|
|
(%9, %10) = destructure_tuple %8 : $(AAA, AAA)
|
|
%11 = tuple (%9 : $AAA, %10 : $AAA)
|
|
destroy_value %0 : $BBB
|
|
return %11 : $(AAA, AAA)
|
|
|
|
bb2(%14 : @owned $Error):
|
|
destroy_value %0 : $BBB
|
|
throw %14 : $Error
|
|
}
|
|
|
|
struct UP<T> {
|
|
|
|
}
|
|
|
|
struct UBP<A> {
|
|
}
|
|
|
|
struct CAB<A> {
|
|
|
|
}
|
|
|
|
sil [ossa] @CABIdentityGetter : $@convention(thin) <τ_0_0> (UBP<τ_0_0>) -> UP<()>
|
|
sil [ossa] @CABwithUnsafeBufferPointer : $@convention(method) <τ_0_0><τ_1_0> (@owned @callee_owned (UBP<τ_0_0>) -> (@out τ_1_0, @error Error), @guaranteed CAB<τ_0_0>) -> (@out τ_1_0, @error Error)
|
|
sil [ossa] @thunk_helper : $@convention(thin) <τ_0_0> (UBP<τ_0_0>, @owned @callee_owned (UBP<τ_0_0>) -> (UP<()>, @error Error)) -> (@out UP<()>, @error Error)
|
|
|
|
// CHECK-LABEL: sil [ossa] @check_parameters_casting_with_generics :
|
|
// CHECK-NOT: try_apply
|
|
// CHECK: apply [nothrow] %{{.*}}<Element, UP<()>>
|
|
// CHECK: return
|
|
sil [ossa] @check_parameters_casting_with_generics : $@convention(method) <Element> (CAB<Element>) -> UP<()> {
|
|
bb0(%0 : $CAB<Element>):
|
|
// function_ref Swift._ContiguousArrayBuffer.withUnsafeBufferPointer <A><B> (CAB<A>)((Swift.UBP<A>) throws -> B) throws -> B
|
|
%2 = function_ref @CABwithUnsafeBufferPointer : $@convention(method) <τ_0_0><τ_1_0> (@owned @callee_owned (UBP<τ_0_0>) -> (@out τ_1_0, @error Error), @guaranteed CAB<τ_0_0>) -> (@out τ_1_0, @error Error)
|
|
// function_ref Swift._ContiguousArrayBuffer.(identity.getter : UP<()>).(closure #1)
|
|
%3 = function_ref @CABIdentityGetter : $@convention(thin) <τ_0_0> (UBP<τ_0_0>) -> UP<()>
|
|
%4 = partial_apply %3<Element>() : $@convention(thin) <τ_0_0> (UBP<τ_0_0>) -> UP<()>
|
|
%5 = convert_function %4 : $@callee_owned (UBP<Element>) -> UP<()> to $@callee_owned (UBP<Element>) -> (UP<()>, @error Error)
|
|
// function_ref reabstraction thunk helper <A> from @callee_owned (@unowned UBP<A>) -> (@unowned UP<()>, @error @owned Swift.Error) to @callee_owned (@unowned UBP<A>) -> (@out UP<()>, @error @owned Swift.Error)
|
|
%6 = function_ref @thunk_helper : $@convention(thin) <τ_0_0> (UBP<τ_0_0>, @owned @callee_owned (UBP<τ_0_0>) -> (UP<()>, @error Error)) -> (@out UP<()>, @error Error)
|
|
%7 = partial_apply %6<Element>(%5) : $@convention(thin) <τ_0_0> (UBP<τ_0_0>, @owned @callee_owned (UBP<τ_0_0>) -> (UP<()>, @error Error)) -> (@out UP<()>, @error Error)
|
|
%8 = alloc_stack $UP<()>
|
|
%9 = unchecked_addr_cast %8 : $*UP<()> to $*UP<()>
|
|
%10 = convert_function %7 : $@callee_owned (UBP<Element>) -> (@out UP<()>, @error Error) to $@callee_owned (UBP<Element>) -> (@out UP<()>, @error Error)
|
|
try_apply %2<Element, UP<()>>(%8, %10, %0) : $@convention(method) <τ_0_0><τ_1_0> (@owned @callee_owned (UBP<τ_0_0>) -> (@out τ_1_0, @error Error), @guaranteed CAB<τ_0_0>) -> (@out τ_1_0, @error Error), normal bb1, error bb2
|
|
|
|
bb1(%12 : $()):
|
|
%13 = load [trivial] %8 : $*UP<()>
|
|
dealloc_stack %8 : $*UP<()>
|
|
return %13 : $UP<()>
|
|
|
|
bb2(%16 : @owned $Error):
|
|
unreachable
|
|
}
|
|
|
|
// Test try_apply to apply conversion where the owned callee is defined in a non-postdominated block.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @test_owned_callee : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32 {
|
|
// CHECK: [[PA:%.*]] = partial_apply %2(%0) : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
// CHECK: [[COPY:%.*]] = copy_value [[PA]] : $@callee_owned (Builtin.Int32) -> Builtin.Int32
|
|
// CHECK: [[CVT:%.*]] = convert_function [[PA]] : $@callee_owned (Builtin.Int32) -> Builtin.Int32 to $@callee_owned (Builtin.Int32) -> (Builtin.Int32, @error any Error)
|
|
// CHECK: cond_br undef, bb1, bb2
|
|
// CHECK: bb1:
|
|
// CHECK: destroy_value %5 : $@callee_owned (Builtin.Int32) -> (Builtin.Int32, @error any Error)
|
|
// CHECK: [[CALL:%.*]] = apply [[COPY]]
|
|
// CHECK: br bb3([[CALL]] : $Builtin.Int32)
|
|
// CHECK: bb2:
|
|
// CHECK: destroy_value [[COPY]] : $@callee_owned (Builtin.Int32) -> Builtin.Int32
|
|
// CHECK: destroy_value [[CVT]] : $@callee_owned (Builtin.Int32) -> (Builtin.Int32, @error any Error)
|
|
// CHECK: br bb3(
|
|
// CHECK: bb3(
|
|
// CHECK-NEXT: return
|
|
// CHECK-LABEL: } // end sil function 'test_owned_callee'
|
|
sil [ossa] @test_owned_callee : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32 {
|
|
bb0(%0 : $Builtin.Int32, %1 : $Builtin.Int32):
|
|
%f = function_ref @adder : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
%pa = partial_apply %f(%0) : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
%conv = convert_function %pa : $@callee_owned (Builtin.Int32) -> (Builtin.Int32) to $@callee_owned (Builtin.Int32) -> (Builtin.Int32, @error Error)
|
|
// Test OSSA cleanup by creating a leaking block.
|
|
cond_br undef, bb1, bb4
|
|
|
|
bb1:
|
|
try_apply %conv(%1) : $@callee_owned (Builtin.Int32) -> (Builtin.Int32, @error Error), normal bb2, error bb3
|
|
|
|
bb2(%r : $Builtin.Int32):
|
|
br bb5(%r : $Builtin.Int32)
|
|
|
|
bb3(%e : $Error):
|
|
%r1 = integer_literal $Builtin.Int32, 0
|
|
br bb5(%r1 : $Builtin.Int32)
|
|
|
|
bb4:
|
|
%const = integer_literal $Builtin.Int32, 1
|
|
destroy_value %conv : $@callee_owned (Builtin.Int32) -> (Builtin.Int32, @error Error)
|
|
br bb5(%const : $Builtin.Int32)
|
|
|
|
bb5(%res : $Builtin.Int32):
|
|
return %res : $Builtin.Int32
|
|
}
|
|
|
|
|
|
// TODO: The extra copy/destroy here could be avoided.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @test_noescape
|
|
// CHECK: [[FN:%.*]] = function_ref @adder
|
|
// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[FN]](%0)
|
|
// CHECK: [[COPY:%.*]] = copy_value [[PA]] : $@callee_guaranteed (Builtin.Int32) -> Builtin.Int32
|
|
// CHECK-NOT: try_apply
|
|
// CHECK: apply [[COPY]](%1)
|
|
// CHECK: destroy_value [[COPY]] : $@callee_guaranteed (Builtin.Int32) -> Builtin.Int32
|
|
// CHECK: return
|
|
sil [ossa] @test_noescape : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32 {
|
|
bb0(%0 : $Builtin.Int32, %1 : $Builtin.Int32):
|
|
%f = function_ref @adder : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
%pa = partial_apply [callee_guaranteed] %f(%0) : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
%conv = convert_function %pa : $@callee_guaranteed (Builtin.Int32) -> (Builtin.Int32) to $@callee_guaranteed (Builtin.Int32) -> (Builtin.Int32, @error Error)
|
|
%ne = convert_escape_to_noescape %conv : $@callee_guaranteed (Builtin.Int32) -> (Builtin.Int32, @error Error) to $@noescape @callee_guaranteed (Builtin.Int32) -> (Builtin.Int32, @error Error)
|
|
try_apply %ne(%1) : $@noescape @callee_guaranteed (Builtin.Int32) -> (Builtin.Int32, @error Error), normal bb1, error bb2
|
|
|
|
bb1(%r : $Builtin.Int32):
|
|
br bb3(%r : $Builtin.Int32)
|
|
|
|
bb2(%e : $Error):
|
|
%r1 = integer_literal $Builtin.Int32, 0
|
|
br bb3(%r1 : $Builtin.Int32)
|
|
|
|
bb3(%res : $Builtin.Int32):
|
|
destroy_value %ne : $@noescape @callee_guaranteed (Builtin.Int32) -> (Builtin.Int32, @error Error)
|
|
destroy_value %conv : $@callee_guaranteed (Builtin.Int32) -> (Builtin.Int32, @error Error)
|
|
return %res : $Builtin.Int32
|
|
}
|
|
|
|
// Test castValueToABICompatibleType with guaranteed tuples and optionals.
|
|
// Create a nested borrow scope for the Optional tuple element
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @replaceTryApplyGuaranteedTuple : $@convention(thin) (@guaranteed Optional<B>, @guaranteed E) -> Int {
|
|
// CHECK: bb0(%0 : @guaranteed $Optional<B>, %1 : @guaranteed $E):
|
|
// CHECK: [[INCAST:%.*]] = unchecked_ref_cast %0 : $Optional<B> to $Optional<AAA>
|
|
// CHECK: [[INTUP:%.*]] = tuple ([[INCAST]] : $Optional<AAA>, %1 : $E)
|
|
// CHECK: ([[EXTR0:%.*]], [[EXTR1:%.*]]) = destructure_tuple [[INTUP]] : $(Optional<AAA>, E)
|
|
// CHECK: switch_enum [[EXTR0]] : $Optional<AAA>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
|
|
// CHECK: bb1([[UNWRAP:%.*]] : @guaranteed $AAA):
|
|
// CHECK: [[ACAST:%.*]] = unchecked_ref_cast [[UNWRAP]] : $AAA to $B
|
|
// CHECK: [[SOME:%.*]] = enum $Optional<B>, #Optional.some!enumelt, [[ACAST]] : $B
|
|
// CHECK: br bb3([[SOME]] : $Optional<B>)
|
|
// CHECK: bb2:
|
|
// CHECK: [[NONE:%.*]] = enum $Optional<B>, #Optional.none!enumelt
|
|
// CHECK: br bb3([[NONE]] : $Optional<B>)
|
|
// CHECK: bb3([[REWRAP:%.*]] : @guaranteed $Optional<B>):
|
|
// CHECK: [[BF:%.*]] = borrowed [[REWRAP]] : $Optional<B> from (%1 : $E, %0 : $Optional<B>)
|
|
// CHECK: [[ECAST:%.*]] = upcast [[EXTR1]] : $E to $B
|
|
// CHECK: [[OUTTUP:%.*]] = tuple ([[BF]] : $Optional<B>, [[ECAST]] : $B)
|
|
// CHECK: apply %{{.*}}([[OUTTUP]]) : $@convention(thin) (@guaranteed (Optional<B>, B)) -> Int
|
|
// CHECK: return
|
|
// CHECK-LABEL: } // end sil function 'replaceTryApplyGuaranteedTuple'
|
|
sil [ossa] @replaceTryApplyGuaranteedTuple : $@convention(thin) (@guaranteed Optional<B>, @guaranteed E) -> Int {
|
|
bb0(%0 : @guaranteed $Optional<B>, %1 : @guaranteed $E):
|
|
%cast = unchecked_ref_cast %0 : $Optional<B> to $Optional<AAA>
|
|
%tuple = tuple (%cast : $Optional<AAA>, %1 : $E)
|
|
%2 = function_ref @rethrowGuaranteed : $@convention(thin) (@guaranteed (Optional<B>, B)) -> Int
|
|
%3 = convert_function %2 : $@convention(thin) (@guaranteed (Optional<B>, B)) -> Int to $@convention(thin) (@guaranteed (Optional<AAA>, E)) -> (Int, @error Error)
|
|
try_apply %3(%tuple) : $@convention(thin) (@guaranteed (Optional<AAA>, E)) -> (Int, @error Error), normal bb1, error bb2
|
|
|
|
bb1(%5 : $Int):
|
|
return %5 : $Int
|
|
|
|
bb2(%8 : @owned $Error):
|
|
unreachable
|
|
}
|
|
|
|
// Test castValueToABICompatibleType with owned tuples and optionals.
|
|
// Create a destructure for the Optional tuple element.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @replaceTryApplyOwnedTuple : $@convention(thin) (@owned Optional<B>, @owned E) -> Int {
|
|
// CHECK: bb0(%0 : @owned $Optional<B>, %1 : @owned $E):
|
|
// CHECK: [[INCAST:%.*]] = unchecked_ref_cast %0 : $Optional<B> to $Optional<AAA>
|
|
// CHECK: [[INTUP:%.*]] = tuple ([[INCAST]] : $Optional<AAA>, %1 : $E)
|
|
// CHECK: ([[EXTR0:%.*]], [[EXTR1:%.*]]) = destructure_tuple [[INTUP]] : $(Optional<AAA>, E)
|
|
// CHECK: switch_enum [[EXTR0]] : $Optional<AAA>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
|
|
// CHECK: bb1([[UNWRAP:%.*]] : @owned $AAA):
|
|
// CHECK: [[ACAST:%.*]] = unchecked_ref_cast [[UNWRAP]] : $AAA to $B
|
|
// CHECK: [[SOME:%.*]] = enum $Optional<B>, #Optional.some!enumelt, [[ACAST]] : $B
|
|
// CHECK: br bb3([[SOME]] : $Optional<B>)
|
|
// CHECK: bb2:
|
|
// CHECK: [[NONE:%.*]] = enum $Optional<B>, #Optional.none!enumelt
|
|
// CHECK: br bb3([[NONE]] : $Optional<B>)
|
|
// CHECK: bb3([[REWRAP:%.*]] : @owned $Optional<B>):
|
|
// CHECK: [[ECAST:%.*]] = upcast [[EXTR1]] : $E to $B
|
|
// CHECK: [[OUTTUP:%.*]] = tuple ([[REWRAP]] : $Optional<B>, [[ECAST]] : $B)
|
|
// CHECK: apply %{{.*}}([[OUTTUP]]) : $@convention(thin) (@owned (Optional<B>, B)) -> Int
|
|
// CHECK: return
|
|
// CHECK-LABEL: } // end sil function 'replaceTryApplyOwnedTuple'
|
|
sil [ossa] @replaceTryApplyOwnedTuple : $@convention(thin) (@owned Optional<B>, @owned E) -> Int {
|
|
bb0(%0 : @owned $Optional<B>, %1 : @owned $E):
|
|
%cast = unchecked_ref_cast %0 : $Optional<B> to $Optional<AAA>
|
|
%tuple = tuple (%cast : $Optional<AAA>, %1 : $E)
|
|
%2 = function_ref @rethrowOwned : $@convention(thin) (@owned (Optional<B>, B)) -> Int
|
|
%3 = convert_function %2 : $@convention(thin) (@owned (Optional<B>, B)) -> Int to $@convention(thin) (@owned (Optional<AAA>, E)) -> (Int, @error Error)
|
|
try_apply %3(%tuple) : $@convention(thin) (@owned (Optional<AAA>, E)) -> (Int, @error Error), normal bb1, error bb2
|
|
|
|
bb1(%5 : $Int):
|
|
return %5 : $Int
|
|
|
|
bb2(%8 : @owned $Error):
|
|
unreachable
|
|
}
|
|
|