Skip to content

Commit 9102c05

Browse files
authored
Compile incrementors in for loops within the initializer's flow (#2826)
It turns out that incrementors were compiled with the body's flow, which meant that the incrementor had access to local variables declared in the body. Now, incrementors no longer have access to such variables. Fixes #2825.
1 parent 9605c03 commit 9102c05

File tree

5 files changed

+101
-0
lines changed

5 files changed

+101
-0
lines changed

src/compiler.ts

+1
Original file line numberDiff line numberDiff line change
@@ -2600,6 +2600,7 @@ export class Compiler extends DiagnosticEmitter {
26002600
if (possiblyLoops) {
26012601
let incrementor = statement.incrementor;
26022602
if (incrementor) {
2603+
this.currentFlow = flow;
26032604
bodyStmts.push(
26042605
this.compileExpression(incrementor, Type.void, Constraints.ConvImplicit | Constraints.WillDrop)
26052606
);

tests/compiler/issues/2825.debug.wat

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
(module
2+
(type $0 (func))
3+
(type $1 (func (param i32 i32 i32 i32)))
4+
(type $2 (func (param i32) (result i32)))
5+
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
6+
(global $~lib/memory/__data_end i32 (i32.const 60))
7+
(global $~lib/memory/__stack_pointer (mut i32) (i32.const 32828))
8+
(global $~lib/memory/__heap_base i32 (i32.const 32828))
9+
(memory $0 1)
10+
(data $0 (i32.const 12) ",\00\00\00\00\00\00\00\00\00\00\00\02\00\00\00\1c\00\00\00i\00s\00s\00u\00e\00s\00/\002\008\002\005\00.\00t\00s\00")
11+
(table $0 1 1 funcref)
12+
(elem $0 (i32.const 1))
13+
(export "memory" (memory $0))
14+
(start $~start)
15+
(func $issues/2825/increment (param $x i32) (result i32)
16+
local.get $x
17+
i32.const 1234
18+
i32.ne
19+
i32.eqz
20+
if
21+
i32.const 0
22+
i32.const 32
23+
i32.const 2
24+
i32.const 3
25+
call $~lib/builtins/abort
26+
unreachable
27+
end
28+
local.get $x
29+
i32.const 1
30+
i32.add
31+
return
32+
)
33+
(func $start:issues/2825
34+
(local $i i32)
35+
(local $i|1 i32)
36+
i32.const 0
37+
local.set $i
38+
loop $for-loop|0
39+
local.get $i
40+
i32.const 10
41+
i32.lt_s
42+
if
43+
i32.const 1234
44+
local.set $i|1
45+
local.get $i
46+
call $issues/2825/increment
47+
local.set $i
48+
br $for-loop|0
49+
end
50+
end
51+
)
52+
(func $~start
53+
call $start:issues/2825
54+
)
55+
)

tests/compiler/issues/2825.json

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
(module
2+
(type $0 (func (param i32 i32 i32 i32)))
3+
(type $1 (func))
4+
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
5+
(memory $0 1)
6+
(data $0 (i32.const 1036) ",")
7+
(data $0.1 (i32.const 1048) "\02\00\00\00\1c\00\00\00i\00s\00s\00u\00e\00s\00/\002\008\002\005\00.\00t\00s")
8+
(export "memory" (memory $0))
9+
(start $~start)
10+
(func $~start
11+
(local $0 i32)
12+
loop $for-loop|0
13+
local.get $0
14+
i32.const 10
15+
i32.lt_s
16+
if
17+
local.get $0
18+
i32.const 1234
19+
i32.eq
20+
if
21+
i32.const 0
22+
i32.const 1056
23+
i32.const 2
24+
i32.const 3
25+
call $~lib/builtins/abort
26+
unreachable
27+
end
28+
local.get $0
29+
i32.const 1
30+
i32.add
31+
local.set $0
32+
br $for-loop|0
33+
end
34+
end
35+
)
36+
)

tests/compiler/issues/2825.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
function increment(x: i32): i32 {
2+
assert(x !== 1234);
3+
return x + 1;
4+
}
5+
6+
for (let i = 0; i < 10; i = increment(i)) {
7+
let i = 1234;
8+
}

0 commit comments

Comments
 (0)