控制流翻译器(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)。
345 lines
15 KiB
Plaintext
345 lines
15 KiB
Plaintext
import t, c
|
||
from stdint import *
|
||
import ast
|
||
import llvmlite
|
||
import memhub
|
||
import string
|
||
import stdio
|
||
import viperlib
|
||
import lib.core.Handles.HandlesBase as HandlesBase
|
||
import lib.core.Handles.HandlesTranslator as HT
|
||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||
import lib.core.Handles.HandlesBody as HandlesBody
|
||
import lib.core.Handles.HandlesType as HandlesType
|
||
import lib.core.Handles.HandlesImports as HandlesImports
|
||
import lib.Projectrans.Config as Config
|
||
|
||
|
||
# ============================================================
|
||
# HandlesIf - if/elif/else 语句处理(P6 对象化后的委托层)
|
||
#
|
||
# 编译期 CIf 求值的模块级函数(_is_cif_attr/_is_cif_call/
|
||
# _get_platform_macro_value/_cif_name_value/_cif_attr_value/
|
||
# _cif_eval_node/_evaluate_cif_test)已迁移为 lib.core.Gen.
|
||
# StmtGenMixin 的方法(_g_cif_eval_ok → gen 实例字段 CifEvalOk),
|
||
# 本模块保留同名模块级函数作为"一行委托";模块级 _g_cif_eval_ok
|
||
# 保留为镜像,委托后同步 gen.CifEvalOk(IfHandle.Handle 直接读它)。
|
||
#
|
||
# IfHandle 类(trans.IfH 的类型)保留:由 HandlesTranslator.
|
||
# _init_state 通过 NewIfHandle 工厂创建,Handle 方法内部经模块级
|
||
# 委托函数访问 gen。
|
||
# ============================================================
|
||
|
||
# 编译期宏条件: if c.CIf(...) / c.CIfdef(...) / c.CIfndef(...)
|
||
#
|
||
# 对齐 TPC HandlesIf.py:编译期求值命中分支并剪枝(不发射运行时 IR)。
|
||
# c.CIf(expr) → 常量表达式求值(CDefine/平台宏/算术/比较/逻辑)
|
||
# c.CIfdef(NAME) → NAME 已定义?(本地 CDefine / 跨模块 CDefine / 平台宏)
|
||
# c.CIfndef(NAME) → NAME 未定义? ← 未定义名特判:返回"未定义"而非报错
|
||
#
|
||
# 求值失败(如运行时变量 val == 1)→ 回退运行时翻译
|
||
# (c.CIf 由 HandlesExprCall.translate_call 特判翻译成运行时真值,
|
||
# c.CIfdef/c.CIfndef 运行时恒真,对齐 TPC HandlesExprCall.py L2434-2446)。
|
||
|
||
_g_cif_eval_ok: int = 0
|
||
|
||
# ============================================================
|
||
# 全局 gen 单例(模块级镜像,同 HandlesStruct 模式)
|
||
#
|
||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||
# 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||
# StmtGenMixin 方法,避免函数体 import 包模块与类/模块名歧义。
|
||
# ============================================================
|
||
_g_gen: t.CVoid | t.CPtr = None
|
||
|
||
|
||
def set_global_gen(gen: t.CVoid | t.CPtr) -> None:
|
||
"""注入全局 gen 单例(BuildPipeline/main 调用)"""
|
||
global _g_gen
|
||
_g_gen = gen
|
||
|
||
|
||
def _is_cif_attr(attr: str) -> int:
|
||
"""检查方法名是否为 CIf 系(CIf/CIfdef/CIfndef)(委托到 gen._is_cif_attr)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._is_cif_attr(attr)
|
||
return 0
|
||
|
||
|
||
def _is_cif_call(node: ast.AST | t.CPtr) -> int:
|
||
"""检查 test 是否为 c.CIf(...)/c.CIfdef(...)/c.CIfndef(...)(或裸 CIf 系)调用(委托到 gen._is_cif_call)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._is_cif_call(node)
|
||
return 0
|
||
|
||
|
||
def _get_platform_macro_value(name: str) -> int:
|
||
"""平台内置宏值(从目标三元组推导,对齐 TPC HandlesIf._get_platform_macros)。
|
||
|
||
命中置 _g_cif_eval_ok=1;未命中置 0 返回 0(委托到 gen._get_platform_macro_value)。
|
||
"""
|
||
global _g_cif_eval_ok
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||
if g is not None:
|
||
v: int = g._get_platform_macro_value(name)
|
||
_g_cif_eval_ok = g.CifEvalOk
|
||
return v
|
||
return 0
|
||
|
||
|
||
def _cif_name_value(pool: memhub.MemBuddy | t.CPtr,
|
||
trans: HT.Translator | t.CPtr,
|
||
name: str) -> int:
|
||
"""查宏名值: 本地 CDefine → 跨模块 CDefine → 平台宏。
|
||
|
||
命中置 _g_cif_eval_ok=1(值 0 也算命中,如 DISABLED=0);未命中置 0(委托到 gen._cif_name_value)。
|
||
"""
|
||
global _g_cif_eval_ok
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||
if g is not None:
|
||
v: int = g._cif_name_value(pool, trans, name)
|
||
_g_cif_eval_ok = g.CifEvalOk
|
||
return v
|
||
return 0
|
||
|
||
|
||
def _cif_attr_value(pool: memhub.MemBuddy | t.CPtr,
|
||
trans: HT.Translator | t.CPtr,
|
||
at: ast.Attribute | t.CPtr) -> int:
|
||
"""Attribute 宏值: platmacro.IS_WINDOWS → 本地 CDefine(attr) → 跨模块 CDefine。
|
||
|
||
命中置 _g_cif_eval_ok=1;未命中置 0(委托到 gen._cif_attr_value)。
|
||
"""
|
||
global _g_cif_eval_ok
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||
if g is not None:
|
||
v: int = g._cif_attr_value(pool, trans, at)
|
||
_g_cif_eval_ok = g.CifEvalOk
|
||
return v
|
||
return 0
|
||
|
||
|
||
def _cif_eval_node(pool: memhub.MemBuddy | t.CPtr,
|
||
trans: HT.Translator | t.CPtr,
|
||
node: ast.AST | t.CPtr) -> int:
|
||
"""递归常量求值 CIf 表达式。
|
||
|
||
支持: Constant(int) / Name(CDefine/跨模块/平台宏) / Attribute(跨模块 CDefine)
|
||
/ BinOp(+ - * // % & | ^ << >>) / Compare(== != < > <= >=)
|
||
/ BoolOp(and/or) / UnaryOp(not - + ~)。
|
||
成功置 _g_cif_eval_ok=1;失败(含运行时变量)置 0 返回 0(委托到 gen._cif_eval_node)。
|
||
"""
|
||
global _g_cif_eval_ok
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||
if g is not None:
|
||
v: int = g._cif_eval_node(pool, trans, node)
|
||
_g_cif_eval_ok = g.CifEvalOk
|
||
return v
|
||
return 0
|
||
|
||
|
||
def _evaluate_cif_test(pool: memhub.MemBuddy | t.CPtr,
|
||
trans: HT.Translator | t.CPtr,
|
||
test: ast.AST | t.CPtr) -> int:
|
||
"""求值 CIf 调用(test 必须是 c.CIf 系调用)。
|
||
|
||
成功: 置 _g_cif_eval_ok=1,返回条件值(0/1)
|
||
失败(运行时变量/未知结构): 置 _g_cif_eval_ok=0,返回 0(委托到 gen._evaluate_cif_test)。
|
||
"""
|
||
global _g_cif_eval_ok
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||
if g is not None:
|
||
v: int = g._evaluate_cif_test(pool, trans, test)
|
||
_g_cif_eval_ok = g.CifEvalOk
|
||
return v
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# HandlesIf - if/elif/else 语句处理(Mixin 继承模式)
|
||
#
|
||
# 翻译 if 语句为 LLVM IR 控制流:
|
||
# br i1 %cond, label %then, label %else
|
||
# then:
|
||
# ... body ...
|
||
# br label %end
|
||
# else:
|
||
# ... orelse ...
|
||
# br label %end
|
||
# end:
|
||
# ============================================================
|
||
|
||
|
||
@t.NoVTable
|
||
class IfHandle(HandlesBase.Mixin):
|
||
"""if/elif/else 语句处理器:继承 Mixin 获得 Trans 回指针"""
|
||
|
||
def __init__(self, trans: HT.Translator | t.CPtr):
|
||
self.Trans = trans
|
||
|
||
# ============================================================
|
||
# Handle - 处理 if 语句,返回新增变量数
|
||
# ============================================================
|
||
def Handle(self, node: ast.AST | t.CPtr) -> int:
|
||
"""翻译 if/elif/else 语句"""
|
||
if node is None:
|
||
return 0
|
||
|
||
trans: HT.Translator | t.CPtr = self.Trans
|
||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||
func: llvmlite.Function | t.CPtr = trans._cur_func
|
||
|
||
if builder is None or func is None:
|
||
return 0
|
||
|
||
if_node: ast.If | t.CPtr = (ast.If | t.CPtr)(node)
|
||
|
||
# 0. 编译期宏条件: if c.CIf(...) / c.CIfdef(...) / c.CIfndef(...)
|
||
# 求值成功 → 只编译命中的分支(剪枝,不发射运行时 IR),elif 递归
|
||
# 求值失败(运行时变量等)→ 回退运行时翻译
|
||
if _is_cif_call(if_node.test) == 1:
|
||
cif_val: int = _evaluate_cif_test(pool, trans, if_node.test)
|
||
if _g_cif_eval_ok != 0:
|
||
if cif_val != 0:
|
||
body_cif: list[ast.AST | t.CPtr] | t.CPtr = if_node.children
|
||
if body_cif is not None:
|
||
bc_cif: t.CSizeT = len(body_cif)
|
||
bi_cif: t.CSizeT
|
||
for bi_cif in range(bc_cif):
|
||
stmt_cif: ast.AST | t.CPtr = body_cif.get(bi_cif)
|
||
if stmt_cif is not None:
|
||
HandlesBody.translate_stmt(trans, stmt_cif)
|
||
else:
|
||
orelse_cif: list[ast.AST | t.CPtr] | t.CPtr = if_node.orelse
|
||
if orelse_cif is not None and len(orelse_cif) == 1:
|
||
sub_cif: ast.AST | t.CPtr = orelse_cif.get(0)
|
||
if sub_cif is not None and sub_cif.kind() == ast.ASTKind.If:
|
||
# elif: 递归(子 If 的 test 仍会走 CIf 判定或运行时翻译)
|
||
self.Handle(sub_cif)
|
||
elif sub_cif is not None:
|
||
HandlesBody.translate_stmt(trans, sub_cif)
|
||
elif orelse_cif is not None:
|
||
oc_cif: t.CSizeT = len(orelse_cif)
|
||
oi_cif: t.CSizeT
|
||
for oi_cif in range(oc_cif):
|
||
stmt_cif2: ast.AST | t.CPtr = orelse_cif.get(oi_cif)
|
||
if stmt_cif2 is not None:
|
||
HandlesBody.translate_stmt(trans, stmt_cif2)
|
||
return 0
|
||
|
||
# 1. 求值条件表达式
|
||
cond_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, if_node.test,
|
||
trans._funcs, trans._func_count, trans)
|
||
|
||
# 2. 转换为 i1 条件
|
||
# Compare/Not 表达式已返回 i1,直接使用;指针类型与 null 比较;其他类型与 0 比较
|
||
if cond_val is None:
|
||
# fail-fast: if 条件表达式翻译失败
|
||
HandlesType.fatal_error(if_node.test, "if 条件表达式翻译失败", "TypeError")
|
||
cond_bits: int = HandlesExpr.get_llvm_type_bits(cond_val.Ty)
|
||
if cond_bits == 1:
|
||
cond_i1: llvmlite.Value | t.CPtr = cond_val
|
||
elif HandlesExpr.is_ptr_type(cond_val.Ty) != 0:
|
||
# 指针类型:与 null 比较(不能用整数 0,否则 llc 报 "integer constant must have integer type")
|
||
null_cond: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, cond_val.Ty, "null")
|
||
cond_i1 = llvmlite.build_icmp(
|
||
builder, llvmlite.ICMP_NE, cond_val, null_cond)
|
||
else:
|
||
zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
|
||
cond_i1 = llvmlite.build_icmp(
|
||
builder, llvmlite.ICMP_NE, cond_val, zero)
|
||
|
||
# 3. 创建基本块(使用 trans._label_counter 生成唯一标签名,不与 SSA 名共享)
|
||
cnt: int = trans._label_counter
|
||
trans._label_counter = cnt + 1
|
||
|
||
name_buf: str = pool.alloc(32)
|
||
viperlib.snprintf(name_buf, 32, "if.then.%d", cnt)
|
||
then_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
viperlib.snprintf(name_buf, 32, "if.end.%d", cnt)
|
||
merge_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
# 检查是否有 else 分支
|
||
has_else: int = 0
|
||
orelse_list: list[ast.AST | t.CPtr] | t.CPtr = if_node.orelse
|
||
if orelse_list is not None:
|
||
if len(orelse_list) > 0:
|
||
has_else = 1
|
||
|
||
else_bb: llvmlite.BasicBlock | t.CPtr = None
|
||
if has_else == 1:
|
||
viperlib.snprintf(name_buf, 32, "if.else.%d", cnt)
|
||
else_bb = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
# 4. 发射条件分支
|
||
if has_else == 1:
|
||
llvmlite.build_cond_br(builder, cond_i1, then_bb, else_bb)
|
||
else:
|
||
llvmlite.build_cond_br(builder, cond_i1, then_bb, merge_bb)
|
||
|
||
# 5. 翻译 then body
|
||
llvmlite.position_at_end(builder, then_bb)
|
||
body: list[ast.AST | t.CPtr] | t.CPtr = if_node.children
|
||
if body is not None:
|
||
body_count: t.CSizeT = len(body)
|
||
for bi in range(body_count):
|
||
stmt: ast.AST | t.CPtr = body.get(bi)
|
||
if stmt is not None:
|
||
HandlesBody.translate_stmt(trans, stmt)
|
||
|
||
# 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)
|
||
for ei in range(else_count):
|
||
stmt: ast.AST | t.CPtr = orelse_list.get(ei)
|
||
if stmt is not None:
|
||
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 块可达性(追加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
|
||
|
||
|
||
# ============================================================
|
||
# NewIfHandle - 工厂函数(委托到 gen.NewIfHandle)
|
||
# ============================================================
|
||
def NewIfHandle(pool: memhub.MemBuddy | t.CPtr,
|
||
trans: HT.Translator | t.CPtr) -> IfHandle | t.CPtr:
|
||
"""创建 IfHandle 实例(委托到 gen.NewIfHandle)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g.NewIfHandle(pool, trans)
|
||
return None
|