Files
swift-mirror/test/SILGen/pack_iteration.swift
Slava Pestov 522a6b7c80 SILGen: Fix break/continue inside 'for ... in ... repeat' loop
We were creating the JumpDests too early, so lowering a 'break' or 'continue'
statement would perform cleanups that were recorded while evaluating the
pack expansion expression, which would cause SIL verifier errors and
runtime crashes.

- Fixes https://github.com/swiftlang/swift/issues/78598
- Fixes rdar://131847933
2025-11-10 20:51:45 -05:00

411 lines
22 KiB
Swift

// RUN: %target-swift-emit-silgen -Xllvm -sil-print-types -module-name pack_iteration %s -target %target-swift-5.9-abi-triple | %FileCheck %s
//////////////////
// Declarations //
//////////////////
@_silgen_name("loopBodyEnd")
func loopBodyEnd() -> ()
@_silgen_name("funcEnd")
func funcEnd() -> ()
@_silgen_name("condition")
func condition() -> Bool
@_silgen_name("loopContinueEnd")
func loopContinueEnd() -> ()
@_silgen_name("loopBreakEnd")
func loopBreakEnd() -> ()
enum E<T> {
case one(T)
case two
}
//////////////
// Tests //
///////////
// CHECK-LABEL: sil hidden [ossa] @$s14pack_iteration14iterateTrivial4overyxxQp_tRvzlF : $@convention(thin) <each Element> (@pack_guaranteed Pack{repeat each Element}) -> () {
// CHECK: bb0([[PACK:%.*]] : $*Pack{repeat each Element}):
// CHECK: [[IDX1:%.*]] = integer_literal $Builtin.Word, 0
// CHECK: [[IDX2:%.*]] = integer_literal $Builtin.Word, 1
// CHECK: [[PACK_LENGTH:%.*]] = pack_length $Pack{repeat each Element}
// CHECK: br [[LOOP_DEST:bb[0-9]+]]([[IDX1]] : $Builtin.Word)
//
// CHECK: [[LOOP_DEST]]([[IDX3:%.*]] : $Builtin.Word):
// CHECK: [[COND:%.*]] = builtin "cmp_eq_Word"([[IDX3]] : $Builtin.Word, [[PACK_LENGTH]] : $Builtin.Word) : $Builtin.Int1
// CHECK: cond_br [[COND]], [[NONE_BB:bb[0-9]+]], [[SOME_BB:bb[0-9]+]]
//
// CHECK: [[NONE_BB]]:
// CHECK: [[FUNC_END_FUNC:%.*]] = function_ref @funcEnd : $@convention(thin) () -> ()
// CHECK: apply [[FUNC_END_FUNC]]() : $@convention(thin) () -> ()
//
// CHECK: [[SOME_BB]]:
// CHECK: [[DYN_PACK_IDX:%.*]] = dynamic_pack_index [[IDX3]] of $Pack{repeat each Element}
// CHECK: open_pack_element [[DYN_PACK_IDX]] of <each Element> at <Pack{repeat each Element}>, shape $each Element, uuid "[[UUID:.*]]"
// CHECK: [[STACK:%.*]] = alloc_stack [lexical] [var_decl] $@pack_element("[[UUID]]") each Element, let, name "el"
// CHECK: [[PACK_ELT_GET:%.*]] = pack_element_get [[DYN_PACK_IDX]] of [[PACK]] : $*Pack{repeat each Element} as $*@pack_element("[[UUID]]") each Element
// CHECK: copy_addr [[PACK_ELT_GET]] to [init] [[STACK]] : $*@pack_element("[[UUID]]") each Element
// CHECK: [[LOOP_END_FUNC:%.*]] = function_ref @loopBodyEnd : $@convention(thin) () -> ()
// CHECK: apply [[LOOP_END_FUNC]]() : $@convention(thin) () -> ()
// CHECK: destroy_addr [[STACK]] : $*@pack_element("[[UUID]]") each Element
// CHECK: dealloc_stack [[STACK]] : $*@pack_element("[[UUID]]") each Element
// CHECK: [[IDX4:%.*]] = builtin "add_Word"([[IDX3]] : $Builtin.Word, [[IDX2]] : $Builtin.Word) : $Builtin.Word
// CHECK: br [[LOOP_DEST]]([[IDX4]] : $Builtin.Word)
//
// CHECK: } // end sil function '$s14pack_iteration14iterateTrivial4overyxxQp_tRvzlF'
func iterateTrivial<each Element>(over element: repeat each Element) {
for el in repeat each element {
loopBodyEnd()
}
funcEnd()
}
// CHECK-LABEL: sil hidden [ossa] @$s14pack_iteration11equalTuples3lhs3rhsSbxxQp_t_xxQp_ttRvzSQRzlF : $@convention(thin) <each Element where repeat each Element : Equatable> (@pack_guaranteed Pack{repeat each Element}, @pack_guaranteed Pack{repeat each Element}) -> Bool {
// CHECK: bb6:
// CHECK: [[STACK1:%.*]] = alloc_stack $(repeat each Element)
// CHECK: [[STACK2:%.*]] = alloc_stack $(repeat each Element)
// CHECK: [[IDX1:%.*]] = integer_literal $Builtin.Word, 0
// CHECK: [[IDX2:%.*]] = integer_literal $Builtin.Word, 1
// CHECK: [[PACK_LENGTH:%.*]] = pack_length $Pack{repeat each Element}
// CHECK: br [[LOOP_DEST:bb[0-9]+]]([[IDX1]] : $Builtin.Word)
//
// CHECK: [[LOOP_DEST]]([[IDX3:%.*]] : $Builtin.Word):
// CHECK: [[COND:%.*]] = builtin "cmp_eq_Word"([[IDX3]] : $Builtin.Word, [[PACK_LENGTH]] : $Builtin.Word) : $Builtin.Int1
// CHECK: cond_br [[COND]], [[NONE_BB:bb[0-9]+]], [[SOME_BB:bb[0-9]+]]
//
// CHECK: [[SOME_BB]]:
// CHECK: [[DYN_PACK_IDX:%.*]] = dynamic_pack_index [[IDX3]] of $Pack{repeat (each Element, each Element)}
// CHECK: [[OPEN_PACK_ELT:%.*]] = open_pack_element [[DYN_PACK_IDX]] of <each Element where repeat each Element : Equatable> at <Pack{repeat each Element}>, shape $each Element, uuid "[[UUID:.*]]"
// CHECK: [[STACK_LEFT:%.*]] = alloc_stack [lexical] [var_decl] $@pack_element("[[UUID]]") each Element, let, name "left"
// CHECK: [[STACK_RIGHT:%.*]] = alloc_stack [lexical] [var_decl] $@pack_element("[[UUID]]") each Element, let, name "right"
// CHECK: tuple_pack_element_addr [[DYN_PACK_IDX]] of [[STACK1]] : $*(repeat each Element) as $*@pack_element("[[UUID]]") each Element
// CHECK: tuple_pack_element_addr [[DYN_PACK_IDX]] of [[STACK2]] : $*(repeat each Element) as $*@pack_element("[[UUID]]") each Element
// CHECK: [[METATYPE:%.*]] = metatype $@thick (@pack_element("[[UUID]]") each Element).Type
// CHECK: [[WITNESS_METHOD:%.*]] = witness_method $@pack_element("[[UUID]]") each Element, #Equatable."==" : <Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool, [[OPEN_PACK_ELT]] : $Builtin.SILToken : $@convention(witness_method: Equatable) <τ_0_0 where τ_0_0 : Equatable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> Bool
// CHECK: apply [[WITNESS_METHOD]]<@pack_element("[[UUID]]") each Element>([[STACK_LEFT]], [[STACK_RIGHT]], [[METATYPE]]) : $@convention(witness_method: Equatable) <τ_0_0 where τ_0_0 : Equatable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> Bool
//
// CHECK: } // end sil function '$s14pack_iteration11equalTuples3lhs3rhsSbxxQp_t_xxQp_ttRvzSQRzlF'
func equalTuples<each Element: Equatable>(lhs: (repeat each Element), rhs: (repeat each Element)) -> Bool {
for (left, right) in repeat (each lhs, each rhs) {
guard left == right else { return false }
}
return true
}
// CHECK-LABEL: sil hidden [ossa] @$s14pack_iteration19iteratePatternMatch4overyAA1EOyxGxQp_tRvzlF : $@convention(thin) <each Element> (@pack_guaranteed Pack{repeat E<each Element>}) -> () {
// CHECK: bb0([[PACK:%.*]] : $*Pack{repeat E<each Element>}):
// CHECK: [[IDX1:%.*]] = integer_literal $Builtin.Word, 0
// CHECK: [[IDX2:%.*]] = integer_literal $Builtin.Word, 1
// CHECK: [[PACK_LENGTH:%.*]] = pack_length $Pack{repeat each Element}
// CHECK: br [[LOOP_DEST:bb[0-9]+]]([[IDX1]] : $Builtin.Word)
//
// CHECK: [[LOOP_DEST]]([[IDX3:%.*]] : $Builtin.Word):
// CHECK: [[COND:%.*]] = builtin "cmp_eq_Word"([[IDX3]] : $Builtin.Word, [[PACK_LENGTH]] : $Builtin.Word) : $Builtin.Int1
// CHECK: cond_br [[COND]], [[NONE_BB:bb[0-9]+]], [[SOME_BB:bb[0-9]+]]
//
// CHECK: [[SOME_BB]]:
// CHECK: [[DYN_PACK_IDX:%.*]] = dynamic_pack_index [[IDX3]] of $Pack{repeat E<each Element>}
// CHECK: open_pack_element [[DYN_PACK_IDX]] of <each Element> at <Pack{repeat each Element}>, shape $each Element, uuid "[[UUID:.*]]"
// CHECK: [[STACK:%.*]] = alloc_stack [lexical] [var_decl] $@pack_element("[[UUID]]") each Element, let, name "value"
// CHECK: [[PACK_ELT_GET:%.*]] = pack_element_get [[DYN_PACK_IDX]] of [[PACK]] : $*Pack{repeat E<each Element>} as $*E<@pack_element("[[UUID]]") each Element>
// CHECK: [[ENUM_STACK:%.*]] = alloc_stack $E<@pack_element("[[UUID]]") each Element>
// CHECK: copy_addr [[PACK_ELT_GET]] to [init] [[ENUM_STACK]] : $*E<@pack_element("[[UUID]]") each Element>
// CHECK: switch_enum_addr [[ENUM_STACK]] : $*E<@pack_element("[[UUID]]") each Element>, case #E.one!enumelt: [[ENUM_MATCH_BB:bb[0-9]+]], case #E.two!enumelt: [[CONTINUE_BB:bb[0-9]+]]
//
// CHECK: [[CONTINUE_BB]]:
// CHECK: destroy_addr [[ENUM_STACK]]
// CHECK: dealloc_stack [[ENUM_STACK]]
// CHECK: dealloc_stack [[STACK]]
// CHECK: br [[LATCH_BB:bb[0-9]+]]
//
// CHECK: [[ENUM_MATCH_BB]]:
// CHECK: [[ENUM_DATA_ADDR:%.*]] = unchecked_take_enum_data_addr %13 : $*E<@pack_element("[[UUID]]") each Element>, #E.one!enumelt
// CHECK: copy_addr [take] [[ENUM_DATA_ADDR]] to [init] [[STACK]]
// CHECK: [[LOOP_END_FUNC:%.*]] = function_ref @loopBodyEnd : $@convention(thin) () -> ()
// CHECK: apply [[LOOP_END_FUNC]]() : $@convention(thin) () -> ()
// CHECK: dealloc_stack [[ENUM_STACK]]
// CHECK: destroy_addr [[STACK]]
// CHECK: dealloc_stack [[STACK]]
// CHECK: br [[LATCH:bb[0-9]+]]
//
// CHECK: [[NONE_BB]]:
// CHECK: [[FUNC_END_FUNC:%.*]] = function_ref @funcEnd : $@convention(thin) () -> ()
// CHECK: apply [[FUNC_END_FUNC]]() : $@convention(thin) () -> ()
//
// CHECK: [[LATCH_BB]]:
// CHECK: [[ADD_WORD:%.*]] = builtin "add_Word"([[IDX3]] : $Builtin.Word, [[IDX2]] : $Builtin.Word) : $Builtin.Word
// CHECK: br [[LOOP_DEST]]([[ADD_WORD]] : $Builtin.Word)
// CHECK: } // end sil function '$s14pack_iteration19iteratePatternMatch4overyAA1EOyxGxQp_tRvzlF'
func iteratePatternMatch<each Element>(over element: repeat E<each Element>) {
for case .one(let value) in repeat each element {
loopBodyEnd()
}
funcEnd()
}
// CHECK-LABEL: sil hidden [ossa] @$s14pack_iteration19iterateTrivialBreak4overyxxQp_tRvzlF : $@convention(thin) <each Element> (@pack_guaranteed Pack{repeat each Element}) -> () {
// CHECK: bb0([[PACK:%.*]] : $*Pack{repeat each Element}):
// CHECK: [[IDX1:%.*]] = integer_literal $Builtin.Word, 0
// CHECK: [[IDX2:%.*]] = integer_literal $Builtin.Word, 1
// CHECK: [[PACK_LENGTH:%.*]] = pack_length $Pack{repeat each Element}
// CHECK: br [[LOOP_DEST:bb[0-9]+]]([[IDX1]] : $Builtin.Word)
//
// CHECK: [[LOOP_DEST]]([[IDX3:%.*]] : $Builtin.Word):
// CHECK: [[COND:%.*]] = builtin "cmp_eq_Word"([[IDX3]] : $Builtin.Word, [[PACK_LENGTH]] : $Builtin.Word) : $Builtin.Int1
// CHECK: cond_br [[COND]], [[NONE_BB:bb[0-9]+]], [[SOME_BB:bb[0-9]+]]
//
// CHECK: [[SOME_BB]]:
// CHECK: [[DYN_PACK_IDX:%.*]] = dynamic_pack_index [[IDX3]] of $Pack{repeat each Element}
// CHECK: open_pack_element [[DYN_PACK_IDX]] of <each Element> at <Pack{repeat each Element}>, shape $each Element, uuid "[[UUID:.*]]"
// CHECK: [[STACK:%.*]] = alloc_stack [lexical] [var_decl] $@pack_element("[[UUID]]") each Element, let, name "el"
// CHECK: [[PACK_ELT_GET:%.*]] = pack_element_get [[DYN_PACK_IDX]] of [[PACK]] : $*Pack{repeat each Element} as $*@pack_element("[[UUID]]") each Element
// CHECK: copy_addr [[PACK_ELT_GET]] to [init] [[STACK]] : $*@pack_element("[[UUID]]") each Element
// CHECK: [[LOOP_END_FUNC:%.*]] = function_ref @loopBreakEnd : $@convention(thin) () -> ()
// CHECK: apply [[LOOP_END_FUNC]]() : $@convention(thin) () -> ()
// CHECK: destroy_addr [[STACK]] : $*@pack_element("[[UUID]]") each Element
// CHECK: dealloc_stack [[STACK]] : $*@pack_element("[[UUID]]") each Element
// CHECK: br [[FUNC_END_BB:bb[0-9]+]]
//
// CHECK: [[NONE_BB]]:
// CHECK: br [[FUNC_END_BB]]
//
// CHECK: [[FUNC_END_BB]]
// CHECK: [[FUNC_END_FUNC:%.*]] = function_ref @funcEnd : $@convention(thin) () -> ()
// CHECK: apply [[FUNC_END_FUNC]]() : $@convention(thin) () -> ()
// CHECK: } // end sil function '$s14pack_iteration19iterateTrivialBreak4overyxxQp_tRvzlF'
func iterateTrivialBreak<each Element>(over element: repeat each Element) {
for el in repeat each element {
loopBreakEnd()
break
}
funcEnd()
}
// CHECK-LABEL: sil hidden [ossa] @$s14pack_iteration20iterateContinueBreak4overyxxQp_tRvzlF : $@convention(thin) <each Element> (@pack_guaranteed Pack{repeat each Element}) -> () {
// CHECK: bb0([[PACK:%.*]] : $*Pack{repeat each Element}):
// CHECK: [[IDX1:%.*]] = integer_literal $Builtin.Word, 0
// CHECK: [[IDX2:%.*]] = integer_literal $Builtin.Word, 1
// CHECK: [[PACK_LENGTH:%.*]] = pack_length $Pack{repeat each Element}
// CHECK: br [[LOOP_DEST:bb[0-9]+]]([[IDX1]] : $Builtin.Word)
//
// CHECK: [[LOOP_DEST]]([[IDX3:%.*]] : $Builtin.Word):
// CHECK: [[COND:%.*]] = builtin "cmp_eq_Word"([[IDX3]] : $Builtin.Word, [[PACK_LENGTH]] : $Builtin.Word) : $Builtin.Int1
// CHECK: cond_br [[COND]], [[NONE_BB:bb[0-9]+]], [[SOME_BB:bb[0-9]+]]
//
// CHECK: [[SOME_BB]]:
// CHECK: [[DYN_PACK_IDX:%.*]] = dynamic_pack_index [[IDX3]] of $Pack{repeat each Element}
// CHECK: open_pack_element [[DYN_PACK_IDX]] of <each Element> at <Pack{repeat each Element}>, shape $each Element, uuid "[[UUID:.*]]"
// CHECK: [[STACK:%.*]] = alloc_stack [lexical] [var_decl] $@pack_element("[[UUID]]") each Element, let, name "el"
// CHECK: [[PACK_ELT_GET:%.*]] = pack_element_get [[DYN_PACK_IDX]] of [[PACK]] : $*Pack{repeat each Element} as $*@pack_element("[[UUID]]") each Element
// CHECK: copy_addr [[PACK_ELT_GET]] to [init] [[STACK]] : $*@pack_element("[[UUID]]") each Element
// CHECK: [[COND_FUNC:%.*]] = function_ref @condition : $@convention(thin) () -> Bool
// CHECK: [[BOOL:%.*]] = apply [[COND_FUNC]]() : $@convention(thin) () -> Bool
// CHECK: [[IF:%.*]] = struct_extract [[BOOL]] : $Bool, #Bool._value
// CHECK: cond_br [[IF]], [[LOOP_BREAK:bb[0-9]+]], [[LOOP_CONDITION:bb[0-9]+]]
//
// CHECK: [[LOOP_BREAK]]:
// CHECK: [[LOOP_BREAK_FUNC:%.*]] = function_ref @loopBreakEnd : $@convention(thin) () -> ()
// CHECK: apply [[LOOP_BREAK_FUNC]]() : $@convention(thin) () -> ()
// CHECK: destroy_addr [[STACK]] : $*@pack_element("[[UUID]]") each Element
// CHECK: dealloc_stack [[STACK]] : $*@pack_element("[[UUID]]") each Element
// br [[FUNC_END:bb[0-9]+]]
//
// CHECK: [[LOOP_CONDITION]]:
// CHECK: [[LOOP_CONDITION_FUNC:%.*]] = function_ref @condition : $@convention(thin) () -> Bool
// CHECK: [[BOOL:%.*]] = apply [[LOOP_CONDITION_FUNC]]() : $@convention(thin) () -> Bool
// CHECK: [[IF:%.*]] = struct_extract [[BOOL]] : $Bool, #Bool._value
// CHECK: cond_br [[IF]], [[LOOP_CONTINUE:bb[0-9]+]], [[LOOP_BODY_END:bb[0-9]+]]
//
// CHECK: [[LOOP_CONTINUE]]:
// CHECK: [[LOOP_CONTINUE_FUNC:%.*]] = function_ref @loopContinueEnd : $@convention(thin) () -> ()
// CHECK: apply [[LOOP_CONTINUE_FUNC]]() : $@convention(thin) () -> ()
// CHECK: destroy_addr [[STACK]] : $*@pack_element("[[UUID]]") each Element
// CHECK: dealloc_stack [[STACK]] : $*@pack_element("[[UUID]]") each Element
// CHECK: br [[LATCH:bb[0-9]+]]
//
// CHECK: [[LOOP_BODY_END]]:
// CHECK: [[LOOP_BODY_END_FUNC:%.*]] = function_ref @loopBodyEnd : $@convention(thin) () -> ()
// CHECK: apply [[LOOP_BODY_END_FUNC]]() : $@convention(thin) () -> ()
// CHECK: destroy_addr [[STACK]] : $*@pack_element("[[UUID]]") each Element
// CHECK: dealloc_stack [[STACK]] : $*@pack_element("[[UUID]]") each Element
// CHECK: br [[LATCH]]
//
// CHECK: [[NONE_BB]]:
// CHECK: br [[FUNC_END_BB:bb[0-9]+]]
//
// CHECK: [[LATCH]]:
// CHECK: [[ADD_WORD:%.*]] = builtin "add_Word"([[IDX3]] : $Builtin.Word, [[IDX2]] : $Builtin.Word) : $Builtin.Word
// CHECK: br [[LOOP_DEST]]([[ADD_WORD]] : $Builtin.Word)
//
// CHECK: [[FUNC_END_BB]]
// CHECK: [[FUNC_END_FUNC:%.*]] = function_ref @funcEnd : $@convention(thin) () -> ()
// CHECK: apply [[FUNC_END_FUNC]]() : $@convention(thin) () -> ()
// CHECK: return
// CHECK: } // end sil function '$s14pack_iteration20iterateContinueBreak4overyxxQp_tRvzlF'
func iterateContinueBreak<each Element>(over element: repeat each Element) {
for el in repeat each element {
if (condition()) {
loopBreakEnd()
break
}
if (condition()) {
loopContinueEnd()
continue
}
loopBodyEnd()
}
funcEnd()
}
// CHECK-LABEL: sil hidden [ossa] @$s14pack_iteration14iterateClosure4overyxxQp_tRvzlF : $@convention(thin) <each Element> (@pack_guaranteed Pack{repeat each Element}) -> () {
//
// CHECK-LABEL: sil private [ossa] @$s14pack_iteration14iterateClosure4overyxxQp_tRvzlFyycfU_ : $@convention(thin) <each Element> (@in_guaranteed (repeat each Element)) -> () {
//
// CHECK: bb0([[PACK:%.*]] : @closureCapture $*(repeat each Element)):
// CHECK: [[ALLOC_PACK:%.*]] = alloc_pack $Pack{repeat each Element}
// CHECK: [[IDX1:%.*]] = integer_literal $Builtin.Word, 0
// CHECK: [[IDX2:%.*]] = integer_literal $Builtin.Word, 1
// CHECK: [[PACK_LENGTH:%.*]] = pack_length $Pack{repeat each Element}
// CHECK: br [[LOOP_DEST:bb[0-9]+]]([[IDX1]] : $Builtin.Word)
//
// CHECK: [[LOOP_DEST]]([[IDX3:%.*]] : $Builtin.Word):
// CHECK: [[COND:%.*]] = builtin "cmp_eq_Word"([[IDX3]] : $Builtin.Word, [[PACK_LENGTH]] : $Builtin.Word) : $Builtin.Int1
// CHECK: cond_br [[COND]], [[SETUP_BB:bb[0-9]+]], [[ITER_BB:bb[0-9]+]]
//
// CHECK: [[ITER_BB]]:
// CHECK: [[PACK_IDX:%.*]] = dynamic_pack_index [[IDX3]] of $Pack{repeat each Element}
// CHECK: [[OPEN_ELT:%.*]] = open_pack_element [[PACK_IDX]] of <each Element> at <Pack{repeat each Element}>, shape $each Element, uuid "[[UUID:.*]]"
// CHECK: [[TUPLE_ADDR:%.*]] = tuple_pack_element_addr [[PACK_IDX]] of [[PACK]] : $*(repeat each Element) as $*@pack_element("[[UUID]]") each Element
// CHECK: pack_element_set [[TUPLE_ADDR]] : $*@pack_element("[[UUID]]") each Element into [[PACK_IDX]] of [[ALLOC_PACK]] : $*Pack{repeat each Element}
// CHECK: [[ADD_WORD:%.*]] = builtin "add_Word"([[IDX3]] : $Builtin.Word, [[IDX2]] : $Builtin.Word) : $Builtin.Word
// CHECK: br [[LOOP_DEST]]([[ADD_WORD]] : $Builtin.Word)
//
// CHECK: [[SETUP_BB]]
// CHECK: debug_value [[ALLOC_PACK]] : $*Pack{repeat each Element}, let, name "element", argno 1, expr op_deref
// CHECK: [[SETUP_0:%.*]] = integer_literal $Builtin.Word, 0
// CHECK: [[SETUP_1:%.*]] = integer_literal $Builtin.Word, 1
// CHECK: [[SETUP_LENGTH:%.*]] = pack_length $Pack{repeat each Element}
// CHECK: br [[LOOP_DEST:bb[0-9]+]]([[SETUP_0]] : $Builtin.Word)
//
// CHECK: [[LOOP_DEST]]([[IDX4:%.*]] : $Builtin.Word):
// CHECK: [[COND:%.*]] = builtin "cmp_eq_Word"([[IDX4]] : $Builtin.Word, [[SETUP_LENGTH]] : $Builtin.Word) : $Builtin.Int1
// CHECK: cond_br [[COND]], [[NONE_BB:bb[0-9]+]], [[SOME_BB:bb[0-9]+]]
//
// CHECK: [[SOME_BB]]:
// CHECK: [[DYN_PACK_IDX:%.*]] = dynamic_pack_index [[IDX4]] of $Pack{repeat each Element}
// CHECK: open_pack_element [[DYN_PACK_IDX]] of <each Element> at <Pack{repeat each Element}>, shape $each Element, uuid "[[UUID:.*]]"
// CHECK: [[STACK:%.*]] = alloc_stack [lexical] [var_decl] $@pack_element("[[UUID]]") each Element, let, name "el"
// CHECK: [[PACK_ELT_GET:%.*]] = pack_element_get [[DYN_PACK_IDX]] of [[ALLOC_PACK]] : $*Pack{repeat each Element} as $*@pack_element("[[UUID]]") each Element
// CHECK: copy_addr [[PACK_ELT_GET]] to [init] [[STACK]] : $*@pack_element("[[UUID]]") each Element
// CHECK: [[LOOP_END_FUNC:%.*]] = function_ref @loopBodyEnd : $@convention(thin) () -> ()
// CHECK: apply [[LOOP_END_FUNC]]() : $@convention(thin) () -> ()
// CHECK: destroy_addr [[STACK]] : $*@pack_element("[[UUID]]") each Element
// CHECK: dealloc_stack [[STACK]] : $*@pack_element("[[UUID]]") each Element
// CHECK: br [[LATCH_BB:bb[0-9]+]]
//
// CHECK: [[NONE_BB]]:
// CHECK: dealloc_pack [[ALLOC_PACK]] : $*Pack{repeat each Element}
//
// CHECK: [[LATCH_BB]]:
// CHECK: [[ADD_WORD:%.*]] = builtin "add_Word"([[IDX4]] : $Builtin.Word, [[SETUP_1]] : $Builtin.Word) : $Builtin.Word
// CHECK: br [[LOOP_DEST]]([[ADD_WORD]] : $Builtin.Word)
func iterateClosure<each Element>(over element: repeat each Element) {
let _ = { () -> Void in
for el in repeat each element {
loopBodyEnd()
}
}
}
struct G<each T> {
var t: (repeat each T)
}
// Make sure the 'break' jump destination uses the correct
// cleanup height.
// CHECK-LABEL: sil hidden [ossa] @$s14pack_iteration0B12BreakCleanupyyAA1GVyxxQp_QPGRvzlF : $@convention(thin) <each T> (@in_guaranteed G<repeat each T>) -> () {
// CHECK: bb0(%0 : $*G<repeat each T>):
// CHECK: [[STACK:%.*]] = alloc_stack $(repeat each T)
// CHECK-NEXT: [[PROJ:%.*]] = struct_element_addr %0 : $*G<repeat each T>, #G.t
// CHECK-NEXT: copy_addr [[PROJ]] to [init] [[STACK]] : $*(repeat each T)
// CHECK-NEXT: [[ZERO:%.*]] = integer_literal $Builtin.Word, 0
// CHECK-NEXT: [[ONE:%.*]] = integer_literal $Builtin.Word, 1
// CHECK-NEXT: [[LEN:%.*]] = pack_length $Pack{repeat each T}
// CHECK-NEXT: br bb1([[ZERO]] : $Builtin.Word)
//
// CHECK: bb1([[IDX:%.*]] : $Builtin.Word):
// CHECK-NEXT: [[CMP:%.*]] = builtin "cmp_eq_Word"([[IDX:%.*]] : $Builtin.Word, [[LEN]] : $Builtin.Word) : $Builtin.Int1
// CHECK-NEXT: cond_br [[CMP]], bb3, bb2
//
// CHECK: bb2:
// CHECK-NEXT: [[PACK_IDX:%.*]] = dynamic_pack_index [[IDX]] of $Pack{repeat each T}
// CHECK-NEXT: [[ELT:%.*]] = open_pack_element [[PACK_IDX]] of <each T> at <Pack{repeat each T}>, shape $each T
// CHECK-NEXT: [[ELT_STACK:%.*]] = alloc_stack [lexical] [var_decl] $@pack_element({{.*}}) each T
// CHECK-NEXT: [[ELT_TUPLE:%.*]] = tuple_pack_element_addr [[PACK_IDX]] of [[STACK]] : $*(repeat each T) as $*@pack_element({{.*}}) each T
// CHECK-NEXT: copy_addr [[ELT_TUPLE]] to [init] [[ELT_STACK]] : $*@pack_element({{.*}}) each T
// CHECK-NEXT: destroy_addr [[ELT_STACK]] : $*@pack_element({{.*}}) each T
// CHECK-NEXT: dealloc_stack [[ELT_STACK]] : $*@pack_element({{.*}}) each T
// CHECK: br bb5
//
// CHECK: bb3:
// CHECK-NEXT: bb5
//
// CHECK: bb4:
// CHECK-NEXT: [[NEXT:%.*]] = builtin "add_Word"([[IDX]] : $Builtin.Word, [[ONE]] : $Builtin.Word) : $Builtin.Word
// CHECK: br bb1([[NEXT]] : $Builtin.Word)
//
// CHECK: bb5:
// CHECK: destroy_addr [[STACK]] : $*(repeat each T)
// CHECK: dealloc_stack [[STACK]] : $*(repeat each T)
// CHECK: [[RESULT:%.*]] = tuple ()
// CHECK: return [[RESULT]] : $()
func iterationBreakCleanup<each T>(_ xs: G<repeat each T>) {
for x in repeat each xs.t {
break
}
}
// CHECK-LABEL: sil hidden [ossa] @$s14pack_iteration0B15ContinueCleanupyyAA1GVyxxQp_QPGRvzlF : $@convention(thin) <each T> (@in_guaranteed G<repeat each T>) -> () {
// CHECK: bb0(%0 : $*G<repeat each T>):
// CHECK: [[STACK:%.*]] = alloc_stack $(repeat each T)
// CHECK-NEXT: [[PROJ:%.*]] = struct_element_addr %0 : $*G<repeat each T>, #G.t
// CHECK-NEXT: copy_addr [[PROJ]] to [init] [[STACK]] : $*(repeat each T)
// CHECK-NEXT: [[ZERO:%.*]] = integer_literal $Builtin.Word, 0
// CHECK-NEXT: [[ONE:%.*]] = integer_literal $Builtin.Word, 1
// CHECK-NEXT: [[LEN:%.*]] = pack_length $Pack{repeat each T}
// CHECK-NEXT: br bb1([[ZERO]] : $Builtin.Word)
//
// CHECK: bb1([[IDX:%.*]] : $Builtin.Word):
// CHECK-NEXT: [[CMP:%.*]] = builtin "cmp_eq_Word"([[IDX:%.*]] : $Builtin.Word, [[LEN]] : $Builtin.Word) : $Builtin.Int1
// CHECK-NEXT: cond_br [[CMP]], bb2, bb3
//
// CHECK: bb2:
// CHECK: destroy_addr [[STACK]] : $*(repeat each T)
// CHECK: dealloc_stack [[STACK]] : $*(repeat each T)
// CHECK: [[RESULT:%.*]] = tuple ()
// CHECK: return [[RESULT]] : $()
//
// CHECK: bb3:
// CHECK-NEXT: [[PACK_IDX:%.*]] = dynamic_pack_index [[IDX]] of $Pack{repeat each T}
// CHECK-NEXT: [[ELT:%.*]] = open_pack_element [[PACK_IDX]] of <each T> at <Pack{repeat each T}>, shape $each T
// CHECK-NEXT: [[ELT_STACK:%.*]] = alloc_stack [lexical] [var_decl] $@pack_element({{.*}}) each T
// CHECK-NEXT: [[ELT_TUPLE:%.*]] = tuple_pack_element_addr [[PACK_IDX]] of [[STACK]] : $*(repeat each T) as $*@pack_element({{.*}}) each T
// CHECK-NEXT: copy_addr [[ELT_TUPLE]] to [init] [[ELT_STACK]] : $*@pack_element({{.*}}) each T
// CHECK-NEXT: destroy_addr [[ELT_STACK]] : $*@pack_element({{.*}}) each T
// CHECK-NEXT: dealloc_stack [[ELT_STACK]] : $*@pack_element({{.*}}) each T
// CHECK-NEXT: [[NEXT:%.*]] = builtin "add_Word"([[IDX]] : $Builtin.Word, [[ONE]] : $Builtin.Word) : $Builtin.Word
// CHECK: br bb1([[NEXT]] : $Builtin.Word)
func iterationContinueCleanup<each T>(_ xs: G<repeat each T>) {
for x in repeat each xs.t {
continue
}
}