From b7afa67acf85c47967b43d37ad6073e72a4e8314 Mon Sep 17 00:00:00 2001 From: CountBleck Date: Sat, 9 Mar 2024 18:20:27 -0800 Subject: [PATCH] Compile incrementors in for loops within the initializer's flow 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. --- src/compiler.ts | 1 + tests/compiler/issues/2825.debug.wat | 55 ++++++++++++++++++++++++++ tests/compiler/issues/2825.json | 1 + tests/compiler/issues/2825.release.wat | 36 +++++++++++++++++ tests/compiler/issues/2825.ts | 8 ++++ 5 files changed, 101 insertions(+) create mode 100644 tests/compiler/issues/2825.debug.wat create mode 100644 tests/compiler/issues/2825.json create mode 100644 tests/compiler/issues/2825.release.wat create mode 100644 tests/compiler/issues/2825.ts diff --git a/src/compiler.ts b/src/compiler.ts index 648b6fa24d..8e5ee85615 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -2600,6 +2600,7 @@ export class Compiler extends DiagnosticEmitter { if (possiblyLoops) { let incrementor = statement.incrementor; if (incrementor) { + this.currentFlow = flow; bodyStmts.push( this.compileExpression(incrementor, Type.void, Constraints.ConvImplicit | Constraints.WillDrop) ); diff --git a/tests/compiler/issues/2825.debug.wat b/tests/compiler/issues/2825.debug.wat new file mode 100644 index 0000000000..7c0913c266 --- /dev/null +++ b/tests/compiler/issues/2825.debug.wat @@ -0,0 +1,55 @@ +(module + (type $0 (func)) + (type $1 (func (param i32 i32 i32 i32))) + (type $2 (func (param i32) (result i32))) + (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) + (global $~lib/memory/__data_end i32 (i32.const 60)) + (global $~lib/memory/__stack_pointer (mut i32) (i32.const 32828)) + (global $~lib/memory/__heap_base i32 (i32.const 32828)) + (memory $0 1) + (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") + (table $0 1 1 funcref) + (elem $0 (i32.const 1)) + (export "memory" (memory $0)) + (start $~start) + (func $issues/2825/increment (param $x i32) (result i32) + local.get $x + i32.const 1234 + i32.ne + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 2 + i32.const 3 + call $~lib/builtins/abort + unreachable + end + local.get $x + i32.const 1 + i32.add + return + ) + (func $start:issues/2825 + (local $i i32) + (local $i|1 i32) + i32.const 0 + local.set $i + loop $for-loop|0 + local.get $i + i32.const 10 + i32.lt_s + if + i32.const 1234 + local.set $i|1 + local.get $i + call $issues/2825/increment + local.set $i + br $for-loop|0 + end + end + ) + (func $~start + call $start:issues/2825 + ) +) diff --git a/tests/compiler/issues/2825.json b/tests/compiler/issues/2825.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/tests/compiler/issues/2825.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/tests/compiler/issues/2825.release.wat b/tests/compiler/issues/2825.release.wat new file mode 100644 index 0000000000..67c8c965ac --- /dev/null +++ b/tests/compiler/issues/2825.release.wat @@ -0,0 +1,36 @@ +(module + (type $0 (func (param i32 i32 i32 i32))) + (type $1 (func)) + (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) + (memory $0 1) + (data $0 (i32.const 1036) ",") + (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") + (export "memory" (memory $0)) + (start $~start) + (func $~start + (local $0 i32) + loop $for-loop|0 + local.get $0 + i32.const 10 + i32.lt_s + if + local.get $0 + i32.const 1234 + i32.eq + if + i32.const 0 + i32.const 1056 + i32.const 2 + i32.const 3 + call $~lib/builtins/abort + unreachable + end + local.get $0 + i32.const 1 + i32.add + local.set $0 + br $for-loop|0 + end + end + ) +) diff --git a/tests/compiler/issues/2825.ts b/tests/compiler/issues/2825.ts new file mode 100644 index 0000000000..556a24a0d5 --- /dev/null +++ b/tests/compiler/issues/2825.ts @@ -0,0 +1,8 @@ +function increment(x: i32): i32 { + assert(x !== 1234); + return x + 1; +} + +for (let i = 0; i < 10; i = increment(i)) { + let i = 1234; +} \ No newline at end of file