@@ -80,15 +80,18 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
80
80
// the corresponding `makeXYZ` function below instead of `visitXYZStart`, but
81
81
// either way must call `visitEnd` and friends at the appropriate times.
82
82
Result<> visitFunctionStart (Function* func);
83
- Result<> visitBlockStart (Block* block);
84
- Result<> visitIfStart (If* iff, Name label = {});
83
+ Result<> visitBlockStart (Block* block, Type inputType = Type::none );
84
+ Result<> visitIfStart (If* iff, Name label = {}, Type inputType = Type::none );
85
85
Result<> visitElse ();
86
- Result<> visitLoopStart (Loop* iff);
87
- Result<> visitTryStart (Try* tryy, Name label = {});
86
+ Result<> visitLoopStart (Loop* iff, Type inputType = Type::none);
87
+ Result<>
88
+ visitTryStart (Try* tryy, Name label = {}, Type inputType = Type::none);
88
89
Result<> visitCatch (Name tag);
89
90
Result<> visitCatchAll ();
90
91
Result<> visitDelegate (Index label);
91
- Result<> visitTryTableStart (TryTable* trytable, Name label = {});
92
+ Result<> visitTryTableStart (TryTable* trytable,
93
+ Name label = {},
94
+ Type inputType = Type::none);
92
95
Result<> visitEnd ();
93
96
94
97
// Used to visit break nodes when traversing a single block without its
@@ -113,9 +116,9 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
113
116
// nodes. This is generally safer than calling `visit` because the function
114
117
// signatures ensure that there are no missing fields.
115
118
Result<> makeNop ();
116
- Result<> makeBlock (Name label, Type type );
117
- Result<> makeIf (Name label, Type type );
118
- Result<> makeLoop (Name label, Type type );
119
+ Result<> makeBlock (Name label, Signature sig );
120
+ Result<> makeIf (Name label, Signature sig );
121
+ Result<> makeLoop (Name label, Signature sig );
119
122
Result<> makeBreak (Index label, bool isConditional);
120
123
Result<> makeSwitch (const std::vector<Index>& labels, Index defaultLabel);
121
124
// Unlike Builder::makeCall, this assumes the function already exists.
@@ -180,9 +183,9 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
180
183
Result<> makeTableFill (Name table);
181
184
Result<> makeTableCopy (Name destTable, Name srcTable);
182
185
Result<> makeTableInit (Name elem, Name table);
183
- Result<> makeTry (Name label, Type type );
186
+ Result<> makeTry (Name label, Signature sig );
184
187
Result<> makeTryTable (Name label,
185
- Type type ,
188
+ Signature sig ,
186
189
const std::vector<Name>& tags,
187
190
const std::vector<Index>& labels,
188
191
const std::vector<bool >& isRefs);
@@ -323,13 +326,21 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
323
326
324
327
// The branch label name for this scope. Always fresh, never shadowed.
325
328
Name label;
329
+
326
330
// For Try/Catch/CatchAll scopes, we need to separately track a label used
327
331
// for branches, since the normal label is only used for delegates.
328
332
Name branchLabel;
329
333
330
334
bool labelUsed = false ;
331
335
336
+ // If the control flow scope has an input type, we need to lower it using a
337
+ // scratch local because we cannot represent control flow input in the IR.
338
+ Type inputType;
339
+ Index inputLocal = -1 ;
340
+
341
+ // The stack of instructions being built in this scope.
332
342
std::vector<Expression*> exprStack;
343
+
333
344
// Whether we have seen an unreachable instruction and are in
334
345
// stack-polymorphic unreachable mode.
335
346
bool unreachable = false ;
@@ -338,29 +349,39 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
338
349
size_t startPos = 0 ;
339
350
340
351
ScopeCtx () : scope(NoScope{}) {}
341
- ScopeCtx (Scope scope) : scope(scope) {}
342
- ScopeCtx (Scope scope, Name label, bool labelUsed)
343
- : scope(scope), label(label), labelUsed(labelUsed) {}
352
+ ScopeCtx (Scope scope, Type inputType)
353
+ : scope(scope), inputType(inputType) {}
354
+ ScopeCtx (
355
+ Scope scope, Name label, bool labelUsed, Type inputType, Index inputLocal)
356
+ : scope(scope), label(label), labelUsed(labelUsed), inputType(inputType),
357
+ inputLocal (inputLocal) {}
344
358
ScopeCtx (Scope scope, Name label, bool labelUsed, Name branchLabel)
345
359
: scope(scope), label(label), branchLabel(branchLabel),
346
360
labelUsed(labelUsed) {}
347
361
348
362
static ScopeCtx makeFunc (Function* func) {
349
- return ScopeCtx (FuncScope{func});
363
+ return ScopeCtx (FuncScope{func}, Type::none );
350
364
}
351
- static ScopeCtx makeBlock (Block* block) {
352
- return ScopeCtx (BlockScope{block});
365
+ static ScopeCtx makeBlock (Block* block, Type inputType ) {
366
+ return ScopeCtx (BlockScope{block}, inputType );
353
367
}
354
- static ScopeCtx makeIf (If* iff, Name originalLabel = {} ) {
355
- return ScopeCtx (IfScope{iff, originalLabel});
368
+ static ScopeCtx makeIf (If* iff, Name originalLabel, Type inputType ) {
369
+ return ScopeCtx (IfScope{iff, originalLabel}, inputType );
356
370
}
357
- static ScopeCtx
358
- makeElse (If* iff, Name originalLabel, Name label, bool labelUsed) {
359
- return ScopeCtx (ElseScope{iff, originalLabel}, label, labelUsed);
371
+ static ScopeCtx makeElse (If* iff,
372
+ Name originalLabel,
373
+ Name label,
374
+ bool labelUsed,
375
+ Type inputType,
376
+ Index inputLocal) {
377
+ return ScopeCtx (
378
+ ElseScope{iff, originalLabel}, label, labelUsed, inputType, inputLocal);
360
379
}
361
- static ScopeCtx makeLoop (Loop* loop) { return ScopeCtx (LoopScope{loop}); }
362
- static ScopeCtx makeTry (Try* tryy, Name originalLabel = {}) {
363
- return ScopeCtx (TryScope{tryy, originalLabel});
380
+ static ScopeCtx makeLoop (Loop* loop, Type inputType) {
381
+ return ScopeCtx (LoopScope{loop}, inputType);
382
+ }
383
+ static ScopeCtx makeTry (Try* tryy, Name originalLabel, Type inputType) {
384
+ return ScopeCtx (TryScope{tryy, originalLabel}, inputType);
364
385
}
365
386
static ScopeCtx makeCatch (Try* tryy,
366
387
Name originalLabel,
@@ -378,8 +399,9 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
378
399
return ScopeCtx (
379
400
CatchAllScope{tryy, originalLabel}, label, labelUsed, branchLabel);
380
401
}
381
- static ScopeCtx makeTryTable (TryTable* trytable, Name originalLabel = {}) {
382
- return ScopeCtx (TryTableScope{trytable, originalLabel});
402
+ static ScopeCtx
403
+ makeTryTable (TryTable* trytable, Name originalLabel, Type inputType) {
404
+ return ScopeCtx (TryTableScope{trytable, originalLabel}, inputType);
383
405
}
384
406
385
407
bool isNone () { return std::get_if<NoScope>(&scope); }
@@ -518,6 +540,7 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
518
540
}
519
541
WASM_UNREACHABLE (" unexpected scope kind" );
520
542
}
543
+ bool isDelimiter () { return getElse () || getCatch () || getCatchAll (); }
521
544
};
522
545
523
546
// The stack of block contexts currently being parsed.
@@ -541,7 +564,7 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
541
564
Index blockHint = 0 ;
542
565
Index labelHint = 0 ;
543
566
544
- void pushScope (ScopeCtx scope) {
567
+ Result<> pushScope (ScopeCtx&& scope) {
545
568
if (auto label = scope.getOriginalLabel ()) {
546
569
// Assign a fresh label to the scope, if necessary.
547
570
if (!scope.label ) {
@@ -554,7 +577,21 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
554
577
scope.startPos = lastBinaryPos;
555
578
lastBinaryPos = *binaryPos;
556
579
}
557
- scopeStack.push_back (scope);
580
+ bool hasInput = scope.inputType != Type::none;
581
+ Index inputLocal = scope.inputLocal ;
582
+ if (hasInput && !scope.isDelimiter ()) {
583
+ if (inputLocal == Index (-1 )) {
584
+ auto scratch = addScratchLocal (scope.inputType );
585
+ CHECK_ERR (scratch);
586
+ inputLocal = scope.inputLocal = *scratch;
587
+ }
588
+ CHECK_ERR (makeLocalSet (inputLocal));
589
+ }
590
+ scopeStack.emplace_back (std::move (scope));
591
+ if (hasInput) {
592
+ CHECK_ERR (makeLocalGet (inputLocal));
593
+ }
594
+ return Ok{};
558
595
}
559
596
560
597
ScopeCtx& getScope () {
@@ -610,6 +647,8 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
610
647
Result<Type> getLabelType (Index label);
611
648
Result<Type> getLabelType (Name labelName);
612
649
650
+ void fixLoopWithInput (Loop* loop, Type inputType, Index scratch);
651
+
613
652
void dump ();
614
653
};
615
654
0 commit comments