Skip to content

Commit

Permalink
fix: Properly handle conditional continue in do loops (#2055)
Browse files Browse the repository at this point in the history
  • Loading branch information
dcodeIO committed Sep 10, 2021
1 parent 1bf3120 commit d864c1a
Show file tree
Hide file tree
Showing 163 changed files with 813 additions and 1,131 deletions.
35 changes: 20 additions & 15 deletions src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2391,13 +2391,15 @@ export class Compiler extends DiagnosticEmitter {
var outerFlow = this.currentFlow;

// (block $break └►┐ flow
// (loop $continue ├◄───────────┐ recompile?
// (body) └─┐ bodyFlow │
// ┌─┘ │
// (loop $loop ├◄───────────┐ recompile?
// (?block $continue └─┐ │
// (body) │ bodyFlow │
// ) ┌─┘ │
// ┌◄┼►╢ │ breaks or terminates?
// (local.set $tcond (condition)) │ └─┐ condFlow │
// │ └─┐ │ but does not continue
// (br_if (cond) $loop) │ │ condFlow │
// │ ┌─┘ │
// (br_if (local.get $tcond) $continue) ├◄┴────────────┘ condition?
// ├◄┴────────────┘ condition?
// ) └─┐
// ) ┌─┘

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

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

// Shortcut if body never falls through
if (bodyFlow.isAny(FlowFlags.TERMINATES | FlowFlags.BREAKS)) {
var possiblyContinues = bodyFlow.isAny(FlowFlags.CONTINUES | FlowFlags.CONDITIONALLY_CONTINUES);
if (bodyFlow.isAny(FlowFlags.TERMINATES | FlowFlags.BREAKS) && !possiblyContinues) {
bodyStmts.push(
module.unreachable()
);
Expand All @@ -2441,6 +2445,12 @@ export class Compiler extends DiagnosticEmitter {
);
let condKind = this.evaluateCondition(condExpr);

if (possiblyContinues) {
bodyStmts = [
module.block(continueLabel, bodyStmts)
];
}

// Shortcut if condition is always false
if (condKind == ConditionKind.FALSE) {
bodyStmts.push(
Expand All @@ -2454,21 +2464,16 @@ export class Compiler extends DiagnosticEmitter {
module.drop(condExpr)
);
bodyStmts.push(
module.br(continueLabel)
module.br(loopLabel)
);
flow.set(FlowFlags.TERMINATES);

} else {
let tcond = condFlow.getTempLocal(Type.bool);
bodyStmts.push(
module.local_set(tcond.index, condExpr, false) // bool
);
bodyStmts.push(
module.br(continueLabel,
module.local_get(tcond.index, TypeRef.I32)
module.br(loopLabel,
condExpr
)
);
condFlow.freeTempLocal(tcond);
flow.inherit(condFlow);

// Detect if local flags are incompatible before and after looping, and
Expand All @@ -2488,7 +2493,7 @@ export class Compiler extends DiagnosticEmitter {
outerFlow.popBreakLabel();
this.currentFlow = outerFlow;
var expr = module.block(breakLabel, [
module.loop(continueLabel,
module.loop(loopLabel,
module.flatten(bodyStmts)
)
]);
Expand Down
4 changes: 2 additions & 2 deletions tests/compiler/NonNullable.optimized.wat
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
select
i32.eqz
if
loop $do-continue|0
loop $do-loop|0
local.get $3
i64.load
local.get $1
Expand All @@ -95,7 +95,7 @@
local.tee $0
i32.const 4
i32.ge_u
br_if $do-continue|0
br_if $do-loop|0
end
end
end
Expand Down
6 changes: 2 additions & 4 deletions tests/compiler/NonNullable.untouched.wat
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
end
if
block $do-break|0
loop $do-continue|0
loop $do-loop|0
local.get $5
i64.load
local.get $6
Expand All @@ -93,9 +93,7 @@
local.get $4
i32.const 4
i32.ge_u
local.set $7
local.get $7
br_if $do-continue|0
br_if $do-loop|0
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions tests/compiler/builtins.optimized.wat
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
select
i32.eqz
if
loop $do-continue|0
loop $do-loop|0
local.get $3
i64.load
local.get $1
Expand All @@ -151,7 +151,7 @@
local.tee $0
i32.const 4
i32.ge_u
br_if $do-continue|0
br_if $do-loop|0
end
end
end
Expand Down
6 changes: 2 additions & 4 deletions tests/compiler/builtins.untouched.wat
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@
end
if
block $do-break|0
loop $do-continue|0
loop $do-loop|0
local.get $5
i64.load
local.get $6
Expand All @@ -171,9 +171,7 @@
local.get $4
i32.const 4
i32.ge_u
local.set $7
local.get $7
br_if $do-continue|0
br_if $do-loop|0
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions tests/compiler/call-super.optimized.wat
Original file line number Diff line number Diff line change
Expand Up @@ -1246,7 +1246,7 @@
block $__inlined_func$~lib/rt/itcms/interrupt
i32.const 2048
local.set $3
loop $do-continue|0
loop $do-loop|0
local.get $3
call $~lib/rt/itcms/step
i32.sub
Expand All @@ -1269,7 +1269,7 @@
local.get $3
i32.const 0
i32.gt_s
br_if $do-continue|0
br_if $do-loop|0
end
global.get $~lib/rt/itcms/total
local.tee $3
Expand Down
7 changes: 2 additions & 5 deletions tests/compiler/call-super.untouched.wat
Original file line number Diff line number Diff line change
Expand Up @@ -1510,7 +1510,6 @@
)
(func $~lib/rt/itcms/interrupt
(local $0 i32)
(local $1 i32)
i32.const 0
drop
i32.const 0
Expand All @@ -1521,7 +1520,7 @@
i32.const 100
i32.div_u
local.set $0
loop $do-continue|0
loop $do-loop|0
local.get $0
call $~lib/rt/itcms/step
i32.sub
Expand Down Expand Up @@ -1549,9 +1548,7 @@
local.get $0
i32.const 0
i32.gt_s
local.set $1
local.get $1
br_if $do-continue|0
br_if $do-loop|0
end
i32.const 0
drop
Expand Down
4 changes: 2 additions & 2 deletions tests/compiler/class-implements.optimized.wat
Original file line number Diff line number Diff line change
Expand Up @@ -1184,7 +1184,7 @@
block $__inlined_func$~lib/rt/itcms/interrupt
i32.const 2048
local.set $1
loop $do-continue|0
loop $do-loop|0
local.get $1
call $~lib/rt/itcms/step
i32.sub
Expand All @@ -1207,7 +1207,7 @@
local.get $1
i32.const 0
i32.gt_s
br_if $do-continue|0
br_if $do-loop|0
end
global.get $~lib/rt/itcms/total
local.tee $1
Expand Down
7 changes: 2 additions & 5 deletions tests/compiler/class-implements.untouched.wat
Original file line number Diff line number Diff line change
Expand Up @@ -1520,7 +1520,6 @@
)
(func $~lib/rt/itcms/interrupt
(local $0 i32)
(local $1 i32)
i32.const 0
drop
i32.const 0
Expand All @@ -1531,7 +1530,7 @@
i32.const 100
i32.div_u
local.set $0
loop $do-continue|0
loop $do-loop|0
local.get $0
call $~lib/rt/itcms/step
i32.sub
Expand Down Expand Up @@ -1559,9 +1558,7 @@
local.get $0
i32.const 0
i32.gt_s
local.set $1
local.get $1
br_if $do-continue|0
br_if $do-loop|0
end
i32.const 0
drop
Expand Down
8 changes: 4 additions & 4 deletions tests/compiler/class-overloading-cast.optimized.wat
Original file line number Diff line number Diff line change
Expand Up @@ -1198,7 +1198,7 @@
block $__inlined_func$~lib/rt/itcms/interrupt
i32.const 2048
local.set $1
loop $do-continue|0
loop $do-loop|0
local.get $1
call $~lib/rt/itcms/step
i32.sub
Expand All @@ -1221,7 +1221,7 @@
local.get $1
i32.const 0
i32.gt_s
br_if $do-continue|0
br_if $do-loop|0
end
global.get $~lib/rt/itcms/total
local.tee $1
Expand Down Expand Up @@ -1469,7 +1469,7 @@
select
i32.eqz
if
loop $do-continue|0
loop $do-loop|0
local.get $3
i64.load
local.get $1
Expand All @@ -1490,7 +1490,7 @@
local.tee $0
i32.const 4
i32.ge_u
br_if $do-continue|0
br_if $do-loop|0
end
end
end
Expand Down
13 changes: 4 additions & 9 deletions tests/compiler/class-overloading-cast.untouched.wat
Original file line number Diff line number Diff line change
Expand Up @@ -1520,7 +1520,6 @@
)
(func $~lib/rt/itcms/interrupt
(local $0 i32)
(local $1 i32)
i32.const 0
drop
i32.const 0
Expand All @@ -1531,7 +1530,7 @@
i32.const 100
i32.div_u
local.set $0
loop $do-continue|0
loop $do-loop|0
local.get $0
call $~lib/rt/itcms/step
i32.sub
Expand Down Expand Up @@ -1559,9 +1558,7 @@
local.get $0
i32.const 0
i32.gt_s
local.set $1
local.get $1
br_if $do-continue|0
br_if $do-loop|0
end
i32.const 0
drop
Expand Down Expand Up @@ -2405,7 +2402,7 @@
end
if
block $do-break|0
loop $do-continue|0
loop $do-loop|0
local.get $5
i64.load
local.get $6
Expand All @@ -2429,9 +2426,7 @@
local.get $4
i32.const 4
i32.ge_u
local.set $7
local.get $7
br_if $do-continue|0
br_if $do-loop|0
end
end
end
Expand Down
8 changes: 4 additions & 4 deletions tests/compiler/class-overloading.optimized.wat
Original file line number Diff line number Diff line change
Expand Up @@ -1222,7 +1222,7 @@
block $__inlined_func$~lib/rt/itcms/interrupt
i32.const 2048
local.set $1
loop $do-continue|0
loop $do-loop|0
local.get $1
call $~lib/rt/itcms/step
i32.sub
Expand All @@ -1245,7 +1245,7 @@
local.get $1
i32.const 0
i32.gt_s
br_if $do-continue|0
br_if $do-loop|0
end
global.get $~lib/rt/itcms/total
local.tee $1
Expand Down Expand Up @@ -1493,7 +1493,7 @@
select
i32.eqz
if
loop $do-continue|0
loop $do-loop|0
local.get $3
i64.load
local.get $1
Expand All @@ -1514,7 +1514,7 @@
local.tee $0
i32.const 4
i32.ge_u
br_if $do-continue|0
br_if $do-loop|0
end
end
end
Expand Down

0 comments on commit d864c1a

Please sign in to comment.