| // RUN: %target-sil-opt %s -escapes-dump -o /dev/null | FileCheck %s |
| |
| // REQUIRES: asserts |
| |
| sil_stage canonical |
| |
| import Builtin |
| import Swift |
| import SwiftShims |
| |
| protocol ClassP : class { |
| func foo() |
| } |
| |
| class X : ClassP { |
| func foo() |
| } |
| |
| class Derived : X { |
| } |
| |
| class Y { |
| @sil_stored var x: X |
| |
| init(newx: X) |
| } |
| |
| protocol P { |
| func foo() |
| } |
| |
| struct Pointer : P { |
| let y : Y |
| func foo() |
| } |
| |
| enum PointerEnum { |
| case B(Pointer, Pointer) |
| } |
| |
| enum PointerEnum2 { |
| case A |
| case B(Pointer) |
| case C |
| } |
| |
| class LinkedNode { |
| @sil_stored var next: LinkedNode; |
| |
| init(_ n: LinkedNode) |
| } |
| |
| struct MyError : ErrorType { |
| } |
| |
| final class ErrorClass : ErrorType { |
| } |
| |
| |
| // Sanity check with a simple function. |
| |
| // CHECK-LABEL: CG of test_simple |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: (%0.1) |
| // CHECK-NEXT: Con %0.1 Esc: A, Succ: %2 |
| // CHECK-NEXT: Arg %1 Esc: G, Succ: |
| // CHECK-NEXT: Val %2 Esc: A, Succ: (%2.1) |
| // CHECK-NEXT: Con %2.1 Esc: A, Succ: (%2.2) |
| // CHECK-NEXT: Con %2.2 Esc: G, Succ: %1 |
| // CHECK-NEXT: End |
| sil @test_simple : $@convention(thin) (@inout Y, @owned X) -> () { |
| bb0(%0 : $*Y, %1 : $X): |
| %2 = alloc_ref $Y |
| %3 = ref_element_addr %2 : $Y, #Y.x |
| store %1 to %3 : $*X |
| %5 = load %0 : $*Y |
| store %2 to %0 : $*Y |
| strong_release %5 : $Y |
| %7 = tuple () |
| return %7 : $() |
| } |
| |
| // Test if a deferring edge is created for a block argument. |
| |
| // CHECK-LABEL: CG of deferringEdge |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: (%3.1) |
| // CHECK-NEXT: Arg %1 Esc: A, Succ: |
| // CHECK-NEXT: Val %3 Esc: %3, Succ: (%3.1), %0 |
| // CHECK-NEXT: Con %3.1 Esc: A, Succ: (%3.2) |
| // CHECK-NEXT: Con %3.2 Esc: A, Succ: %1 |
| // CHECK-NEXT: Ret Esc: R, Succ: %0 |
| // CHECK-NEXT: End |
| sil @deferringEdge : $@convention(thin) (@owned LinkedNode, @owned LinkedNode) -> @owned LinkedNode { |
| bb0(%0 : $LinkedNode, %1 : $LinkedNode): |
| br bb1(%0 : $LinkedNode) |
| |
| bb1(%3 : $LinkedNode): |
| %4 = ref_element_addr %3 : $LinkedNode, #LinkedNode.next |
| store %1 to %4 : $*LinkedNode |
| return %0 : $LinkedNode |
| } |
| |
| // Test a local object just escaping via return. |
| |
| // CHECK-LABEL: CG of escapes_via_return |
| // CHECK-NEXT: Val %0 Esc: R, Succ: |
| // CHECK-NEXT: Ret Esc: R, Succ: %0 |
| // CHECK-NEXT: End |
| sil @escapes_via_return : $@convention(thin) () -> @owned X { |
| bb0: |
| %0 = alloc_ref $X |
| return %0 : $X |
| } |
| |
| // A linear chain of assignments is collapsed to a single node. |
| |
| // CHECK-LABEL: CG of test_linked_list |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: (%1.1) |
| // CHECK-NEXT: Val %1 Esc: A, Succ: (%1.1) |
| // CHECK-NEXT: Con %1.1 Esc: A, Succ: (%11.1) |
| // CHECK-NEXT: Val %4 Esc: A, Succ: (%1.1) |
| // CHECK-NEXT: Val %7 Esc: %11, Succ: (%1.1) |
| // CHECK-NEXT: Val %11 Esc: %11, Succ: (%1.1), %7, %11.1 |
| // CHECK-NEXT: Con %11.1 Esc: A, Succ: (%1.1), %0, %1, %4 |
| // CHECK-NEXT: Ret Esc: R, Succ: %11.1 |
| // CHECK-NEXT: End |
| sil @test_linked_list : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode { |
| bb0(%0 : $LinkedNode): |
| %1 = alloc_ref $LinkedNode |
| %2 = ref_element_addr %1 : $LinkedNode, #LinkedNode.next |
| store %0 to %2 : $*LinkedNode |
| %4 = alloc_ref $LinkedNode |
| %5 = ref_element_addr %4 : $LinkedNode, #LinkedNode.next |
| store %1 to %5 : $*LinkedNode |
| %7 = alloc_ref $LinkedNode |
| %8 = ref_element_addr %7 : $LinkedNode, #LinkedNode.next |
| store %4 to %8 : $*LinkedNode |
| br bb1(%7 : $LinkedNode) |
| |
| // This "x = x.next" loop let's the chain collapse to a single node. |
| bb1(%11 : $LinkedNode): |
| %12 = ref_element_addr %11 : $LinkedNode, #LinkedNode.next |
| %13 = load %12 : $*LinkedNode |
| cond_br undef, bb1(%13 : $LinkedNode), bb2 |
| |
| bb2: |
| return %13 : $LinkedNode |
| } |
| |
| // The same example as above but distributed over two functions. |
| |
| // CHECK-LABEL: CG of create_chain |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: (%7.1) |
| // CHECK-NEXT: Val %1 Esc: A, Succ: (%7.1) |
| // CHECK-NEXT: Con %1.1 Esc: A, Succ: %0, %1, %4 |
| // CHECK-NEXT: Val %4 Esc: A, Succ: (%7.1) |
| // CHECK-NEXT: Val %7 Esc: %11, Succ: (%7.1) |
| // CHECK-NEXT: Con %7.1 Esc: A, Succ: (%1.1) |
| // CHECK-NEXT: Val %11 Esc: R, Succ: (%7.1), %1.1 |
| // CHECK-NEXT: Ret Esc: R, Succ: %11 |
| // CHECK-NEXT: End |
| sil @create_chain : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode { |
| bb0(%0 : $LinkedNode): |
| %1 = alloc_ref $LinkedNode |
| %2 = ref_element_addr %1 : $LinkedNode, #LinkedNode.next |
| store %0 to %2 : $*LinkedNode |
| %4 = alloc_ref $LinkedNode |
| %5 = ref_element_addr %4 : $LinkedNode, #LinkedNode.next |
| store %1 to %5 : $*LinkedNode |
| %7 = alloc_ref $LinkedNode |
| %8 = ref_element_addr %7 : $LinkedNode, #LinkedNode.next |
| store %4 to %8 : $*LinkedNode |
| |
| %10 = function_ref @loadNext : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode |
| %11 = apply %10(%7) : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode |
| return %11 : $LinkedNode |
| } |
| |
| // CHECK-LABEL: CG of loadNext |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: (%2.1) |
| // CHECK-NEXT: Val %2 Esc: %2, Succ: (%2.1), %0, %2.2 |
| // CHECK-NEXT: Con %2.1 Esc: A, Succ: (%2.2) |
| // CHECK-NEXT: Con %2.2 Esc: A, Succ: (%2.1) |
| // CHECK-NEXT: Ret Esc: R, Succ: %2.2 |
| // CHECK-NEXT: End |
| sil @loadNext : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode { |
| bb0(%0 : $LinkedNode): |
| br bb1(%0 : $LinkedNode) |
| |
| bb1(%2 : $LinkedNode): |
| %3 = ref_element_addr %2 : $LinkedNode, #LinkedNode.next |
| %4 = load %3 : $*LinkedNode |
| cond_br undef, bb1(%4 : $LinkedNode), bb2 |
| |
| bb2: |
| return %4 : $LinkedNode |
| } |
| |
| // Content nodes in the callee are duplicated in the caller. |
| |
| // CHECK-LABEL: CG of call_load_next3 |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: (%0.1) |
| // CHECK-NEXT: Con %0.1 Esc: A, Succ: (%0.2) |
| // CHECK-NEXT: Con %0.2 Esc: A, Succ: (%0.3) |
| // CHECK-NEXT: Con %0.3 Esc: A, Succ: (%0.4) |
| // CHECK-NEXT: Con %0.4 Esc: A, Succ: (%0.5) |
| // CHECK-NEXT: Con %0.5 Esc: A, Succ: (%0.6) |
| // CHECK-NEXT: Con %0.6 Esc: A, Succ: |
| // CHECK-NEXT: Val %2 Esc: R, Succ: %0.6 |
| // CHECK-NEXT: Ret Esc: R, Succ: %2 |
| // CHECK-NEXT: End |
| sil @call_load_next3 : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode { |
| bb0(%0 : $LinkedNode): |
| %1 = function_ref @load_next3 : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode |
| %2 = apply %1(%0) : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode |
| return %2 : $LinkedNode |
| } |
| |
| // CHECK-LABEL: CG of load_next3 |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: (%0.1) |
| // CHECK-NEXT: Con %0.1 Esc: A, Succ: (%0.2) |
| // CHECK-NEXT: Con %0.2 Esc: A, Succ: (%0.3) |
| // CHECK-NEXT: Con %0.3 Esc: A, Succ: (%0.4) |
| // CHECK-NEXT: Con %0.4 Esc: A, Succ: (%0.5) |
| // CHECK-NEXT: Con %0.5 Esc: A, Succ: (%0.6) |
| // CHECK-NEXT: Con %0.6 Esc: A, Succ: |
| // CHECK-NEXT: Ret Esc: R, Succ: %0.6 |
| // CHECK-NEXT: End |
| sil @load_next3 : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode { |
| bb0(%0 : $LinkedNode): |
| %1 = ref_element_addr %0 : $LinkedNode, #LinkedNode.next |
| %2 = load %1 : $*LinkedNode |
| %3 = ref_element_addr %2 : $LinkedNode, #LinkedNode.next |
| %4 = load %3 : $*LinkedNode |
| %5 = ref_element_addr %4 : $LinkedNode, #LinkedNode.next |
| %6 = load %5 : $*LinkedNode |
| return %6 : $LinkedNode |
| } |
| |
| sil_global @global_pointer : $Pointer |
| sil_global @global_x : $X |
| |
| // The argument escapes because it is stored to a global variable in the callee. |
| |
| // CHECK-LABEL: CG of call_store_pointer |
| // CHECK-NEXT: Arg %0 Esc: G, Succ: (%0.1) |
| // CHECK-NEXT: Con %0.1 Esc: G, Succ: (%0.2) |
| // CHECK-NEXT: Con %0.2 Esc: G, Succ: |
| // CHECK-NEXT: Ret Esc: R, Succ: %0.2 |
| // CHECK-NEXT: End |
| sil @call_store_pointer : $@convention(thin) (@owned Pointer) -> @owned X { |
| bb0(%0 : $Pointer): |
| debug_value %0 : $Pointer |
| %2 = function_ref @store_pointer : $@convention(thin) (@owned Pointer) -> () |
| %3 = struct_extract %0 : $Pointer, #Pointer.y |
| %5 = apply %2(%0) : $@convention(thin) (@owned Pointer) -> () |
| %6 = ref_element_addr %3 : $Y, #Y.x |
| %7 = load %6 : $*X |
| return %7 : $X |
| } |
| |
| // CHECK-LABEL: CG of store_pointer |
| // CHECK-NEXT: Arg %0 Esc: G, Succ: |
| // CHECK-NEXT: Val %1 Esc: G, Succ: (%1.1) |
| // CHECK-NEXT: Con %1.1 Esc: G, Succ: %0 |
| // CHECK-NEXT: End |
| sil @store_pointer : $@convention(thin) (@owned Pointer) -> () { |
| bb0(%0 : $Pointer): |
| %1 = global_addr @global_pointer : $*Pointer |
| store %0 to %1 : $*Pointer |
| %3 = tuple () |
| return %3 : $() |
| } |
| |
| // The argument does not escape because only the content is stored to a |
| // global variable in the callee. |
| |
| // CHECK-LABEL: CG of store_content |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: (%0.1) |
| // CHECK-NEXT: Con %0.1 Esc: A, Succ: (%0.2) |
| // CHECK-NEXT: Con %0.2 Esc: G, Succ: |
| // CHECK-NEXT: Val %1 Esc: G, Succ: (%1.1) |
| // CHECK-NEXT: Con %1.1 Esc: G, Succ: %0.2 |
| // CHECK-NEXT: End |
| sil @store_content : $@convention(thin) (@owned Pointer) -> () { |
| bb0(%0 : $Pointer): |
| %1 = global_addr @global_x : $*X |
| %3 = struct_extract %0 : $Pointer, #Pointer.y |
| %4 = ref_element_addr %3 : $Y, #Y.x |
| %5 = load %4 : $*X |
| store %5 to %1 : $*X |
| %11 = tuple () |
| return %11 : $() |
| } |
| |
| // CHECK-LABEL: CG of call_store_content |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: (%0.1) |
| // CHECK-NEXT: Con %0.1 Esc: A, Succ: (%0.2) |
| // CHECK-NEXT: Con %0.2 Esc: G, Succ: |
| // CHECK-NEXT: Ret Esc: R, Succ: %0.2 |
| // CHECK-NEXT: End |
| sil @call_store_content : $@convention(thin) (@owned Pointer) -> @owned X { |
| bb0(%0 : $Pointer): |
| %2 = function_ref @store_content : $@convention(thin) (@owned Pointer) -> () |
| %3 = struct_extract %0 : $Pointer, #Pointer.y |
| %5 = apply %2(%0) : $@convention(thin) (@owned Pointer) -> () |
| %6 = ref_element_addr %3 : $Y, #Y.x |
| %7 = load %6 : $*X |
| return %7 : $X |
| } |
| |
| // Test partial_apply. The partial_apply and the boxes do not escape. |
| // The X parameter does escape because it is stored in Y and the release |
| // of Y's box _could_ capture Y.x in Y's deinit. |
| |
| // CHECK-LABEL: CG of test_partial_apply |
| // CHECK-NEXT: Arg %1 Esc: G, Succ: |
| // CHECK-NEXT: Arg %2 Esc: A, Succ: (%5.2) |
| // CHECK-NEXT: Val %3 Esc: %12,%13,%15, Succ: (%5.1) |
| // CHECK-NEXT: Val %5 Esc: %12,%13,%14, Succ: (%5.1) |
| // CHECK-NEXT: Con %5.1 Esc: %12,%13,%14,%15, Succ: %2 |
| // CHECK-NEXT: Con %5.2 Esc: G, Succ: |
| // CHECK-NEXT: Val %10 Esc: %12,%13, Succ: %3, %5 |
| // CHECK-NEXT: End |
| sil @test_partial_apply : $@convention(thin) (Int64, @owned X, @owned Y) -> Int64 { |
| bb0(%0 : $Int64, %1 : $X, %2 : $Y): |
| %3 = alloc_box $Int64 |
| store %0 to %3#1 : $*Int64 |
| %5 = alloc_box $Y |
| store %2 to %5#1 : $*Y |
| %7 = function_ref @closure1 : $@convention(thin) (@owned X, @owned @box Int64, @owned @box Y) -> Int64 |
| strong_retain %3#0 : $@box Int64 |
| strong_retain %5#0 : $@box Y |
| %10 = partial_apply %7(%3#0, %5#0) : $@convention(thin) (@owned X, @owned @box Int64, @owned @box Y) -> Int64 |
| strong_retain %10 : $@callee_owned (@owned X) -> Int64 |
| %12 = apply %10(%1) : $@callee_owned (@owned X) -> Int64 |
| strong_release %10 : $@callee_owned (@owned X) -> Int64 |
| strong_release %5#0 : $@box Y |
| strong_release %3#0 : $@box Int64 |
| return %12 : $Int64 |
| } |
| |
| // CHECK-LABEL: CG of closure1 |
| // CHECK-NEXT: Arg %0 Esc: G, Succ: |
| // CHECK-NEXT: Arg %1 Esc: A, Succ: (%1.1) |
| // CHECK-NEXT: Con %1.1 Esc: A, Succ: (%1.2) |
| // CHECK-NEXT: Con %1.2 Esc: G, Succ: |
| // CHECK-NEXT: Arg %2 Esc: A, Succ: (%2.1) |
| // CHECK-NEXT: Con %2.1 Esc: A, Succ: (%2.2) |
| // CHECK-NEXT: Con %2.2 Esc: G, Succ: |
| // CHECK-NEXT: Val %7 Esc: %8, Succ: %2 |
| // CHECK-NEXT: End |
| sil @closure1 : $@convention(thin) (@owned X, @owned @box Int64, @owned @box Y) -> Int64 { |
| bb0(%0 : $X, %1 : $@box Int64, %2 : $@box Y): |
| %3 = project_box %1 : $@box Int64 |
| %4 = project_box %2 : $@box Y |
| %5 = load %3 : $*Int64 |
| %6 = function_ref @closure2 : $@convention(thin) (@owned X, @owned @box Y) -> () |
| %7 = partial_apply %6(%2) : $@convention(thin) (@owned X, @owned @box Y) -> () |
| %8 = apply %7(%0) : $@callee_owned (@owned X) -> () |
| strong_release %1 : $@box Int64 |
| return %5 : $Int64 |
| } |
| |
| // CHECK-LABEL: CG of closure2 |
| // CHECK-NEXT: Arg %0 Esc: G, Succ: |
| // CHECK-NEXT: Arg %1 Esc: A, Succ: (%1.1) |
| // CHECK-NEXT: Con %1.1 Esc: A, Succ: (%1.2) |
| // CHECK-NEXT: Con %1.2 Esc: G, Succ: (%1.3) |
| // CHECK-NEXT: Con %1.3 Esc: G, Succ: (%1.4) |
| // CHECK-NEXT: Con %1.4 Esc: G, Succ: %0 |
| // CHECK-NEXT: End |
| sil @closure2 : $@convention(thin) (@owned X, @owned @box Y) -> () { |
| bb0(%0 : $X, %1 : $@box Y): |
| %2 = project_box %1 : $@box Y |
| %3 = load %2 : $*Y |
| %4 = ref_element_addr %3 : $Y, #Y.x |
| store %0 to %4 : $*X |
| strong_release %1 : $@box Y |
| %7 = tuple () |
| return %7 : $() |
| } |
| |
| // Test partial_apply. The box escapes in the callee. |
| |
| // CHECK-LABEL: CG of test_escaped_box |
| // CHECK-NEXT: Val %1 Esc: G, Succ: (%5.1) |
| // CHECK-NEXT: Val %5 Esc: G, Succ: %1 |
| // CHECK-NEXT: Con %5.1 Esc: G, Succ: (%5.2) |
| // CHECK-NEXT: Con %5.2 Esc: G, Succ: |
| // CHECK-NEXT: End |
| sil @test_escaped_box : $@convention(thin) (Int64) -> Int64 { |
| bb0(%0 : $Int64): |
| %1 = alloc_box $Int64 |
| store %0 to %1#1 : $*Int64 |
| |
| %3 = function_ref @let_box_escape : $@convention(thin) (@owned @box Int64) -> Int64 |
| strong_retain %1#0 : $@box Int64 |
| %5 = partial_apply %3(%1#0) : $@convention(thin) (@owned @box Int64) -> Int64 |
| strong_retain %5 : $@callee_owned () -> Int64 |
| %7 = apply %5() : $@callee_owned () -> Int64 |
| strong_release %5 : $@callee_owned () -> Int64 |
| strong_release %1#0 : $@box Int64 |
| return %7 : $Int64 |
| } |
| |
| |
| // CHECK-LABEL: CG of let_box_escape |
| // CHECK-NEXT: Arg %0 Esc: G, Succ: (%0.1) |
| // CHECK-NEXT: Con %0.1 Esc: G, Succ: (%0.2) |
| // CHECK-NEXT: Con %0.2 Esc: G, Succ: |
| // CHECK-NEXT: End |
| sil @let_box_escape : $@convention(thin) (@owned @box Int64) -> Int64 { |
| bb0(%0 : $@box Int64): |
| %1 = project_box %0 : $@box Int64 |
| %2 = load %1 : $*Int64 |
| |
| %3 = function_ref @takebox : $@convention(thin) (@owned @box Int64) -> () |
| %4 = apply %3(%0) : $@convention(thin) (@owned @box Int64) -> () |
| strong_release %0 : $@box Int64 |
| return %2 : $Int64 |
| } |
| |
| sil @takebox : $@convention(thin) (@owned @box Int64) -> () |
| |
| |
| // The partial_apply itself escapes and therefore also the box escapes. |
| |
| // CHECK-LABEL: CG of test_escaped_partial_apply |
| // CHECK-NEXT: Val %1 Esc: G, Succ: |
| // CHECK-NEXT: Val %5 Esc: G, Succ: %1 |
| // CHECK-NEXT: Con %5.1 Esc: G, Succ: |
| // CHECK-NEXT: End |
| sil @test_escaped_partial_apply : $@convention(thin) (Int64) -> () { |
| bb0(%0 : $Int64): |
| %1 = alloc_box $Int64 |
| store %0 to %1#1 : $*Int64 |
| %3 = function_ref @closure3 : $@convention(thin) (@owned @box Int64) -> Int64 |
| strong_retain %1#0 : $@box Int64 |
| %5 = partial_apply %3(%1#0) : $@convention(thin) (@owned @box Int64) -> Int64 |
| strong_retain %5 : $@callee_owned () -> Int64 |
| %6 = function_ref @take_partial_apply : $@convention(thin) (@owned @callee_owned () -> Int64) -> () |
| %7 = apply %6(%5) : $@convention(thin) (@owned @callee_owned () -> Int64) -> () |
| %8 = tuple() |
| return %8 : $() |
| } |
| |
| // CHECK-LABEL: CG of closure3 |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: (%0.1) |
| // CHECK-NEXT: Con %0.1 Esc: A, Succ: (%0.2) |
| // CHECK-NEXT: Con %0.2 Esc: G, Succ: |
| // CHECK-NEXT: End |
| sil @closure3 : $@convention(thin) (@owned @box Int64) -> Int64 { |
| bb0(%0 : $@box Int64): |
| %1 = project_box %0 : $@box Int64 |
| %2 = load %1 : $*Int64 |
| strong_release %0 : $@box Int64 |
| return %2 : $Int64 |
| } |
| |
| sil @take_partial_apply : $@convention(thin) (@owned @callee_owned () -> Int64) -> () |
| |
| // Test if the global escape state is propagated through recursive functions. |
| |
| sil_global @global_ln : $LinkedNode |
| |
| // CHECK-LABEL: CG of load_next_recursive |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: (%0.1) |
| // CHECK-NEXT: Con %0.1 Esc: A, Succ: (%0.2) |
| // CHECK-NEXT: Con %0.2 Esc: G, Succ: (%4.1) |
| // CHECK-NEXT: Val %4 Esc: R, Succ: %0.2 |
| // CHECK-NEXT: Con %4.1 Esc: G, Succ: |
| // CHECK-NEXT: Ret Esc: R, Succ: %4 |
| // CHECK-NEXT: End |
| sil @load_next_recursive : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode { |
| bb0(%0 : $LinkedNode): |
| %1 = ref_element_addr %0 : $LinkedNode, #LinkedNode.next |
| %2 = load %1 : $*LinkedNode |
| %3 = function_ref @let_escape : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode |
| %4 = apply %3(%2) : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode |
| return %4 : $LinkedNode |
| } |
| |
| // CHECK-LABEL: CG of let_escape |
| // CHECK-NEXT: Arg %0 Esc: G, Succ: (%0.1) |
| // CHECK-NEXT: Con %0.1 Esc: G, Succ: |
| // CHECK-NEXT: Val %1 Esc: G, Succ: (%1.1) |
| // CHECK-NEXT: Con %1.1 Esc: G, Succ: %0 |
| // CHECK-NEXT: Val %4 Esc: R, Succ: %0 |
| // CHECK-NEXT: Ret Esc: R, Succ: %4 |
| // CHECK-NEXT: End |
| sil @let_escape : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode { |
| bb0(%0 : $LinkedNode): |
| %1 = global_addr @global_ln : $*LinkedNode |
| store %0 to %1 : $*LinkedNode |
| %3 = function_ref @return_same : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode |
| %4 = apply %3(%0) : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode |
| return %4 : $LinkedNode |
| } |
| |
| // CHECK-LABEL: CG of return_same |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: (%0.1) |
| // CHECK-NEXT: Con %0.1 Esc: G, Succ: (%0.2) |
| // CHECK-NEXT: Con %0.2 Esc: G, Succ: (%0.1) |
| // CHECK-NEXT: Val %3 Esc: R, Succ: (%0.1), %0.2 |
| // CHECK-NEXT: Val %5 Esc: R, Succ: %0, %3 |
| // CHECK-NEXT: Ret Esc: R, Succ: %5 |
| // CHECK-NEXT: End |
| sil @return_same : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode { |
| bb0(%0 : $LinkedNode): |
| cond_br undef, bb1, bb2(%0 : $LinkedNode) |
| |
| bb1: |
| %2 = function_ref @load_next_recursive : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode |
| %3 = apply %2(%0) : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode |
| br bb2(%3 : $LinkedNode) |
| |
| bb2(%5 : $LinkedNode): |
| return %5 : $LinkedNode |
| } |
| |
| // Another recursion test. |
| |
| // CHECK-LABEL: CG of loadNext2 |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: (%0.1) |
| // CHECK-NEXT: Con %0.1 Esc: A, Succ: (%0.2) |
| // CHECK-NEXT: Con %0.2 Esc: A, Succ: (%0.3) |
| // CHECK-NEXT: Con %0.3 Esc: A, Succ: (%0.4) |
| // CHECK-NEXT: Con %0.4 Esc: A, Succ: (%4.1) |
| // CHECK-NEXT: Val %4 Esc: R, Succ: %0.4, %4.2 |
| // CHECK-NEXT: Con %4.1 Esc: A, Succ: (%4.2) |
| // CHECK-NEXT: Con %4.2 Esc: A, Succ: (%4.1) |
| // CHECK-NEXT: Ret Esc: R, Succ: %4 |
| // CHECK-NEXT: End |
| sil @loadNext2 : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode { |
| bb0(%0 : $LinkedNode): |
| %1 = ref_element_addr %0 : $LinkedNode, #LinkedNode.next |
| %2 = load %1 : $*LinkedNode |
| %3 = function_ref @returnNext2 : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode |
| %4 = apply %3(%2) : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode |
| return %4 : $LinkedNode |
| } |
| |
| // CHECK-LABEL: CG of returnNext2 |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: (%0.1) |
| // CHECK-NEXT: Con %0.1 Esc: A, Succ: (%0.2) |
| // CHECK-NEXT: Con %0.2 Esc: A, Succ: (%0.3) |
| // CHECK-NEXT: Con %0.3 Esc: A, Succ: (%0.4) |
| // CHECK-NEXT: Con %0.4 Esc: A, Succ: (%0.3) |
| // CHECK-NEXT: Val %3 Esc: R, Succ: (%0.3), %0.4 |
| // CHECK-NEXT: Val %8 Esc: R, Succ: %0.2, %3 |
| // CHECK-NEXT: Ret Esc: R, Succ: %8 |
| // CHECK-NEXT: End |
| sil @returnNext2 : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode { |
| bb0(%0 : $LinkedNode): |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| %2 = function_ref @loadNext2 : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode |
| %3 = apply %2(%0) : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode |
| br bb3(%3 : $LinkedNode) |
| |
| bb2: |
| %5 = ref_element_addr %0 : $LinkedNode, #LinkedNode.next |
| %6 = load %5 : $*LinkedNode |
| br bb3(%6 : $LinkedNode) |
| |
| bb3(%8 : $LinkedNode): |
| return %8 : $LinkedNode |
| } |
| |
| // A single-cycle recursion test. |
| |
| // CHECK-LABEL: CG of single_cycle_recursion |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: (%0.2) |
| // CHECK-NEXT: Con %0.1 Esc: A, Succ: (%0.2) |
| // CHECK-NEXT: Con %0.2 Esc: A, Succ: (%0.1) |
| // CHECK-NEXT: Val %5 Esc: R, Succ: (%0.2), %0.1 |
| // CHECK-NEXT: Val %7 Esc: R, Succ: %0, %5 |
| // CHECK-NEXT: Ret Esc: R, Succ: %7 |
| // CHECK-NEXT: End |
| sil @single_cycle_recursion : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode { |
| bb0(%0 : $LinkedNode): |
| cond_br undef, bb1, bb2(%0 : $LinkedNode) |
| |
| bb1: |
| %1 = ref_element_addr %0 : $LinkedNode, #LinkedNode.next |
| %2 = load %1 : $*LinkedNode |
| %3 = function_ref @single_cycle_recursion : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode |
| %4 = apply %3(%2) : $@convention(thin) (@owned LinkedNode) -> @owned LinkedNode |
| br bb2(%4 : $LinkedNode) |
| |
| bb2(%5 : $LinkedNode): |
| return %5 : $LinkedNode |
| } |
| |
| // Test if a try_apply is represented correctly in the connection graph. |
| |
| // CHECK-LABEL: CG of call_throwing_func |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: |
| // CHECK-NEXT: Val %3 Esc: R, Succ: %0 |
| // CHECK-NEXT: Ret Esc: R, Succ: %3 |
| // CHECK-NEXT: End |
| sil @call_throwing_func : $@convention(thin) (@owned X) -> (@owned X, @error ErrorType) { |
| bb0(%0 : $X): |
| %1 = function_ref @throwing_func : $@convention(thin) (@owned X) -> (@owned X, @error ErrorType) |
| try_apply %1(%0) : $@convention(thin) (@owned X) -> (@owned X, @error ErrorType), normal bb1, error bb2 |
| |
| bb1(%3 : $X): |
| return %3 : $X |
| |
| bb2(%5 : $ErrorType): |
| throw %5 : $ErrorType |
| } |
| |
| // CHECK-LABEL: CG of throwing_func |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: |
| // CHECK-NEXT: Ret Esc: R, Succ: %0 |
| // CHECK-NEXT: End |
| sil @throwing_func : $@convention(thin) (@owned X) -> (@owned X, @error ErrorType) { |
| bb0(%0 : $X): |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| %2 = alloc_existential_box $ErrorType, $MyError |
| %3 = struct $MyError () |
| store %3 to %2#1 : $*MyError |
| throw %2#0 : $ErrorType |
| |
| bb2: |
| return %0 : $X |
| } |
| |
| // Test if a try_apply to an unknown function is handled correctly. |
| |
| // CHECK-LABEL: CG of call_unknown_throwing_func |
| // CHECK-NEXT: Arg %0 Esc: G, Succ: |
| // CHECK-NEXT: Con %0.1 Esc: G, Succ: |
| // CHECK-NEXT: Val %3 Esc: G, Succ: |
| // CHECK-NEXT: Con %3.1 Esc: G, Succ: |
| // CHECK-NEXT: Ret Esc: R, Succ: %3 |
| // CHECK-NEXT: End |
| sil @call_unknown_throwing_func : $@convention(thin) (@owned X) -> (@owned X, @error ErrorType) { |
| bb0(%0 : $X): |
| %1 = function_ref @unknown_throwing_func : $@convention(thin) (@owned X) -> (@owned X, @error ErrorType) |
| try_apply %1(%0) : $@convention(thin) (@owned X) -> (@owned X, @error ErrorType), normal bb1, error bb2 |
| |
| bb1(%3 : $X): |
| return %3 : $X |
| |
| bb2(%5 : $ErrorType): |
| throw %5 : $ErrorType |
| } |
| |
| sil @unknown_throwing_func : $@convention(thin) (@owned X) -> (@owned X, @error ErrorType) |
| |
| // Test is an unknown value is merged correctly into the caller graph. |
| |
| // CHECK-LABEL: CG of store_to_unknown_reference |
| // CHECK-NEXT: Arg %0 Esc: G, Succ: |
| // CHECK-NEXT: Val %2 Esc: , Succ: (%2.1) |
| // CHECK-NEXT: Con %2.1 Esc: G, Succ: (%2.2) |
| // CHECK-NEXT: Con %2.2 Esc: G, Succ: %0 |
| // CHECK-NEXT: End |
| sil @store_to_unknown_reference : $@convention(thin) (@owned X) -> () { |
| bb0(%0 : $X): |
| %1 = function_ref @get_reference : $@convention(thin) () -> @owned Y |
| %2 = apply %1() : $@convention(thin) () -> @owned Y |
| %3 = ref_element_addr %2 : $Y, #Y.x |
| store %0 to %3 : $*X |
| %5 = tuple () |
| return %5 : $() |
| } |
| |
| // CHECK-LABEL: CG of get_reference |
| // CHECK-NEXT: Val %1 Esc: G, Succ: (%1.1) |
| // CHECK-NEXT: Con %1.1 Esc: G, Succ: |
| // CHECK-NEXT: Ret Esc: R, Succ: %1 |
| // CHECK-NEXT: End |
| sil @get_reference : $@convention(thin) () -> @owned Y { |
| bb0: |
| %0 = function_ref @unknown_get_reference : $@convention(thin) () -> @owned Y |
| %1 = apply %0() : $@convention(thin) () -> @owned Y |
| return %1 : $Y |
| } |
| |
| sil @unknown_get_reference : $@convention(thin) () -> @owned Y |
| |
| // Test types which are considered as pointers. |
| |
| // CHECK-LABEL: CG of pointer_types |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: %1 |
| // CHECK-NEXT: Arg %1 Esc: A, Succ: |
| // CHECK-NEXT: Val %7 Esc: R, Succ: %0 |
| // CHECK-NEXT: Ret Esc: R, Succ: %7 |
| // CHECK-NEXT: End |
| sil @pointer_types : $@convention(thin) (@owned Y, @owned Y) -> @owned Y { |
| bb0(%0 : $Y, %1 : $Y): |
| %2 = struct $Pointer (%0 : $Y) |
| %3 = struct $Pointer (%1 : $Y) |
| %4 = tuple (%2 : $Pointer, %3 : $Pointer) |
| %5 = enum $PointerEnum, #PointerEnum.B!enumelt.1, %4 : $(Pointer, Pointer) |
| switch_enum %5 : $PointerEnum, case #PointerEnum.B!enumelt.1: bb1 |
| |
| bb1(%7 : $(Pointer, Pointer)): |
| %8 = tuple_extract %7 : $(Pointer, Pointer), 1 |
| %9 = struct_extract %8 : $Pointer, #Pointer.y |
| return %9 : $Y |
| } |
| |
| // CHECK-LABEL: CG of test_select_enum |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: |
| // CHECK-NEXT: Arg %1 Esc: A, Succ: |
| // CHECK-NEXT: Arg %2 Esc: A, Succ: |
| // CHECK-NEXT: Arg %3 Esc: A, Succ: |
| // CHECK-NEXT: Val %4 Esc: R, Succ: %1, %2, %3 |
| // CHECK-NEXT: Ret Esc: R, Succ: %4 |
| // CHECK-NEXT: End |
| sil @test_select_enum : $@convention(thin) (PointerEnum2, @owned X, @owned X, @owned X) -> @owned X { |
| bb0(%0 : $PointerEnum2, %1 : $X, %2 : $X, %3 : $X): |
| %4 = select_enum %0 : $PointerEnum2, case #PointerEnum2.A!enumelt: %1, case #PointerEnum2.B!enumelt: %2, default %3 : $X |
| return %4 : $X |
| } |
| |
| // CHECK-LABEL: CG of test_select_enum_addr |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: |
| // CHECK-NEXT: Arg %1 Esc: A, Succ: |
| // CHECK-NEXT: Arg %2 Esc: A, Succ: |
| // CHECK-NEXT: Arg %3 Esc: A, Succ: |
| // CHECK-NEXT: Val %4 Esc: R, Succ: %1, %2, %3 |
| // CHECK-NEXT: Ret Esc: R, Succ: %4 |
| // CHECK-NEXT: End |
| sil @test_select_enum_addr : $@convention(thin) (@in PointerEnum2, @owned X, @owned X, @owned X) -> @owned X { |
| bb0(%0 : $*PointerEnum2, %1 : $X, %2 : $X, %3 : $X): |
| %4 = select_enum_addr %0 : $*PointerEnum2, case #PointerEnum2.A!enumelt: %1, case #PointerEnum2.B!enumelt: %2, default %3 : $X |
| return %4 : $X |
| } |
| |
| // CHECK-LABEL: CG of test_select_value |
| // CHECK-NEXT: Arg %1 Esc: A, Succ: |
| // CHECK-NEXT: Arg %2 Esc: A, Succ: |
| // CHECK-NEXT: Arg %3 Esc: A, Succ: |
| // CHECK-NEXT: Val %6 Esc: R, Succ: %1, %2, %3 |
| // CHECK-NEXT: Ret Esc: R, Succ: %6 |
| // CHECK-NEXT: End |
| sil @test_select_value : $@convention(thin) (Builtin.Int64, @owned X, @owned X, @owned X) -> @owned X { |
| bb0(%0 : $Builtin.Int64, %1 : $X, %2 : $X, %3 : $X): |
| %4 = integer_literal $Builtin.Int64, 0 |
| %5 = integer_literal $Builtin.Int64, 1 |
| %6 = select_value %0 : $Builtin.Int64, case %4: %1, case %5: %2, default %3 : $X |
| return %6 : $X |
| } |
| |
| // CHECK-LABEL: CG of test_existential_addr |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: |
| // CHECK-NEXT: Val %1 Esc: , Succ: (%1.1) |
| // CHECK-NEXT: Con %1.1 Esc: , Succ: (%1.2) |
| // CHECK-NEXT: Con %1.2 Esc: , Succ: %0 |
| // CHECK-NEXT: End |
| sil @test_existential_addr : $@convention(thin) (@owned Pointer) -> () { |
| bb0(%0 : $Pointer): |
| %1 = alloc_stack $P |
| %2 = init_existential_addr %1#1 : $*P, $Pointer |
| store %0 to %2 : $*Pointer |
| %4 = open_existential_addr %1#1 : $*P to $*@opened("C62B1408-97C8-11E5-8D7C-685B35C48C83") P |
| %5 = witness_method $@opened("C62B1408-97C8-11E5-8D7C-685B35C48C83") P, #P.foo!1, %4 : $*@opened("C62B1408-97C8-11E5-8D7C-685B35C48C83") P : $@convention(witness_method) <Ï„_0_0 where Ï„_0_0 : P> (@in_guaranteed Ï„_0_0) -> () |
| dealloc_stack %1#0 : $*@local_storage P |
| %7 = tuple () |
| return %7 : $() |
| } |
| |
| // CHECK-LABEL: CG of test_existential_ref |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: |
| // CHECK-NEXT: End |
| sil @test_existential_ref : $@convention(thin) (@owned X) -> () { |
| bb0(%0 : $X): |
| %1 = init_existential_ref %0 : $X : $X, $ClassP |
| %2 = open_existential_ref %1 : $ClassP to $@opened("EC6B6A86-9887-11E5-926E-685B35C48C83") ClassP |
| %3 = witness_method $@opened("EC6B6A86-9887-11E5-926E-685B35C48C83") ClassP, #ClassP.foo!1, %2 : $@opened("EC6B6A86-9887-11E5-926E-685B35C48C83") ClassP : $@convention(witness_method) <Ï„_0_0 where Ï„_0_0 : ClassP> (@guaranteed Ï„_0_0) -> () |
| %7 = tuple () |
| return %7 : $() |
| } |
| |
| // We don't handle existential boxes currently. |
| // Check that we don't crash on this. |
| |
| // CHECK-LABEL: CG of test_unknown_store |
| // CHECK-NEXT: Arg %0 Esc: G, Succ: |
| // CHECK-NEXT: Con %0.1 Esc: G, Succ: |
| // CHECK-NEXT: End |
| sil @test_unknown_store : $@convention(thin) (@owned ErrorClass) -> () { |
| bb0(%0 : $ErrorClass): |
| %2 = alloc_existential_box $ErrorType, $ErrorClass |
| store %0 to %2#1 : $*ErrorClass |
| %4 = tuple () |
| return %4 : $() |
| } |
| |
| // CHECK-LABEL: CG of test_raw_pointer_to_ref |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: |
| // CHECK-NEXT: Ret Esc: R, Succ: %0 |
| // CHECK-NEXT: End |
| sil @test_raw_pointer_to_ref : $@convention(thin) (@owned X) -> @owned X { |
| bb0(%0 : $X): |
| %1 = ref_to_raw_pointer %0 : $X to $Builtin.RawPointer |
| %2 = raw_pointer_to_ref %1 : $Builtin.RawPointer to $X |
| return %2 : $X |
| } |
| |
| // CHECK-LABEL: CG of test_bridge_object_to_ref |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: |
| // CHECK-NEXT: Ret Esc: R, Succ: %0 |
| // CHECK-NEXT: End |
| sil @test_bridge_object_to_ref : $@convention(thin) (@owned X, Builtin.Word) -> @owned X { |
| bb0(%0 : $X, %1 : $Builtin.Word): |
| %2 = ref_to_bridge_object %0 : $X, %1 : $Builtin.Word |
| %3 = bridge_object_to_ref %2 : $Builtin.BridgeObject to $X |
| return %3 : $X |
| } |
| |
| // CHECK-LABEL: CG of test_address_to_pointer |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: (%0.1) |
| // CHECK-NEXT: Con %0.1 Esc: A, Succ: %1 |
| // CHECK-NEXT: Arg %1 Esc: A, Succ: |
| // CHECK-NEXT: End |
| sil @test_address_to_pointer : $@convention(thin) (@out X, @owned X) -> () { |
| bb0(%0 : $*X, %1 : $X): |
| %2 = address_to_pointer %0 : $*X to $Builtin.RawPointer |
| %3 = pointer_to_address %2 : $Builtin.RawPointer to $*X |
| store %1 to %3 : $*X |
| %7 = tuple () |
| return %7 : $() |
| } |
| |
| // CHECK-LABEL: CG of test_casts |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: |
| // CHECK-NEXT: Ret Esc: R, Succ: %0 |
| // CHECK-NEXT: End |
| sil @test_casts : $@convention(thin) (@owned AnyObject) -> @owned X { |
| bb0(%0 : $AnyObject): |
| %1 = unchecked_ref_cast %0 : $AnyObject to $Derived |
| %2 = upcast %1 : $Derived to $X |
| return %2 : $X |
| } |
| |
| // CHECK-LABEL: CG of test_unchecked_ref_cast_addr |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: %1 |
| // CHECK-NEXT: Arg %1 Esc: A, Succ: |
| // CHECK-NEXT: End |
| sil @test_unchecked_ref_cast_addr : $@convention(thin) <T, U> (@out U, @in T, @thick U.Type) -> () { |
| bb0(%0 : $*U, %1 : $*T, %2 : $@thick U.Type): |
| unchecked_ref_cast_addr T in %1 : $*T to U in %0 : $*U |
| %5 = tuple () |
| return %5 : $() |
| } |
| |
| // CHECK-LABEL: CG of arraysemantics_is_native_no_typecheck |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: |
| // CHECK-NEXT: End |
| sil @arraysemantics_is_native_no_typecheck : $@convention(thin) (Array<X>) -> () { |
| bb0(%0 : $Array<X>): |
| %f = function_ref @is_native_type_checked : $@convention(method) (@guaranteed Array<X>) -> Bool |
| %a = apply %f(%0) : $@convention(method) (@guaranteed Array<X>) -> Bool |
| |
| %r = tuple() |
| return %r : $() |
| } |
| |
| // CHECK-LABEL: CG of arraysemantics_check_subscript |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: |
| // CHECK-NEXT: End |
| sil @arraysemantics_check_subscript : $@convention(thin) (Array<X>) -> () { |
| bb0(%0 : $Array<X>): |
| %il = integer_literal $Builtin.Int32, 0 |
| %i = struct $Int32(%il : $Builtin.Int32) |
| %bl = integer_literal $Builtin.Int1, 0 |
| %b = struct $Bool (%bl : $Builtin.Int1) |
| |
| %f = function_ref @check_subscript : $@convention(method) (Int32, Bool, @guaranteed Array<X>) -> () |
| %a = apply %f(%i, %b, %0) : $@convention(method) (Int32, Bool, @guaranteed Array<X>) -> () |
| |
| %r = tuple() |
| return %r : $() |
| } |
| |
| // CHECK-LABEL: CG of arraysemantics_check_index |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: |
| // CHECK-NEXT: End |
| sil @arraysemantics_check_index : $@convention(thin) (Array<X>) -> () { |
| bb0(%0 : $Array<X>): |
| %il = integer_literal $Builtin.Int32, 0 |
| %i = struct $Int32(%il : $Builtin.Int32) |
| |
| %f = function_ref @check_index : $@convention(method) (Int32, @guaranteed Array<X>) -> () |
| %a = apply %f(%i, %0) : $@convention(method) (Int32, @guaranteed Array<X>) -> () |
| |
| %r = tuple() |
| return %r : $() |
| } |
| |
| // CHECK-LABEL: CG of arraysemantics_get_element |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: (%0.1) |
| // CHECK-NEXT: Con %0.1 Esc: A, Succ: %1.2 |
| // CHECK-NEXT: Arg %1 Esc: A, Succ: (%1.1) |
| // CHECK-NEXT: Con %1.1 Esc: A, Succ: (%1.2) |
| // CHECK-NEXT: Con %1.2 Esc: A, Succ: |
| // CHECK-NEXT: End |
| sil @arraysemantics_get_element : $@convention(thin) (@out X, Array<X>) -> () { |
| bb0(%io : $*X, %1 : $Array<X>): |
| %il = integer_literal $Builtin.Int32, 0 |
| %i = struct $Int32(%il : $Builtin.Int32) |
| %bl = integer_literal $Builtin.Int1, 0 |
| %b = struct $Bool (%bl : $Builtin.Int1) |
| |
| %f = function_ref @get_element : $@convention(method) (@out X, Int32, Bool, @guaranteed Array<X>) -> () |
| %a = apply %f(%io, %i, %b, %1) : $@convention(method) (@out X, Int32, Bool, @guaranteed Array<X>) -> () |
| |
| %r = tuple() |
| return %r : $() |
| } |
| |
| // CHECK-LABEL: CG of arraysemantics_make_mutable |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: |
| // CHECK-NEXT: End |
| sil @arraysemantics_make_mutable : $@convention(thin) (@inout Array<X>) -> () { |
| bb0(%0 : $*Array<X>): |
| %f = function_ref @make_mutable : $@convention(method) (@inout Array<X>) -> () |
| %a = apply %f(%0) : $@convention(method) (@inout Array<X>) -> () |
| |
| %r = tuple() |
| return %r : $() |
| } |
| |
| // CHECK-LABEL: CG of arraysemantics_get_element_address |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: (%0.1) |
| // CHECK-NEXT: Con %0.1 Esc: A, Succ: |
| // CHECK-NEXT: Val %4 Esc: , Succ: %0.1 |
| // CHECK-NEXT: End |
| sil @arraysemantics_get_element_address : $@convention(thin) (Array<X>) -> () { |
| bb0(%0 : $Array<X>): |
| %il = integer_literal $Builtin.Int32, 0 |
| %i = struct $Int32(%il : $Builtin.Int32) |
| |
| %f = function_ref @get_element_address : $@convention(method) (Int32, @guaranteed Array<X>) -> UnsafeMutablePointer<X> |
| %a = apply %f(%i, %0) : $@convention(method) (Int32, @guaranteed Array<X>) -> UnsafeMutablePointer<X> |
| |
| %r = tuple() |
| return %r : $() |
| } |
| |
| // CHECK-LABEL: CG of arraysemantics_get_count |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: |
| // CHECK-NEXT: End |
| sil @arraysemantics_get_count : $@convention(thin) (Array<X>) -> () { |
| bb0(%0 : $Array<X>): |
| |
| %f = function_ref @get_count : $@convention(method) (@guaranteed Array<X>) -> Int32 |
| %a = apply %f(%0) : $@convention(method) (@guaranteed Array<X>) -> Int32 |
| |
| %r = tuple() |
| return %r : $() |
| } |
| |
| // CHECK-LABEL: CG of arraysemantics_get_capacity |
| // CHECK-NEXT: Arg %0 Esc: A, Succ: |
| // CHECK-NEXT: End |
| sil @arraysemantics_get_capacity : $@convention(thin) (Array<X>) -> () { |
| bb0(%0 : $Array<X>): |
| |
| %f = function_ref @get_capacity : $@convention(method) (@guaranteed Array<X>) -> Int32 |
| %a = apply %f(%0) : $@convention(method) (@guaranteed Array<X>) -> Int32 |
| |
| %r = tuple() |
| return %r : $() |
| } |
| |
| sil [_semantics "array.props.isNativeTypeChecked"] @is_native_type_checked : $@convention(method) (@guaranteed Array<X>) -> Bool |
| sil [_semantics "array.check_subscript"] @check_subscript : $@convention(method) (Int32, Bool, @guaranteed Array<X>) -> () |
| sil [_semantics "array.check_index"] @check_index : $@convention(method) (Int32, @guaranteed Array<X>) -> () |
| sil [_semantics "array.get_element"] @get_element : $@convention(method) (@out X, Int32, Bool, @guaranteed Array<X>) -> () |
| sil [_semantics "array.make_mutable"] @make_mutable : $@convention(method) (@inout Array<X>) -> () |
| sil [_semantics "array.get_element_address"] @get_element_address : $@convention(method) (Int32, @guaranteed Array<X>) -> UnsafeMutablePointer<X> |
| sil [_semantics "array.get_count"] @get_count : $@convention(method) (@guaranteed Array<X>) -> Int32 |
| sil [_semantics "array.get_capacity"] @get_capacity : $@convention(method) (@guaranteed Array<X>) -> Int32 |
| |