Skip to content

Commit 004299a

Browse files
committed
Add break/continue support
1 parent 24b7823 commit 004299a

File tree

2 files changed

+96
-3
lines changed

2 files changed

+96
-3
lines changed

lib/SILGen/SILGenStmt.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,6 +1227,10 @@ void StmtEmitter::visitForEachStmt(ForEachStmt *S) {
12271227

12281228
JumpDest loopDest = createJumpDest(S->getBody());
12291229

1230+
// Set the destinations for 'break' and 'continue'.
1231+
JumpDest endDest = createJumpDest(S->getBody());
1232+
SGF.BreakContinueDestStack.push_back({S, endDest, loopDest});
1233+
12301234
SGF.emitDynamicPackLoop(
12311235
SILLocation(expansion), formalPackType, 0,
12321236
expansion->getGenericEnvironment(),
@@ -1241,6 +1245,10 @@ void StmtEmitter::visitForEachStmt(ForEachStmt *S) {
12411245
return;
12421246
},
12431247
loopDest.getBlock());
1248+
1249+
emitOrDeleteBlock(SGF, endDest, S);
1250+
SGF.BreakContinueDestStack.pop_back();
1251+
12441252
return;
12451253
}
12461254

test/SILGen/pack_iteration.swift

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ func loopBodyEnd() -> ()
1010
@_silgen_name("funcEnd")
1111
func funcEnd() -> ()
1212

