Skip to content

fix: JIT multi-return specialization, tail-arg stmt splicing, varargs UB, reserved C names - #21

Merged
esrrhs merged 1 commit into
masterfrom
fix/jit-multireturn-tailargs-varargs-main
Oct 2, 2026
Merged

esrrhs merged 1 commit into
masterfrom
fix/jit-multireturn-tailargs-varargs-main

Conversation

@esrrhs

@esrrhs esrrhs commented Oct 2, 2026

Copy link
Copy Markdown
Owner

Summary

修复外部 JIT bug 报告(FAKELUA_JIT_BUG_REPORT.md)中的 4 个缺陷,全部在最新 master 上复现并修复,TCC / GCC / INTERP 三后端验证通过。

1. 多返回值函数被数学参数特化,生成非法 C(严重)

mr(x) 返回 y, y+1, y+2 时,特化变体 mr_0(int64_t) / mr_1(double) 在标量返回值函数体里生成 return FlMakeMulti(...)(CVar),TCC 报 cannot convert 'struct CVar' to 'long long',GCC 同理。return ...、return f()(f 可能返回多值)同属此类。

修复:

  • TypeInferencer 新增 IsEligibleForMathSpec,遍历函数全部语句(含 if/while/repeat/for/do 嵌套,不进入嵌套函数定义),凡存在多值 return、尾 vararg 展开、或尾调用无法静态证明为单返回值者,一律不做特化,只生成通用 CVar 变体;裸 return 仍允许(返回类型安全退化为 CVar)。
  • SemanticAnalysis 新增 function_effective_returns:把「return f() 沿被调链的有效返回数」做定点求解,可穿透多层尾调用,并为带单值基线的递归(如阶乘)保留特化;vararg/未知外部被调/无锚点递归环保守判为不可知。该字段仅用于资格判定,不改变既有代码生成路径。

2. 尾参数展开把语句宏拼进表达式位置(严重)

CompileCallArgs 中 Out() << ... << CompileExp(...) << ... 的链式输出,会被 CompileExp 中途写入的慢路径语句(OpAdd 展开的 do{}while(0)、math.floor 的 if/else 类型分支)撕成 x = do{...}while(0);,TCC 报 expression expected before 'do'。generic-for 超过 3 个表达式时的丢弃位((void)(...))有完全相同的隐患。

修复:两处都改为「先求值 CompileExp,再拼接输出」。

3. FlMakeClosure 用 bool 作 va_start 锚点(UB)

C17 7.16.1.4 规定 va_start 最后一个具名形参若受默认实参提升影响(bool→int)行为未定义,Clang 产生 -Wvarargs。参数类型 bool is_vararg 改为 int is_vararg,调用处 true/false 隐式转换,改后 GCC JIT 编译零警告。

4. 用户函数占用 C 保留/外部符号名

Lua 顶层函数名为 main 时 Clang 报 first parameter of 'main' must be of type 'int';名为 sin 时连 TCC 都报 incompatible types for redefinition of 'sin'(与 libc 冲突)。

修复:顶层用户函数的 C 符号统一加 flua_fn_ 前缀(嵌套函数本就是 __fl_func_N),Lua 侧函数名与调用方式完全不变;去重逻辑保留。

Tests

  • 新增 3 个 infer 回归(test/lua/infer/test_jitbug_*.lua + test/test_infer.cpp),每个用例经 InferRunHelper 在 TCC/GCC/INTERP × debug/release 共 6 种配置下运行:
    • test_jitbug_multi_return_no_spec:多返回值/vararg/尾透传不生成标量特化且多返回值语义正确(115/235、120/240),并反向锁定带单值基线的尾递归仍特化(factacc_0_0);
    • test_jitbug_tail_expand_stmt:尾实参展开 + generic-for 第 4 表达式,语句宏不再撕裂表达式;
    • test_jitbug_reserved_func_name:main/sin 生成 flua_fn_main/flua_fn_sin,Lua 原名调用正常。
  • 更新 test_infer.cpp 中受符号前缀影响的既有断言(统一为 flua_fn_ 前缀)。
  • 本地全量 unit_tests:1553 中 1549 通过;唯一 4 个失败为 test_redis.integration_*,原因是本机无 Redis(connect failed: Connection refused),与本改动无关。

Fix four JIT codegen defects found via FAKELUA_JIT_BUG_REPORT:

1. Multi-return/vararg/tail-call functions are no longer math-specialized.
   A scalar specialization could emit "return FlMakeMulti(...)" inside an
   int64_t/double function, producing illegal C (TCC: cannot convert
   'struct CVar' to 'long long'). TypeInferencer now runs an eligibility
   walk over every return statement; "return f()" is allowed only when f's
   effective return count is statically 1, solved by a new
   function_effective_returns fixed-point in SemanticAnalysis that also
   resolves transitive tail calls and recursion with a single-value base.

2. Tail-argument expansion no longer splices statement macros into
   expression position: CompileExp is evaluated before streaming the
   assignment in CompileCallArgs, and generic-for discarded expressions
   (>3 exps) use the same evaluate-then-emit ordering (TCC: expression
   expected before 'do').

3. FlMakeClosure's is_vararg parameter is int instead of bool: using a
   bool as the va_start anchor is undefined behavior per C17 7.16.1.4
   and triggered -Wvarargs.

4. Top-level user functions are emitted with a unified flua_fn_ C-symbol
   prefix, avoiding Clang's main() signature check and redefinition
   conflicts with libc symbols (e.g. sin, TCC redefinition error). Lua
   names are unchanged.

Add infer regression tests (all JIT backends x debug modes) covering
multi-return/vararg/tail-transparency/recursive-anchor eligibility,
tail-expansion statement ordering, and reserved function naming.
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 93.07692% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.82%. Comparing base (d0db1dc) to head (9b3b522).

Files with missing lines Patch % Lines
src/compile/type_inferencer.cpp 88.13% 7 Missing ⚠️
src/compile/c_gen.cpp 90.00% 1 Missing ⚠️
src/compile/semantic_analysis.cpp 98.33% 1 Missing ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@            Coverage Diff             @@
##           master      #21      +/-   ##
==========================================
+ Coverage   87.80%   87.82%   +0.02%     
==========================================
  Files         119      119              
  Lines       24042    24161     +119     
==========================================
+ Hits        21110    21220     +110     
- Misses       2932     2941       +9     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@esrrhs
esrrhs merged commit 236a757 into master Oct 2, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants