// RUN: %target-sil-opt -enable-sil-verify-all %s -function-order-printer -o /dev/null | %FileCheck --check-prefix=CHECK %s sil_stage canonical import Builtin // CHECK: Bottom up function order: // CHECK-NEXT: private_bottom // CHECK-NEXT: private_middle // CHECK-NEXT: private_top // CHECK-NEXT: internal_bottom // CHECK-NEXT: internal_middle // CHECK-NEXT: internal_top // CHECK-NEXT: public_bottom // CHECK-NEXT: public_middle // CHECK-NEXT: public_top // CHECK-NEXT: private_base_foo // CHECK-NEXT: private_derived_foo // CHECK-NEXT: call_private // CHECK-NEXT: internal_base_foo // CHECK-NEXT: internal_derived_foo // CHECK-NEXT: internal_base_bar // CHECK-NEXT: internal_derived_bar // CHECK-NEXT: call_internal // CHECK-NEXT: public_base_foo // CHECK-NEXT: public_derived_foo // CHECK-NEXT: public_base_bar // CHECK-NEXT: public_derived_bar // CHECK-NEXT: public_base_baz // CHECK-NEXT: public_derived_baz // CHECK-NEXT: call_public // CHECK-NEXT: private_proto_private_class_theMethod // CHECK-NEXT: private_proto_1_private_class_witness // CHECK-NEXT: call_through_private_proto_1 // CHECK-NEXT: private_proto_internal_class_theMethod // CHECK-NEXT: private_proto_2_internal_class_witness // CHECK-NEXT: call_through_private_proto_2 // CHECK-NEXT: private_proto_public_class_theMethod // CHECK-NEXT: private_proto_3_public_class_witness // CHECK-NEXT: call_through_private_proto_3 // CHECK-NEXT: private_proto_public_class_private_method_theMethod // CHECK-NEXT: private_proto_4_public_class_private_method_witness // CHECK-NEXT: call_through_private_proto_4 // CHECK-NEXT: Non-trivial SCC: // CHECK-NEXT: second_recursive // CHECK-NEXT: first_recursive sil private @private_top : $@convention(thin) () -> () { bb0: %0 = function_ref @private_middle : $@convention(thin) () -> () %1 = apply %0() : $@convention(thin) () -> () %2 = tuple () return %2 : $() } sil private @private_middle : $@convention(thin) () -> () { bb0: %0 = function_ref @private_bottom : $@convention(thin) () -> () %1 = apply %0() : $@convention(thin) () -> () %2 = tuple () return %2 : $() } sil private @private_bottom : $@convention(thin) () -> () { bb0: %0 = tuple () return %0 : $() } sil hidden @internal_top : $@convention(thin) () -> () { bb0: %0 = function_ref @internal_middle : $@convention(thin) () -> () %1 = apply %0() : $@convention(thin) () -> () %2 = tuple () return %2 : $() } sil hidden @internal_middle : $@convention(thin) () -> () { bb0: %0 = function_ref @internal_bottom : $@convention(thin) () -> () %1 = apply %0() : $@convention(thin) () -> () %2 = tuple () return %2 : $() } sil hidden @internal_bottom : $@convention(thin) () -> () { bb0: %0 = tuple () return %0 : $() } sil @public_top : $@convention(thin) () -> () { bb0: %0 = function_ref @public_middle : $@convention(thin) () -> () %1 = apply %0() : $@convention(thin) () -> () %2 = tuple () return %2 : $() } sil @public_middle : $@convention(thin) () -> () { bb0: %0 = function_ref @public_bottom : $@convention(thin) () -> () %1 = apply %0() : $@convention(thin) () -> () %2 = tuple () return %2 : $() } sil @public_bottom : $@convention(thin) () -> () { bb0: %0 = tuple () return %0 : $() } private class private_base { func foo() } private class private_derived : private_base { override func foo() } @inline(never) private func call_private(b: private_base) class internal_base { func foo() private func bar() } class internal_derived : internal_base { override func foo() override func bar() } @inline(never) func call_internal(b: internal_base) public class public_base { func foo() public func bar() private func baz() } public class public_derived : public_base { override func foo() public override func bar() public override func baz() } sil private [noinline] @call_private : $@convention(thin) (@owned private_base) -> () { bb0(%0 : $private_base): debug_value %0 : $private_base %2 = class_method %0 : $private_base, #private_base.foo : (private_base) -> () -> (), $@convention(method) (@guaranteed private_base) -> () %3 = apply %2(%0) : $@convention(method) (@guaranteed private_base) -> () strong_release %0 : $private_base %5 = tuple () return %5 : $() } sil private @private_derived_foo : $@convention(method) (@guaranteed private_derived) -> () { bb0(%0 : $private_derived): debug_value %0 : $private_derived %2 = tuple () return %2 : $() } sil private @private_base_foo : $@convention(method) (@guaranteed private_base) -> () { bb0(%0 : $private_base): debug_value %0 : $private_base %2 = tuple () return %2 : $() } sil hidden [noinline] @call_internal : $@convention(thin) (@owned internal_base) -> () { bb0(%0 : $internal_base): debug_value %0 : $internal_base %2 = class_method %0 : $internal_base, #internal_base.foo : (internal_base) -> () -> (), $@convention(method) (@guaranteed internal_base) -> () %3 = apply %2(%0) : $@convention(method) (@guaranteed internal_base) -> () %4 = class_method %0 : $internal_base, #internal_base.bar : (internal_base) -> () -> (), $@convention(method) (@guaranteed internal_base) -> () %5 = apply %4(%0) : $@convention(method) (@guaranteed internal_base) -> () strong_release %0 : $internal_base %7 = tuple () return %7 : $() } sil hidden @internal_base_foo : $@convention(method) (@guaranteed internal_base) -> () { bb0(%0 : $internal_base): debug_value %0 : $internal_base %2 = tuple () return %2 : $() } sil private @internal_base_bar : $@convention(method) (@guaranteed internal_base) -> () { bb0(%0 : $internal_base): debug_value %0 : $internal_base %2 = tuple () return %2 : $() } sil hidden @internal_derived_foo : $@convention(method) (@guaranteed internal_derived) -> () { bb0(%0 : $internal_derived): debug_value %0 : $internal_derived %2 = tuple () return %2 : $() } sil hidden @internal_derived_bar : $@convention(method) (@guaranteed internal_derived) -> () { bb0(%0 : $internal_derived): debug_value %0 : $internal_derived %2 = tuple () return %2 : $() } sil hidden [noinline] @call_public : $@convention(thin) (@owned public_base) -> () { bb0(%0 : $public_base): debug_value %0 : $public_base %2 = class_method %0 : $public_base, #public_base.foo : (public_base) -> () -> (), $@convention(method) (@guaranteed public_base) -> () %3 = apply %2(%0) : $@convention(method) (@guaranteed public_base) -> () %4 = class_method %0 : $public_base, #public_base.bar : (public_base) -> () -> (), $@convention(method) (@guaranteed public_base) -> () %5 = apply %4(%0) : $@convention(method) (@guaranteed public_base) -> () %6 = class_method %0 : $public_base, #public_base.baz : (public_base) -> () -> (), $@convention(method) (@guaranteed public_base) -> () %7 = apply %6(%0) : $@convention(method) (@guaranteed public_base) -> () strong_release %0 : $public_base %9 = tuple () return %9 : $() } sil hidden @public_base_foo : $@convention(method) (@guaranteed public_base) -> () { bb0(%0 : $public_base): debug_value %0 : $public_base %2 = tuple () return %2 : $() } sil @public_base_bar : $@convention(method) (@guaranteed public_base) -> () { bb0(%0 : $public_base): debug_value %0 : $public_base %2 = tuple () return %2 : $() } sil private @public_base_baz : $@convention(method) (@guaranteed public_base) -> () { bb0(%0 : $public_base): debug_value %0 : $public_base %2 = tuple () return %2 : $() } sil hidden @public_derived_foo : $@convention(method) (@guaranteed public_derived) -> () { bb0(%0 : $public_derived): debug_value %0 : $public_derived %2 = tuple () return %2 : $() } sil @public_derived_bar : $@convention(method) (@guaranteed public_derived) -> () { bb0(%0 : $public_derived): debug_value %0 : $public_derived %2 = tuple () return %2 : $() } sil @public_derived_baz : $@convention(method) (@guaranteed public_derived) -> () { bb0(%0 : $public_derived): debug_value %0 : $public_derived %2 = tuple () return %2 : $() } sil_vtable private_base { #private_base.foo: @private_base_foo } sil_vtable private_derived { #private_base.foo: @private_derived_foo [override] } sil_vtable internal_base { #internal_base.foo: @internal_base_foo #internal_base.bar: @internal_base_bar } sil_vtable internal_derived { #internal_base.foo: @internal_derived_foo [override] #internal_base.bar: @internal_derived_bar [override] } sil_vtable public_base { #public_base.foo: @public_base_foo #public_base.bar: @public_base_bar #public_base.baz: @public_base_baz } sil_vtable public_derived { #public_base.foo: @public_derived_foo [override] #public_base.bar: @public_derived_bar [override] #public_base.baz: @public_derived_baz [override] } private protocol private_proto_1 { func theMethod() } private class private_proto_private_class : private_proto_1 { func theMethod() } private func call_through_private_proto_1(x: T) private protocol private_proto_2 { func theMethod() } class private_proto_internal_class : private_proto_2 { func theMethod() } private func call_through_private_proto_2(x: T) private protocol private_proto_3 { func theMethod() } public class private_proto_public_class : private_proto_3 { public func theMethod() } private func call_through_private_proto_3(x: T) private protocol private_proto_4 { func theMethod() } public class private_proto_public_class_private_method : private_proto_4 { fileprivate func theMethod() } private func call_through_private_proto_4(x: T) sil private @private_proto_private_class_theMethod : $@convention(method) (@guaranteed private_proto_private_class) -> () { bb0(%0 : $private_proto_private_class): debug_value %0 : $private_proto_private_class %2 = tuple () return %2 : $() } sil private [transparent] [thunk] @private_proto_1_private_class_witness : $@convention(witness_method: private_proto_1) (@in_guaranteed private_proto_private_class) -> () { bb0(%0 : $*private_proto_private_class): %1 = load %0 : $*private_proto_private_class strong_retain %1 : $private_proto_private_class %3 = class_method %1 : $private_proto_private_class, #private_proto_private_class.theMethod : (private_proto_private_class) -> () -> (), $@convention(method) (@guaranteed private_proto_private_class) -> () %4 = apply %3(%1) : $@convention(method) (@guaranteed private_proto_private_class) -> () strong_release %1 : $private_proto_private_class return %4 : $() } sil private @call_through_private_proto_1 : $@convention(thin) (@in T) -> () { bb0(%0 : $*T): debug_value %0 : $*T, expr op_deref %2 = witness_method $T, #private_proto_1.theMethod : $@convention(witness_method: private_proto_1) <τ_0_0 where τ_0_0 : private_proto_1> (@in_guaranteed τ_0_0) -> () %3 = apply %2(%0) : $@convention(witness_method: private_proto_1) <τ_0_0 where τ_0_0 : private_proto_1> (@in_guaranteed τ_0_0) -> () destroy_addr %0 : $*T %5 = tuple () return %5 : $() } sil hidden @private_proto_internal_class_theMethod : $@convention(method) (@guaranteed private_proto_internal_class) -> () { bb0(%0 : $private_proto_internal_class): debug_value %0 : $private_proto_internal_class %2 = tuple () return %2 : $() } sil private [transparent] [thunk] @private_proto_2_internal_class_witness : $@convention(witness_method: private_proto_2) (@in_guaranteed private_proto_internal_class) -> () { bb0(%0 : $*private_proto_internal_class): %1 = load %0 : $*private_proto_internal_class strong_retain %1 : $private_proto_internal_class %3 = class_method %1 : $private_proto_internal_class, #private_proto_internal_class.theMethod : (private_proto_internal_class) -> () -> (), $@convention(method) (@guaranteed private_proto_internal_class) -> () %4 = apply %3(%1) : $@convention(method) (@guaranteed private_proto_internal_class) -> () strong_release %1 : $private_proto_internal_class return %4 : $() } sil private @call_through_private_proto_2 : $@convention(thin) (@in T) -> () { bb0(%0 : $*T): debug_value %0 : $*T, expr op_deref %2 = witness_method $T, #private_proto_2.theMethod : $@convention(witness_method: private_proto_2) <τ_0_0 where τ_0_0 : private_proto_2> (@in_guaranteed τ_0_0) -> () %3 = apply %2(%0) : $@convention(witness_method: private_proto_2) <τ_0_0 where τ_0_0 : private_proto_2> (@in_guaranteed τ_0_0) -> () destroy_addr %0 : $*T %5 = tuple () return %5 : $() } sil @private_proto_public_class_theMethod : $@convention(method) (@guaranteed private_proto_public_class) -> () { bb0(%0 : $private_proto_public_class): debug_value %0 : $private_proto_public_class %2 = tuple () return %2 : $() } sil private [transparent] [thunk] @private_proto_3_public_class_witness : $@convention(witness_method: private_proto_3) (@in_guaranteed private_proto_public_class) -> () { bb0(%0 : $*private_proto_public_class): %1 = load %0 : $*private_proto_public_class strong_retain %1 : $private_proto_public_class %3 = class_method %1 : $private_proto_public_class, #private_proto_public_class.theMethod : (private_proto_public_class) -> () -> (), $@convention(method) (@guaranteed private_proto_public_class) -> () %4 = apply %3(%1) : $@convention(method) (@guaranteed private_proto_public_class) -> () strong_release %1 : $private_proto_public_class return %4 : $() } sil private @call_through_private_proto_3 : $@convention(thin) (@in T) -> () { bb0(%0 : $*T): debug_value %0 : $*T, expr op_deref %2 = witness_method $T, #private_proto_3.theMethod : $@convention(witness_method: private_proto_3) <τ_0_0 where τ_0_0 : private_proto_3> (@in_guaranteed τ_0_0) -> () %3 = apply %2(%0) : $@convention(witness_method: private_proto_3) <τ_0_0 where τ_0_0 : private_proto_3> (@in_guaranteed τ_0_0) -> () destroy_addr %0 : $*T %5 = tuple () return %5 : $() } sil private @private_proto_public_class_private_method_theMethod : $@convention(method) (@guaranteed private_proto_public_class_private_method) -> () { bb0(%0 : $private_proto_public_class_private_method): debug_value %0 : $private_proto_public_class_private_method %2 = tuple () return %2 : $() } sil private [transparent] [thunk] @private_proto_4_public_class_private_method_witness : $@convention(witness_method: private_proto_4) (@in_guaranteed private_proto_public_class_private_method) -> () { bb0(%0 : $*private_proto_public_class_private_method): %1 = load %0 : $*private_proto_public_class_private_method strong_retain %1 : $private_proto_public_class_private_method %3 = class_method %1 : $private_proto_public_class_private_method, #private_proto_public_class_private_method.theMethod : (private_proto_public_class_private_method) -> () -> (), $@convention(method) (@guaranteed private_proto_public_class_private_method) -> () %4 = apply %3(%1) : $@convention(method) (@guaranteed private_proto_public_class_private_method) -> () strong_release %1 : $private_proto_public_class_private_method return %4 : $() } sil private @call_through_private_proto_4 : $@convention(thin) (@in T) -> () { bb0(%0 : $*T): debug_value %0 : $*T, expr op_deref %2 = witness_method $T, #private_proto_4.theMethod : $@convention(witness_method: private_proto_4) <τ_0_0 where τ_0_0 : private_proto_4> (@in_guaranteed τ_0_0) -> () %3 = apply %2(%0) : $@convention(witness_method: private_proto_4) <τ_0_0 where τ_0_0 : private_proto_4> (@in_guaranteed τ_0_0) -> () destroy_addr %0 : $*T %5 = tuple () return %5 : $() } sil_vtable private_proto_private_class { #private_proto_private_class.theMethod: @private_proto_private_class_theMethod } sil_vtable private_proto_internal_class { #private_proto_internal_class.theMethod: @private_proto_internal_class_theMethod } sil_vtable private_proto_public_class { #private_proto_public_class.theMethod: @private_proto_public_class_theMethod } sil_vtable private_proto_public_class_private_method { #private_proto_public_class_private_method.theMethod: @private_proto_public_class_private_method_theMethod } sil_witness_table private private_proto_private_class: private_proto_1 module witness { method #private_proto_1.theMethod: @private_proto_1_private_class_witness } sil_witness_table private private_proto_internal_class: private_proto_2 module witness { method #private_proto_2.theMethod: @private_proto_2_internal_class_witness } sil_witness_table private private_proto_public_class: private_proto_3 module witness { method #private_proto_3.theMethod: @private_proto_3_public_class_witness } sil_witness_table private private_proto_public_class_private_method: private_proto_4 module witness { method #private_proto_4.theMethod: @private_proto_4_public_class_private_method_witness } sil hidden @first_recursive : $@convention(thin) (Builtin.Int32) -> Builtin.Int32 { bb0(%0 : $Builtin.Int32): %2 = integer_literal $Builtin.Int32, 0 %4 = builtin "cmp_sgt_Int32"(%0 : $Builtin.Int32, %2 : $Builtin.Int32) : $Builtin.Int1 cond_br %4, bb1, bb2 bb1: %8 = function_ref @second_recursive : $@convention(thin) (Builtin.Int32) -> Builtin.Int32 %9 = integer_literal $Builtin.Int32, 1 %11 = integer_literal $Builtin.Int1, -1 %12 = builtin "ssub_with_overflow_Int32"(%0 : $Builtin.Int32, %9 : $Builtin.Int32, %11 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) %13 = tuple_extract %12 : $(Builtin.Int32, Builtin.Int1), 0 %14 = tuple_extract %12 : $(Builtin.Int32, Builtin.Int1), 1 cond_fail %14 : $Builtin.Int1 %17 = apply %8(%13) : $@convention(thin) (Builtin.Int32) -> Builtin.Int32 br bb3(%17 : $Builtin.Int32) bb2: %19 = integer_literal $Builtin.Int32, 27 br bb3(%19 : $Builtin.Int32) bb3(%22 : $Builtin.Int32): return %22 : $Builtin.Int32 } sil hidden @second_recursive : $@convention(thin) (Builtin.Int32) -> Builtin.Int32 { bb0(%0 : $Builtin.Int32): %2 = integer_literal $Builtin.Int32, 0 %4 = builtin "cmp_sgt_Int32"(%0 : $Builtin.Int32, %2 : $Builtin.Int32) : $Builtin.Int1 cond_br %4, bb1, bb2 bb1: %8 = function_ref @first_recursive : $@convention(thin) (Builtin.Int32) -> Builtin.Int32 %9 = integer_literal $Builtin.Int32, 3 %11 = integer_literal $Builtin.Int1, -1 %12 = builtin "ssub_with_overflow_Int32"(%0 : $Builtin.Int32, %9 : $Builtin.Int32, %11 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) %13 = tuple_extract %12 : $(Builtin.Int32, Builtin.Int1), 0 %14 = tuple_extract %12 : $(Builtin.Int32, Builtin.Int1), 1 cond_fail %14 : $Builtin.Int1 %17 = apply %8(%13) : $@convention(thin) (Builtin.Int32) -> Builtin.Int32 br bb3(%17 : $Builtin.Int32) bb2: %19 = integer_literal $Builtin.Int32, 9 br bb3(%19 : $Builtin.Int32) bb3(%22 : $Builtin.Int32): return %22 : $Builtin.Int32 }