fix(core): 末句控制流 merge 可达性存 trans 字段(追加90)

控制流翻译器(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)。
This commit is contained in:
TermiNexus committed 2026-08-17 05:46:47 +08:00
1 parent f4a990c074
commit 996f08fb46
7 files changed
+58 -8

No files matched your search

+7 -3
View File
@@ -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:
# 无返回类型注解 → 无返回值过程方法,默认零值返回
+8 -3
View File
@@ -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:
# 无返回类型注解 → 无返回值过程函数,默认零值返回
+14
View File
@@ -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
+14 -2
View File
@@ -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
+10
View File
@@ -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)
@@ -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
+2
View File
@@ -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