Files
ViperC/App/lib/core/Handles/HandlesWhile.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

160 lines
6.3 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
# ============================================================
# HandlesWhile - while 循环语句处理(P6 对象化后的委托层)
#
# NewWhileHandle 工厂已迁移为 lib.core.Gen.StmtGenMixin 的方法
# (WhileHandle 类保留:trans.WhileH 的类型,由 HandlesTranslator.
# _init_state 经 NewWhileHandle 委托创建)。
#
# 翻译 while 语句为 LLVM IR 控制流:
# br label %cond
# cond:
# %t = <test>
# %c = icmp ne i32 %t, 0
# br i1 %c, label %body, label %end
# body:
# ... body ...
# br label %cond
# end:
# ============================================================
# ============================================================
# 全局 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
@t.NoVTable
class WhileHandle(HandlesBase.Mixin):
"""while 循环语句处理器:继承 Mixin 获得 Trans 回指针"""
def __init__(self, trans: HT.Translator | t.CPtr):
self.Trans = trans
# ============================================================
# Handle - 处理 while 语句,返回新增变量数
# ============================================================
def Handle(self, node: ast.AST | t.CPtr) -> int:
"""翻译 while 循环语句"""
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
while_node: ast.While | t.CPtr = (ast.While | t.CPtr)(node)
# 1. 创建基本块: cond / body / end(使用 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, "while.cond.%d", cnt)
cond_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
viperlib.snprintf(name_buf, 32, "while.body.%d", cnt)
body_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
viperlib.snprintf(name_buf, 32, "while.end.%d", cnt)
end_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
# 2. 跳转到 cond 块
llvmlite.build_br(builder, cond_bb)
# 3. cond 块: 求值条件,条件分支
llvmlite.position_at_end(builder, cond_bb)
cond_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
builder, pool, trans.Module, while_node.test,
trans._funcs, trans._func_count, trans)
if cond_val is None:
# fail-fast: while 条件表达式翻译失败
HandlesType.fatal_error(while_node.test, "while 条件表达式翻译失败", "TypeError")
# Compare/Not 表达式已返回 i1,直接使用;指针类型与 null 比较;其他类型与 0 比较
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)
llvmlite.build_cond_br(builder, cond_i1, body_bb, end_bb)
# 4. body 块: 翻译循环体,跳回 cond
llvmlite.position_at_end(builder, body_bb)
# 保存旧循环上下文,设置 break/continue 目标
old_break: llvmlite.BasicBlock | t.CPtr = trans._break_bb
old_continue: llvmlite.BasicBlock | t.CPtr = trans._continue_bb
trans._break_bb = end_bb
trans._continue_bb = cond_bb
body: list[ast.AST | t.CPtr] | t.CPtr = while_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)
# 恢复旧循环上下文
trans._break_bb = old_break
trans._continue_bb = old_continue
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
llvmlite.build_br(builder, cond_bb)
# 5. 定位到 end 块
llvmlite.position_at_end(builder, end_bb)
# 追加90:while 的 cond_br 恒引用 end_bb → merge 恒可达(需正常收尾)
trans._ctrl_merge_reachable = 1
return 0
# ============================================================
# NewWhileHandle - 工厂函数(委托到 gen.NewWhileHandle)
# ============================================================
def NewWhileHandle(pool: memhub.MemBuddy | t.CPtr,
trans: HT.Translator | t.CPtr) -> WhileHandle | t.CPtr:
"""创建 WhileHandle 实例(委托到 gen.NewWhileHandle)"""
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.NewWhileHandle(pool, trans)
return None