From 528a480963301fa0f46f36ca9bd349ba56fbb201 Mon Sep 17 00:00:00 2001
From: Congcong Cai <congcong.cai@bmw.com>
Date: Wed, 10 Apr 2024 10:35:31 +0800
Subject: [PATCH] fix: for loop statement incrementor will be processed in
 correct context

Fixes: #2838
incrementor in for loop statement should be processed after executing body.
---
 src/compiler.ts                        | 16 ++++++++--------
 tests/compiler/issues/2825.debug.wat   | 14 ++++++++++++++
 tests/compiler/issues/2825.json        |  2 +-
 tests/compiler/issues/2825.release.wat | 11 +++++++++--
 tests/compiler/issues/2825.ts          |  9 ++++++++-
 5 files changed, 40 insertions(+), 12 deletions(-)

diff --git a/src/compiler.ts b/src/compiler.ts
index 8e5ee85615..d40804d9e0 100644
--- a/src/compiler.ts
+++ b/src/compiler.ts
@@ -2595,6 +2595,14 @@ export class Compiler extends DiagnosticEmitter {
       bodyStmts.length = 1;
     }
 
+    if (condKind == ConditionKind.True) {
+      // Body executes at least once
+      flow.inherit(bodyFlow);
+    } else {
+      // Otherwise executes conditionally
+      flow.mergeBranch(bodyFlow);
+    }
+
     // Compile the incrementor if it possibly executes
     let possiblyLoops = possiblyContinues || possiblyFallsThrough;
     if (possiblyLoops) {
@@ -2618,14 +2626,6 @@ export class Compiler extends DiagnosticEmitter {
       }
     }
 
-    // Body executes at least once
-    if (condKind == ConditionKind.True) {
-      flow.inherit(bodyFlow);
-
-    // Otherwise executes conditionally
-    } else {
-      flow.mergeBranch(bodyFlow);
-    }
 
     // Finalize
     outerFlow.inherit(flow);
diff --git a/tests/compiler/issues/2825.debug.wat b/tests/compiler/issues/2825.debug.wat
index 7c0913c266..4ecc4ddd57 100644
--- a/tests/compiler/issues/2825.debug.wat
+++ b/tests/compiler/issues/2825.debug.wat
@@ -10,6 +10,7 @@
  (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 "init" (func $issues/2825/init))
  (export "memory" (memory $0))
  (start $~start)
  (func $issues/2825/increment (param $x i32) (result i32)
@@ -49,6 +50,19 @@
    end
   end
  )
+ (func $issues/2825/init
+  (local $not_unassigned i32)
+  loop $for-loop|0
+   i32.const 1
+   if
+    i32.const 0
+    local.set $not_unassigned
+    local.get $not_unassigned
+    drop
+    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
index 9e26dfeeb6..0967ef424b 100644
--- a/tests/compiler/issues/2825.json
+++ b/tests/compiler/issues/2825.json
@@ -1 +1 @@
-{}
\ No newline at end of file
+{}
diff --git a/tests/compiler/issues/2825.release.wat b/tests/compiler/issues/2825.release.wat
index 67c8c965ac..c11fb2dae0 100644
--- a/tests/compiler/issues/2825.release.wat
+++ b/tests/compiler/issues/2825.release.wat
@@ -1,12 +1,19 @@
 (module
- (type $0 (func (param i32 i32 i32 i32)))
- (type $1 (func))
+ (type $0 (func))
+ (type $1 (func (param i32 i32 i32 i32)))
  (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 "init" (func $issues/2825/init))
  (export "memory" (memory $0))
  (start $~start)
+ (func $issues/2825/init
+  loop $for-loop|0
+   br $for-loop|0
+  end
+  unreachable
+ )
  (func $~start
   (local $0 i32)
   loop $for-loop|0
diff --git a/tests/compiler/issues/2825.ts b/tests/compiler/issues/2825.ts
index 556a24a0d5..f563fd5bf7 100644
--- a/tests/compiler/issues/2825.ts
+++ b/tests/compiler/issues/2825.ts
@@ -5,4 +5,11 @@ function increment(x: i32): i32 {
 
 for (let i = 0; i < 10; i = increment(i)) {
   let i = 1234;
-}
\ No newline at end of file
+}
+
+export function init(): void {
+  let not_unassigned: i32;
+  for (; ; not_unassigned) {
+    not_unassigned = 0;
+  }
+}