// RUN: %target-sil-opt -sil-print-types %s -allocbox-to-stack | %FileCheck %s --check-prefix=CHECK --check-prefix=OPT // RUN: %target-sil-opt -sil-print-types %s -mandatory-allocbox-to-stack | %FileCheck %s --check-prefix=CHECK --check-prefix=MANDATORY sil_stage raw import Builtin struct Int { var _value: Builtin.Int64 } struct Bool { var _value: Builtin.Int1 } protocol Error {} // CHECK-LABEL: sil [ossa] @simple_promotion sil [ossa] @simple_promotion : $@convention(thin) (Int) -> Int { bb0(%0 : $Int): %1 = alloc_box ${ var Int } %1a = project_box %1 : ${ var Int }, 0 store %0 to [trivial] %1a : $*Int %3 = load [trivial] %1a : $*Int destroy_value %1 : ${ var Int } return %3 : $Int // CHECK: alloc_stack // CHECK-NOT: alloc_box // CHECK-NOT: destroy_value // CHECK: return } // CHECK-LABEL: sil [ossa] @double_project_box sil [ossa] @double_project_box : $@convention(thin) (Int) -> (Int, Int) { bb0(%0 : $Int): %1 = alloc_box ${ var Int } %1a = project_box %1 : ${ var Int }, 0 store %0 to [trivial] %1a : $*Int %3 = load [trivial] %1a : $*Int %1b = project_box %1 : ${ var Int }, 0 %3b = load [trivial] %1b : $*Int destroy_value %1 : ${ var Int } %r = tuple (%3 : $Int, %3b : $Int) return %r : $(Int, Int) // CHECK: alloc_stack // CHECK-NOT: alloc_box // CHECK-NOT: project_box // CHECK-NOT: destroy_value // CHECK: return } // CHECK-LABEL: sil [ossa] @init_var sil [ossa] @init_var : $@convention(thin) (Int) -> Int { bb0(%0 : $Int): %1 = alloc_box ${ var Int } %1a = project_box %1 : ${ var Int }, 0 store %0 to [trivial] %1a : $*Int %3 = load [trivial] %1a : $*Int destroy_value %1 : ${ var Int } return %3 : $Int // CHECK: %1 = alloc_stack // CHECK-NOT: alloc_box // CHECK-NOT: destroy_value // CHECK-NOT: destroy_addr // CHECK: dealloc_stack %1 : $*Int // CHECK: return } // CHECK-LABEL: sil [ossa] @multi_destroy_value sil [ossa] @multi_destroy_value : $@convention(thin) () -> Int { bb0: %1 = alloc_box ${ var Int } %1a = mark_uninitialized [rootself] %1 : ${ var Int } %2 = project_box %1a : ${ var Int }, 0 %3 = load [trivial] %2 : $*Int %x = copy_value %1a : ${ var Int } destroy_value %1a : ${ var Int } br bb1 bb1: destroy_value %x : ${ var Int } return %3 : $Int // CHECK: %0 = alloc_stack // CHECK: bb1: // CHECK: dealloc_stack %0 : $*Int // CHECK: return } struct TestStruct { var Elt : Int } // CHECK-LABEL: sil [ossa] @struct_tuple_element_addr sil [ossa] @struct_tuple_element_addr : $@convention(thin) (Int) -> Int { bb1(%0 : $Int): // CHECK-DAG: [[STRUCT:%.*]] = alloc_stack $TestStruct // CHECK-DAG: [[TUPLE:%.*]] = alloc_stack $(Int, Int) %1 = alloc_box ${ var TestStruct } %1a = project_box %1 : ${ var TestStruct }, 0 %a = alloc_box ${ var (Int, Int) } %aa = project_box %a : ${ var (Int, Int) }, 0 %2 = struct_element_addr %1a : $*TestStruct, #TestStruct.Elt store %0 to [trivial] %2 : $*Int %b = tuple_element_addr %aa : $*(Int, Int), 0 store %0 to [trivial] %b : $*Int %6 = struct_element_addr %1a : $*TestStruct, #TestStruct.Elt %7 = load [trivial] %6 : $*Int destroy_value %a : ${ var (Int, Int) } destroy_value %1 : ${ var TestStruct } return %7 : $Int // CHECK-DAG: dealloc_stack [[STRUCT]] // CHECK-DAG: dealloc_stack [[TUPLE]] // CHECK: return } sil [ossa] @callee : $@convention(thin) (@inout Int) -> () // CHECK-LABEL: sil [ossa] @escaping_pointer sil [ossa] @escaping_pointer : $@convention(thin) () -> Int { bb0: %1 = alloc_box ${ var Int } %1a = project_box %1 : ${ var Int }, 0 %6 = function_ref @callee : $@convention(thin) (@inout Int) -> () %7 = apply %6(%1a) : $@convention(thin) (@inout Int) -> () %8 = load [trivial] %1a : $*Int destroy_value %1 : ${ var Int } %10 = address_to_pointer %1a : $*Int to $Builtin.RawPointer %11 = pointer_to_address %10 : $Builtin.RawPointer to [strict] $*Int %12 = load [trivial] %11 : $*Int return %8 : $Int // CHECK: return } protocol P { } sil [ossa] @returns_protocol : $@convention(thin) () -> @out P // CHECK-LABEL: sil [ossa] @test_indirect_return sil [ossa] @test_indirect_return : $@convention(thin) () -> () { bb0: // CHECK: alloc_stack %1 = function_ref @returns_protocol : $@convention(thin) () -> @out P %2 = alloc_box ${ var P } %2a = project_box %2 : ${ var P }, 0 %3 = apply %1(%2a) : $@convention(thin) () -> @out P destroy_value %2 : ${ var P } %0 = tuple () return %0 : $() // CHECK: return } class SomeClass {} // CHECK-LABEL: sil [ossa] @class_promotion sil [ossa] @class_promotion : $@convention(thin) (@owned SomeClass) -> @owned SomeClass { bb0(%0 : @owned $SomeClass): %1 = alloc_box ${ var SomeClass } %1a = project_box %1 : ${ var SomeClass }, 0 store %0 to [init] %1a : $*SomeClass %3 = load [copy] %1a : $*SomeClass destroy_value %1 : ${ var SomeClass } return %3 : $SomeClass // CHECK: %1 = alloc_stack // CHECK-NOT: alloc_box // CHECK-NOT: destroy_value // CHECK: destroy_addr {{.*}} : $*SomeClass // CHECK: return } protocol LogicValue { func getLogicValue() -> Bool } // CHECK-LABEL: @protocols sil [ossa] @protocols : $@convention(thin) (@in LogicValue, @thin Bool.Type) -> Bool { bb0(%0 : $*LogicValue, %1 : $@thin Bool.Type): %2 = alloc_box ${ var LogicValue } %2a = project_box %2 : ${ var LogicValue }, 0 // CHECK: %2 = alloc_stack $any LogicValue copy_addr [take] %0 to [init] %2a : $*LogicValue %6 = open_existential_addr mutable_access %2a : $*LogicValue to $*@opened("01234567-89ab-cdef-0123-000000000000", LogicValue) Self %7 = witness_method $@opened("01234567-89ab-cdef-0123-000000000000", LogicValue) Self, #LogicValue.getLogicValue, %6 : $*@opened("01234567-89ab-cdef-0123-000000000000", LogicValue) Self : $@convention(witness_method: LogicValue) (@in_guaranteed T) -> Bool %8 = apply %7<@opened("01234567-89ab-cdef-0123-000000000000", LogicValue) Self>(%6) : $@convention(witness_method: LogicValue) (@in_guaranteed T) -> Bool destroy_value %2 : ${ var LogicValue } // CHECK: destroy_addr %2 : $*any LogicValue // CHECK-NEXT: dealloc_stack %2 : $*any LogicValue // CHECK-NEXT: return return %8 : $Bool } // Generics test, which is address-only. class Generic {} // CHECK-LABEL: sil [ossa] @dealloc_box_test sil [ossa] @dealloc_box_test : $@convention(thin) () -> () { bb0: // CHECK-NEXT: bb0: // CHECK-NEXT: alloc_stack %1 = alloc_box $<τ_0_0> { var Generic<τ_0_0> } dealloc_box %1 : $<τ_0_0> { var Generic<τ_0_0> } %0 = tuple () // CHECK: tuple () return %0 : $() // CHECK: return } enum SomeUnion { case x(Int) case y(SomeClass) } sil [ossa] @$s1t9SomeUnionO1yfMS0_FCS_9SomeClassS0_ : $@convention(thin) (@owned SomeClass, @thin SomeUnion.Type) -> @owned SomeUnion sil [ossa] @$s1t9SomeClassCCfMS0_FT_S0_ : $@convention(thin) (@thick SomeClass.Type) -> @owned SomeClass // CHECK-LABEL: sil [ossa] @union_test sil [ossa] @union_test : $@convention(thin) () -> () { bb0: // CHECK: [[UNION:%.*]] = alloc_stack %1 = alloc_box ${ var SomeUnion } %1a = project_box %1 : ${ var SomeUnion }, 0 %2 = function_ref @$s1t9SomeUnionO1yfMS0_FCS_9SomeClassS0_ : $@convention(thin) (@owned SomeClass, @thin SomeUnion.Type) -> @owned SomeUnion // user: %7 %3 = metatype $@thin SomeUnion.Type %4 = function_ref @$s1t9SomeClassCCfMS0_FT_S0_ : $@convention(thin) (@thick SomeClass.Type) -> @owned SomeClass // user: %6 %5 = metatype $@thick SomeClass.Type %6 = apply %4(%5) : $@convention(thin) (@thick SomeClass.Type) -> @owned SomeClass %7 = apply %2(%6, %3) : $@convention(thin) (@owned SomeClass, @thin SomeUnion.Type) -> @owned SomeUnion store %7 to [init] %1a : $*SomeUnion destroy_value %1 : ${ var SomeUnion } %10 = tuple () return %10 : $() // CHECK: dealloc_stack [[UNION]] // CHECK: [[T0:%.*]] = tuple () // CHECK-NEXT: return [[T0]] : $() } // CHECK-LABEL: sil [ossa] @multiple_destroy_test sil [ossa] @multiple_destroy_test : $@convention(thin) (Bool) -> Bool { bb0(%0 : $Bool): %1 = alloc_box ${ var Bool } %1a = project_box %1 : ${ var Bool }, 0 store %0 to [trivial] %1a : $*Bool %2 = copy_value %1 : ${ var Bool } %3 = copy_value %1 : ${ var Bool } %5 = tuple () %6 = load [trivial] %1a : $*Bool destroy_value %3 : ${ var Bool } destroy_value %2 : ${ var Bool } destroy_value %1 : ${ var Bool } return %6 : $Bool // CHECK: alloc_stack $Bool // CHECK-NEXT: store // CHECK-NEXT: tuple () // CHECK-NEXT: load // CHECK-NEXT: dealloc_stack // CHECK-NEXT: return } // Make sure that we can promote this box and dealloc_stack // on each path. // // CHECK-LABEL: sil [ossa] @box_reachable_from_destroy_test sil [ossa] @box_reachable_from_destroy_test : $@convention(thin) () -> () { bb0: br bb1 // CHECK: bb1: // CHECK-NEXT: alloc_stack bb1: %1 = alloc_box ${ var Bool } cond_br undef, bb2, bb3 // CHECK: bb2: // CHECK-NEXT: dealloc_stack bb2: destroy_value %1 : ${ var Bool } br bb1 // CHECK: bb3: // CHECK-NEXT: dealloc_stack bb3: destroy_value %1 : ${ var Bool } %2 = tuple () // CHECK: return return %2 : $() } sil [ossa] @useSomeClass : $@convention(thin) (@owned SomeClass) -> () // DI misses destroy_addr because allocbox_to_stack isn't preserving mark_uninitialized invariants // When allocbox_to_stack promotes the box, it should rewrite the multiple // destroy_values into destroy_addr/dealloc_stack pairs. However, it needs to // make sure to use the MUI result for the destroy addr. public protocol My_Incrementable { } extension Int : My_Incrementable { } // CHECK-LABEL: sil [ossa] @test_mui sil [ossa] @test_mui : $@convention(thin) (Builtin.Int1) -> () { bb0(%0 : $Builtin.Int1): %2 = alloc_box ${ var SomeClass } %2a = mark_uninitialized [var] %2 : ${ var SomeClass } %3 = project_box %2a : ${ var SomeClass }, 0 // CHECK: [[STACK:%[0-9]+]] = alloc_stack // CHECK: [[MUI:%[0-9]+]] = mark_uninitialized cond_br %0, bb1, bb3 bb1: %7 = function_ref @$s1t9SomeClassCCfMS0_FT_S0_ : $@convention(thin) (@thick SomeClass.Type) -> @owned SomeClass // user: %6 %8 = metatype $@thick SomeClass.Type %9 = apply %7(%8) : $@convention(thin) (@thick SomeClass.Type) -> @owned SomeClass assign %9 to %3 : $*SomeClass %11 = function_ref @useSomeClass : $@convention(thin) (@owned SomeClass) -> () %12 = load [copy] %3 : $*SomeClass %14 = apply %11(%12) : $@convention(thin) (@owned SomeClass) -> () destroy_value %2a : ${ var SomeClass } // CHECK: destroy_addr [[MUI]] // CHECK-NEXT: dealloc_stack [[STACK]] br bb2 // CHECK: bb2 bb2: %17 = tuple () // CHECK: return return %17 : $() bb3: destroy_value %2a : ${ var SomeClass } // CHECK: destroy_addr [[MUI]] // CHECK-NEXT: dealloc_stack [[STACK]] br bb2 } // CHECK-LABEL: sil [ossa] @$s6struct5apply1fS2iyc_tF // struct.apply (f : () -> Swift.Int) -> Swift.Int sil [ossa] @$s6struct5apply1fS2iyc_tF : $@convention(thin) (@owned @callee_owned () -> Int) -> Int { bb0(%0 : @owned $@callee_owned () -> Int): debug_value %0 : $@callee_owned () -> Int, let, name "f" // id: %1 %1 = copy_value %0 : $@callee_owned () -> Int // id: %2 %3 = apply %1() : $@callee_owned () -> Int // user: %5 destroy_value %0 : $@callee_owned () -> Int // id: %4 return %3 : $Int // id: %5 } // CHECK-LABEL: sil [ossa] @$s6struct6escape1fSiycSiyc_tF // struct.escape (f : () -> Swift.Int) -> () -> Swift.Int sil [ossa] @$s6struct6escape1fSiycSiyc_tF : $@convention(thin) (@owned @callee_owned () -> Int) -> @owned @callee_owned () -> Int { bb0(%0 : @owned $@callee_owned () -> Int): debug_value %0 : $@callee_owned () -> Int, let, name "f" // id: %1 return %0 : $@callee_owned () -> Int // id: %2 } // CHECK-LABEL: sil [ossa] @$s6struct8useStack1tySi_tF // struct.useStack (t : Swift.Int) -> () sil [ossa] @$s6struct8useStack1tySi_tF : $@convention(thin) (Int) -> () { bb0(%0 : $Int): debug_value %0 : $Int, let, name "t" // id: %1 // CHECK: alloc_stack %2 = alloc_box $<τ_0_0> { var τ_0_0 } , var, name "s" // users: %3, %6, %7, %7, %9 %2a = project_box %2 : $<τ_0_0> { var τ_0_0 } , 0 store %0 to [trivial] %2a : $*Int // id: %3 // function_ref struct.apply (f : () -> Swift.Int) -> Swift.Int %4 = function_ref @$s6struct5apply1fS2iyc_tF : $@convention(thin) (@owned @callee_owned () -> Int) -> Int // user: %8 // CHECK: [[FUNC:%[a-zA-Z0-9]+]] = function_ref @$s6struct8useStack1tySi_tFSiycfU_Tf0s_n // function_ref struct.(useStack (t : Swift.Int) -> ()).(closure #1) %5 = function_ref @$s6struct8useStack1tySi_tFSiycfU_ : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } ) -> Int // user: %7 %6 = copy_value %2 : $<τ_0_0> { var τ_0_0 } // id: %6 // CHECK: [[PA:%[a-zA-Z0-9]+]] = partial_apply [[FUNC]] %7 = partial_apply %5(%6) : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } ) -> Int // user: %8 %8 = apply %4(%7) : $@convention(thin) (@owned @callee_owned () -> Int) -> Int destroy_value %2 : $<τ_0_0> { var τ_0_0 } %10 = tuple () // user: %11 return %10 : $() // id: %11 } // CHECK-LABEL: sil private [transparent] [ossa] @$s6struct8useStack1tySi_tFSiycfU_Tf0s_n // OPT-LABEL: sil private [transparent] [ossa] @$s6struct8useStack1tySi_tFSiycfU_ : // MANDATORY-NOT: sil private [transparent] [ossa] @$s6struct8useStack1tySi_tFSiycfU_ : sil private [transparent] [ossa] @$s6struct8useStack1tySi_tFSiycfU_ : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } ) -> Int { bb0(%0 : @owned $<τ_0_0> { var τ_0_0 } ): %1 = project_box %0 : $<τ_0_0> { var τ_0_0 } , 0 // function_ref Swift.++ @postfix (x : @inout A) -> A %2 = function_ref @_TFsoP2ppUs14_Incrementable__FT1xRQ__Q_ : $@convention(thin) <τ_0_0 where τ_0_0 : My_Incrementable> (@inout τ_0_0) -> @out τ_0_0 // user: %4 %3 = alloc_stack $Int // users: %4, %5, %6 %4 = apply %2(%3, %1) : $@convention(thin) <τ_0_0 where τ_0_0 : My_Incrementable> (@inout τ_0_0) -> @out τ_0_0 %5 = load [trivial] %3 : $*Int // user: %8 dealloc_stack %3 : $*Int // id: %6 destroy_value %0 : $<τ_0_0> { var τ_0_0 } // id: %7 return %5 : $Int // id: %8 } // Swift.++ @postfix (x : @inout A) -> A sil [transparent] @_TFsoP2ppUs14_Incrementable__FT1xRQ__Q_ : $@convention(thin) <τ_0_0 where τ_0_0 : My_Incrementable> (@inout τ_0_0) -> @out τ_0_0 // CHECK-LABEL: sil [ossa] @$s6struct6useBox1tySi_tF // struct.useBox (t : Swift.Int) -> () sil [ossa] @$s6struct6useBox1tySi_tF : $@convention(thin) (Int) -> () { bb0(%0 : $Int): debug_value %0 : $Int, let, name "t" // id: %1 // CHECK: alloc_box %2 = alloc_box $<τ_0_0> { var τ_0_0 } , var, name "s" // users: %3, %6, %7, %7, %10 %2a = project_box %2 : $<τ_0_0> { var τ_0_0 } , 0 store %0 to [trivial] %2a : $*Int // id: %3 // function_ref struct.escape (f : () -> Swift.Int) -> () -> Swift.Int %4 = function_ref @$s6struct6escape1fSiycSiyc_tF : $@convention(thin) (@owned @callee_owned () -> Int) -> @owned @callee_owned () -> Int // user: %8 // function_ref struct.(useBox (t : Swift.Int) -> ()).(closure #1) %5 = function_ref @$s6struct6useBox1tySi_tFSiycfU_ : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } ) -> Int // user: %7 %6 = copy_value %2 : $<τ_0_0> { var τ_0_0 } // id: %6 %7 = partial_apply %5(%6) : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } ) -> Int // user: %8 %8 = apply %4(%7) : $@convention(thin) (@owned @callee_owned () -> Int) -> @owned @callee_owned () -> Int // user: %9 %9 = apply %8() : $@callee_owned () -> Int destroy_value %2 : $<τ_0_0> { var τ_0_0 } // id: %10 %11 = tuple () // user: %12 return %11 : $() // id: %12 } // CHECK-LABEL: sil private [ossa] @$s6struct6useBox1tySi_tFSiycfU_ // struct.(useBox (t : Swift.Int) -> ()).(closure #1) sil private [ossa] @$s6struct6useBox1tySi_tFSiycfU_ : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } ) -> Int { bb0(%0 : @owned $<τ_0_0> { var τ_0_0 } ): %1 = project_box %0 : $<τ_0_0> { var τ_0_0 } , 0 // function_ref Swift.++ @postfix (x : @inout A) -> A %2 = function_ref @_TFsoP2ppUs14_Incrementable__FT1xRQ__Q_ : $@convention(thin) <τ_0_0 where τ_0_0 : My_Incrementable> (@inout τ_0_0) -> @out τ_0_0 // user: %4 %3 = alloc_stack $Int // users: %4, %5, %6 %4 = apply %2(%3, %1) : $@convention(thin) <τ_0_0 where τ_0_0 : My_Incrementable> (@inout τ_0_0) -> @out τ_0_0 %5 = load [trivial] %3 : $*Int // user: %8 dealloc_stack %3 : $*Int // id: %6 destroy_value %0 : $<τ_0_0> { var τ_0_0 } // id: %7 return %5 : $Int // id: %8 } // CHECK-LABEL: sil @closure sil @closure : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } ) -> () // CHECK-LABEL: sil [ossa] @no_final_destroy sil [ossa] @no_final_destroy : $@convention(thin) (Int) -> Bool { bb0(%0 : $Int): // This is not destroyed, but the unreachable makes the verifier not trip. %1 = alloc_box $<τ_0_0> { var τ_0_0 } %1a = project_box %1 : $<τ_0_0> { var τ_0_0 } , 0 store %0 to [trivial] %1a : $*Int // function_ref main.(newFoo (Swift.Int) -> Swift.Bool).(modify #1) (())() %3 = function_ref @closure : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } ) -> () %4 = copy_value %1 : $<τ_0_0> { var τ_0_0 } %5 = partial_apply %3(%4) : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } ) -> () %6 = copy_value %5 : $@callee_owned () -> () apply %6() : $@callee_owned () -> () destroy_value %5 : $@callee_owned () -> () unreachable } // CHECK-LABEL: sil [ossa] @test_copy_and_borrow_of_closure // CHECK-NOT: alloc_box // CHECK: alloc_stack // CHECK-NOT: alloc_box // CHECK: } // end sil function 'test_copy_and_borrow_of_closure' sil [ossa] @test_copy_and_borrow_of_closure : $@convention(thin) (Int) -> () { bb0(%0 : $Int): // This is not destroyed, but the unreachable makes the verifier not trip. %1 = alloc_box $<τ_0_0> { var τ_0_0 } %1a = project_box %1 : $<τ_0_0> { var τ_0_0 } , 0 store %0 to [trivial] %1a : $*Int %3 = function_ref @closure3 : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } ) -> () %4 = copy_value %1 : $<τ_0_0> { var τ_0_0 } %5 = partial_apply %3(%4) : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } ) -> () %6 = begin_borrow %5 : $@callee_owned () -> () %7 = copy_value %6 : $@callee_owned () -> () apply %7() : $@callee_owned () -> () end_borrow %6 : $@callee_owned () -> () destroy_value %5 : $@callee_owned () -> () destroy_value %1 : $<τ_0_0> { var τ_0_0 } %r = tuple () return %r : $() } sil [ossa] @closure3 : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } ) -> () { bb0(%0 : @owned $<τ_0_0> { var τ_0_0 } ): %1 = project_box %0 : $<τ_0_0> { var τ_0_0 } , 0 destroy_value %0 : $<τ_0_0> { var τ_0_0 } // id: %7 %r = tuple () return %r : $() } sil [ossa] @closureWithBoxArg : $@convention(thin) (@guaranteed { var SomeClass }) -> () { bb0(%0 : @guaranteed ${ var SomeClass }): %r = tuple () return %r : $() } sil [ossa] @useClosure : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () { bb0(%0 : @guaranteed $@callee_guaranteed () -> ()): %r = tuple () return %r : $() } // CHECK-LABEL: sil [ossa] @finalReleaseWithBorrow // CHECK: [[S:%[0-9]+]] = alloc_stack {{.*}}$SomeClass // CHECK-NOT: destroy_addr // CHECK: [[F:%[0-9]+]] = function_ref @useClosure // CHECK: apply [[F]] // CHECK: destroy_addr [[S]] // CHECK: } // end sil function 'finalReleaseWithBorrow' sil [ossa] @finalReleaseWithBorrow : $@convention(thin) (@owned SomeClass) -> () { bb0(%0 : @owned $SomeClass): %1 = alloc_box $ { var SomeClass } %2 = begin_borrow %1 : ${ var SomeClass } %1a = project_box %2 : ${ var SomeClass }, 0 store %0 to [init] %1a : $*SomeClass %3 = function_ref @closureWithBoxArg : $@convention(thin) (@guaranteed { var SomeClass }) -> () %4 = copy_value %2 : ${ var SomeClass } %5 = partial_apply [callee_guaranteed] %3(%4) : $@convention(thin) (@guaranteed { var SomeClass }) -> () end_borrow %2 : ${ var SomeClass } destroy_value %1 : ${ var SomeClass } %6 = function_ref @useClosure : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () apply %6(%5) : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () destroy_value %5 : $@callee_guaranteed () -> () %10 = tuple () return %10 : $() } // CHECK-LABEL: sil [transparent] [serialized] [ossa] @mightApply : $@convention(thin) (@owned @callee_owned () -> @out U) -> () sil [transparent] [serialized] [ossa] @mightApply : $@convention(thin) (@owned @callee_owned () -> @out U) -> () { // CHECK: bb0 bb0(%0 : @owned $@callee_owned () -> @out U): debug_value %0 : $@callee_owned () -> @out U %1 = copy_value %0 : $@callee_owned () -> @out U %3 = alloc_stack $U %4 = apply %1(%3) : $@callee_owned () -> @out U destroy_addr %3 : $*U dealloc_stack %3 : $*U destroy_value %0 : $@callee_owned () -> @out U %8 = tuple () // CHECK: return return %8 : $() } sil [transparent] [serialized] [ossa] @mightApplyGuaranteed : $@convention(thin) (@guaranteed @callee_guaranteed () -> @out U) -> () { // CHECK: bb0 bb0(%0 : @guaranteed $@callee_guaranteed () -> @out U): debug_value %0 : $@callee_guaranteed () -> @out U %3 = alloc_stack $U %4 = apply %0(%3) : $@callee_guaranteed () -> @out U destroy_addr %3 : $*U dealloc_stack %3 : $*U %8 = tuple () // CHECK: return return %8 : $() } // CHECK-LABEL: sil [ossa] @callWithAutoclosure sil [ossa] @callWithAutoclosure : $@convention(thin) (@in T) -> () { // CHECK: bb0 bb0(%0 : $*T): // CHECK: debug_value {{.*}} expr op_deref debug_value %0 : $*T, expr op_deref // CHECK: function_ref @mightApply %2 = function_ref @mightApply : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned @callee_owned () -> @out τ_0_0) -> () %3 = function_ref @closure_to_specialize : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0 // CHECK-NOT: alloc_box // CHECK: [[STACK:%[0-9a-zA-Z_]+]] = alloc_stack $T %4 = alloc_box $<τ_0_0> { var τ_0_0 } %4a = project_box %4 : $<τ_0_0> { var τ_0_0 } , 0 // CHECK: copy_addr %0 to [init] [[STACK]] : $*T copy_addr %0 to [init] %4a : $*T // CHECK: [[CLOSURE:%[0-9a-zA-Z]+]] = function_ref @$s21closure_to_specializeTf0ns_n // CHECK: partial_apply [[CLOSURE]]([[STACK]]) %6 = partial_apply %3(%4) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0 %7 = apply %2(%6) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned @callee_owned () -> @out τ_0_0) -> () // CHECK: destroy_addr [[STACK]] : $*T // CHECK: dealloc_stack [[STACK]] : $*T destroy_addr %0 : $*T %9 = tuple () // CHECK: return return %9 : $() } // CHECK-LABEL: sil [ossa] @callWithAutoclosure_2 : $@convention(thin) (@in T) -> () { sil [ossa] @callWithAutoclosure_2 : $@convention(thin) (@in T) -> () { // CHECK: bb0 bb0(%0 : $*T): // CHECK: debug_value {{.*}} expr op_deref debug_value %0 : $*T, expr op_deref // CHECK: function_ref @mightApply %2 = function_ref @mightApply : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned @callee_owned () -> @out τ_0_0) -> () %3 = function_ref @closure_to_specialize : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0 // CHECK-NOT: alloc_box // CHECK: [[STACK:%[0-9a-zA-Z_]+]] = alloc_stack $T %4 = alloc_box $<τ_0_0> { var τ_0_0 } %4a = project_box %4 : $<τ_0_0> { var τ_0_0 } , 0 %4copy = copy_value %4 : $<τ_0_0> { var τ_0_0 } // CHECK: copy_addr %0 to [init] [[STACK]] : $*T copy_addr %0 to [init] %4a : $*T // CHECK: [[CLOSURE:%[0-9a-zA-Z]+]] = function_ref @$s21closure_to_specializeTf0ns_n // CHECK: partial_apply [[CLOSURE]]([[STACK]]) %6 = partial_apply %3(%4copy) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0 %7 = apply %2(%6) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned @callee_owned () -> @out τ_0_0) -> () // CHECK: destroy_addr [[STACK]] : $*T // CHECK: dealloc_stack [[STACK]] : $*T destroy_addr %0 : $*T destroy_value %4 : $<τ_0_0> { var τ_0_0 } %9 = tuple () // CHECK: return return %9 : $() } // CHECK: } // end sil function 'callWithAutoclosure_2' // CHECK-LABEL: sil [ossa] @callWithAutoclosure_3 : $@convention(thin) (@in T) -> () { sil [ossa] @callWithAutoclosure_3 : $@convention(thin) (@in T) -> () { // CHECK: bb0 bb0(%0 : $*T): // CHECK: debug_value {{.*}} expr op_deref debug_value %0 : $*T, expr op_deref // CHECK: function_ref @mightApply %2 = function_ref @mightApply : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned @callee_owned () -> @out τ_0_0) -> () %3 = function_ref @closure_to_specialize : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0 // CHECK-NOT: alloc_box // CHECK: [[STACK_UNMARKED:%[0-9a-zA-Z_]+]] = alloc_stack $T // CHECK: [[STACK:%.*]] = mark_uninitialized [var] [[STACK_UNMARKED]] %4 = alloc_box $<τ_0_0> { var τ_0_0 } %4c = mark_uninitialized [var] %4 : $<τ_0_0> { var τ_0_0 } %4a = project_box %4c : $<τ_0_0> { var τ_0_0 } , 0 %4copy = copy_value %4c : $<τ_0_0> { var τ_0_0 } // CHECK: copy_addr %0 to [init] [[STACK]] : $*T copy_addr %0 to [init] %4a : $*T // CHECK: [[CLOSURE:%[0-9a-zA-Z]+]] = function_ref @$s21closure_to_specializeTf0ns_n // CHECK: partial_apply [[CLOSURE]]([[STACK]]) %6 = partial_apply %3(%4copy) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0 %7 = apply %2(%6) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned @callee_owned () -> @out τ_0_0) -> () // CHECK: destroy_addr [[STACK]] : $*T // CHECK: dealloc_stack [[STACK_UNMARKED]] : $*T destroy_addr %0 : $*T destroy_value %4c : $<τ_0_0> { var τ_0_0 } %9 = tuple () // CHECK: return return %9 : $() } // CHECK: } // end sil function 'callWithAutoclosure_3' // CHECK-LABEL: sil shared [ossa] @$s21closure_to_specializeTf0ns_n : $@convention(thin) (@inout_aliasable T) -> @out T sil shared [ossa] @closure_to_specialize : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } ) -> @out T { // CHECK: bb0 bb0(%0 : $*T, %1 : @owned $<τ_0_0> { var τ_0_0 } ): %2 = project_box %1 : $<τ_0_0> { var τ_0_0 } , 0 // CHECK-NEXT: copy_addr copy_addr %2 to [init] %0 : $*T // CHECK-NOT: destroy_value destroy_value %1 : $<τ_0_0> { var τ_0_0 } %5 = tuple () // CHECK: return return %5 : $() } protocol Count { var count: Int { get } } struct Q : Count { var count: Int { get } init() } struct S { @_hasStorage var t: T var count: Int { get } func test(i: Int) -> Bool init(t: T) } // CHECK-LABEL: sil [noinline] [ossa] @inner sil [noinline] [ossa] @inner : $@convention(thin) (@owned @callee_owned () -> Bool) -> Bool { // CHECK: bb0 bb0(%0 : @owned $@callee_owned () -> Bool): debug_value %0 : $@callee_owned () -> Bool %1 = copy_value %0 : $@callee_owned () -> Bool %3 = apply %1() : $@callee_owned () -> Bool destroy_value %0 : $@callee_owned () -> Bool // CHECK: return return %3 : $Bool } // CHECK-LABEL: sil [noinline] [ossa] @outer sil [noinline] [ossa] @outer : $@convention(thin) (@owned @callee_owned () -> Bool) -> Bool { // CHECK: bb0 bb0(%0 : @owned $@callee_owned () -> Bool): debug_value %0 : $@callee_owned () -> Bool %1 = copy_value %0 : $@callee_owned () -> Bool %3 = apply %1() : $@callee_owned () -> Bool destroy_value %0 : $@callee_owned () -> Bool // CHECK: return return %3 : $Bool } // CHECK-LABEL: sil @get sil @get : $@convention(method) (@in S) -> Int // CHECK-LABEL: sil shared [ossa] @specialized sil shared [ossa] @specialized : $@convention(method) (Int, @in S) -> Bool { // CHECK: bb0 bb0(%0 : $Int, %1 : $*S): debug_value %0 : $Int debug_value %1 : $*S, expr op_deref %4 = function_ref @outer : $@convention(thin) (@owned @callee_owned () -> Bool) -> Bool %5 = function_ref @closure1 : $@convention(thin) (Int, @owned <τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } ) -> Bool %6 = alloc_box $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } %6a = project_box %6 : $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } , 0 copy_addr %1 to [init] %6a : $*S %8 = partial_apply %5(%0, %6) : $@convention(thin) <τ_0_0 where τ_0_0 : Count> (Int, @owned <τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } <τ_0_0>) -> Bool %9 = apply %4(%8) : $@convention(thin) (@owned @callee_owned () -> Bool) -> Bool destroy_addr %1 : $*S // CHECK: return return %9 : $Bool } // CHECK-LABEL: sil [ossa] @unspecialized sil [ossa] @unspecialized : $@convention(method) (Int, @in S) -> Bool { // CHECK: bb0 bb0(%0 : $Int, %1 : $*S): debug_value %0 : $Int debug_value %1 : $*S, expr op_deref %4 = function_ref @outer : $@convention(thin) (@owned @callee_owned () -> Bool) -> Bool %5 = function_ref @closure1 : $@convention(thin) <τ_0_0 where τ_0_0 : Count> (Int, @owned <τ_0_0 : Count> { var S<τ_0_0> } <τ_0_0>) -> Bool %6 = alloc_box $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } %6a = project_box %6 : $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } , 0 copy_addr %1 to [init] %6a : $*S %8 = partial_apply %5(%0, %6) : $@convention(thin) <τ_0_0 where τ_0_0 : Count> (Int, @owned <τ_0_0 : Count> { var S<τ_0_0> } <τ_0_0>) -> Bool %9 = apply %4(%8) : $@convention(thin) (@owned @callee_owned () -> Bool) -> Bool destroy_addr %1 : $*S // CHECK: return return %9 : $Bool } // OPT-LABEL: sil shared [ossa] @closure1 : // MANDATORY-NOT: sil shared [ossa] @closure1 : sil shared [ossa] @closure1 : $@convention(thin) (Int, @owned <τ_0_0 : Count> { var S<τ_0_0> } ) -> Bool { // CHECK: bb0 bb0(%0 : $Int, %1 : @owned $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } ): %2 = project_box %1 : $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } , 0 %3 = function_ref @inner : $@convention(thin) (@owned @callee_owned () -> Bool) -> Bool %4 = function_ref @closure2 : $@convention(thin) <τ_0_0 where τ_0_0 : Count> (Int, @owned <τ_0_0 : Count> { var S<τ_0_0> } <τ_0_0>) -> Bool %5 = alloc_box $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } %5a = project_box %5 : $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } , 0 copy_addr %2 to [init] %5a : $*S %7 = partial_apply %4(%0, %5) : $@convention(thin) <τ_0_0 where τ_0_0 : Count> (Int, @owned <τ_0_0 : Count> { var S<τ_0_0> } <τ_0_0>) -> Bool %8 = apply %3(%7) : $@convention(thin) (@owned @callee_owned () -> Bool) -> Bool destroy_value %1 : $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } // CHECK: return return %8 : $Bool } // CHECK-LABEL: sil shared [ossa] @$s8closure2Tf0ns_n // CHECK: bb0 // CHECK: return // CHECK-NOT: bb1 // OPT-LABEL: sil shared [ossa] @closure2 : // MANDATORY-NOT: sil shared [ossa] @closure2 : sil shared [ossa] @closure2 : $@convention(thin) (Int, @owned <τ_0_0 : Count> { var S<τ_0_0> } ) -> Bool { bb0(%0 : $Int, %1 : @owned $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } ): %2 = project_box %1 : $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } , 0 %3 = function_ref @binary : $@convention(thin) (Int, Int) -> Bool %4 = alloc_stack $S copy_addr %2 to [init] %4 : $*S %6 = function_ref @get : $@convention(method) <τ_0_0 where τ_0_0 : Count> (@in S<τ_0_0>) -> Int %7 = apply %6(%4) : $@convention(method) <τ_0_0 where τ_0_0 : Count> (@in S<τ_0_0>) -> Int %8 = apply %3(%0, %7) : $@convention(thin) (Int, Int) -> Bool %9 = copy_value %1 : $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } %10 = project_box %9 : $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } , 0 copy_addr %10 to [init] %4 : $*S destroy_value %9 : $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } destroy_addr %4 : $*S dealloc_stack %4 : $*S destroy_value %1 : $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } return %8 : $Bool } // CHECK-LABEL: sil [transparent] [serialized] @binary sil [transparent] [serialized] @binary : $@convention(thin) (Int, Int) -> Bool // CHECK-LABEL: sil [ossa] @destroy_stack_value_after_closure sil [ossa] @destroy_stack_value_after_closure : $@convention(thin) (@in T) -> @out T { // CHECK: bb0 bb0(%0 : $*T, %1 : $*T): // CHECK: [[STACK:%.*]] = alloc_stack // CHECK: copy_addr %1 to [init] [[STACK]] // CHECK: [[APPLIED:%.*]] = function_ref %3 = function_ref @applied : $@convention(thin) <τ_0_0> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> () %4 = alloc_box $<τ_0_0> { var τ_0_0 } %4a = project_box %4 : $<τ_0_0> { var τ_0_0 } , 0 copy_addr %1 to [init] %4a : $*T // CHECK: [[PARTIAL:%.*]] = partial_apply [[APPLIED]]([[STACK]]) %6 = partial_apply %3(%4) : $@convention(thin) <τ_0_0> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> () // CHECK: debug_value [[PARTIAL]] debug_value %6 : $@callee_owned () -> () // CHECK: [[COPIED_PARTIAL:%.*]] = copy_value [[PARTIAL]] %7 = copy_value %6 : $@callee_owned () -> () // CHECK: apply [[COPIED_PARTIAL]]() : $@callee_owned () -> () %9 = apply %7() : $@callee_owned () -> () copy_addr %1 to [init] %0 : $*T // CHECK: destroy_value [[PARTIAL]] destroy_value %6 : $@callee_owned () -> () // CHECK: destroy_addr [[STACK]] // CHECK: destroy_addr %1 destroy_addr %1 : $*T %13 = tuple () return %13 : $() } sil [ossa] @applied : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } ) -> () { bb0(%0 : @owned $<τ_0_0> { var τ_0_0 } ): %1 = project_box %0 : $<τ_0_0> { var τ_0_0 } , 0 %2 = function_ref @consume : $@convention(thin) <τ_0_0> (@in τ_0_0) -> () %3 = alloc_stack $T copy_addr %1 to [init] %3 : $*T %5 = apply %2(%3) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> () dealloc_stack %3 : $*T destroy_value %0 : $<τ_0_0> { var τ_0_0 } %8 = tuple () return %8 : $() } sil hidden [noinline] @consume : $@convention(thin) (@in T) -> () { bb0(%0 : $*T): debug_value %0 : $*T, expr op_deref destroy_addr %0 : $*T %3 = tuple () return %3 : $() } class ThrowBaseClass { required init() throws init(noFail: ()) } class ThrowDerivedClass : ThrowBaseClass { //final init(failBeforeFullInitialization: Int) throws } sil [ossa] @throwing_unwrap : $@convention(thin) (Int) -> (Int, @error any Error) sil [ossa] @fake_throwing_init : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error) sil hidden [ossa] @try_apply_during_chaining_init : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error) { // %0 // users: %11, %5 // %1 // user: %7 bb0(%0 : $Int, %1 : @owned $ThrowDerivedClass): %2 = alloc_box ${ var ThrowDerivedClass }, let, name "self" %3 = mark_uninitialized [delegatingself] %2 : ${ var ThrowDerivedClass } %4 = project_box %3 : ${ var ThrowDerivedClass }, 0 store %1 to [init] %4 : $*ThrowDerivedClass %8 = load [take] %4 : $*ThrowDerivedClass %9 = function_ref @fake_throwing_init : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error) %10 = function_ref @throwing_unwrap : $@convention(thin) (Int) -> (Int, @error any Error) try_apply %10(%0) : $@convention(thin) (Int) -> (Int, @error any Error), normal bb1, error bb3 // %12 // user: %13 bb1(%12 : $Int): // Preds: bb0 try_apply %9(%12, %8) : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error), normal bb2, error bb4 // %14 // user: %15 bb2(%14 : @owned $ThrowDerivedClass): // Preds: bb1 store %14 to [init] %4 : $*ThrowDerivedClass %16 = load [copy] %4 : $*ThrowDerivedClass destroy_value %3 : ${ var ThrowDerivedClass } return %16 : $ThrowDerivedClass // %20 // user: %22 bb3(%20 : @owned $Error): // Preds: bb0 destroy_value %8 : $ThrowDerivedClass br bb5(%20 : $Error) // %23 // user: %24 bb4(%23 : @owned $Error): // Preds: bb1 br bb5(%23 : $Error) // %25 // user: %27 bb5(%25 : @owned $Error): // Preds: bb4 bb3 destroy_value %3 : ${ var ThrowDerivedClass } throw %25 : $Error } // CHECK-LABEL: sil [ossa] @deal_with_wrong_nesting // CHECK: bb0(%0 : $Int): // CHECK-NEXT: [[STACK1:%[0-9]+]] = alloc_stack $Bool // CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int // CHECK: bb1: // CHECK-NEXT: dealloc_stack [[BOX]] // CHECK-NEXT: dealloc_stack [[STACK1]] // CHECK: bb2: // CHECK: store // CHECK: [[STACK2:%[0-9]+]] = alloc_stack $Bool // CHECK-NEXT: dealloc_stack [[STACK2]] // CHECK-NEXT: dealloc_stack [[BOX]] // CHECK-NEXT: dealloc_stack [[STACK1]] // CHECK: bb3: // CHECK-NEXT: tuple // CHECK-NEXT: return sil [ossa] @deal_with_wrong_nesting : $@convention(thin) (Int) -> () { bb0(%0 : $Int): %as1 = alloc_stack $Bool %1 = alloc_box ${ var Int } cond_br undef, bb1, bb2 bb1: destroy_value %1 : ${ var Int } dealloc_stack %as1 : $*Bool br bb3 bb2: %1a = project_box %1 : ${ var Int }, 0 store %0 to [trivial] %1a : $*Int dealloc_stack %as1 : $*Bool %3 = load [trivial] %1a : $*Int %as2 = alloc_stack $Bool destroy_value %1 : ${ var Int } dealloc_stack %as2 : $*Bool br bb3 bb3: %r = tuple () return %r : $() } // CHECK-LABEL: sil [ossa] @wrong_nesting_with_alloc_ref // CHECK: bb0(%0 : $Int): // CHECK-NEXT: [[REF:%[0-9]+]] = alloc_ref [stack] $SomeClass // CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int // CHECK: store // CHECK: dealloc_stack [[BOX]] // CHECK-NEXT: dealloc_stack_ref [[REF]] // CHECK-NEXT: tuple // CHECK-NEXT: return sil [ossa] @wrong_nesting_with_alloc_ref : $@convention(thin) (Int) -> () { bb0(%0 : $Int): %as1 = alloc_ref [stack] $SomeClass %1 = alloc_box ${ var Int } %1a = project_box %1 : ${ var Int }, 0 store %0 to [trivial] %1a : $*Int dealloc_ref %as1 : $SomeClass dealloc_stack_ref %as1 : $SomeClass %3 = load [trivial] %1a : $*Int destroy_value %1 : ${ var Int } %r = tuple () return %r : $() } // CHECK-LABEL: sil [ossa] @nesting_and_unreachable1 // CHECK: bb0(%0 : $Int): // CHECK-NEXT: [[STACK1:%[0-9]+]] = alloc_stack $Bool // CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int // CHECK: bb1: // CHECK-NEXT: [[STACK2:%[0-9]+]] = alloc_stack $Bool // CHECK-NEXT: dealloc_stack [[STACK2]] // CHECK-NEXT: unreachable // CHECK: bb2: // CHECK: store // CHECK: dealloc_stack [[BOX]] // CHECK-NEXT: dealloc_stack [[STACK1]] // CHECK-NEXT: tuple // CHECK-NEXT: return sil [ossa] @nesting_and_unreachable1 : $@convention(thin) (Int) -> () { bb0(%0 : $Int): %as1 = alloc_stack $Bool %1 = alloc_box ${ var Int } %1a = project_box %1 : ${ var Int }, 0 cond_br undef, bb1, bb2 bb1: %as2 = alloc_stack $Bool dealloc_stack %as2 : $*Bool unreachable bb2: store %0 to [trivial] %1a : $*Int dealloc_stack %as1 : $*Bool %3 = load [trivial] %1a : $*Int destroy_value %1 : ${ var Int } %r = tuple () return %r : $() } // CHECK-LABEL: sil [ossa] @nesting_and_unreachable2 // CHECK: bb0(%0 : $Int): // CHECK-NEXT: [[STACK1:%[0-9]+]] = alloc_stack $Bool // CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int // CHECK: bb1: // CHECK-NEXT: [[STACK2:%[0-9]+]] = alloc_stack $Bool // CHECK-NEXT: dealloc_stack [[STACK2]] // CHECK-NEXT: dealloc_stack [[BOX]] // CHECK-NEXT: unreachable // CHECK: bb2: // CHECK: store // CHECK: dealloc_stack [[BOX]] // CHECK-NEXT: dealloc_stack [[STACK1]] // CHECK-NEXT: tuple // CHECK-NEXT: return sil [ossa] @nesting_and_unreachable2 : $@convention(thin) (Int) -> () { bb0(%0 : $Int): %as1 = alloc_stack $Bool %1 = alloc_box ${ var Int } %1a = project_box %1 : ${ var Int }, 0 cond_br undef, bb1, bb2 bb1: %as2 = alloc_stack $Bool destroy_value %1 : ${ var Int } dealloc_stack %as2 : $*Bool unreachable bb2: store %0 to [trivial] %1a : $*Int dealloc_stack %as1 : $*Bool %3 = load [trivial] %1a : $*Int destroy_value %1 : ${ var Int } %r = tuple () return %r : $() } // CHECK-LABEL: sil [ossa] @nesting_and_unreachable3 // CHECK: bb0(%0 : $Int): // CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int // CHECK-NEXT: [[STACK:%[0-9]+]] = alloc_stack $Bool // CHECK: bb1: // CHECK-NEXT: unreachable // CHECK: bb2: // CHECK: store // CHECK: dealloc_stack [[STACK]] // CHECK-NEXT: dealloc_stack [[BOX]] // CHECK-NEXT: tuple // CHECK-NEXT: return sil [ossa] @nesting_and_unreachable3 : $@convention(thin) (Int) -> () { bb0(%0 : $Int): %1 = alloc_box ${ var Int } %as1 = alloc_stack $Bool %1a = project_box %1 : ${ var Int }, 0 cond_br undef, bb1, bb2 bb1: destroy_value %1 : ${ var Int } unreachable bb2: store %0 to [trivial] %1a : $*Int %3 = load [trivial] %1a : $*Int dealloc_stack %as1 : $*Bool destroy_value %1 : ${ var Int } %r = tuple () return %r : $() } // CHECK-LABEL: sil [ossa] @nesting_and_unreachable4 // CHECK: bb0(%0 : $Int): // CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int // CHECK: bb1: // CHECK-NEXT: unreachable // CHECK: bb2: // CHECK: store // CHECK: dealloc_stack [[BOX]] // CHECK-NEXT: tuple // CHECK-NEXT: return sil [ossa] @nesting_and_unreachable4 : $@convention(thin) (Int) -> () { bb0(%0 : $Int): %1 = alloc_box ${ var Int } %1a = project_box %1 : ${ var Int }, 0 cond_br undef, bb1, bb2 bb1: unreachable bb2: store %0 to [trivial] %1a : $*Int %3 = load [trivial] %1a : $*Int destroy_value %1 : ${ var Int } %r = tuple () return %r : $() } // CHECK-LABEL: sil [ossa] @nesting_and_unreachable5 // CHECK: bb0(%0 : $Int): // CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int // CHECK: bb1: // CHECK-NEXT: {{.*}} = alloc_stack $Bool // CHECK-NEXT: {{.*}} = alloc_stack $Bool // CHECK-NEXT: unreachable // CHECK: bb2: // CHECK: store // CHECK: dealloc_stack [[BOX]] // CHECK-NEXT: tuple // CHECK-NEXT: return sil [ossa] @nesting_and_unreachable5 : $@convention(thin) (Int) -> () { bb0(%0 : $Int): %1 = alloc_box ${ var Int } %1a = project_box %1 : ${ var Int }, 0 cond_br undef, bb1, bb2 bb1: %as1 = alloc_stack $Bool %as2 = alloc_stack $Bool unreachable bb2: store %0 to [trivial] %1a : $*Int %3 = load [trivial] %1a : $*Int destroy_value %1 : ${ var Int } %r = tuple () return %r : $() } // CHECK-LABEL: sil [ossa] @deinit_access : $@convention(thin) (@in T) -> (@out T, @out T) { // CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T): // CHECK: [[STK:%.*]] = alloc_stack $T, var, name "x" // CHECK: copy_addr %2 to [init] [[STK]] : $*T // CHECK: [[READ:%.*]] = begin_access [read] [static] [[STK]] : $*T // CHECK: copy_addr [[READ]] to [init] %0 : $*T // CHECK: end_access [[READ]] : $*T // CHECK: [[READ:%.*]] = begin_access [read] [static] [[STK]] : $*T // CHECK: copy_addr [[READ]] to [init] %1 : $*T // CHECK: end_access [[READ]] : $*T // CHECK: destroy_addr [[STK]] // CHECK: dealloc_stack [[STK]] : $*T // CHECK: destroy_addr %2 : $*T // CHECK: return %{{.*}} : $() // CHECK-LABEL: } // end sil function 'deinit_access' sil [ossa] @deinit_access : $@convention(thin) (@in T) -> (@out T, @out T) { bb0(%0 : $*T, %1 : $*T, %2 : $*T): %4 = alloc_box $<τ_0_0> { var τ_0_0 } , var, name "x" %5 = project_box %4 : $<τ_0_0> { var τ_0_0 } , 0 copy_addr %2 to [init] %5 : $*T %7 = begin_access [read] [static] %5 : $*T copy_addr %7 to [init] %0 : $*T end_access %7 : $*T %10 = begin_access [read] [static] %5 : $*T copy_addr %10 to [init] %1 : $*T end_access %10 : $*T destroy_value %4 : $<τ_0_0> { var τ_0_0 } destroy_addr %2 : $*T %15 = tuple () return %15 : $() } // Test that // begin_access [read], , copy_addr, end_access, destroy_addr // is *not* folded into // begin_access [deinit], copy_addr [take], end_access // // CHECK-LABEL: sil [ossa] @nodeinit_access : $@convention(thin) (@in T) -> (@out T, @out T) { // CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T): // CHECK: [[STK:%.*]] = alloc_stack $T, var, name "x" // CHECK: copy_addr %2 to [init] [[STK]] : $*T // CHECK: [[READ:%.*]] = begin_access [read] [static] [[STK]] : $*T // CHECK: copy_addr [[READ]] to [init] %0 : $*T // CHECK: end_access [[READ]] : $*T // CHECK: [[READ:%.*]] = begin_access [read] [static] [[STK]] : $*T // CHECK: [[INNER:%.*]] = begin_access [read] [static] [[READ]] : $*T // CHECK: end_access [[INNER]] : $*T // CHECK: copy_addr [[READ]] to [init] %1 : $*T // CHECK: end_access [[READ]] : $*T // CHECK: destroy_addr [[STK]] : $*T // CHECK: dealloc_stack [[STK]] : $*T // CHECK: destroy_addr %2 : $*T // CHECK: return %{{.*}} : $() // CHECK-LABEL: } // end sil function 'nodeinit_access' sil [ossa] @nodeinit_access : $@convention(thin) (@in T) -> (@out T, @out T) { bb0(%0 : $*T, %1 : $*T, %2 : $*T): %4 = alloc_box $<τ_0_0> { var τ_0_0 } , var, name "x" %5 = project_box %4 : $<τ_0_0> { var τ_0_0 } , 0 copy_addr %2 to [init] %5 : $*T %7 = begin_access [read] [static] %5 : $*T copy_addr %7 to [init] %0 : $*T end_access %7 : $*T %10 = begin_access [read] [static] %5 : $*T %innerAccess = begin_access [read] [static] %10 : $*T end_access %innerAccess : $*T copy_addr %10 to [init] %1 : $*T end_access %10 : $*T destroy_value %4 : $<τ_0_0> { var τ_0_0 } destroy_addr %2 : $*T %15 = tuple () return %15 : $() } // CHECK-LABEL: sil [ossa] @alloc_box_in_specialized_callee : // CHECK-NOT: alloc_box // CHECK-LABEL: } // end sil function 'alloc_box_in_specialized_callee' sil [ossa] @alloc_box_in_specialized_callee : $@convention(thin) (Int) -> () { bb0(%0 : $Int): %1 = alloc_box ${ var Int } %2 = project_box %1, 0 store %0 to [trivial] %2 %4 = function_ref @callee_with_allocbox : $@convention(thin) (@guaranteed { var Int }) -> () %5 = apply %4(%1) : $@convention(thin) (@guaranteed { var Int }) -> () destroy_value %1 %r = tuple () return %r } // CHECK-LABEL: sil shared [ossa] @$s20callee_with_allocboxTf0s_n : // CHECK-NOT: alloc_box // CHECK-LABEL: } // end sil function '$s20callee_with_allocboxTf0s_n' // CHECK-LABEL: sil [ossa] @callee_with_allocbox : // CHECK-NOT: alloc_box // CHECK-LABEL: } // end sil function 'callee_with_allocbox' sil [ossa] @callee_with_allocbox : $@convention(thin) (@guaranteed { var Int }) -> () { bb0(%0 : @guaranteed ${ var Int }): %1 = alloc_box ${ var Int } %2 = project_box %1 : ${ var Int }, 0 %3 = project_box %0 : ${ var Int }, 0 copy_addr %3 to %2 destroy_value %1 %r = tuple () return %r }