From 996f08fb4646d5f8539d22b56217f87e4dd339e2 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 17 Aug 2026 05:46:47 +0800 Subject: [PATCH] =?UTF-8?q?fix(core):=20=E6=9C=AB=E5=8F=A5=E6=8E=A7?= =?UTF-8?q?=E5=88=B6=E6=B5=81=20merge=20=E5=8F=AF=E8=BE=BE=E6=80=A7?= =?UTF-8?q?=E5=AD=98=20trans=20=E5=AD=97=E6=AE=B5=EF=BC=88=E8=BF=BD?= =?UTF-8?q?=E5=8A=A090=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 控制流翻译器(If/While/For/Match)记录 merge 可达性到 trans._ctrl_merge_reachable; FuncGenMixin/ClassGenMixin 仅在全分支 return(结构性不可达)时生成 unreachable, 可达则正常收尾(ConstZero/fail-fast)。修复 llc O2 优化 br-to-unreachable 为 fall-through 导致 check 类函数 PASS+FAIL 双分支执行 + int3 崩溃(FuncTest)。 --- App/lib/core/Gen/ClassGenMixin.vp | 10 +++++++--- App/lib/core/Gen/FuncGenMixin.vp | 11 ++++++++--- App/lib/core/Handles/HandlesFor.vp | 14 ++++++++++++++ App/lib/core/Handles/HandlesIf.vp | 16 ++++++++++++++-- App/lib/core/Handles/HandlesMatch.vp | 10 ++++++++++ App/lib/core/Handles/HandlesTranslator.vp | 3 +++ App/lib/core/Handles/HandlesWhile.vp | 2 ++ 7 files changed, 58 insertions(+), 8 deletions(-) diff --git a/App/lib/core/Gen/ClassGenMixin.vp b/App/lib/core/Gen/ClassGenMixin.vp index 3488a8e..e9fa573 100644 --- a/App/lib/core/Gen/ClassGenMixin.vp +++ b/App/lib/core/Gen/ClassGenMixin.vp @@ -4533,9 +4533,13 @@ class ClassGenMixin: pass if _is_void != 0: llvmlite.build_ret_void(func_builder) - elif last_is_ctrl != 0: - # 非 void 方法末句是控制流且块未 terminated:merge 块 - # 结构性不可达(不可能抵达),LLVM 语义 unreachable + elif last_is_ctrl != 0 and trans._ctrl_merge_reachable == 0: + # 追加90(与 FuncGenMixin 同步):非 void 方法末句是控制流 + # 且 merge 块结构性不可达(全分支 return,无 br 到 merge) + # → LLVM 语义 unreachable。merge 可达(分支 br 到 merge)时 + # 不是结构性不可达,需正常收尾(下方 ConstZero / fail-fast)。 + # 原无条件 unreachable 使 llc O2 优化 br-to-unreachable 为 + # fall-through → 双分支执行崩溃(FuncTest check) llvmlite.build_unreachable(func_builder) elif fd.returns is None: # 无返回类型注解 → 无返回值过程方法,默认零值返回 diff --git a/App/lib/core/Gen/FuncGenMixin.vp b/App/lib/core/Gen/FuncGenMixin.vp index 0ff8f25..65ca968 100644 --- a/App/lib/core/Gen/FuncGenMixin.vp +++ b/App/lib/core/Gen/FuncGenMixin.vp @@ -1137,9 +1137,14 @@ class FuncGenMixin: pass if _is_void != 0: llvmlite.build_ret_void(func_builder) - elif last_is_ctrl != 0: - # 非 void 函数末句是控制流且块未 terminated:merge 块 - # 结构性不可达(不可能抵达),LLVM 语义 unreachable + elif last_is_ctrl != 0 and trans._ctrl_merge_reachable == 0: + # 追加90:非 void 函数末句是控制流且 merge 块结构性不可达 + # (全分支 return,无 br 到 merge)→ LLVM 语义 unreachable。 + # 注意:merge 可达(分支 br 到 merge,如 testcheck.check 的 + # if/else 无 return)时不是结构性不可达,需正常收尾(下方 + # ConstZero / fail-fast)。原实现无条件 unreachable 使 llc + # O2 把 br-to-unreachable 优化为 fall-through → 双分支执行 + # 崩溃(FuncTest check PASS+FAIL 双打印) llvmlite.build_unreachable(func_builder) elif fd.returns is None: # 无返回类型注解 → 无返回值过程函数,默认零值返回 diff --git a/App/lib/core/Handles/HandlesFor.vp b/App/lib/core/Handles/HandlesFor.vp index 8a01718..2ba73bc 100644 --- a/App/lib/core/Handles/HandlesFor.vp +++ b/App/lib/core/Handles/HandlesFor.vp @@ -418,6 +418,8 @@ class ForHandle(HandlesBase.Mixin): # 11. 定位到 end 块 llvmlite.position_at_end(builder, end_bb) + # 追加90:for 循环正常结束路径 br 到 end_bb → merge 恒可达(需正常收尾) + trans._ctrl_merge_reachable = 1 return new_vars # ============================================================ @@ -564,6 +566,8 @@ class ForHandle(HandlesBase.Mixin): # 定位到 end 块 llvmlite.position_at_end(builder, end_bb) + # 追加90:for 循环正常结束路径 br 到 end_bb → merge 恒可达(需正常收尾) + trans._ctrl_merge_reachable = 1 return new_vars # ============================================================ @@ -696,6 +700,8 @@ class ForHandle(HandlesBase.Mixin): # 定位到 end 块 llvmlite.position_at_end(builder, end_bb) + # 追加90:for 循环正常结束路径 br 到 end_bb → merge 恒可达(需正常收尾) + trans._ctrl_merge_reachable = 1 return new_vars # ============================================================ @@ -891,6 +897,8 @@ class ForHandle(HandlesBase.Mixin): # 定位到 end 块 llvmlite.position_at_end(builder, end_bb) + # 追加90:for 循环正常结束路径 br 到 end_bb → merge 恒可达(需正常收尾) + trans._ctrl_merge_reachable = 1 return new_vars def _handle_dict_iter(self, for_node: ast.For | t.CPtr, @@ -1000,6 +1008,8 @@ class ForHandle(HandlesBase.Mixin): # 定位到 end 块 llvmlite.position_at_end(builder, end_bb) + # 追加90:for 循环正常结束路径 br 到 end_bb → merge 恒可达(需正常收尾) + trans._ctrl_merge_reachable = 1 return new_vars # ============================================================ @@ -1183,6 +1193,8 @@ class ForHandle(HandlesBase.Mixin): llvmlite.position_at_end(builder, step_bb) llvmlite.build_br(builder, cond_bb) llvmlite.position_at_end(builder, end_bb) + # 追加90:for 循环正常结束路径 br 到 end_bb → merge 恒可达(需正常收尾) + trans._ctrl_merge_reachable = 1 return new_vars # ============================================================ @@ -1570,6 +1582,8 @@ class ForHandle(HandlesBase.Mixin): # 定位到 end 块 llvmlite.position_at_end(builder, end_bb) + # 追加90:for 循环正常结束路径 br 到 end_bb → merge 恒可达(需正常收尾) + trans._ctrl_merge_reachable = 1 return new_vars diff --git a/App/lib/core/Handles/HandlesIf.vp b/App/lib/core/Handles/HandlesIf.vp index dbd66fd..e260795 100644 --- a/App/lib/core/Handles/HandlesIf.vp +++ b/App/lib/core/Handles/HandlesIf.vp @@ -299,11 +299,14 @@ class IfHandle(HandlesBase.Mixin): if stmt is not None: HandlesBody.translate_stmt(trans, stmt) - # then 块未终止则跳到 merge + # then 块未终止则跳到 merge(记录 then 是否 br 到 merge) + then_branches_merge: int = 0 if llvmlite.builder_cur_block_is_terminated(builder) == 0: llvmlite.build_br(builder, merge_bb) + then_branches_merge = 1 # 6. 翻译 else body(若有) + else_branches_merge: int = 0 if has_else == 1: llvmlite.position_at_end(builder, else_bb) else_count: t.CSizeT = len(orelse_list) @@ -313,8 +316,17 @@ class IfHandle(HandlesBase.Mixin): HandlesBody.translate_stmt(trans, stmt) if llvmlite.builder_cur_block_is_terminated(builder) == 0: llvmlite.build_br(builder, merge_bb) + else_branches_merge = 1 - # 7. 定位到 merge 块继续后续代码 + # 7. merge 块可达性(追加90,末句控制流收尾判定用): + # 无 else 时 cond_br 直接跳 merge(恒可达);有 else 时任一分支 + # br 到 merge 即可达;全分支 return(无 br)才结构性不可达。 + # 经 HandlesBase 模块级全局传递(避免依赖 Translator 字段表) + trans._ctrl_merge_reachable = 1 + if has_else == 1 and then_branches_merge == 0 and else_branches_merge == 0: + trans._ctrl_merge_reachable = 0 + + # 8. 定位到 merge 块继续后续代码 llvmlite.position_at_end(builder, merge_bb) return 0 diff --git a/App/lib/core/Handles/HandlesMatch.vp b/App/lib/core/Handles/HandlesMatch.vp index ed01ab3..96abab4 100644 --- a/App/lib/core/Handles/HandlesMatch.vp +++ b/App/lib/core/Handles/HandlesMatch.vp @@ -80,6 +80,9 @@ class MatchHandle(HandlesBase.Mixin): if builder is None or func is None: return 0 + # 追加90:match merge 可达性重置(下方 br end_bb 处置 1) + trans._ctrl_merge_reachable = 0 + m_node: ast.Match | t.CPtr = (ast.Match | t.CPtr)(node) # 1. 求值 subject @@ -509,6 +512,7 @@ class MatchHandle(HandlesBase.Mixin): if llvmlite.builder_cur_block_is_terminated(builder) == 0 \ and nb == 0: llvmlite.build_br(builder, end_bb) + trans._ctrl_merge_reachable = 1 i = i + 1 @@ -518,6 +522,7 @@ class MatchHandle(HandlesBase.Mixin): # 无显式 default:default 直接跳 end if llvmlite.builder_cur_block_is_terminated(builder) == 0: llvmlite.build_br(builder, end_bb) + trans._ctrl_merge_reachable = 1 else: # 有显式 default:翻译 default case body(找到 is_def==1 的 case) di: int = 0 @@ -542,6 +547,7 @@ class MatchHandle(HandlesBase.Mixin): di = di + 1 if llvmlite.builder_cur_block_is_terminated(builder) == 0: llvmlite.build_br(builder, end_bb) + trans._ctrl_merge_reachable = 1 # 9. 定位到 end 块 llvmlite.position_at_end(builder, end_bb) @@ -980,6 +986,7 @@ class MatchHandle(HandlesBase.Mixin): llvmlite.build_br(builder, default_bb) else: llvmlite.build_br(builder, end_bb) + trans._ctrl_merge_reachable = 1 ci = ci + 1 # 7. default 块 @@ -1197,6 +1204,7 @@ class MatchHandle(HandlesBase.Mixin): if llvmlite.builder_cur_block_is_terminated(builder) == 0 \ and nb == 0: llvmlite.build_br(builder, end_bb) + trans._ctrl_merge_reachable = 1 i = i + 1 @@ -1205,6 +1213,7 @@ class MatchHandle(HandlesBase.Mixin): if has_default == 0: if llvmlite.builder_cur_block_is_terminated(builder) == 0: llvmlite.build_br(builder, end_bb) + trans._ctrl_merge_reachable = 1 else: di: int = 0 while di < collected: @@ -1228,6 +1237,7 @@ class MatchHandle(HandlesBase.Mixin): di = di + 1 if llvmlite.builder_cur_block_is_terminated(builder) == 0: llvmlite.build_br(builder, end_bb) + trans._ctrl_merge_reachable = 1 # 8. 定位到 end llvmlite.position_at_end(builder, end_bb) diff --git a/App/lib/core/Handles/HandlesTranslator.vp b/App/lib/core/Handles/HandlesTranslator.vp index ff74fce..c998ae5 100644 --- a/App/lib/core/Handles/HandlesTranslator.vp +++ b/App/lib/core/Handles/HandlesTranslator.vp @@ -109,6 +109,9 @@ class Translator: # 独立标签计数器(不与 builder.Counter 共享,避免 SSA 编号非单调) _label_counter: t.CInt + # 追加90:控制流 merge 块可达性(1=有 br 进入可达/0=全分支 return 结构性不可达) + _ctrl_merge_reachable: t.CInt + # global 声明的变量名集合(当前函数内) _global_names: str _global_name_count: t.CInt diff --git a/App/lib/core/Handles/HandlesWhile.vp b/App/lib/core/Handles/HandlesWhile.vp index 5c9da60..20ffde8 100644 --- a/App/lib/core/Handles/HandlesWhile.vp +++ b/App/lib/core/Handles/HandlesWhile.vp @@ -141,6 +141,8 @@ class WhileHandle(HandlesBase.Mixin): # 5. 定位到 end 块 llvmlite.position_at_end(builder, end_bb) + # 追加90:while 的 cond_br 恒引用 end_bb → merge 恒可达(需正常收尾) + trans._ctrl_merge_reachable = 1 return 0