Files
ViperC/App/lib/core/Handles/HandlesIf.vp
T
TermiNexus 996f08fb46 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)。
2026-08-17 05:46:47 +08:00

345 lines
15 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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