fix(match): case 体末句控制流全 return 补 unreachable 不 br end_bb
根因(ClassGenEnum._get_type_align 掉出末尾):case 体末句是 If/控制流且 全分支 return 时,处理器把 builder 停在无 terminator 的 merge 块,case 循环的 is_terminated 误判未终止 → 补 br end_bb → rm/sq/sm_merge_reach=1 → 全 case return 的 match 被误判 merge 可达 → 函数收尾 fail-fast '流程掉出末尾'。新增模块级 _case_tail_unreachable:末句控制流 (If/While/For/Match)且 _ctrl_merge_reachable==0 时补 unreachable, 与 HandlesIf L309-315 / ClassGenVTable L1084 同语义;应用于 renum/ sequence/simple 三路的 case 体与 default 收尾(不含 Try/With,其处理器 不维护该标志)。
This commit is contained in:
1 parent
fa52fbd4e5
commit
4d7a6db31a
1 file changed
+62
-9
@@ -44,6 +44,44 @@ MAX_MATCH_CASES: t.CDefine = 32
|
||||
SCOPE_MATCH: t.CDefine = 6
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _case_tail_unreachable - case 体末尾结构性不可达判定
|
||||
#
|
||||
# case 体翻译后当前块若未终止,且末句是控制流语句(If/While/For/Match)
|
||||
# 且其 merge 结构性不可达(全分支 return,如 case Int(bits): if ... return)
|
||||
# 时,当前块是控制流的 merge(无 terminator),与 HandlesIf L309-315/
|
||||
# ClassGenVTable L1084 同语义补 unreachable。返回 1= 已补 unreachable
|
||||
# (调用方不应 br end_bb);0= 正常收尾(应 br end_bb)。
|
||||
#
|
||||
# 根因(ClassGenEnum._get_type_align):case 体末句 If 全 return 时,If
|
||||
# 处理器把 builder 停在无 terminator 的 merge 块,case 循环的
|
||||
# is_terminated 检查误判"未终止" → 补 br end_bb → rm_merge_reach=1 →
|
||||
# 全 case return 的 match 被误判 merge 可达 → 函数收尾 fail-fast
|
||||
# "流程掉出末尾"。不含 Try/With:其处理器不维护 _ctrl_merge_reachable,
|
||||
# 避免残留值误判。
|
||||
# ============================================================
|
||||
def _case_tail_unreachable(trans: HT.Translator | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
body_list: list[ast.AST | t.CPtr] | t.CPtr) -> int:
|
||||
if trans is None or builder is None:
|
||||
return 0
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) != 0:
|
||||
return 0
|
||||
if body_list is None or len(body_list) == 0:
|
||||
return 0
|
||||
lst: ast.AST | t.CPtr = body_list.get(len(body_list) - 1)
|
||||
if lst is None:
|
||||
return 0
|
||||
lk: int = lst.kind()
|
||||
if lk != ast.ASTKind.If and lk != ast.ASTKind.While \
|
||||
and lk != ast.ASTKind.For and lk != ast.ASTKind.Match:
|
||||
return 0
|
||||
if trans._ctrl_merge_reachable != 0:
|
||||
return 0
|
||||
llvmlite.build_unreachable(builder)
|
||||
return 1
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesStruct 模式)
|
||||
#
|
||||
@@ -519,8 +557,10 @@ class MatchHandle(HandlesBase.Mixin):
|
||||
HandlesVar.exit_scope(trans.SymTab)
|
||||
|
||||
# 若未终止且无 NoBreak,跳到 end
|
||||
# 末句控制流全 return(结构性不可达)时补 unreachable,不 br end_bb
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0 \
|
||||
and nb == 0:
|
||||
and nb == 0 \
|
||||
and _case_tail_unreachable(trans, builder, body_list) == 0:
|
||||
llvmlite.build_br(builder, end_bb)
|
||||
trans._ctrl_merge_reachable = 1
|
||||
rm_merge_reach = 1
|
||||
@@ -537,6 +577,7 @@ class MatchHandle(HandlesBase.Mixin):
|
||||
rm_merge_reach = 1
|
||||
else:
|
||||
# 有显式 default:翻译 default case body(找到 is_def==1 的 case)
|
||||
dbody: list[ast.AST | t.CPtr] | t.CPtr = None
|
||||
di: int = 0
|
||||
while di < collected:
|
||||
if def_arr[di] == 1:
|
||||
@@ -545,7 +586,7 @@ class MatchHandle(HandlesBase.Mixin):
|
||||
dmc: ast.MatchCase | t.CPtr = (
|
||||
ast.MatchCase | t.CPtr)(dcase)
|
||||
HandlesVar.enter_scope(trans.SymTab, SCOPE_MATCH)
|
||||
dbody: list[ast.AST | t.CPtr] | t.CPtr = dmc.children
|
||||
dbody = dmc.children
|
||||
if dbody is not None:
|
||||
dn: t.CSizeT = len(dbody)
|
||||
dj: int = 0
|
||||
@@ -557,7 +598,9 @@ class MatchHandle(HandlesBase.Mixin):
|
||||
HandlesVar.exit_scope(trans.SymTab)
|
||||
break
|
||||
di = di + 1
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
|
||||
# 末句控制流全 return → 补 unreachable(不 br end_bb)
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0 \
|
||||
and _case_tail_unreachable(trans, builder, dbody) == 0:
|
||||
llvmlite.build_br(builder, end_bb)
|
||||
trans._ctrl_merge_reachable = 1
|
||||
rm_merge_reach = 1
|
||||
@@ -988,7 +1031,9 @@ class MatchHandle(HandlesBase.Mixin):
|
||||
HandlesBody.translate_stmt(trans, stmt)
|
||||
bi = bi + 1
|
||||
HandlesVar.exit_scope(trans.SymTab)
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
|
||||
# 末句控制流全 return → 补 unreachable(不 br end,无 fallthrough)
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0 \
|
||||
and _case_tail_unreachable(trans, builder, body_list2) == 0:
|
||||
if nb_arr[ci] == 0:
|
||||
llvmlite.build_br(builder, end_bb)
|
||||
else:
|
||||
@@ -1011,6 +1056,7 @@ class MatchHandle(HandlesBase.Mixin):
|
||||
|
||||
# 7. default 块
|
||||
llvmlite.position_at_end(builder, default_bb)
|
||||
dbody: list[ast.AST | t.CPtr] | t.CPtr = None
|
||||
if has_default == 1:
|
||||
di: int = 0
|
||||
while di < collected:
|
||||
@@ -1020,7 +1066,7 @@ class MatchHandle(HandlesBase.Mixin):
|
||||
dmc: ast.MatchCase | t.CPtr = (
|
||||
ast.MatchCase | t.CPtr)(dnode)
|
||||
HandlesVar.enter_scope(trans.SymTab, SCOPE_MATCH)
|
||||
dbody: list[ast.AST | t.CPtr] | t.CPtr = dmc.children
|
||||
dbody = dmc.children
|
||||
if dbody is not None:
|
||||
dn: t.CSizeT = len(dbody)
|
||||
dj: int = 0
|
||||
@@ -1032,7 +1078,9 @@ class MatchHandle(HandlesBase.Mixin):
|
||||
HandlesVar.exit_scope(trans.SymTab)
|
||||
break
|
||||
di = di + 1
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
|
||||
# 末句控制流全 return → 补 unreachable(不 br end_bb)
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0 \
|
||||
and _case_tail_unreachable(trans, builder, dbody) == 0:
|
||||
llvmlite.build_br(builder, end_bb)
|
||||
sq_merge_reach = 1
|
||||
|
||||
@@ -1227,8 +1275,10 @@ class MatchHandle(HandlesBase.Mixin):
|
||||
|
||||
HandlesVar.exit_scope(trans.SymTab)
|
||||
|
||||
# 末句控制流全 return → 补 unreachable(不 br end_bb)
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0 \
|
||||
and nb == 0:
|
||||
and nb == 0 \
|
||||
and _case_tail_unreachable(trans, builder, body_list) == 0:
|
||||
llvmlite.build_br(builder, end_bb)
|
||||
trans._ctrl_merge_reachable = 1
|
||||
sm_merge_reach = 1
|
||||
@@ -1243,6 +1293,7 @@ class MatchHandle(HandlesBase.Mixin):
|
||||
trans._ctrl_merge_reachable = 1
|
||||
sm_merge_reach = 1
|
||||
else:
|
||||
dbody: list[ast.AST | t.CPtr] | t.CPtr = None
|
||||
di: int = 0
|
||||
while di < collected:
|
||||
if def_arr[di] == 1:
|
||||
@@ -1251,7 +1302,7 @@ class MatchHandle(HandlesBase.Mixin):
|
||||
dmc: ast.MatchCase | t.CPtr = (
|
||||
ast.MatchCase | t.CPtr)(dcase)
|
||||
HandlesVar.enter_scope(trans.SymTab, SCOPE_MATCH)
|
||||
dbody: list[ast.AST | t.CPtr] | t.CPtr = dmc.children
|
||||
dbody = dmc.children
|
||||
if dbody is not None:
|
||||
dn: t.CSizeT = len(dbody)
|
||||
dj: int = 0
|
||||
@@ -1263,7 +1314,9 @@ class MatchHandle(HandlesBase.Mixin):
|
||||
HandlesVar.exit_scope(trans.SymTab)
|
||||
break
|
||||
di = di + 1
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
|
||||
# 末句控制流全 return → 补 unreachable(不 br end_bb)
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0 \
|
||||
and _case_tail_unreachable(trans, builder, dbody) == 0:
|
||||
llvmlite.build_br(builder, end_bb)
|
||||
trans._ctrl_merge_reachable = 1
|
||||
sm_merge_reach = 1
|
||||
|
||||
Reference in new issue
Block a user