From f5b3e465431f7ded241d6a8ce7134acda5a35f13 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 19 Aug 2026 20:35:22 +0800 Subject: [PATCH] =?UTF-8?q?fix(gen):=20while=201=20=E6=97=A0=E9=99=90?= =?UTF-8?q?=E5=BE=AA=E7=8E=AF=E6=97=A0=20break=20=E5=88=A4=E5=AE=9A=20merg?= =?UTF-8?q?e=20=E4=B8=8D=E5=8F=AF=E8=BE=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HandlesWhile 翻译 while 后无条件置 _ctrl_merge_reachable=1,导致末句为 `while 1:`(条件常量真且循环体仅 return 无 break)的函数在收尾检查被 误判"流程掉出末尾未显式 return"(vrandom.gammavariate TypeError)。 新增 _IsConstTrue/_StmtHasBreak(跳过嵌套循环子树):常量真且无本层 break 时 merge 结构性不可达 → 置 0,函数收尾对末句 While 生成 unreachable。 --- App/lib/core/Handles/HandlesWhile.vp | 67 ++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/App/lib/core/Handles/HandlesWhile.vp b/App/lib/core/Handles/HandlesWhile.vp index 20ffde8..21a38a3 100644 --- a/App/lib/core/Handles/HandlesWhile.vp +++ b/App/lib/core/Handles/HandlesWhile.vp @@ -143,6 +143,13 @@ class WhileHandle(HandlesBase.Mixin): llvmlite.position_at_end(builder, end_bb) # 追加90:while 的 cond_br 恒引用 end_bb → merge 恒可达(需正常收尾) trans._ctrl_merge_reachable = 1 + # 无限循环(条件常量真 1/True)且循环体无本层 break → 运行时无任何边 + # 到达 end 块(merge 结构性不可达)→ 置 0,函数收尾对末句 While 生成 + # unreachable(追加90:无 br 到达 merge 时才安全;否则 llc O2 把 + # br-to-unreachable 优化为 fall-through → 双分支执行崩溃)。 + # 修复 vrandom.gammavariate 的 while 1 全 return 被误判"流程掉出末尾"。 + if _IsConstTrue(while_node.test) != 0 and _StmtHasBreak(body) == 0: + trans._ctrl_merge_reachable = 0 return 0 @@ -157,3 +164,63 @@ def NewWhileHandle(pool: memhub.MemBuddy | t.CPtr, if g is not None: return g.NewWhileHandle(pool, trans) return None + + +# ============================================================ +# 无限循环判定辅助(merge 可达性) +# +# _IsConstTrue: while 条件为常量真(CONST_INT 非 0 / CONST_BOOL 真) +# _NodeHasBreak / _StmtHasBreak: 扫描本层 break(跳过嵌套 While/For +# 子树——嵌套循环的 break 归内层,不影响外层 merge 可达性) +# ============================================================ +def _IsConstTrue(test: ast.AST | t.CPtr) -> int: + """while 条件为常量真(1 / True)返回 1""" + if test is None: + return 0 + if test.kind() == ast.ASTKind.Constant: + cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(test) + if cn.const_kind == ast.CONST_INT and cn.int_val != 0: + return 1 + if cn.const_kind == ast.CONST_BOOL and cn.int_val != 0: + return 1 + return 0 + + +def _NodeHasBreak(node: ast.AST | t.CPtr) -> int: + """递归扫描节点子树(跳过嵌套 While/For 子树),含 Break 返回 1""" + if node is None: + return 0 + ch: list[ast.AST | t.CPtr] | t.CPtr = node.children + if ch is not None: + n: t.CSizeT = len(ch) + for bi in range(n): + c: ast.AST | t.CPtr = ch.get(bi) + if c is None: + continue + k: int = c.kind() + if k == ast.ASTKind.Break: + return 1 + if k == ast.ASTKind.While or k == ast.ASTKind.For: + continue + if _NodeHasBreak(c) != 0: + return 1 + return 0 + + +def _StmtHasBreak(body: list[ast.AST | t.CPtr] | t.CPtr) -> int: + """语句列表是否含本层 break(嵌套循环的 break 归内层)""" + if body is None: + return 0 + n: t.CSizeT = len(body) + for bi in range(n): + s: ast.AST | t.CPtr = body.get(bi) + if s is None: + continue + k: int = s.kind() + if k == ast.ASTKind.Break: + return 1 + if k == ast.ASTKind.While or k == ast.ASTKind.For: + continue + if _NodeHasBreak(s) != 0: + return 1 + return 0