13+
@_silgen_name("condition")
14+
func condition() -> Bool
15+
16+
@_silgen_name("loopContinueEnd")
17+
func loopContinueEnd() -> ()
18+
19+
@_silgen_name("loopBreakEnd")
20+
func loopBreakEnd() -> ()
21+
1322
enum E<T> {
1423
case one(T)
1524
case two
@@ -37,7 +46,7 @@ enum E<T> {
3746
// CHECK: [[SOME_BB]]:
3847
// CHECK: [[DYN_PACK_IDX:%.*]] = dynamic_pack_index [[IDX3]] of $Pack{repeat each Element}
3948
// CHECK: open_pack_element [[DYN_PACK_IDX]] of <each Element> at <Pack{repeat each Element}>, shape $each Element, uuid "[[UUID:.*]]"
40-
// CHECK: [[STACK:%.*]] = alloc_stack [lexical] $@pack_element("[[UUID]]") each Element, let, name "element"
49+
// CHECK: [[STACK:%.*]] = alloc_stack [lexical] $@pack_element("[[UUID]]") each Element, let, name "el"
4150
// CHECK: [[PACK_ELT_GET:%.*]] = pack_element_get [[DYN_PACK_IDX]] of [[PACK]] : $*Pack{repeat each Element} as $*@pack_element("[[UUID]]") each Element
4251
// CHECK: copy_addr [[PACK_ELT_GET]] to [init] [[STACK]] : $*@pack_element("[[UUID]]") each Element
4352
// CHECK: [[LOOP_END_FUNC:%.*]] = function_ref @loopBodyEnd : $@convention(thin) () -> ()
@@ -48,8 +57,8 @@ enum E<T> {
4857
// CHECK: br [[LOOP_DEST]]([[IDX4]] : $Builtin.Word)
4958
//
5059
// CHECK: } // end sil function '$s14pack_iteration14iterateTrivial4overyxxQp_tRvzlF'
51-
func iterateTrivial<each Element>(over elements: repeat each Element) {
52-
for element in repeat each elements {
60+
func iterateTrivial<each Element>(over element: repeat each Element) {
61+
for el in repeat each element {
5362
loopBodyEnd()
5463
}
5564
funcEnd()
@@ -140,4 +149,80 @@ func iteratePatternMatch<each Element>(over element: repeat E<each Element>) {
140149
funcEnd()
141150
}
142151

152+
// CHECK-LABEL: sil hidden [ossa] @$s14pack_iteration20iterateContinueBreak4overyxxQp_tRvzlF : $@convention(thin) <each Element> (@pack_guaranteed Pack{repeat each Element}) -> () {
153+
// CHECK: bb0([[PACK:%.*]] : $*Pack{repeat each Element}):
154+
// CHECK: [[IDX1:%.*]] = integer_literal $Builtin.Word, 0
155+
// CHECK: [[IDX2:%.*]] = integer_literal $Builtin.Word, 1
156+
// CHECK: [[PACK_LENGTH:%.*]] = pack_length $Pack{repeat each Element}
157+
// CHECK: br [[LOOP_DEST:bb[0-9]+]]([[IDX1]] : $Builtin.Word)
158+
//
159+
// CHECK: [[LOOP_DEST]]([[IDX3:%.*]] : $Builtin.Word):
160+
// CHECK: [[COND:%.*]] = builtin "cmp_eq_Word"([[IDX3]] : $Builtin.Word, [[PACK_LENGTH]] : $Builtin.Word) : $Builtin.Int1
161+
// CHECK: cond_br [[COND]], [[NONE_BB:bb[0-9]+]], [[SOME_BB:bb[0-9]+]]
162+
//
163+
// CHECK: [[SOME_BB]]:
164+
// CHECK: [[DYN_PACK_IDX:%.*]] = dynamic_pack_index [[IDX3]] of $Pack{repeat each Element}
165+
// CHECK: open_pack_element [[DYN_PACK_IDX]] of <each Element> at <Pack{repeat each Element}>, shape $each Element, uuid "[[UUID:.*]]"
166+
// CHECK: [[STACK:%.*]] = alloc_stack [lexical] $@pack_element("[[UUID]]") each Element, let, name "el"
167+
// CHECK: [[PACK_ELT_GET:%.*]] = pack_element_get [[DYN_PACK_IDX]] of [[PACK]] : $*Pack{repeat each Element} as $*@pack_element("[[UUID]]") each Element
168+
// CHECK: copy_addr [[PACK_ELT_GET]] to [init] [[STACK]] : $*@pack_element("[[UUID]]") each Element
169+
// CHECK: [[COND_FUNC:%.*]] = function_ref @condition : $@convention(thin) () -> Bool
170+
// CHECK: [[BOOL:%.*]] = apply [[COND_FUNC]]() : $@convention(thin) () -> Bool
171+
// CHECK: [[IF:%.*]] = struct_extract [[BOOL]] : $Bool, #Bool._value
172+
// CHECK: cond_br [[IF]], [[LOOP_BREAK:bb[0-9]+]], [[LOOP_CONDITION:bb[0-9]+]]
173+
//
174+
// CHECK: [[LOOP_BREAK]]:
175+
// CHECK: [[LOOP_BREAK_FUNC:%.*]] = function_ref @loopBreakEnd : $@convention(thin) () -> ()
176+
// CHECK: apply [[LOOP_BREAK_FUNC]]() : $@convention(thin) () -> ()
177+
// CHECK: destroy_addr [[STACK]] : $*@pack_element("[[UUID]]") each Element
178+
// CHECK: dealloc_stack [[STACK]] : $*@pack_element("[[UUID]]") each Element
179+
// br [[FUNC_END:bb[0-9]+]]
180+
//
181+
// CHECK: [[LOOP_CONDITION]]:
182+
// CHECK: [[LOOP_CONDITION_FUNC:%.*]] = function_ref @condition : $@convention(thin) () -> Bool
183+
// CHECK: [[BOOL:%.*]] = apply [[LOOP_CONDITION_FUNC]]() : $@convention(thin) () -> Bool
184+
// CHECK: [[IF:%.*]] = struct_extract [[BOOL]] : $Bool, #Bool._value
185+
// CHECK: cond_br [[IF]], [[LOOP_CONTINUE:bb[0-9]+]], [[LOOP_BODY_END:bb[0-9]+]]
186+
//
187+
// CHECK: [[LOOP_CONTINUE]]:
188+
// CHECK: [[LOOP_CONTINUE_FUNC:%.*]] = function_ref @loopContinueEnd : $@convention(thin) () -> ()
189+
// CHECK: apply [[LOOP_CONTINUE_FUNC]]() : $@convention(thin) () -> ()
190+
// CHECK: destroy_addr [[STACK]] : $*@pack_element("[[UUID]]") each Element
191+
// CHECK: dealloc_stack [[STACK]] : $*@pack_element("[[UUID]]") each Element
192+
// CHECK: br [[LATCH:bb[0-9]+]]
193+
//
194+
// CHECK: [[LOOP_BODY_END]]:
195+
// CHECK: [[LOOP_BODY_END_FUNC:%.*]] = function_ref @loopBodyEnd : $@convention(thin) () -> ()
196+
// CHECK: apply [[LOOP_BODY_END_FUNC]]() : $@convention(thin) () -> ()
197+
// CHECK: destroy_addr [[STACK]] : $*@pack_element("[[UUID]]") each Element
198+
// CHECK: dealloc_stack [[STACK]] : $*@pack_element("[[UUID]]") each Element
199+
// CHECK: br [[LATCH]]
200+
//
201+
// CHECK: [[NONE_BB]]:
202+
// CHECK: br [[FUNC_END_BB:bb[0-9]+]]
203+
//
204+
// CHECK: [[FUNC_END_BB]]
205+
// CHECK: [[FUNC_END_FUNC:%.*]] = function_ref @funcEnd : $@convention(thin) () -> ()
206+
// CHECK: apply [[FUNC_END_FUNC]]() : $@convention(thin) () -> ()
207+
//
208+
// CHECK: [[LATCH]]:
209+
// CHECK: [[ADD_WORD:%.*]] = builtin "add_Word"([[IDX3]] : $Builtin.Word, [[IDX2]] : $Builtin.Word) : $Builtin.Word
210+
// CHECK: br [[LOOP_DEST]]([[ADD_WORD]] : $Builtin.Word)
211+
// CHECK: } // end sil function '$s14pack_iteration20iterateContinueBreak4overyxxQp_tRvzlF'
212+
func iterateContinueBreak<each Element>(over element: repeat each Element) {
213+
for el in repeat each element {
214+
if (condition()) {
215+
loopBreakEnd()
216+
break
217+
}
218+
219+
if (condition()) {
220+
loopContinueEnd()
221+
continue
222+
}
223+
loopBodyEnd()
224+
}
225+
226+
funcEnd()
227+
}
143228

0 commit comments

Comments
 (0)