mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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
411 lines
22 KiB
Swift
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
|
|
}
|
|
} |