Skip to content

Commit e9cab1f

Browse files
committed
SIL
1 parent 5c39fc3 commit e9cab1f

File tree

2 files changed

+114
-3
lines changed

2 files changed

+114
-3
lines changed

lib/SILGen/SILGenStmt.cpp

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,11 +1248,37 @@ void StmtEmitter::visitRepeatWhileStmt(RepeatWhileStmt *S) {
12481248
void StmtEmitter::visitForEachStmt(ForEachStmt *S) {
12491249
// Emit the 'iterator' variable that we'll be using for iteration.
12501250
LexicalScope OuterForScope(SGF, CleanupLocation(S));
1251-
{
1252-
SGF.emitPatternBinding(S->getIteratorVar(),
1253-
/*index=*/0, /*debuginfo*/ true);
1251+
1252+
if (auto *expansion =
1253+
dyn_cast<PackExpansionExpr>(S->getTypeCheckedSequence())) {
1254+
auto formalPackType = dyn_cast<PackType>(
1255+
PackType::get(SGF.getASTContext(), expansion->getType())
1256+
->getCanonicalType());
1257+
1258+
// Create a new basic block and jump into it.
1259+
JumpDest loopDest = createJumpDest(S->getBody());
1260+
SGF.B.emitBlock(loopDest.getBlock(), S);
1261+
1262+
SGF.emitDynamicPackLoop(
1263+
SILLocation(expansion), formalPackType, 0,
1264+
expansion->getGenericEnvironment(),
1265+
[&](SILValue indexWithinComponent, SILValue packExpansionIndex,
1266+
SILValue packIndex) {
1267+
Scope innerForScope(SGF.Cleanups, CleanupLocation(S->getBody()));
1268+
auto letValueInit =
1269+
SGF.emitPatternBindingInitialization(S->getPattern(), loopDest);
1270+
1271+
SGF.emitExprInto(expansion->getPatternExpr(), letValueInit.get());
1272+
visit(S->getBody());
1273+
return;
1274+
});
1275+
1276+
return;
12541277
}
12551278

1279+
SGF.emitPatternBinding(S->getIteratorVar(),
1280+
/*index=*/0, /*debuginfo*/ true);
1281+
12561282
// If we ever reach an unreachable point, stop emitting statements.
12571283
// This will need revision if we ever add goto.
12581284
if (!SGF.B.hasValidInsertionPoint()) return;

test/SILGen/pack_iteration.swift

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
2+
// RUN: %target-swift-emit-silgen -module-name pack_iteration %s | %FileCheck %s
3+
4+
//////////////////
5+
// Declarations //
6+
//////////////////
7+
@_silgen_name("loopBodyEnd")
8+
func loopBodyEnd() -> ()
9+
10+
@_silgen_name("funcEnd")
11+
func funcEnd() -> ()
12+
13+
enum E<T> {
14+
case one(T)
15+
case two
16+
}
17+
18+
//////////////
19+
// Tests //
20+
///////////
21+
22+
// CHECK-LABEL: sil hidden [ossa] @$s14pack_iteration14iterateTrivial4overyxxQp_tRvzlF : $@convention(thin) <each Element> (@pack_guaranteed Pack{repeat each Element}) -> () {
23+
// CHECK: bb0([[PACK:%.*]] : $*Pack{repeat each Element}):
24+
// CHECK: [[IDX1:%.*]] = integer_literal $Builtin.Word, 0
25+
// CHECK: [[IDX2:%.*]] = integer_literal $Builtin.Word, 1
26+
// CHECK: [[PACK_LENGTH:%.*]] = pack_length $Pack{repeat each Element}
27+
// CHECK: br [[LOOP_DEST:bb[0-9]+]]([[IDX1]] : $Builtin.Word)
28+
//
29+
// CHECK: [[LOOP_DEST]]([[IDX3:%.*]] : $Builtin.Word):
30+
// CHECK: [[COND:%.*]] = builtin "cmp_eq_Word"([[IDX3]] : $Builtin.Word, [[PACK_LENGTH]] : $Builtin.Word) : $Builtin.Int1
31+
// CHECK: cond_br [[COND]], [[NONE_BB:bb[0-9]+]], [[SOME_BB:bb[0-9]+]]
32+
//
33+
// CHECK: [[SOME_BB]]:
34+
// CHECK: [[DYN_PACK_IDX:%.*]] = dynamic_pack_index [[IDX3]] of $Pack{repeat each Element}
35+
// CHECK: open_pack_element [[DYN_PACK_IDX]] of <each Element> at <Pack{repeat each Element}>, shape $each Element, uuid "[[UUID:.*]]"
36+
// CHECK: [[STACK:%.*]] = alloc_stack [lexical] $@pack_element("[[UUID]]") each Element, let, name "element"
37+
// CHECK: [[PACK_ELT_GET:%.*]] = pack_element_get [[DYN_PACK_IDX]] of [[PACK]] : $*Pack{repeat each Element} as $*@pack_element("[[UUID]]") each Element
38+
// CHECK: copy_addr [[PACK_ELT_GET]] to [init] [[STACK]] : $*@pack_element("[[UUID]]") each Element
39+
// CHECK: [[LOOP_END_FUNC:%.*]] = function_ref @loopBodyEnd : $@convention(thin) () -> ()
40+
// CHECK: apply [[LOOP_END_FUNC]]() : $@convention(thin) () -> ()
41+
// CHECK: destroy_addr [[STACK]] : $*@pack_element("[[UUID]]") each Element
42+
// CHECK: dealloc_stack [[STACK]] : $*@pack_element("[[UUID]]") each Element
43+
// CHECK: [[IDX4:%.*]] = builtin "add_Word"([[IDX3]] : $Builtin.Word, [[IDX2]] : $Builtin.Word) : $Builtin.Word
44+
// CHECK: br [[LOOP_DEST]]([[IDX4]] : $Builtin.Word)
45+
//
46+
// CHECK: [[NONE_BB]]:
47+
// CHECK: [[FUNC_END_FUNC:%.*]] = function_ref @funcEnd : $@convention(thin) () -> ()
48+
// CHECK: apply [[FUNC_END_FUNC]]() : $@convention(thin) () -> ()
49+
// CHECK: } // end sil function '$s14pack_iteration14iterateTrivial4overyxxQp_tRvzlF'
50+
func iterateTrivial<each Element>(over elements: repeat each Element) {
51+
for element in repeat each elements {
52+
loopBodyEnd()
53+
}
54+
funcEnd()
55+
}
56+
57+
// TODO: Write this test
58+
func equalTuples<each Element: Equatable>(lhs: (repeat each Element), rhs: (repeat each Element)) -> Bool {
59+
60+
// %12 = dynamic_pack_index %9 of $Pack{repeat (each Element, each Element)} // users: %19, %17, %14, %13
61+
// %13 = open_pack_element %12 of <each Element where repeat each Element : Equatable> at <Pack{repeat each Element}>, shape $each Element, uuid "E53D635E-3D89-11EE-82A2-7AABAFDC7DCA" // users: %19, %17, %14
62+
// %14 = tuple_pack_element_addr %12 of %4 : $*(repeat (each Element, each Element)) as $*(@pack_element("E53D635E-3D89-11EE-82A2-7AABAFDC7DCA") each Element, @pack_element("E53D635E-3D89-11EE-82A2-7AABAFDC7DCA") each Element) // users: %16, %15
63+
// %15 = tuple_element_addr %14 : $*(@pack_element("E53D635E-3D89-11EE-82A2-7AABAFDC7DCA") each Element, @pack_element("E53D635E-3D89-11EE-82A2-7AABAFDC7DCA") each Element), 0 // user: %18
64+
// %16 = tuple_element_addr %14 : $*(@pack_element("E53D635E-3D89-11EE-82A2-7AABAFDC7DCA") each Element, @pack_element("E53D635E-3D89-11EE-82A2-7AABAFDC7DCA") each Element), 1 // user: %20
65+
// %17 = pack_element_get %12 of %0 : $*Pack{repeat each Element} as $*@pack_element("E53D635E-3D89-11EE-82A2-7AABAFDC7DCA") each Element // user: %18
66+
// copy_addr %17 to [init] %15 : $*@pack_element("E53D635E-3D89-11EE-82A2-7AABAFDC7DCA") each Element // id: %18
67+
// %19 = pack_element_get %12 of %1 : $*Pack{repeat each Element} as $*@pack_element("E53D635E-3D89-11EE-82A2-7AABAFDC7DCA") each Element // user: %20
68+
// copy_addr %19 to [init] %16 : $*@pack_element("E53D635E-3D89-11EE-82A2-7AABAFDC7DCA") each Element // id: %20
69+
// %21 = builtin "add_Word"(%9 : $Builtin.Word, %6 : $Builtin.Word) : $Builtin.Word // user: %22
70+
// br bb1(%21 : $Builtin.Word)
71+
72+
for (left, right) in repeat (each lhs, each rhs) {
73+
guard left == right else { return false }
74+
}
75+
return true
76+
}
77+
78+
// TODO: Write this test
79+
func iteratePatternMatch<each Element>(over element: repeat E<each Element>) {
80+
for case .one(let value) in repeat each element {
81+
print(value)
82+
}
83+
}
84+
85+

0 commit comments

Comments
 (0)