// RUN: env DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib %target-sil-opt -sil-print-types -enable-objc-interop -module-name mandatory_inlining -enable-sil-verify-all %s -mandatory-inlining | %FileCheck %s // guardmalloc is incompatible with ASAN // REQUIRES: no_asan import Builtin import Swift protocol CP : class { func f() -> Self } protocol P2 { var c: Int32 { get } } extension P2 { func s() -> Int32 } struct L { var start: Int32 { get } @_hasStorage let o: P2 init(o: P2) } sil @plus : $@convention(thin) (Int64, Int64) -> Int64 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 @fromLiteral : $@convention(thin) (Builtin.Int128, @thin Int64.Type) -> Int64 sil @use_nativeobject : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () class Klass {} ////////////////////////////////////// // Multiple Inline in a Block Tests // ////////////////////////////////////// // CHECK-LABEL: sil [transparent] @test_add : $@convention(thin) (Int64) -> Int64 { sil [transparent] @test_add : $@convention(thin) (Int64) -> Int64 { bb0(%0 : $Int64): %1 = alloc_box ${ var Int64 } %1a = project_box %1 : ${ var Int64 }, 0 store %0 to %1a : $*Int64 %3 = function_ref @plus : $@convention(thin) (Int64, Int64) -> Int64 %4 = load %1a : $*Int64 %5 = function_ref @fromLiteral : $@convention(thin) (Builtin.Int128, @thin Int64.Type) -> Int64 %6 = metatype $@thin Int64.Type %7 = integer_literal $Builtin.Int128, 20 %8 = apply %5(%7, %6) : $@convention(thin) (Builtin.Int128, @thin Int64.Type) -> Int64 %9 = apply %3(%4, %8) : $@convention(thin) (Int64, Int64) -> Int64 strong_release %1 : ${ var Int64 } return %9 : $Int64 } // CHECK-LABEL: sil @inline_test_add : $@convention(thin) (Int64) -> Int64 { sil @inline_test_add : $@convention(thin) (Int64) -> Int64 { // CHECK: [[BB0:.*]]([[VAL0:%.*]] : $Int64): // CHECK: [[VAL1:%.*]] = alloc_box ${ var Int64 } // CHECK: [[PB1:%.*]] = project_box [[VAL1]] // CHECK: store [[VAL0]] to [[PB1]] // CHECK: [[VAL3:%.*]] = function_ref @plus // CHECK: [[VAL4:%.*]] = function_ref @plus // CHECK: [[VAL5:%.*]] = load [[PB1]] // CHECK: [[VAL6:%.*]] = function_ref @fromLiteral // CHECK: [[VAL7:%.*]] = metatype $@thin Int64.Type // CHECK: [[VAL8:%.*]] = integer_literal $Builtin.Int128, 10 // CHECK: [[VAL9:%.*]] = apply [[VAL6]]([[VAL8]], [[VAL7]]) // CHECK: [[VAL10:%.*]] = apply [[VAL4]]([[VAL5]], [[VAL9]]) // CHECK: [[VAL11:%.*]] = alloc_box ${ var Int64 } // CHECK: [[PB11:%.*]] = project_box [[VAL11]] // CHECK: store [[VAL10]] to [[PB11]] // CHECK: [[VAL13:%.*]] = function_ref @plus // CHECK: [[VAL14:%.*]] = load [[PB11]] // CHECK: [[VAL15:%.*]] = function_ref @fromLiteral // CHECK: [[VAL16:%.*]] = metatype $@thin Int64.Type // CHECK: [[VAL17:%.*]] = integer_literal $Builtin.Int128, 20 // CHECK: [[VAL18:%.*]] = apply [[VAL15]]([[VAL17]], [[VAL16]]) // CHECK: [[VAL19:%.*]] = apply [[VAL13]]([[VAL14]], [[VAL18]]) // CHECK: strong_release [[VAL11]] // CHECK: [[VAL21:%.*]] = function_ref @fromLiteral // CHECK: [[VAL22:%.*]] = metatype $@thin Int64.Type // CHECK: [[VAL23:%.*]] = integer_literal $Builtin.Int128, 30 // CHECK: [[VAL24:%.*]] = apply [[VAL21]]([[VAL23]], [[VAL22]]) // CHECK: [[VAL25:%.*]] = apply [[VAL3]]([[VAL19]], [[VAL24]]) // CHECK: strong_release [[VAL1]] // CHECK: return [[VAL25]] bb0(%0 : $Int64): %1 = alloc_box ${ var Int64 } %1a = project_box %1 : ${ var Int64 }, 0 store %0 to %1a : $*Int64 %3 = function_ref @plus : $@convention(thin) (Int64, Int64) -> Int64 %4 = function_ref @test_add : $@convention(thin) (Int64) -> Int64 %5 = function_ref @plus : $@convention(thin) (Int64, Int64) -> Int64 %6 = load %1a : $*Int64 %7 = function_ref @fromLiteral : $@convention(thin) (Builtin.Int128, @thin Int64.Type) -> Int64 %8 = metatype $@thin Int64.Type %9 = integer_literal $Builtin.Int128, 10 %10 = apply %7(%9, %8) : $@convention(thin) (Builtin.Int128, @thin Int64.Type) -> Int64 %11 = apply %5(%6, %10) : $@convention(thin) (Int64, Int64) -> Int64 %12 = apply %4(%11) : $@convention(thin) (Int64) -> Int64 %13 = function_ref @fromLiteral : $@convention(thin) (Builtin.Int128, @thin Int64.Type) -> Int64 %14 = metatype $@thin Int64.Type %15 = integer_literal $Builtin.Int128, 30 %16 = apply %13(%15, %14) : $@convention(thin) (Builtin.Int128, @thin Int64.Type) -> Int64 %17 = apply %3(%12, %16) : $@convention(thin) (Int64, Int64) -> Int64 strong_release %1 : ${ var Int64 } return %17 : $Int64 } // CHECK-LABEL: sil @inline_twice_test_add : $@convention(thin) (Int64) -> Int64 { sil @inline_twice_test_add : $@convention(thin) (Int64) -> Int64 { // CHECK: [[BB0:.*]]([[VAL0:%.*]] : $Int64): // CHECK: [[VAL1:%.*]] = alloc_box ${ var Int64 } // CHECK: [[PB1:%.*]] = project_box [[VAL1]] // CHECK: store [[VAL0]] to [[PB1]] // CHECK: [[VAL3:%.*]] = function_ref @plus // CHECK: [[VAL4:%.*]] = function_ref @plus // CHECK: [[VAL5:%.*]] = load [[PB1]] // CHECK: [[VAL6:%.*]] = function_ref @fromLiteral // CHECK: [[VAL7:%.*]] = metatype $@thin Int64.Type // CHECK: [[VAL8:%.*]] = integer_literal $Builtin.Int128, 10 // CHECK: [[VAL9:%.*]] = apply [[VAL6]]([[VAL8]], [[VAL7]]) // CHECK: [[VAL10:%.*]] = apply [[VAL4]]([[VAL5]], [[VAL9]]) // CHECK: [[VAL11:%.*]] = alloc_box ${ var Int64 } // CHECK: [[PB11:%.*]] = project_box [[VAL11]] // CHECK: store [[VAL10]] to [[PB11]] // CHECK: [[VAL13:%.*]] = function_ref @plus // CHECK: [[VAL14:%.*]] = load [[PB11]] // CHECK: [[VAL15:%.*]] = function_ref @fromLiteral // CHECK: [[VAL16:%.*]] = metatype $@thin Int64.Type // CHECK: [[VAL17:%.*]] = integer_literal $Builtin.Int128, 20 // CHECK: [[VAL18:%.*]] = apply [[VAL15]]([[VAL17]], [[VAL16]]) // CHECK: [[VAL19:%.*]] = apply [[VAL13]]([[VAL14]], [[VAL18]]) // CHECK: strong_release [[VAL11]] // CHECK: [[VAL21:%.*]] = alloc_box ${ var Int64 } // CHECK: [[PB21:%.*]] = project_box [[VAL21]] // CHECK: store [[VAL19]] to [[PB21]] // CHECK: [[VAL23:%.*]] = function_ref @plus // CHECK: [[VAL24:%.*]] = load [[PB21]] // CHECK: [[VAL25:%.*]] = function_ref @fromLiteral // CHECK: [[VAL26:%.*]] = metatype $@thin Int64.Type // CHECK: [[VAL27:%.*]] = integer_literal $Builtin.Int128, 20 // CHECK: [[VAL28:%.*]] = apply [[VAL25]]([[VAL27]], [[VAL26]]) // CHECK: [[VAL29:%.*]] = apply [[VAL23]]([[VAL24]], [[VAL28]]) // CHECK: strong_release [[VAL21]] // CHECK: [[VAL31:%.*]] = function_ref @fromLiteral // CHECK: [[VAL32:%.*]] = metatype $@thin Int64.Type // CHECK: [[VAL33:%.*]] = integer_literal $Builtin.Int128, 30 // CHECK: [[VAL34:%.*]] = apply [[VAL31]]([[VAL33]], [[VAL32]]) // CHECK: [[VAL35:%.*]] = apply [[VAL3]]([[VAL29]], [[VAL34]]) // CHECK: strong_release [[VAL1]] // CHECK: return [[VAL35]] bb0(%0 : $Int64): %1 = alloc_box ${ var Int64 } %1a = project_box %1 : ${ var Int64 }, 0 store %0 to %1a : $*Int64 %3 = function_ref @plus : $@convention(thin) (Int64, Int64) -> Int64 %4 = function_ref @test_add : $@convention(thin) (Int64) -> Int64 %5 = function_ref @test_add : $@convention(thin) (Int64) -> Int64 %6 = function_ref @plus : $@convention(thin) (Int64, Int64) -> Int64 %7 = load %1a : $*Int64 %8 = function_ref @fromLiteral : $@convention(thin) (Builtin.Int128, @thin Int64.Type) -> Int64 %9 = metatype $@thin Int64.Type %10 = integer_literal $Builtin.Int128, 10 %11 = apply %8(%10, %9) : $@convention(thin) (Builtin.Int128, @thin Int64.Type) -> Int64 %12 = apply %6(%7, %11) : $@convention(thin) (Int64, Int64) -> Int64 %13 = apply %5(%12) : $@convention(thin) (Int64) -> Int64 %14 = apply %4(%13) : $@convention(thin) (Int64) -> Int64 %15 = function_ref @fromLiteral : $@convention(thin) (Builtin.Int128, @thin Int64.Type) -> Int64 %16 = metatype $@thin Int64.Type %17 = integer_literal $Builtin.Int128, 30 %18 = apply %15(%17, %16) : $@convention(thin) (Builtin.Int128, @thin Int64.Type) -> Int64 %19 = apply %3(%14, %18) : $@convention(thin) (Int64, Int64) -> Int64 strong_release %1 : ${ var Int64 } return %19 : $Int64 } /////////////////////// // Existential Tests // /////////////////////// protocol SomeProtocol { } // CHECK-LABEL: sil [transparent] @test_existential_metatype : $@convention(thin) (@in any SomeProtocol) -> @thick any SomeProtocol.Type sil [transparent] @test_existential_metatype : $@convention(thin) (@in SomeProtocol) -> @thick SomeProtocol.Type { bb0(%0 : $*SomeProtocol): %1 = alloc_box ${ var SomeProtocol } %1a = project_box %1 : ${ var SomeProtocol }, 0 copy_addr [take] %0 to [init] %1a : $*SomeProtocol %4 = alloc_stack $SomeProtocol copy_addr %1a to [init] %4 : $*SomeProtocol %6 = existential_metatype $@thick SomeProtocol.Type, %4 : $*SomeProtocol destroy_addr %4 : $*SomeProtocol dealloc_stack %4 : $*SomeProtocol strong_release %1 : ${ var SomeProtocol } return %6 : $@thick SomeProtocol.Type } // CHECK-LABEL: sil @inline_test_existential_metatype : $@convention(thin) (@in any SomeProtocol) -> @thick any SomeProtocol.Type sil @inline_test_existential_metatype : $@convention(thin) (@in SomeProtocol) -> @thick SomeProtocol.Type { // CHECK: [[BB0:.*]]([[VAL0:%.*]] : $*any SomeProtocol): // CHECK: [[VAL1:%.*]] = alloc_box ${ var any SomeProtocol } // CHECK: [[PB1:%.*]] = project_box [[VAL1]] // CHECK: copy_addr [take] %0 to [init] [[PB1]] // CHECK: [[VAL4:%.*]] = alloc_stack $any SomeProtocol // CHECK: copy_addr [[PB1]] to [init] [[VAL4]] // CHECK: [[VAL6:%.*]] = existential_metatype $@thick any SomeProtocol.Type, [[VAL4]] // CHECK: destroy_addr [[VAL4]] // CHECK: dealloc_stack [[VAL4]] // CHECK: strong_release [[VAL1]] // CHECK: return [[VAL6]] bb0(%0 : $*SomeProtocol): %1 = function_ref @test_existential_metatype : $@convention(thin) (@in SomeProtocol) -> @thick SomeProtocol.Type %2 = apply %1(%0) : $@convention(thin) (@in SomeProtocol) -> @thick SomeProtocol.Type return %2 : $@thick SomeProtocol.Type } //////////////////////// // Control Flow Tests // //////////////////////// sil @get_logic_value : $@convention(method) (@inout Bool) -> Builtin.Int1 sil @add_floats : $@convention(thin) (Float32, Float32) -> Float32 sil @convertFromBuiltinFloatLiteral : $@convention(thin) (Builtin.FPIEEE64, @thin Float32.Type) -> Float32 sil @sub_floats : $@convention(thin) (Float32, Float32) -> Float32 sil @foo : $@convention(thin) (Float32, Float32) -> Bool sil @bar : $@convention(thin) (Float32) -> Bool // CHECK-LABEL: sil [transparent] @test_control_flow : $@convention(thin) (Float, Float) -> Float sil [transparent] @test_control_flow : $@convention(thin) (Float, Float) -> Float { bb0(%0 : $Float, %1 : $Float): %2 = alloc_box ${ var Float } %2a = project_box %2 : ${ var Float }, 0 %3 = alloc_box ${ var Float } %3a = project_box %3 : ${ var Float }, 0 store %0 to %2a : $*Float store %1 to %3a : $*Float %6 = function_ref @get_logic_value : $@convention(method) (@inout Bool) -> Builtin.Int1 %7 = function_ref @foo : $@convention(thin) (Float, Float) -> Bool %8 = load %2a : $*Float %9 = load %3a : $*Float %10 = apply %7(%8, %9) : $@convention(thin) (Float, Float) -> Bool %11 = alloc_stack $Bool store %10 to %11 : $*Bool %13 = apply %6(%11) : $@convention(method) (@inout Bool) -> Builtin.Int1 dealloc_stack %11 : $*Bool cond_br %13, bb1, bb2 bb1: %16 = load %2a : $*Float unreachable bb2: br bb3 bb3: %19 = function_ref @get_logic_value : $@convention(method) (@inout Bool) -> Builtin.Int1 %20 = function_ref @bar : $@convention(thin) (Float) -> Bool %21 = load %3a : $*Float %22 = apply %20(%21) : $@convention(thin) (Float) -> Bool %23 = alloc_stack $Bool store %22 to %23 : $*Bool %25 = apply %19(%23) : $@convention(method) (@inout Bool) -> Builtin.Int1 dealloc_stack %23 : $*Bool cond_br %25, bb4, bb5 bb4: %28 = function_ref @add_floats : $@convention(thin) (Float, Float) -> Float %29 = load %3a : $*Float %30 = function_ref @convertFromBuiltinFloatLiteral : $@convention(thin) (Builtin.FPIEEE64, @thin Float.Type) -> Float %31 = metatype $@thin Float.Type %32 = float_literal $Builtin.FPIEEE64, 0x3FF0000000000000 %33 = apply %30(%32, %31) : $@convention(thin) (Builtin.FPIEEE64, @thin Float.Type) -> Float %34 = apply %28(%29, %33) : $@convention(thin) (Float, Float) -> Float store %34 to %3a : $*Float br bb3 bb5: %37 = load %3a : $*Float br bb6(%37 : $Float) bb6(%39 : $Float): strong_release %3 : ${ var Float } strong_release %2 : ${ var Float } return %39 : $Float } // CHECK-LABEL: sil @inline_test_control_flow : $@convention(thin) (Float) -> Float sil @inline_test_control_flow : $@convention(thin) (Float) -> Float { // CHECK: [[BB0:.*]]([[VAL0:%.*]] : $Float): // CHECK: [[VAL1:%.*]] = alloc_box ${ var Float } // CHECK: [[PB1:%.*]] = project_box [[VAL1]] // CHECK: store [[VAL0]] to [[PB1]] // CHECK: [[VAL3:%.*]] = function_ref @sub_floats // CHECK: [[VAL4:%.*]] = function_ref @add_floats // CHECK: [[VAL5:%.*]] = load [[PB1]] // CHECK: [[VAL6:%.*]] = function_ref @convertFromBuiltinFloatLiteral // CHECK: [[VAL7:%.*]] = metatype $@thin Float.Type // CHECK: [[VAL8:%.*]] = float_literal $Builtin.FPIEEE64, 0x3FF0000000000000 // CHECK: [[VAL9:%.*]] = apply [[VAL6]]([[VAL8]], [[VAL7]]) // CHECK: [[VAL10:%.*]] = apply [[VAL4]]([[VAL5]], [[VAL9]]) // CHECK: [[VAL11:%.*]] = function_ref @convertFromBuiltinFloatLiteral // CHECK: [[VAL12:%.*]] = metatype $@thin Float.Type // CHECK: [[VAL13:%.*]] = float_literal $Builtin.FPIEEE64, 0x4000000000000000 // CHECK: [[VAL14:%.*]] = apply [[VAL11]]([[VAL13]], [[VAL12]]) // CHECK: [[VAL15:%.*]] = alloc_box ${ var Float } // CHECK: [[PB15:%.*]] = project_box [[VAL15]] // CHECK: [[VAL16:%.*]] = alloc_box ${ var Float } // CHECK: [[PB16:%.*]] = project_box [[VAL16]] // CHECK: store [[VAL10]] to [[PB15]] // CHECK: store [[VAL14]] to [[PB16]] // CHECK: [[VAL19:%.*]] = function_ref @get_logic_value // CHECK: [[VAL20:%.*]] = function_ref @foo // CHECK: [[VAL21:%.*]] = load [[PB15]] // CHECK: [[VAL22:%.*]] = load [[PB16]] // CHECK: [[VAL23:%.*]] = apply [[VAL20]]([[VAL21]], [[VAL22]]) // CHECK: [[VAL24:%.*]] = alloc_stack $Bool // CHECK: store [[VAL23]] to [[VAL24]] // CHECK: [[VAL26:%.*]] = apply [[VAL19]]([[VAL24]]) // CHECK: dealloc_stack [[VAL24]] // CHECK: cond_br [[VAL26]], [[BB1:bb[0-9]+]], [[BB2:bb[0-9]+]] // CHECK: [[BB1]]: // CHECK: [[VAL29:%.*]] = load [[PB15]] // CHECK: unreachable // CHECK: [[BB2]]: // CHECK: br [[BB3:bb[0-9]+]] // CHECK: [[BB3]]: // CHECK: [[VAL32:%.*]] = function_ref @get_logic_value // CHECK: [[VAL33:%.*]] = function_ref @bar // CHECK: [[VAL34:%.*]] = load [[PB16]] // CHECK: [[VAL35:%.*]] = apply [[VAL33]]([[VAL34]]) // CHECK: [[VAL36:%.*]] = alloc_stack $Bool // CHECK: store [[VAL35]] to [[VAL36]] // CHECK: [[VAL38:%.*]] = apply [[VAL32]]([[VAL36]]) // CHECK: dealloc_stack [[VAL36]] // CHECK: cond_br [[VAL38]], [[BB4:bb[0-9]+]], [[BB5:bb[0-9]+]] // CHECK: [[BB4]]: // CHECK: [[VAL41:%.*]] = function_ref @add_floats // CHECK: [[VAL42:%.*]] = load [[PB16]] // CHECK: [[VAL43:%.*]] = function_ref @convertFromBuiltinFloatLiteral // CHECK: [[VAL44:%.*]] = metatype $@thin Float.Type // CHECK: [[VAL45:%.*]] = float_literal $Builtin.FPIEEE64, 0x3FF0000000000000 // CHECK: [[VAL46:%.*]] = apply [[VAL43]]([[VAL45]], [[VAL44]]) // CHECK: [[VAL47:%.*]] = apply [[VAL41]]([[VAL42]], [[VAL46]]) // CHECK: store [[VAL47]] to [[PB16]] // CHECK: br [[BB3]] // CHECK: [[BB5]]: // CHECK: [[VAL50:%.*]] = load [[PB16]] // CHECK: strong_release [[VAL16]] // CHECK: strong_release [[VAL15]] // CHECK: [[VAL57:%.*]] = function_ref @convertFromBuiltinFloatLiteral // CHECK: [[VAL58:%.*]] = metatype $@thin Float.Type // CHECK: [[VAL59:%.*]] = float_literal $Builtin.FPIEEE64, 0x4008000000000000 // CHECK: [[VAL60:%.*]] = apply [[VAL57]]([[VAL59]], [[VAL58]]) // CHECK: [[VAL61:%.*]] = apply [[VAL3]]([[VAL50]], [[VAL60]]) // CHECK: strong_release [[VAL1]] // CHECK: return [[VAL61]] bb0(%0 : $Float): %1 = alloc_box ${ var Float } %1a = project_box %1 : ${ var Float }, 0 store %0 to %1a : $*Float %3 = function_ref @sub_floats : $@convention(thin) (Float, Float) -> Float %4 = function_ref @test_control_flow : $@convention(thin) (Float, Float) -> Float %5 = function_ref @add_floats : $@convention(thin) (Float, Float) -> Float %6 = load %1a : $*Float %7 = function_ref @convertFromBuiltinFloatLiteral : $@convention(thin) (Builtin.FPIEEE64, @thin Float.Type) -> Float %8 = metatype $@thin Float.Type %9 = float_literal $Builtin.FPIEEE64, 0x3FF0000000000000 %10 = apply %7(%9, %8) : $@convention(thin) (Builtin.FPIEEE64, @thin Float.Type) -> Float %11 = apply %5(%6, %10) : $@convention(thin) (Float, Float) -> Float %12 = function_ref @convertFromBuiltinFloatLiteral : $@convention(thin) (Builtin.FPIEEE64, @thin Float.Type) -> Float %13 = metatype $@thin Float.Type %14 = float_literal $Builtin.FPIEEE64, 0x4000000000000000 %15 = apply %12(%14, %13) : $@convention(thin) (Builtin.FPIEEE64, @thin Float.Type) -> Float %16 = apply %4(%11, %15) : $@convention(thin) (Float, Float) -> Float %17 = function_ref @convertFromBuiltinFloatLiteral : $@convention(thin) (Builtin.FPIEEE64, @thin Float.Type) -> Float %18 = metatype $@thin Float.Type %19 = float_literal $Builtin.FPIEEE64, 0x4008000000000000 %20 = apply %17(%19, %18) : $@convention(thin) (Builtin.FPIEEE64, @thin Float.Type) -> Float %21 = apply %3(%16, %20) : $@convention(thin) (Float, Float) -> Float strong_release %1 : ${ var Float } return %21 : $Float } /////////////////////////////////////// // Recursion and Partial Apply Tests // /////////////////////////////////////// // CHECK-LABEL: [transparent] @test_recursive_foo : $@convention(thin) (Float) -> Float sil [transparent] @test_recursive_foo : $@convention(thin) (Float) -> Float { // CHECK-NOT: function_ref // CHECK-NOT: apply // CHECK: return bb0(%0 : $Float): %3 = function_ref @test_recursive_bar : $@convention(thin) (Float) -> Float %5 = apply %3(%0) : $@convention(thin) (Float) -> Float return %5 : $Float } // CHECK-LABEL: sil [transparent] @test_recursive_bar : $@convention(thin) (Float) -> Float sil [transparent] @test_recursive_bar : $@convention(thin) (Float) -> Float { // CHECK-NOT: function_ref // CHECK-NOT: apply // CHECK: return bb0(%0 : $Float): %3 = function_ref @test_recursive_baz : $@convention(thin) (Float) -> Float %5 = apply %3(%0) : $@convention(thin) (Float) -> Float return %5 : $Float } // CHECK-LABEL: sil [transparent] @test_recursive_baz : $@convention(thin) (Float) -> Float sil [transparent] @test_recursive_baz : $@convention(thin) (Float) -> Float { // CHECK-NOT: function_ref // CHECK-NOT: apply // CHECK: return bb0(%0 : $Float): return %0 : $Float } // CHECK-LABEL: sil [transparent] @test_partial_foo : $@convention(thin) (Int64) -> Int64 { sil [transparent] @test_partial_foo : $@convention(thin) (Int64) -> Int64 { // CHECK: [[BB0:.*]]([[VAL0:%.*]] : $Int64): // CHECK: [[VAL1:%.*]] = function_ref @plus // CHECK: [[VAL2:%.*]] = apply [[VAL1]]([[VAL0]], [[VAL0]]) // CHECK: return [[VAL2]] bb0(%0 : $Int64): %2 = function_ref @test_partial_bar : $@convention(thin) (@callee_owned (Int64) -> Int64, Int64) -> Int64 %3 = function_ref @test_partial_baz : $@convention(thin) (Int64, Int64) -> Int64 %5 = partial_apply %3(%0) : $@convention(thin) (Int64, Int64) -> Int64 %13 = apply %2(%5, %0) : $@convention(thin) (@callee_owned (Int64) -> Int64, Int64) -> Int64 return %13 : $Int64 } sil [transparent] @test_partial_baz : $@convention(thin) (Int64, Int64) -> Int64 { bb0(%0 : $Int64, %1 : $Int64): %6 = function_ref @plus : $@convention(thin) (Int64, Int64) -> Int64 %7 = apply %6(%0, %1) : $@convention(thin) (Int64, Int64) -> Int64 return %7 : $Int64 } sil [transparent] @test_partial_bar : $@convention(thin) (@callee_owned (Int64) -> Int64, Int64) -> Int64 { bb0(%0 : $@callee_owned (Int64) -> Int64, %1 : $Int64): %7 = apply %0(%1) : $@callee_owned (Int64) -> Int64 return %7 : $Int64 } // CHECK-LABEL: [transparent] @test_recursive_nativeobject_foo : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject sil [transparent] @test_recursive_nativeobject_foo : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject { // CHECK-NOT: function_ref // CHECK-NOT: apply // CHECK: return bb0(%0 : $Builtin.NativeObject): %3 = function_ref @test_recursive_nativeobject_bar : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject %5 = apply %3(%0) : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject return %5 : $Builtin.NativeObject } // CHECK-LABEL: sil [transparent] @test_recursive_nativeobject_bar : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject sil [transparent] @test_recursive_nativeobject_bar : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject { // CHECK-NOT: function_ref // CHECK-NOT: apply // CHECK: return bb0(%0 : $Builtin.NativeObject): %3 = function_ref @test_recursive_nativeobject_baz : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject %5 = apply %3(%0) : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject return %5 : $Builtin.NativeObject } // CHECK-LABEL: sil [transparent] @test_recursive_nativeobject_baz : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject { // CHECK: bb0 // CHECK-NEXT: return // CHECK: } // end sil function 'test_recursive_nativeobject_baz' sil [transparent] @test_recursive_nativeobject_baz : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject { bb0(%0 : $Builtin.NativeObject): return %0 : $Builtin.NativeObject } sil [transparent] @test_partial_nativeobject_baz : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject { bb0(%0 : $Builtin.NativeObject, %1 : $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 [transparent] @test_partial_nativeobject_bar : $@convention(thin) (@owned @callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject { bb0(%0 : $@callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject, %1 : $Builtin.NativeObject): %7 = apply %0(%1) : $@callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject return %7 : $Builtin.NativeObject } // CHECK-LABEL: sil [transparent] @test_partial_nativeobject_foo : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject { // CHECK: bb0([[ARG:%.*]] : $Builtin.NativeObject): // CHECK: [[FN:%.*]] = function_ref @test_partial_nativeobject_baz : // CHECK: strong_retain [[ARG]] // CHECK: strong_retain [[ARG]] // CHECK: [[PAI:%.*]] = partial_apply [[FN]]([[ARG]]) // CHECK: strong_retain [[ARG]] // CHECK: [[FN2:%.*]] = function_ref @nativeobject_plus : // CHECK: [[RESULT:%.*]] = apply [[FN2]]([[ARG]], [[ARG]]) // CHECK: strong_retain [[PAI]] // CHECK: [[OPAQUE_FN:%.*]] = function_ref @partial_apply_user // CHECK: apply [[OPAQUE_FN]]([[PAI]]) // CHECK: strong_release [[PAI]] // CHECK: strong_release [[ARG]] // CHECK: return [[RESULT]] // CHECK: } // end sil function 'test_partial_nativeobject_foo' sil [transparent] @test_partial_nativeobject_foo : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject { bb0(%0 : $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: strong_retain %0 : $Builtin.NativeObject %5 = partial_apply %3(%0) : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject br bb2 bb2: strong_retain %0 : $Builtin.NativeObject strong_retain %5 : $@callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject %13 = apply %2(%5, %0) : $@convention(thin) (@owned @callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject br bb3 bb3: strong_retain %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(%5) : $@convention(thin) (@owned @callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject) -> () strong_release %5 : $@callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject strong_release %0 : $Builtin.NativeObject return %13 : $Builtin.NativeObject } /////////////////////// // Autoclosure Tests // /////////////////////// sil @true_getter : $@convention(thin) () -> Bool sil [transparent] @short_circuit_or : $@convention(thin) (Bool, @callee_owned () -> Bool) -> Bool { bb0(%0 : $Bool, %1 : $@callee_owned () -> Bool): %2 = alloc_box ${ var Bool } %2a = project_box %2 : ${ var Bool }, 0 %3 = alloc_box ${ var @callee_owned () -> Bool } %3a = project_box %3 : ${ var @callee_owned () -> Bool }, 0 store %0 to %2a : $*Bool store %1 to %3a : $*@callee_owned () -> Bool %6 = function_ref @get_logic_value : $@convention(method) (@inout Bool) -> Builtin.Int1 %7 = apply %6(%2a) : $@convention(method) (@inout Bool) -> Builtin.Int1 cond_br %7, bb1, bb2 bb1: %9 = function_ref @true_getter : $@convention(thin) () -> Bool %10 = apply %9() : $@convention(thin) () -> Bool br bb3(%10 : $Bool) bb2: %m2 = integer_literal $Builtin.Int32, 2 // Marker %12 = load %3a : $*@callee_owned () -> Bool strong_retain %12 : $@callee_owned () -> Bool %m3 = integer_literal $Builtin.Int32, 3 // Marker %14 = apply %12() : $@callee_owned () -> Bool br bb3(%14 : $Bool) bb3(%16 : $Bool): strong_release %3 : ${ var @callee_owned () -> Bool } strong_release %2 : ${ var Bool } return %16 : $Bool } sil private [transparent] @closure0 : $@convention(thin) (@owned { var Bool }) -> Bool { bb0(%0 : ${ var Bool }): %1 = project_box %0 : ${ var Bool }, 0 %2 = tuple () %3 = load %1 : $*Bool strong_release %0 : ${ var Bool } return %3 : $Bool } sil @test_short_circuit : $@convention(thin) (Bool, Bool) -> Bool { // CHECK-LABEL: sil @test_short_circuit : $@convention(thin) (Bool, Bool) -> Bool { // CHECK: cond_br {{%.*}}, [[BB1:bb[0-9]+]], [[BB2:bb[0-9]+]] // CHECK: bb1: // CHECK: br [[BB3:.*]]( // CHECK: bb2: // CHECK: [[OLD_CALLEE:%.*]] = load {{%[0-9]+}} : // CHECK: strong_retain [[OLD_CALLEE]] // Separation marker // CHECK: integer_literal $Builtin.Int32, 3 // CHECK: [[ADDR4:%.*]] = project_box [[VAL4:%.*]] : // CHECK: {{%.*}} = tuple () // CHECK: {{%.*}} = load [[ADDR4]] // CHECK: strong_release [[VAL4]] // CHECK: strong_release [[OLD_CALLEE]] // CHECK: br [[BB3]]( // CHECK: [[BB3]]( // CHECK: strong_release [[VAL4]] // CHECK: return {{.*}} bb0(%0 : $Bool, %1 : $Bool): %2 = alloc_box ${ var Bool } %2a = project_box %2 : ${ var Bool }, 0 %3 = alloc_box ${ var Bool } %3a = project_box %3 : ${ var Bool }, 0 store %0 to %2a : $*Bool store %1 to %3a : $*Bool %6 = function_ref @short_circuit_or : $@convention(thin) (Bool, @callee_owned () -> Bool) -> Bool %7 = load %2a : $*Bool %8 = function_ref @closure0 : $@convention(thin) (@owned { var Bool }) -> Bool strong_retain %3 : ${ var Bool } %10 = partial_apply %8(%3) : $@convention(thin) (@owned { var Bool }) -> Bool %12 = integer_literal $Builtin.Int32, 1 // Marker %11 = apply %6(%7, %10) : $@convention(thin) (Bool, @callee_owned () -> Bool) -> Bool strong_release %3 : ${ var Bool } strong_release %2 : ${ var Bool } return %11 : $Bool } sil @test_short_circuit2 : $@convention(thin) (Bool, Bool) -> Bool { // CHECK-LABEL: sil @test_short_circuit2 : $@convention(thin) (Bool, Bool) -> Bool { // CHECK: cond_br {{%.*}}, [[BB1:bb[0-9]+]], [[BB2:bb[0-9]+]] // CHECK: bb1: // CHECK: br [[BB3:.*]]( // CHECK: [[BB2]]: // Marker - // CHECK: integer_literal $Builtin.Int32, 2 // CHECK: [[OLD_CALLEE:%.*]] = load {{%.*}} // CHECK: strong_retain [[OLD_CALLEE]] // Marker - // CHECK: integer_literal $Builtin.Int32, 3 // CHECK: [[ADDR4:%.*]] = project_box [[VAL4:%[0-9]+]] // CHECK: {{%.*}} = tuple () // CHECK: {{%.*}} = load [[ADDR4]] // CHECK: strong_release [[VAL4]] // CHECK: strong_release [[OLD_CALLEE]] // CHECK: br [[BB3]]( // CHECK: [[BB3]]( // CHECK: strong_release [[VAL3]] // CHECK: return {{.*}} bb0(%0 : $Bool, %1 : $Bool): %2 = alloc_box ${ var Bool } %2a = project_box %2 : ${ var Bool }, 0 %3 = alloc_box ${ var Bool } %3a = project_box %3 : ${ var Bool }, 0 store %0 to %2a : $*Bool store %1 to %3a : $*Bool %6 = function_ref @short_circuit_or : $@convention(thin) (Bool, @callee_owned () -> Bool) -> Bool %7 = load %2a : $*Bool %8 = function_ref @closure0 : $@convention(thin) (@owned { var Bool }) -> Bool strong_retain %3 : ${ var Bool } %10 = partial_apply %8(%3) : $@convention(thin) (@owned { var Bool }) -> Bool strong_retain %10 : $@callee_owned () -> Bool %12 = tuple () %11 = apply %6(%7, %10) : $@convention(thin) (Bool, @callee_owned () -> Bool) -> Bool strong_release %3 : ${ var Bool } strong_release %2 : ${ var Bool } return %11 : $Bool } sil [transparent] @convertFromBuiltinIntegerLiteral : $@convention(thin) (Builtin.IntLiteral, @thin Int64.Type) -> Int64 { bb0(%0 : $Builtin.IntLiteral, %1 : $@thin Int64.Type): %3 = builtin "s_to_s_checked_trunc_IntLiteral_Int64"(%0 : $Builtin.IntLiteral) : $(Builtin.Int64, Builtin.Int1) %4 = tuple_extract %3 : $(Builtin.Int64, Builtin.Int1), 0 %5 = struct $Int64 (%4 : $Builtin.Int64) return %5 : $Int64 } sil @test_with_dead_argument : $@convention(thin) () -> () { bb0: %0 = tuple () %1 = alloc_box ${ var Int64 } %1a = project_box %1 : ${ var Int64 }, 0 %2 = function_ref @convertFromBuiltinIntegerLiteral : $@convention(thin) (Builtin.IntLiteral, @thin Int64.Type) -> Int64 %3 = metatype $@thin Int64.Type %4 = integer_literal $Builtin.IntLiteral, 1 %5 = apply %2(%4, %3) : $@convention(thin) (Builtin.IntLiteral, @thin Int64.Type) -> Int64 store %5 to %1a : $*Int64 strong_release %1 : ${ var Int64 } %8 = tuple () return %8 : $() } // CHECK-LABEL: sil @test_with_dead_argument : $@convention(thin) () -> () { // CHECK-NOT: Type sil [transparent] @_TF2t222inner_open_existentialFT2cpPS_2CP__T_ : $@convention(thin) (@owned CP) -> () { bb0(%0 : $CP): strong_retain %0 : $CP // id: %2 %3 = open_existential_ref %0 : $CP to $@opened("01234567-89ab-cdef-0123-000000000000", CP) Self // user: %5 %9 = tuple () // user: %10 return %9 : $() // id: %10 } // CHECK-LABEL: sil @_TF2t222outer_open_existentialFT3cp1PS_2CP_3cp2PS0___T_ sil @_TF2t222outer_open_existentialFT3cp1PS_2CP_3cp2PS0___T_ : $@convention(thin) (@owned CP, @owned CP) -> () { bb0(%0 : $CP, %1 : $CP): %4 = function_ref @_TF2t222inner_open_existentialFT2cpPS_2CP__T_ : $@convention(thin) (@owned CP) -> () // user: %6 strong_retain %0 : $CP // id: %5 // CHECK: open_existential_ref %0 : $any CP to $@opened([[N1:".*"]], any CP) Self %6 = apply %4(%0) : $@convention(thin) (@owned CP) -> () %7 = function_ref @_TF2t222inner_open_existentialFT2cpPS_2CP__T_ : $@convention(thin) (@owned CP) -> () // user: %9 strong_retain %1 : $CP // id: %8 // CHECK: open_existential_ref %1 : $any CP to $@opened([[N2:".*"]], any CP) Self %9 = apply %7(%1) : $@convention(thin) (@owned CP) -> () strong_release %1 : $CP // id: %10 strong_release %0 : $CP // id: %11 %12 = tuple () // user: %13 return %12 : $() // id: %13 } class C : CP { func f() -> Self } sil [transparent] @transparent_generic : $@convention(thin) (@owned T, @owned C) -> () { bb0(%0 : $T, %1 : $C): debug_value %0 : $T debug_value %1 : $C strong_release %1 : $C strong_release %0 : $T %6 = tuple () return %6 : $() } // CHECK-LABEL: sil @fully_concrete_call : $@convention(thin) (@owned C) -> () { sil @fully_concrete_call : $@convention(thin) (@owned C) -> () { bb0(%0 : $C): debug_value %0 : $C // CHECK-NOT: function_ref @transparent_generic %2 = function_ref @transparent_generic : $@convention(thin) <τ_0_0 where τ_0_0 : CP> (@owned τ_0_0, @owned C) -> () strong_retain %0 : $C strong_retain %0 : $C // CHECK-NOT: apply %5 = apply %2(%0, %0) : $@convention(thin) <τ_0_0 where τ_0_0 : CP> (@owned τ_0_0, @owned C) -> () strong_release %0 : $C %7 = tuple () return %7 : $() } // CHECK-LABEL: sil [transparent] @inner : $@convention(thin) (@in T1, @in T2) -> @out T2 { sil [transparent] @inner : $@convention(thin) (@in T1, @in T2) -> @out T2 { bb0(%0 : $*T2, %1 : $*T1, %2 : $*T2): debug_value %1 : $*T1, expr op_deref debug_value %2 : $*T2, expr op_deref copy_addr [take] %2 to [init] %0 : $*T2 destroy_addr %1 : $*T1 %7 = tuple () return %7 : $() } // FIXME: We currently do not inline generics unless we have concrete types // for all substitutions. // CHECK-LABEL: sil [transparent] @middle : $@convention(thin) (Int, @in T) -> @out T { sil [transparent] @middle : $@convention(thin) (Int, @in T) -> @out T { bb0(%0 : $*T, %1 : $Int, %2 : $*T): debug_value %1 : $Int debug_value %2 : $*T, expr op_deref // CHECK-NOT: [[REF:%[a-zA-Z0-9]+]] = function_ref @inner %5 = function_ref @inner : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @in τ_0_1) -> @out τ_0_1 %6 = alloc_stack $Int store %1 to %6 : $*Int %8 = alloc_stack $T copy_addr %2 to [init] %8 : $*T // CHECK-NOT: apply %10 = apply %5(%0, %6, %8) : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @in τ_0_1) -> @out τ_0_1 dealloc_stack %8 : $*T dealloc_stack %6 : $*Int destroy_addr %2 : $*T %14 = tuple () return %14 : $() } // CHECK-LABEL: sil [transparent] @outer : $@convention(thin) (Int) -> Int { sil [transparent] @outer : $@convention(thin) (Int) -> Int { bb0(%0 : $Int): debug_value %0 : $Int // CHECK-NOT: function_ref @middle %2 = function_ref @middle : $@convention(thin) <τ_0_0> (Int, @in τ_0_0) -> @out τ_0_0 %7 = alloc_stack $Int store %0 to %7 : $*Int %9 = alloc_stack $Int // CHECK-NOT: apply %10 = apply %2(%9, %0, %7) : $@convention(thin) <τ_0_0> (Int, @in τ_0_0) -> @out τ_0_0 %11 = load %9 : $*Int dealloc_stack %9 : $*Int dealloc_stack %7 : $*Int return %11 : $Int } @objc protocol Foo { func foo() } // CHECK-LABEL: sil hidden [transparent] @protocolConstrained sil hidden [transparent] @protocolConstrained : $@convention(thin) (@owned T) -> () { bb0(%0 : $T): debug_value %0 : $T strong_retain %0 : $T %3 = objc_method %0 : $T, #Foo.foo!foreign, $@convention(objc_method) <τ_0_0 where τ_0_0 : Foo> (τ_0_0) -> () %4 = apply %3(%0) : $@convention(objc_method) <τ_0_0 where τ_0_0 : Foo> (τ_0_0) -> () strong_release %0 : $T strong_release %0 : $T %7 = tuple () return %7 : $() } // CHECK-LABEL: sil hidden @protocolTypedParam sil hidden @protocolTypedParam : $@convention(thin) (@owned Foo) -> () { bb0(%0 : $Foo): debug_value %0 : $Foo // CHECK-NOT: function_ref @protocolConstrained %2 = function_ref @protocolConstrained : $@convention(thin) <τ_0_0 where τ_0_0 : Foo> (@owned τ_0_0) -> () strong_retain %0 : $Foo // CHECK-NOT: apply // CHECK: [[METHOD:%[a-zA-Z0-9]+]] = objc_method %0 : $any Foo, #Foo.foo!foreign : {{.*}}, $@convention(objc_method) <τ_0_0 where τ_0_0 : Foo> (τ_0_0) -> () // CHECK: apply [[METHOD]](%0) : $@convention(objc_method) <τ_0_0 where τ_0_0 : Foo> (τ_0_0) -> () %4 = apply %2(%0) : $@convention(thin) <τ_0_0 where τ_0_0 : Foo> (@owned τ_0_0) -> () strong_release %0 : $Foo %6 = tuple () return %6 : $() } // CHECK-LABEL: sil [transparent] @identity sil [transparent] @identity : $@convention(thin) (@in T) -> @out T { bb0(%0 : $*T, %1 : $*T): debug_value %1 : $*T, expr op_deref copy_addr [take] %1 to [init] %0 : $*T %4 = tuple () // CHECK: return return %4 : $() } // CHECK-LABEL: sil @applyIdentity sil @applyIdentity : $@convention(thin) (@in T) -> @out T { bb0(%0 : $*T, %1 : $*T): debug_value %1 : $*T, expr op_deref %3 = function_ref @identity : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0 %4 = alloc_stack $T copy_addr %1 to [init] %4 : $*T // CHECK-NOT: apply %6 = apply %3(%0, %4) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0 dealloc_stack %4 : $*T destroy_addr %1 : $*T %9 = tuple () // CHECK: return return %9 : $() } // CHECK-LABEL: sil [transparent] @partial sil [transparent] @partial : $@convention(thin) (@in T, @owned @callee_owned (@in T) -> @out U) -> @out U { bb0(%0 : $*U, %1 : $*T, %2 : $@callee_owned (@in T) -> @out U): debug_value %1 : $*T, expr op_deref debug_value %2 : $@callee_owned (@in T) -> @out U strong_retain %2 : $@callee_owned (@in T) -> @out U %6 = alloc_stack $T copy_addr %1 to [init] %6 : $*T // CHECK: apply %2 %8 = apply %2(%0, %6) : $@callee_owned (@in T) -> @out U dealloc_stack %6 : $*T strong_release %2 : $@callee_owned (@in T) -> @out U destroy_addr %1 : $*T %12 = tuple () // CHECK: return return %12 : $() } // CHECK-LABEL: sil @applyPartial sil @applyPartial : $@convention(thin) (Builtin.Int32, @owned @callee_owned (Builtin.Int32) -> @out U) -> @out U { bb0(%0 : $*U, %1 : $Builtin.Int32, %2 : $@callee_owned (Builtin.Int32) -> @out U): debug_value %1 : $Builtin.Int32 debug_value %2 : $@callee_owned (Builtin.Int32) -> @out U %5 = function_ref @partial : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @owned @callee_owned (@in τ_0_0) -> @out τ_0_1) -> @out τ_0_1 %6 = alloc_stack $Builtin.Int32 store %1 to %6 : $*Builtin.Int32 strong_retain %2 : $@callee_owned (Builtin.Int32) -> @out U // CHECK-NOT: function_ref @reabstractionThunk %9 = function_ref @reabstractionThunk : $@convention(thin) <τ_0_0> (@in Builtin.Int32, @owned @callee_owned (Builtin.Int32) -> @out τ_0_0) -> @out τ_0_0 // CHECK-NOT: partial_apply %10 = partial_apply %9(%2) : $@convention(thin) <τ_0_0> (@in Builtin.Int32, @owned @callee_owned (Builtin.Int32) -> @out τ_0_0) -> @out τ_0_0 // CHECK-NOT: apply // CHECK: apply %2 %11 = apply %5(%0, %6, %10) : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @owned @callee_owned (@in τ_0_0) -> @out τ_0_1) -> @out τ_0_1 dealloc_stack %6 : $*Builtin.Int32 strong_release %2 : $@callee_owned (Builtin.Int32) -> @out U %14 = tuple () // CHECK: return return %14 : $() } // CHECK-LABEL: sil [transparent] @reabstractionThunk sil [transparent] @reabstractionThunk : $@convention(thin) (@in Builtin.Int32, @owned @callee_owned (Builtin.Int32) -> @out U) -> @out U { bb0(%0 : $*U, %1 : $*Builtin.Int32, %2 : $@callee_owned (Builtin.Int32) -> @out U): %3 = load %1 : $*Builtin.Int32 %4 = apply %2(%0, %3) : $@callee_owned (Builtin.Int32) -> @out U // CHECK: return return %4 : $() } // CHECK-LABEL: sil [transparent] @inner_transparent sil [transparent] @inner_transparent : $@convention(thin) (@owned @callee_owned () -> Builtin.Int8) -> Builtin.Int8 { // CHECK: bb0 bb0(%0 : $@callee_owned () -> Builtin.Int8): strong_retain %0 : $@callee_owned () -> Builtin.Int8 %3 = apply %0() : $@callee_owned () -> Builtin.Int8 strong_release %0 : $@callee_owned () -> Builtin.Int8 // CHECK: return return %3 : $Builtin.Int8 } // CHECK-LABEL: sil [transparent] @outer_transparent sil [transparent] @outer_transparent : $@convention(thin) (@owned @callee_owned () -> Builtin.Int8) -> Builtin.Int8 { // CHECK: bb0 bb0(%0 : $@callee_owned () -> Builtin.Int8): %2 = function_ref @inner_transparent : $@convention(thin) (@owned @callee_owned () -> Builtin.Int8) -> Builtin.Int8 strong_retain %0 : $@callee_owned () -> Builtin.Int8 %4 = apply %2(%0) : $@convention(thin) (@owned @callee_owned () -> Builtin.Int8) -> Builtin.Int8 strong_release %0 : $@callee_owned () -> Builtin.Int8 // CHECK: return return %4 : $Builtin.Int8 } // We remove everything here now. // CHECK-LABEL: sil @testouter_transparent sil @testouter_transparent : $@convention(thin) (Builtin.Int8) -> Builtin.Int8 { // CHECK: bb0 // CHECK-NEXT: return bb0(%0 : $Builtin.Int8): %2 = function_ref @outer_transparent : $@convention(thin) (@owned @callee_owned () -> Builtin.Int8) -> Builtin.Int8 %3 = function_ref @identity_closure : $@convention(thin) (Builtin.Int8) -> Builtin.Int8 %4 = partial_apply %3(%0) : $@convention(thin) (Builtin.Int8) -> Builtin.Int8 %5 = apply %2(%4) : $@convention(thin) (@owned @callee_owned () -> Builtin.Int8) -> Builtin.Int8 return %5 : $Builtin.Int8 } // This isn't removed in Onone anymore. sil shared [transparent] @identity_closure : $@convention(thin) (Builtin.Int8) -> Builtin.Int8 { bb0(%0 : $Builtin.Int8): return %0 : $Builtin.Int8 } sil [transparent] @P2_s : $@convention(method) (@in_guaranteed Self) -> Int32 { bb0(%0 : $*Self): %2 = alloc_stack $Self copy_addr %0 to [init] %2 : $*Self %4 = witness_method $Self, #P2.c!getter : $@convention(witness_method: P2) <τ_0_0 where τ_0_0 : P2> (@in_guaranteed τ_0_0) -> Int32 %5 = apply %4(%2) : $@convention(witness_method: P2) <τ_0_0 where τ_0_0 : P2> (@in_guaranteed τ_0_0) -> Int32 destroy_addr %2 : $*Self %7 = integer_literal $Builtin.Int32, 1 %8 = struct_extract %5 : $Int32, #Int32._value %9 = integer_literal $Builtin.Int1, -1 %10 = builtin "sadd_with_overflow_Int32"(%8 : $Builtin.Int32, %7 : $Builtin.Int32, %9 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) %11 = tuple_extract %10 : $(Builtin.Int32, Builtin.Int1), 0 %12 = tuple_extract %10 : $(Builtin.Int32, Builtin.Int1), 1 cond_fail %12 : $Builtin.Int1 %14 = struct $Int32 (%11 : $Builtin.Int32) dealloc_stack %2 : $*Self return %14 : $Int32 } // Check that P2_s call can be properly inlined and the resulting witness_method instruction // uses the opened archetype from the caller. // CHECK-LABEL: sil hidden @L_start // CHECK: open_existential_addr immutable_access {{.*}}$*@[[OPENED_ARCHETYPE:opened\("[A-Z0-9-]+", any P2\) Self]] // CHECK: witness_method $@[[OPENED_ARCHETYPE]], #P2.c!getter : {{.*}}, %{{[0-9]+}} : $*@[[OPENED_ARCHETYPE]] // CHECK: return sil hidden @L_start : $@convention(method) (@in_guaranteed L) -> Int32 { bb0(%0 : $*L): %2 = struct_element_addr %0 : $*L, #L.o %3 = alloc_stack $P2 copy_addr %2 to [init] %3 : $*P2 %5 = open_existential_addr immutable_access %3 : $*P2 to $*@opened("5C6E227C-235E-11E6-AA98-B8E856428C60", P2) Self %6 = function_ref @P2_s : $@convention(method) <τ_0_0 where τ_0_0 : P2> (@in_guaranteed τ_0_0) -> Int32 %7 = apply %6<@opened("5C6E227C-235E-11E6-AA98-B8E856428C60", P2) Self>(%5) : $@convention(method) <τ_0_0 where τ_0_0 : P2> (@in_guaranteed τ_0_0) -> Int32 destroy_addr %3 : $*P2 dealloc_stack %3 : $*P2 return %7 : $Int32 } sil_default_witness_table hidden P2 { no_default } // Test function_ref -> convert_function -> apply. sil [transparent] @testMandatoryConvertedHelper : $@convention(thin) (C) -> C { bb0(%0 : $C): return %0 : $C } sil [transparent] @testMandatoryConvertedHelper2 : $@convention(thin) (Optional) -> C { bb0(%0 : $Optional): %o = unchecked_enum_data %0 : $Optional, #Optional.some!enumelt return %o : $C } // CHECK-LABEL: sil @testMandatoryConverted : $@convention(thin) (C) -> C { // CHECK: bb0(%0 : $C): // CHECK: [[F1:%.*]] = function_ref @testMandatoryConvertedHelper : $@convention(thin) (C) -> C // CHECK: [[CVT1:%.*]] = convert_function [[F1]] : $@convention(thin) (C) -> C to $@convention(thin) (C) -> (C, @error any Error) // CHECK: try_apply [[CVT1]](%0) : $@convention(thin) (C) -> (C, @error any Error), normal bb1, error bb2 // CHECK: bb1(%{{.*}} : $C): // CHECK: br bb3(%{{.*}} : $C) // CHECK: bb2(%{{.*}} : $any Error): // CHECK: [[F2:%.*]] = function_ref @testMandatoryConvertedHelper2 : $@convention(thin) (Optional) -> C // CHECK: [[CVT2:%.*]] = convert_function [[F2]] : $@convention(thin) (Optional) -> C to $@convention(thin) (C) -> C // CHECK: %{{.*}} = apply [[CVT2]](%0) : $@convention(thin) (C) -> C // CHECK: br bb3(%{{.*}} : $C) // CHECK: bb3(%{{.*}} : $C): // CHECK: return %{{.*}} : $C // CHECK-LABEL: } // end sil function 'testMandatoryConverted' sil @testMandatoryConverted : $@convention(thin) (C) -> C { bb0(%0 : $C): // Inline this one. %f = function_ref @testMandatoryConvertedHelper : $@convention(thin) (C) -> C %cf1 = convert_function %f : $@convention(thin) (C) -> C to $@convention(thin) @noescape (C) -> C %call1 = apply %cf1(%0) : $@convention(thin) @noescape (C) -> C // Don't (currently) inline conversion away from throws. %cf2 = convert_function %f : $@convention(thin) (C) -> C to $@convention(thin) (C) -> (C, @error Error) try_apply %cf2(%0) : $@convention(thin) (C) -> (C, @error Error), normal bb7, error bb11 bb7(%callret : $C): br bb12(%callret : $C) bb11(%128 : $Error): // Don't (currently) inline conversion away from Optional. %f2 = function_ref @testMandatoryConvertedHelper2 : $@convention(thin) (Optional) -> C %cf3 = convert_function %f2 : $@convention(thin) (Optional) -> C to $@convention(thin) (C) -> C %call3 = apply %cf3(%0) : $@convention(thin) (C) -> C br bb12(%call3 : $C) bb12(%result : $C): return %result : $C } sil @use_c : $@convention(thin) (@guaranteed C) -> () sil @use_c_unowned : $@convention(thin) (C) -> () sil [transparent] @guaranteed_closure_func : $@convention(thin) (@guaranteed C) -> () { bb0(%0 : $C): %use = function_ref @use_c : $@convention(thin) (@guaranteed C) -> () apply %use(%0) : $@convention(thin) (@guaranteed C) -> () %t = tuple () return %t : $() } sil [transparent] @unowned_closure_func : $@convention(thin) (C) -> () { bb0(%0 : $C): %use = function_ref @use_c_unowned : $@convention(thin) (C) -> () apply %use(%0) : $@convention(thin) (C) -> () %t = tuple () return %t : $() } // CHECK-LABEL: sil @test_guaranteed_closure_capture // CHECK: bb0([[ARG:%.*]] : $C): // CHECK: strong_retain [[ARG]] : $C // CHECK: strong_retain [[ARG]] // CHECK: [[F:%.*]] = function_ref @use_c // CHECK: apply [[F]]([[ARG]]) // CHECK: strong_release [[ARG]] // CHECK: strong_release [[ARG]] // CHECK: return sil @test_guaranteed_closure_capture : $@convention(thin) (@guaranteed C) -> () { bb0(%0: $C): strong_retain %0 : $C %closure_fun = function_ref @guaranteed_closure_func : $@convention(thin) (@guaranteed C) -> () %closure = partial_apply [callee_guaranteed] %closure_fun(%0) : $@convention(thin) (@guaranteed C) -> () apply %closure() : $@callee_guaranteed () -> () strong_release %closure : $@callee_guaranteed () -> () %t = tuple () return %t : $() } // CHECK-LABEL: sil @test_guaranteed_closure_capture2 // CHECK: bb0([[ARG:%.*]] : $C): // CHECK: strong_retain [[ARG]] : $C // CHECK: strong_retain [[ARG]] // CHECK: [[F:%.*]] = function_ref @use_c // CHECK: apply [[F]]([[ARG]]) // CHECK: strong_release [[ARG]] : $C // CHECK: strong_release [[ARG]] : $C // CHECK: return sil @test_guaranteed_closure_capture2 : $@convention(thin) (@guaranteed C) -> () { bb0(%0: $C): strong_retain %0 : $C %closure_fun = function_ref @guaranteed_closure_func : $@convention(thin) (@guaranteed C) -> () %closure = partial_apply %closure_fun(%0) : $@convention(thin) (@guaranteed C) -> () apply %closure() : $@callee_owned () -> () %t = tuple () return %t : $() } // CHECK-LABEL: sil @test_unowned_closure_capture2 // CHECK: bb0([[ARG:%.*]] : $C): // CHECK: strong_retain [[ARG]] // CHECK: strong_retain [[ARG]] // CHECK: [[F:%.*]] = function_ref @use_c_unowned // CHECK: apply [[F]]([[ARG]]) : $@convention(thin) (C) -> () // CHECK: strong_release [[ARG]] // CHECK: strong_release [[ARG]] // CHECK: return sil @test_unowned_closure_capture2 : $@convention(thin) (@guaranteed C) -> () { bb0(%0: $C): strong_retain %0 : $C %closure_fun = function_ref @unowned_closure_func : $@convention(thin) (C) -> () %closure = partial_apply %closure_fun(%0) : $@convention(thin) (C) -> () apply %closure() : $@callee_owned () -> () %t = tuple () return %t : $() } // CHECK-LABEL: sil @test_guaranteed_closure // CHECK: bb0([[ARG:%.*]] : $C): // CHECK: strong_retain [[ARG]] : $C // CHECK: [[F:%.*]] = function_ref @guaranteed_closure_func // CHECK: [[C:%.*]] = partial_apply [callee_guaranteed] [[F]]([[ARG]]) // @guaranteed closure captures *don't* release the capture in the closure implementation. // CHECK-NOT: strong_retain [[ARG]] : $C // @callee_guaranteed closures *don't* release the context on application. // CHECK-NOT: strong_release [[C]] // CHECK: [[F:%.*]] = function_ref @use_c // CHECK: apply [[F]]([[ARG]]) // CHECK: return [[C]] sil @test_guaranteed_closure : $@convention(thin) (@guaranteed C) -> @owned @callee_guaranteed () -> () { bb0(%0: $C): strong_retain %0 : $C %closure_fun = function_ref @guaranteed_closure_func : $@convention(thin) (@guaranteed C) -> () %closure = partial_apply [callee_guaranteed] %closure_fun(%0) : $@convention(thin) (@guaranteed C) -> () // NOTE: No ``strong_retain %closure`` is needed here because the context is // @callee_guaranteed. apply %closure() : $@callee_guaranteed () -> () return %closure : $@callee_guaranteed () -> () } sil [transparent] @return_one : $@convention(thin) () -> Builtin.Int32 { bb0: %0 = integer_literal $Builtin.Int32, 1 return %0 : $Builtin.Int32 } // CHECK-LABEL: sil @test_thin_convert_function_inline // CHECK-NEXT: bb0 // CHECK-NEXT: [[RES:%.*]] = integer_literal $Builtin.Int32, 1 // CHECK-NEXT: return [[RES]] sil @test_thin_convert_function_inline : $@convention(thin) () -> Builtin.Int32 { bb0: %0 = function_ref @return_one : $@convention(thin) () -> Builtin.Int32 %1 = convert_function %0 : $@convention(thin) () -> Builtin.Int32 to $@convention(thin) @noescape () -> Builtin.Int32 %2 = thin_to_thick_function %1 : $@convention(thin) @noescape () -> Builtin.Int32 to $@noescape () -> Builtin.Int32 %3 = apply %2() : $@noescape () -> Builtin.Int32 return %3 : $Builtin.Int32 } // CHECK-LABEL: sil @test_guaranteed_on_stack_closure // CHECK: strong_retain %0 : $C // CHECK: [[F:%.*]] = function_ref @use_c : $@convention(thin) (@guaranteed C) -> () // CHECK: apply [[F]](%0) : $@convention(thin) (@guaranteed C) -> () // CHECK: strong_release %0 : $C // CHECK: return sil @test_guaranteed_on_stack_closure : $@convention(thin) (@guaranteed C) -> () { bb0(%0: $C): strong_retain %0 : $C %closure_fun = function_ref @guaranteed_closure_func : $@convention(thin) (@guaranteed C) -> () %closure = partial_apply [on_stack] [callee_guaranteed] %closure_fun(%0) : $@convention(thin) (@guaranteed C) -> () %closure2 = mark_dependence %closure : $@noescape @callee_guaranteed () -> () on %0 : $C apply %closure2() : $@noescape @callee_guaranteed () -> () strong_release %0: $C dealloc_stack %closure : $@noescape @callee_guaranteed () -> () %tuple = tuple() return %tuple : $() } // CHECK-LABEL: sil @test_apply_pai_in_loop : $@convention(thin) (@guaranteed C) -> () { // CHECK: bb0([[ARG:%.*]] : $C): // CHECK-NEXT: strong_retain [[ARG]] // CHECK-NEXT: strong_retain [[ARG]] // CHECK-NEXT: br bb1 // // CHECK: bb1: // CHECK-NEXT: cond_br undef, bb2, bb3 // // CHECK: bb2: // CHECK-NEXT: function_ref use_c // CHECK-NEXT: [[FUNC:%.*]] = function_ref @use_c // CHECK-NEXT: apply [[FUNC]]([[ARG]]) // CHECK-NEXT: tuple // CHECK-NEXT: br bb1 // // CHECK: bb3: // CHECK-NEXT: strong_release [[ARG]] // CHECK-NEXT: strong_release [[ARG]] // CHECK-NEXT: tuple // CHECK-NEXT: return // CHECK-NEXT: } // end sil function 'test_apply_pai_in_loop' sil @test_apply_pai_in_loop : $@convention(thin) (@guaranteed C) -> () { bb0(%0: $C): strong_retain %0 : $C %closure_fun = function_ref @guaranteed_closure_func : $@convention(thin) (@guaranteed C) -> () %closure = partial_apply [callee_guaranteed] %closure_fun(%0) : $@convention(thin) (@guaranteed C) -> () br bb1 bb1: cond_br undef, bb2, bb3 bb2: apply %closure() : $@callee_guaranteed () -> () br bb1 bb3: strong_release %0: $C %tuple = tuple() return %tuple : $() } // CHECK-LABEL: sil @test_apply_pai_in_loop_with_diamond : $@convention(thin) (@guaranteed C) -> () { // CHECK: bb0([[ARG:%.*]] : $C): // CHECK-NEXT: strong_retain [[ARG]] // CHECK-NEXT: strong_retain [[ARG]] // CHECK-NEXT: strong_retain [[ARG]] // CHECK-NEXT: cond_br undef, bb1, bb4 // // CHECK: bb1: // CHECK-NEXT: function_ref use_c // CHECK-NEXT: [[FUNC:%.*]] = function_ref @use_c // CHECK-NEXT: apply [[FUNC]]([[ARG]]) // CHECK-NEXT: tuple // CHECK-NEXT: cond_br undef, bb2, bb3 // // CHECK: bb2: // CHECK-NEXT: function_ref use_c // CHECK-NEXT: [[FUNC:%.*]] = function_ref @use_c // CHECK-NEXT: apply [[FUNC]]([[ARG]]) // CHECK-NEXT: tuple // CHECK-NEXT: br bb1 // // CHECK: bb3: // CHECK-NEXT: br bb1 // // CHECK: bb4: // CHECK-NEXT: strong_release [[ARG]] // CHECK-NEXT: strong_release [[ARG]] // CHECK-NEXT: strong_release [[ARG]] // CHECK-NEXT: tuple // CHECK-NEXT: return // CHECK-NEXT: } // end sil function 'test_apply_pai_in_loop_with_diamond' sil @test_apply_pai_in_loop_with_diamond : $@convention(thin) (@guaranteed C) -> () { bb0(%0: $C): strong_retain %0 : $C %closure_fun = function_ref @guaranteed_closure_func : $@convention(thin) (@guaranteed C) -> () %closure = partial_apply [callee_guaranteed] %closure_fun(%0) : $@convention(thin) (@guaranteed C) -> () cond_br undef, bb2, bb5 bb2: apply %closure() : $@callee_guaranteed () -> () cond_br undef, bb3, bb4 bb3: apply %closure() : $@callee_guaranteed () -> () br bb2 bb4: br bb2 bb5: strong_release %0: $C %tuple = tuple() return %tuple : $() } // CHECK-LABEL: sil @test_apply_pai_in_diamond : $@convention(thin) (@guaranteed C) -> () { // CHECK: bb0([[ARG:%.*]] : $C): // CHECK-NEXT: strong_retain [[ARG]] // CHECK-NEXT: strong_retain [[ARG]] // CHECK-NEXT: cond_br undef, bb1, bb2 // // CHECK: bb1: // CHECK-NEXT: strong_release [[ARG]] // CHECK-NEXT: br bb3 // // CHECK: bb2: // CHECK-NEXT: function_ref use_c // CHECK-NEXT: [[FUNC:%.*]] = function_ref @use_c // CHECK-NEXT: apply [[FUNC]]([[ARG]]) // CHECK-NEXT: tuple // CHECK-NEXT: strong_release [[ARG]] // CHECK-NEXT: br bb3 // // CHECK: bb3: // CHECK-NEXT: strong_release [[ARG]] // CHECK-NEXT: tuple // CHECK-NEXT: return // CHECK: } // end sil function 'test_apply_pai_in_diamond' sil @test_apply_pai_in_diamond : $@convention(thin) (@guaranteed C) -> () { bb0(%0: $C): strong_retain %0 : $C %closure_fun = function_ref @guaranteed_closure_func : $@convention(thin) (@guaranteed C) -> () %closure = partial_apply [callee_guaranteed] %closure_fun(%0) : $@convention(thin) (@guaranteed C) -> () cond_br undef, bb1, bb2 bb1: br bb3 bb2: apply %closure() : $@callee_guaranteed () -> () br bb3 bb3: strong_release %0: $C %tuple = tuple() return %tuple : $() } // CHECK-LABEL: sil @test_apply_pai_in_diamond_non_post_dominate_non_post_dominate : $@convention(thin) (@guaranteed C) -> () { // CHECK: bb0([[ARG:%.*]] : $C): // CHECK-NEXT: cond_br undef, [[BB_TRAMPOLINE:bb[0-9]+]], [[BB_DIAMOND_BEGIN:bb[0-9]+]] // // CHECK: [[BB_TRAMPOLINE]]: // CHECK-NEXT: br [[BB_END:bb[0-9]+]] // // CHECK: [[BB_DIAMOND_BEGIN]]: // CHECK-NEXT: strong_retain [[ARG]] // CHECK-NEXT: strong_retain [[ARG]] // CHECK-NEXT: cond_br undef, [[NO_CALL_BB:bb[0-9]+]], [[CALL_BB:bb[0-9]+]] // // CHECK: [[NO_CALL_BB]]: // CHECK-NEXT: strong_release [[ARG]] // CHECK-NEXT: br [[MERGE_BB:bb[0-9]+]] // // CHECK: [[CALL_BB]]: // CHECK-NEXT: function_ref use_c // CHECK-NEXT: [[FUNC:%.*]] = function_ref @use_c : $@convention(thin) // CHECK-NEXT: apply [[FUNC]] // CHECK-NEXT: tuple // CHECK-NEXT: strong_release [[ARG]] // CHECK-NEXT: br [[MERGE_BB]] // // CHECK: [[MERGE_BB]]: // CHECK-NEXT: strong_release [[ARG]] // CHECK-NEXT: br [[BB_END]] // // CHECK: [[BB_END]]: // CHECK-NEXT: tuple // CHECK-NEXT: return // CHECK: } // end sil function 'test_apply_pai_in_diamond_non_post_dominate_non_post_dominate' sil @test_apply_pai_in_diamond_non_post_dominate_non_post_dominate : $@convention(thin) (@guaranteed C) -> () { bb0(%0: $C): cond_br undef, bb1, bb2 bb1: br bb6 bb2: strong_retain %0 : $C %closure_fun = function_ref @guaranteed_closure_func : $@convention(thin) (@guaranteed C) -> () %closure = partial_apply [callee_guaranteed] %closure_fun(%0) : $@convention(thin) (@guaranteed C) -> () cond_br undef, bb3, bb4 bb3: br bb5 bb4: apply %closure() : $@callee_guaranteed () -> () br bb5 bb5: strong_release %closure : $@callee_guaranteed () -> () br bb6 bb6: %tuple = tuple() return %tuple : $() } sil [transparent] @escaping_thunk : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () { bb0(%1 : $@callee_guaranteed () -> ()): %9999 = tuple() return %9999 : $() } // Make sure that we do not crash here. // // CHECK-LABEL: sil @partial_apply_stack_failure : $@convention(thin) (@callee_guaranteed () -> ()) -> () { // CHECK: } // end sil function 'partial_apply_stack_failure' sil @partial_apply_stack_failure : $@convention(thin) (@callee_guaranteed () -> ()) -> () { bb0(%0 : $@callee_guaranteed () -> ()): %1 = alloc_stack $@callee_guaranteed () -> () store %0 to %1 : $*@callee_guaranteed () -> () %2 = load %1 : $*@callee_guaranteed () -> () strong_retain %2 : $@callee_guaranteed () -> () %thunk = function_ref @escaping_thunk : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () %2a = partial_apply [callee_guaranteed] [on_stack] %thunk(%2) : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () %2b = mark_dependence %2a : $@noescape @callee_guaranteed () -> () on %2 : $@callee_guaranteed () -> () apply %2b() : $@noescape @callee_guaranteed () -> () dealloc_stack %2a : $@noescape @callee_guaranteed () -> () destroy_addr %1 : $*@callee_guaranteed () -> () dealloc_stack %1 : $*@callee_guaranteed () -> () %9999 = tuple() return %9999 : $() } struct Mystruct { var s: String } sil @use_string : $@convention(thin) (@guaranteed String) -> () sil private [transparent] [ossa] @callee_with_guaranteed : $@convention(thin) (Bool, @in_guaranteed Mystruct) -> () { bb0(%0 : $Bool, %1 : $*Mystruct): %4 = struct_element_addr %1 : $*Mystruct, #Mystruct.s %5 = load [copy] %4 : $*String %6 = function_ref @use_string : $@convention(thin) (@guaranteed String) -> () %7 = apply %6(%5) : $@convention(thin) (@guaranteed String) -> () destroy_value %5 : $String %19 = tuple () return %19 : $() } // Make sure that this doesn't cause a memory lifetime failure. // // CHECK-LABEL: sil [ossa] @partial_apply_with_indirect_param // CHECK: } // end sil function 'partial_apply_with_indirect_param' sil [ossa] @partial_apply_with_indirect_param : $@convention(thin) (@in_guaranteed Mystruct, Bool) -> () { bb0(%0 : $*Mystruct, %1 : $Bool): %216 = function_ref @callee_with_guaranteed : $@convention(thin) (Bool, @in_guaranteed Mystruct) -> () %217 = alloc_stack $Mystruct copy_addr %0 to [init] %217 : $*Mystruct %219 = partial_apply [callee_guaranteed] %216(%217) : $@convention(thin) (Bool, @in_guaranteed Mystruct) -> () %220 = apply %219(%1) : $@callee_guaranteed (Bool) -> () destroy_value %219 : $@callee_guaranteed (Bool) -> () dealloc_stack %217 : $*Mystruct %19 = tuple () return %19 : $() } sil [transparent] [ossa] @callee : $@convention(thin) () -> () { bb0: %r = tuple () return %r : $() } // This test needs the guard malloc to crash without the fix in #35037 // Tests there is no use-after-free in ClosureCleanup::recordDeadFunction when deleting debug instructions // CHECK-LABEL: sil [ossa] @$test_no_use_after_free : // CHECK-LABEL: } // end sil function '$test_no_use_after_free' sil [ossa] @$test_no_use_after_free : $@convention(thin) () -> () { bb0: %12 = function_ref @callee : $@convention(thin) () -> () %13 = thin_to_thick_function %12 : $@convention(thin) () -> () to $@callee_guaranteed () -> () debug_value %13 : $@callee_guaranteed () -> () %28 = apply %13() : $@callee_guaranteed () -> () %r = tuple () return %r : $() } sil [transparent] @hop_to_executor : $@convention(thin) @async (@guaranteed Builtin.Executor) -> () { entry(%executor: $Builtin.Executor): hop_to_executor %executor : $Builtin.Executor %r = tuple () return %r : $() } // CHECK-LABEL: sil @test_inline_nonasync // CHECK-NOT: hop_to_executor // CHECK-NOT: apply // CHECK: } // end sil function 'test_inline_nonasync' sil @test_inline_nonasync : $@convention(thin) (@guaranteed Builtin.Executor) -> () { entry(%executor: $Builtin.Executor): %f = function_ref @hop_to_executor : $@convention(thin) @async (@guaranteed Builtin.Executor) -> () %c = apply [noasync] %f(%executor) : $@convention(thin) @async (@guaranteed Builtin.Executor) -> () %r = tuple () return %r : $() } private class X { func foo(_ e: E.Type) throws(E) where E : Error } sil private [ossa] @X_foo : $@convention(method) (@thick E.Type, @guaranteed X) -> @error_indirect E { bb0(%0 : $*E, %1 : $@thick E.Type, %2 : @guaranteed $X): %5 = tuple () return %5 : $() } // CHECK-LABEL: sil [ossa] @class_method_with_typed_throw // CHECK: function_ref // CHECK: } // end sil function 'class_method_with_typed_throw' sil [ossa] @class_method_with_typed_throw : $@convention(thin) (@guaranteed X, @thick E.Type) -> () { bb0(%0 : @guaranteed $X, %1 : $@thick E.Type): %4 = alloc_stack $E %5 = class_method %0 : $X, #X.foo : (X) -> (E.Type) throws(E) -> (), $@convention(method) <τ_0_0 where τ_0_0 : Error> (@thick τ_0_0.Type, @guaranteed X) -> @error_indirect τ_0_0 %6 = alloc_stack $E try_apply %5(%6, %1, %0) : $@convention(method) <τ_0_0 where τ_0_0 : Error> (@thick τ_0_0.Type, @guaranteed X) -> @error_indirect τ_0_0, normal bb1, error bb2 bb1(%8 : $()): dealloc_stack %6 : $*E dealloc_stack %4 : $*E %11 = tuple () return %11 : $() bb2: unreachable } sil_vtable X { #X.foo: (X) -> (E.Type) throws(E) -> () : @X_foo }