Skip to content

Commit d864c1a

Browse files
authored
fix: Properly handle conditional continue in do loops (#2055)
1 parent 1bf3120 commit d864c1a

File tree

163 files changed

+813
-1131
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

163 files changed

+813
-1131
lines changed

src/compiler.ts

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2391,13 +2391,15 @@ export class Compiler extends DiagnosticEmitter {
23912391
var outerFlow = this.currentFlow;
23922392

23932393
// (block $break └►┐ flow
2394-
// (loop $continue ├◄───────────┐ recompile?
2395-
// (body) └─┐ bodyFlow │
2396-
// ┌─┘ │
2394+
// (loop $loop ├◄───────────┐ recompile?
2395+
// (?block $continue └─┐ │
2396+
// (body) │ bodyFlow │
2397+
// ) ┌─┘ │
23972398
// ┌◄┼►╢ │ breaks or terminates?
2398-
// (local.set $tcond (condition)) │ └─┐ condFlow │
2399+
// │ └─┐ │ but does not continue
2400+
// (br_if (cond) $loop) │ │ condFlow │
23992401
// │ ┌─┘ │
2400-
// (br_if (local.get $tcond) $continue) ├◄┴────────────┘ condition?
2402+
// ├◄┴────────────┘ condition?
24012403
// ) └─┐
24022404
// ) ┌─┘
24032405

@@ -2411,6 +2413,7 @@ export class Compiler extends DiagnosticEmitter {
24112413
flow.breakLabel = breakLabel;
24122414
var continueLabel = "do-continue|" + label;
24132415
flow.continueLabel = continueLabel;
2416+
var loopLabel = "do-loop|" + label;
24142417

24152418
// Compile the body (always executes)
24162419
var bodyFlow = flow.fork();
@@ -2424,7 +2427,8 @@ export class Compiler extends DiagnosticEmitter {
24242427
}
24252428

24262429
// Shortcut if body never falls through
2427-
if (bodyFlow.isAny(FlowFlags.TERMINATES | FlowFlags.BREAKS)) {
2430+
var possiblyContinues = bodyFlow.isAny(FlowFlags.CONTINUES | FlowFlags.CONDITIONALLY_CONTINUES);
2431+
if (bodyFlow.isAny(FlowFlags.TERMINATES | FlowFlags.BREAKS) && !possiblyContinues) {
24282432
bodyStmts.push(
24292433
module.unreachable()
24302434
);
@@ -2441,6 +2445,12 @@ export class Compiler extends DiagnosticEmitter {
24412445
);
24422446
let condKind = this.evaluateCondition(condExpr);
24432447

2448+
if (possiblyContinues) {
2449+
bodyStmts = [
2450+
module.block(continueLabel, bodyStmts)
2451+
];
2452+
}
2453+
24442454
// Shortcut if condition is always false
24452455
if (condKind == ConditionKind.FALSE) {
24462456
bodyStmts.push(
@@ -2454,21 +2464,16 @@ export class Compiler extends DiagnosticEmitter {
24542464
module.drop(condExpr)
24552465
);
24562466
bodyStmts.push(
2457-
module.br(continueLabel)
2467+
module.br(loopLabel)
24582468
);
24592469
flow.set(FlowFlags.TERMINATES);
24602470

24612471
} else {
2462-
let tcond = condFlow.getTempLocal(Type.bool);
24632472
bodyStmts.push(
2464-
module.local_set(tcond.index, condExpr, false) // bool
2465-
);
2466-
bodyStmts.push(
2467-
module.br(continueLabel,
2468-
module.local_get(tcond.index, TypeRef.I32)
2473+
module.br(loopLabel,
2474+
condExpr
24692475
)
24702476
);
2471-
condFlow.freeTempLocal(tcond);
24722477
flow.inherit(condFlow);
24732478

24742479
// Detect if local flags are incompatible before and after looping, and
@@ -2488,7 +2493,7 @@ export class Compiler extends DiagnosticEmitter {
24882493
outerFlow.popBreakLabel();
24892494
this.currentFlow = outerFlow;
24902495
var expr = module.block(breakLabel, [
2491-
module.loop(continueLabel,
2496+
module.loop(loopLabel,
24922497
module.flatten(bodyStmts)
24932498
)
24942499
]);

tests/compiler/NonNullable.optimized.wat

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
select
7575
i32.eqz
7676
if
77-
loop $do-continue|0
77+
loop $do-loop|0
7878
local.get $3
7979
i64.load
8080
local.get $1
@@ -95,7 +95,7 @@
9595
local.tee $0
9696
i32.const 4
9797
i32.ge_u
98-
br_if $do-continue|0
98+
br_if $do-loop|0
9999
end
100100
end
101101
end

tests/compiler/NonNullable.untouched.wat

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
end
7070
if
7171
block $do-break|0
72-
loop $do-continue|0
72+
loop $do-loop|0
7373
local.get $5
7474
i64.load
7575
local.get $6
@@ -93,9 +93,7 @@
9393
local.get $4
9494
i32.const 4
9595
i32.ge_u
96-
local.set $7
97-
local.get $7
98-
br_if $do-continue|0
96+
br_if $do-loop|0
9997
end
10098
end
10199
end

tests/compiler/builtins.optimized.wat

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@
130130
select
131131
i32.eqz
132132
if
133-
loop $do-continue|0
133+
loop $do-loop|0
134134
local.get $3
135135
i64.load
136136
local.get $1
@@ -151,7 +151,7 @@
151151
local.tee $0
152152
i32.const 4
153153
i32.ge_u
154-
br_if $do-continue|0
154+
br_if $do-loop|0
155155
end
156156
end
157157
end

tests/compiler/builtins.untouched.wat

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@
147147
end
148148
if
149149
block $do-break|0
150-
loop $do-continue|0
150+
loop $do-loop|0
151151
local.get $5
152152
i64.load
153153
local.get $6
@@ -171,9 +171,7 @@
171171
local.get $4
172172
i32.const 4
173173
i32.ge_u
174-
local.set $7
175-
local.get $7
176-
br_if $do-continue|0
174+
br_if $do-loop|0
177175
end
178176
end
179177
end

tests/compiler/call-super.optimized.wat

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,7 +1246,7 @@
12461246
block $__inlined_func$~lib/rt/itcms/interrupt
12471247
i32.const 2048
12481248
local.set $3
1249-
loop $do-continue|0
1249+
loop $do-loop|0
12501250
local.get $3
12511251
call $~lib/rt/itcms/step
12521252
i32.sub
@@ -1269,7 +1269,7 @@
12691269
local.get $3
12701270
i32.const 0
12711271
i32.gt_s
1272-
br_if $do-continue|0
1272+
br_if $do-loop|0
12731273
end
12741274
global.get $~lib/rt/itcms/total
12751275
local.tee $3

tests/compiler/call-super.untouched.wat

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1510,7 +1510,6 @@
15101510
)
15111511
(func $~lib/rt/itcms/interrupt
15121512
(local $0 i32)
1513-
(local $1 i32)
15141513
i32.const 0
15151514
drop
15161515
i32.const 0
@@ -1521,7 +1520,7 @@
15211520
i32.const 100
15221521
i32.div_u
15231522
local.set $0
1524-
loop $do-continue|0
1523+
loop $do-loop|0
15251524
local.get $0
15261525
call $~lib/rt/itcms/step
15271526
i32.sub
@@ -1549,9 +1548,7 @@
15491548
local.get $0
15501549
i32.const 0
15511550
i32.gt_s
1552-
local.set $1
1553-
local.get $1
1554-
br_if $do-continue|0
1551+
br_if $do-loop|0
15551552
end
15561553
i32.const 0
15571554
drop

tests/compiler/class-implements.optimized.wat

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,7 +1184,7 @@
11841184
block $__inlined_func$~lib/rt/itcms/interrupt
11851185
i32.const 2048
11861186
local.set $1
1187-
loop $do-continue|0
1187+
loop $do-loop|0
11881188
local.get $1
11891189
call $~lib/rt/itcms/step
11901190
i32.sub
@@ -1207,7 +1207,7 @@
12071207
local.get $1
12081208
i32.const 0
12091209
i32.gt_s
1210-
br_if $do-continue|0
1210+
br_if $do-loop|0
12111211
end
12121212
global.get $~lib/rt/itcms/total
12131213
local.tee $1

tests/compiler/class-implements.untouched.wat

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1520,7 +1520,6 @@
15201520
)
15211521
(func $~lib/rt/itcms/interrupt
15221522
(local $0 i32)
1523-
(local $1 i32)
15241523
i32.const 0
15251524
drop
15261525
i32.const 0
@@ -1531,7 +1530,7 @@
15311530
i32.const 100
15321531
i32.div_u
15331532
local.set $0
1534-
loop $do-continue|0
1533+
loop $do-loop|0
15351534
local.get $0
15361535
call $~lib/rt/itcms/step
15371536
i32.sub
@@ -1559,9 +1558,7 @@
15591558
local.get $0
15601559
i32.const 0
15611560
i32.gt_s
1562-
local.set $1
1563-
local.get $1
1564-
br_if $do-continue|0
1561+
br_if $do-loop|0
15651562
end
15661563
i32.const 0
15671564
drop

tests/compiler/class-overloading-cast.optimized.wat

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,7 +1198,7 @@
11981198
block $__inlined_func$~lib/rt/itcms/interrupt
11991199
i32.const 2048
12001200
local.set $1
1201-
loop $do-continue|0
1201+
loop $do-loop|0
12021202
local.get $1
12031203
call $~lib/rt/itcms/step
12041204
i32.sub
@@ -1221,7 +1221,7 @@
12211221
local.get $1
12221222
i32.const 0
12231223
i32.gt_s
1224-
br_if $do-continue|0
1224+
br_if $do-loop|0
12251225
end
12261226
global.get $~lib/rt/itcms/total
12271227
local.tee $1
@@ -1469,7 +1469,7 @@
14691469
select
14701470
i32.eqz
14711471
if
1472-
loop $do-continue|0
1472+
loop $do-loop|0
14731473
local.get $3
14741474
i64.load
14751475
local.get $1
@@ -1490,7 +1490,7 @@
14901490
local.tee $0
14911491
i32.const 4
14921492
i32.ge_u
1493-
br_if $do-continue|0
1493+
br_if $do-loop|0
14941494
end
14951495
end
14961496
end

tests/compiler/class-overloading-cast.untouched.wat

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1520,7 +1520,6 @@
15201520
)
15211521
(func $~lib/rt/itcms/interrupt
15221522
(local $0 i32)
1523-
(local $1 i32)
15241523
i32.const 0
15251524
drop
15261525
i32.const 0
@@ -1531,7 +1530,7 @@
15311530
i32.const 100
15321531
i32.div_u
15331532
local.set $0
1534-
loop $do-continue|0
1533+
loop $do-loop|0
15351534
local.get $0
15361535
call $~lib/rt/itcms/step
15371536
i32.sub
@@ -1559,9 +1558,7 @@
15591558
local.get $0
15601559
i32.const 0
15611560
i32.gt_s
1562-
local.set $1
1563-
local.get $1
1564-
br_if $do-continue|0
1561+
br_if $do-loop|0
15651562
end
15661563
i32.const 0
15671564
drop
@@ -2405,7 +2402,7 @@
24052402
end
24062403
if
24072404
block $do-break|0
2408-
loop $do-continue|0
2405+
loop $do-loop|0
24092406
local.get $5
24102407
i64.load
24112408
local.get $6
@@ -2429,9 +2426,7 @@
24292426
local.get $4
24302427
i32.const 4
24312428
i32.ge_u
2432-
local.set $7
2433-
local.get $7
2434-
br_if $do-continue|0
2429+
br_if $do-loop|0
24352430
end
24362431
end
24372432
end

tests/compiler/class-overloading.optimized.wat

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,7 +1222,7 @@
12221222
block $__inlined_func$~lib/rt/itcms/interrupt
12231223
i32.const 2048
12241224
local.set $1
1225-
loop $do-continue|0
1225+
loop $do-loop|0
12261226
local.get $1
12271227
call $~lib/rt/itcms/step
12281228
i32.sub
@@ -1245,7 +1245,7 @@
12451245
local.get $1
12461246
i32.const 0
12471247
i32.gt_s
1248-
br_if $do-continue|0
1248+
br_if $do-loop|0
12491249
end
12501250
global.get $~lib/rt/itcms/total
12511251
local.tee $1
@@ -1493,7 +1493,7 @@
14931493
select
14941494
i32.eqz
14951495
if
1496-
loop $do-continue|0
1496+
loop $do-loop|0
14971497
local.get $3
14981498
i64.load
14991499
local.get $1
@@ -1514,7 +1514,7 @@
15141514
local.tee $0
15151515
i32.const 4
15161516
i32.ge_u
1517-
br_if $do-continue|0
1517+
br_if $do-loop|0
15181518
end
15191519
end
15201520
end

0 commit comments

Comments
 (0)