@@ -34,6 +34,93 @@ struct StmtVisitor {
34
34
return *block.release ();
35
35
}
36
36
37
+ LogicalResult recursiveForeach (const slang::ast::ForeachLoopStatement &stmt,
38
+ uint32_t level) {
39
+ // find current dimension we are operate.
40
+ const auto &loopDim = stmt.loopDims [level];
41
+ if (!loopDim.range .has_value ()) {
42
+ emitError (loc) << " dynamic loop variable is unsupported" ;
43
+ }
44
+ auto &exitBlock = createBlock ();
45
+ auto &stepBlock = createBlock ();
46
+ auto &bodyBlock = createBlock ();
47
+ auto &checkBlock = createBlock ();
48
+
49
+ // Push the blocks onto the loop stack such that we can continue and break.
50
+ context.loopStack .push_back ({&stepBlock, &exitBlock});
51
+ auto done = llvm::make_scope_exit ([&] { context.loopStack .pop_back (); });
52
+
53
+ const auto &iter = loopDim.loopVar ;
54
+ auto type = context.convertType (*iter->getDeclaredType ());
55
+ if (!type)
56
+ return failure ();
57
+
58
+ Value initial = builder.create <moore::ConstantOp>(
59
+ loc, cast<moore::IntType>(type), loopDim.range ->lower ());
60
+
61
+ // Create loop varirable in this dimension
62
+ Value varOp = builder.create <moore::VariableOp>(
63
+ loc, moore::RefType::get (cast<moore::UnpackedType>(type)),
64
+ builder.getStringAttr (iter->name ), initial);
65
+ context.valueSymbols .insertIntoScope (context.valueSymbols .getCurScope (),
66
+ iter, varOp);
67
+
68
+ builder.create <cf::BranchOp>(loc, &checkBlock);
69
+ builder.setInsertionPointToEnd (&checkBlock);
70
+
71
+ // When the loop variable is greater than the upper bound, goto exit
72
+ auto upperBound = builder.create <moore::ConstantOp>(
73
+ loc, cast<moore::IntType>(type), loopDim.range ->upper ());
74
+
75
+ auto var = builder.create <moore::ReadOp>(loc, varOp);
76
+ Value cond = builder.create <moore::SleOp>(loc, var, upperBound);
77
+ if (!cond)
78
+ return failure ();
79
+ cond = builder.createOrFold <moore::BoolCastOp>(loc, cond);
80
+ cond = builder.create <moore::ConversionOp>(loc, builder.getI1Type (), cond);
81
+ builder.create <cf::CondBranchOp>(loc, cond, &bodyBlock, &exitBlock);
82
+
83
+ builder.setInsertionPointToEnd (&bodyBlock);
84
+
85
+ // find next dimension in this foreach statement, it finded then recuersive
86
+ // resolve, else perform body statement
87
+ bool hasNext = false ;
88
+ for (uint32_t nextLevel = level + 1 ; nextLevel < stmt.loopDims .size ();
89
+ nextLevel++) {
90
+ if (stmt.loopDims [nextLevel].loopVar ) {
91
+ if (failed (recursiveForeach (stmt, nextLevel)))
92
+ return failure ();
93
+ hasNext = true ;
94
+ break ;
95
+ }
96
+ }
97
+
98
+ if (!hasNext) {
99
+ if (failed (context.convertStatement (stmt.body )))
100
+ return failure ();
101
+ }
102
+ if (!isTerminated ())
103
+ builder.create <cf::BranchOp>(loc, &stepBlock);
104
+
105
+ builder.setInsertionPointToEnd (&stepBlock);
106
+
107
+ // add one to loop variable
108
+ var = builder.create <moore::ReadOp>(loc, varOp);
109
+ auto one =
110
+ builder.create <moore::ConstantOp>(loc, cast<moore::IntType>(type), 1 );
111
+ auto postValue = builder.create <moore::AddOp>(loc, var, one).getResult ();
112
+ builder.create <moore::BlockingAssignOp>(loc, varOp, postValue);
113
+ builder.create <cf::BranchOp>(loc, &checkBlock);
114
+
115
+ if (exitBlock.hasNoPredecessors ()) {
116
+ exitBlock.erase ();
117
+ setTerminated ();
118
+ } else {
119
+ builder.setInsertionPointToEnd (&exitBlock);
120
+ }
121
+ return success ();
122
+ }
123
+
37
124
// Skip empty statements (stray semicolons).
38
125
LogicalResult visit (const slang::ast::EmptyStatement &) { return success (); }
39
126
@@ -309,6 +396,14 @@ struct StmtVisitor {
309
396
return success ();
310
397
}
311
398
399
+ LogicalResult visit (const slang::ast::ForeachLoopStatement &stmt) {
400
+ for (uint32_t level = 0 ; level < stmt.loopDims .size (); level++) {
401
+ if (stmt.loopDims [level].loopVar )
402
+ return recursiveForeach (stmt, level);
403
+ }
404
+ return success ();
405
+ }
406
+
312
407
// Handle `repeat` loops.
313
408
LogicalResult visit (const slang::ast::RepeatLoopStatement &stmt) {
314
409
auto count = context.convertRvalueExpression (stmt.count );
0 commit comments