stdint.vp 翻译中崩溃(退出码 -1073741815=0xC0000005 访问违规), 发生在 translate 内部 printf.fmt 创建后。在 translate 声明完成/ main 检查/模块级各步骤(import、容器可见性、CTypedef 扫描、vpi 注入、 变量预注册、前向声明、translate_children)加断点,崩溃前最后打印的 步骤即为崩点。
711 lines
34 KiB
Plaintext
711 lines
34 KiB
Plaintext
import t, c
|
||
from stdint import *
|
||
import ast
|
||
import llvmlite
|
||
import memhub
|
||
import string
|
||
import stdio
|
||
import stdlib
|
||
import viperlib
|
||
import lib.core.VLogger as VLogger
|
||
import lib.core.Handles.HandlesVar as HandlesVar
|
||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||
import lib.core.Handles.HandlesMain as HandlesMain
|
||
import lib.core.Handles.HandlesAssign as HandlesAssign
|
||
import lib.core.Handles.HandlesReturn as HandlesReturn
|
||
import lib.core.Handles.HandlesImports as HandlesImports
|
||
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
|
||
import lib.core.Handles.HandlesAugAssign as HandlesAugAssign
|
||
import lib.core.Handles.HandlesIf as HandlesIf
|
||
import lib.core.Handles.HandlesWhile as HandlesWhile
|
||
import lib.core.Handles.HandlesFor as HandlesFor
|
||
import lib.core.Handles.HandlesMatch as HandlesMatch
|
||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||
import lib.core.Handles.HandlesType as HandlesType
|
||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||
import lib.Projectrans.Config as Config
|
||
import lib.core.StubMergerBuild as StubMergerBuild
|
||
import lib.core.Handles.ExprCallHandle as ExprCallHandle
|
||
import lib.core.Handles.ExprCallTable as ExprCallTable
|
||
|
||
# ============================================================
|
||
# HandlesTranslator - 翻译器状态管理 + 主入口
|
||
#
|
||
# 从 translator.py 拆分出来,负责:
|
||
# 1. Translator 类 - 状态管理(Module, 变量表, 函数表, 导入)
|
||
# 2. translate() - 主翻译入口
|
||
# 3. dump_ir() - IR 输出
|
||
#
|
||
# 语句/表达式翻译全部委托给 Handles 模块:
|
||
# HandlesMain - wrapper main 创建 + children 遍历
|
||
# HandlesBody - 语句分派
|
||
# HandlesExpr - 表达式翻译
|
||
# HandlesFunctions - 函数定义处理
|
||
# 注意:str = bytes = t.CChar | t.CPtr = i8*
|
||
#
|
||
# P6-E 对象化重构:模块级 global/nonlocal 名称管理函数已迁移为
|
||
# lib.core.Gen.TranslatorGenMixin 的方法,本模块保留同名模块级
|
||
# 函数作为"一行委托"(同 P2-P5 模式)。Translator 类保留在本模块。
|
||
# ============================================================
|
||
|
||
# 常量
|
||
MAX_VARS: t.CDefine = 1024
|
||
MAX_FUNCS: t.CDefine = 1024
|
||
MAX_GLOBAL_NAMES: t.CDefine = 32
|
||
|
||
|
||
# ============================================================
|
||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||
#
|
||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||
# P6-E 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||
# TranslatorGenMixin 方法,避免函数体 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 Translator:
|
||
"""翻译器:管理编译状态,委托 Handles 模块执行翻译"""
|
||
|
||
# LLVM 上下文(共享状态)
|
||
Module: llvmlite.LLVMModule | t.CPtr
|
||
Pool: memhub.MemBuddy | t.CPtr
|
||
|
||
# 函数表
|
||
_funcs: HandlesExprCall.FuncEntry | t.CPtr
|
||
_func_count: t.CInt
|
||
|
||
# 导入模块跟踪
|
||
_imported_modules: str
|
||
_from_imports: str
|
||
|
||
# 当前翻译上下文
|
||
_cur_func: llvmlite.Function | t.CPtr
|
||
_cur_builder: llvmlite.IRBuilder | t.CPtr
|
||
|
||
# 当前赋值语句的注解节点(AnnAssign 翻译 rhs 前设置,Assign 翻译前清空)。
|
||
# 供 c.Deref(i8*) 推断读取宽度:v: int = c.Deref(p) → bitcast i32* load,
|
||
# 对齐 TPC HandlesSpecialCall._infer_deref_target_type(DictTest 500→-12 根因:
|
||
# i8* Deref 固定读 1 字节 + sext 截断)。
|
||
CurAssignAnnot: ast.AST | t.CPtr
|
||
|
||
# 当前赋值语句的 RHS 节点(AnnAssign 翻译 rhs 前设置,rhs 翻译后清除)。
|
||
# 供 c.Deref 判定"是否为赋值直接 RHS":仅 v: int = c.Deref(p) 时用
|
||
# CurAssignAnnot 推断读取宽度;嵌套在 while 条件/比较/binop/类型转换
|
||
# 调用中(如 while c.Deref(p) != 0、total += t.CInt(c.Deref(p)))不推断,
|
||
# 否则 i8* 会被残留 CurAssignAnnot 误判为 i32* 读 4 字节(对齐 TPC
|
||
# _infer_deref_target_type 的直接 RHS 检查)。
|
||
CurAssignNode: ast.AST | t.CPtr
|
||
|
||
# 循环控制流目标(break/continue)
|
||
_break_bb: llvmlite.BasicBlock | t.CPtr
|
||
_continue_bb: llvmlite.BasicBlock | t.CPtr
|
||
|
||
# 独立标签计数器(不与 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
|
||
|
||
# nonlocal 声明的变量名集合(当前函数内)
|
||
_nonlocal_names: str
|
||
_nonlocal_name_count: t.CInt
|
||
# nonlocal 变量的类型信息(LLVMType 指针数组,与 _nonlocal_names 一一对应)
|
||
# 用于 env 指针数组方案:子函数访问 nonlocal 变量时需要知道原始类型
|
||
_nonlocal_types: str
|
||
|
||
# 闭包相关:当前函数名(用于嵌套函数提升命名)
|
||
_cur_func_name: str
|
||
|
||
# *args 变长参数支持:当前函数的 va_list 指针(i8* alloca)
|
||
# 仅当函数声明了 *args 时设置,供 arg(type) 糖函数使用
|
||
_va_list_ptr: llvmlite.Value | t.CPtr
|
||
# *args 参数名(如 "args"),用于符号表注册
|
||
_vararg_name: str
|
||
|
||
# OOP iter 协议:当前 __next__ 方法的隐藏 stop-flag 参数(i1*)。
|
||
# _translate_method 注入 __stop_iter_flag__ 参数时设置;translate_raise
|
||
# 检测 raise StopIteration 时对该指针 store 1(对齐 TPC HandlesRaise.py)。
|
||
# 非 __next__ 函数中为 None。
|
||
_stop_iter_flag_ptr: llvmlite.Value | t.CPtr
|
||
|
||
# try-except 机制(对齐 TPC HandlesTry.py):当前最内层 try 的
|
||
# 分发块 + 异常编码/消息 alloca。translate_try 设置,translate_raise
|
||
# 与调用侧 EH 检测写入/跳转。try 外为 None。
|
||
_eh_dispatch_bb: llvmlite.BasicBlock | t.CPtr
|
||
_eh_code_ptr: llvmlite.Value | t.CPtr
|
||
_eh_msg_ptr: llvmlite.Value | t.CPtr
|
||
# 当前函数的 __eh_msg_out__(i8**)/__eh_code_out__(i32*)输出参数
|
||
# (函数签名含 raise 时由 translate_function_def/_translate_method 注入)。
|
||
# 无 EH 参数时 _cur_func_has_eh == 0。
|
||
_eh_msg_out_param: llvmlite.Value | t.CPtr
|
||
_eh_code_out_param: llvmlite.Value | t.CPtr
|
||
_cur_func_has_eh: int
|
||
|
||
# 模块 SHA1 前缀(16 字符),用于函数名混淆(SHA1 命名空间)
|
||
ModuleSha1: str
|
||
# 当前文件所属包名(如 "llvmlite"),用于解析相对导入(from . import ...)
|
||
# None 表示当前文件是顶级模块(无包),相对导入无法解析
|
||
CurrentPackage: str
|
||
# 闭包 env 中的 nonlocal 变量偏移映射(每个 nonlocal 变量在 env 中的字节偏移)
|
||
_closure_env_offsets: t.CInt
|
||
_closure_env_count: t.CInt
|
||
# lambda 表达式全局唯一 ID 计数器(生成提升函数名 __lambda_{id})
|
||
# 独立于 _closure_env_count:后者随函数进入被 clear_scope_names 重置,
|
||
# lambda ID 需跨函数全局唯一(提升函数名避免冲突)
|
||
_lambda_count: t.CInt
|
||
# 函数链内 nonlocal 变量集合(预扫描收集,含嵌套函数声明的 nonlocal)。
|
||
# 用于"不同层捕获不同变量"场景(如 level1→a, level2→b):b 定义在最外层
|
||
# 但 level1 不捕获——level1 env 无 b 槽,level2 无法经 env 链获取 b 的堆。
|
||
# 解决:在最外层函数中为链内所有 nonlocal 建堆,并把堆地址 store 到
|
||
# 模块级映射变量 @nlheap.{sha1}.{name};内层闭包创建时从映射 load。
|
||
_nl_chain_names: t.CVoid | t.CPtr
|
||
_nl_chain_count: t.CInt
|
||
# 链内 nonlocal 堆预建标志(每函数只建一次):translate_function_def 进入
|
||
# 新函数时重置为 0;_prepare_chain_nonlocals 首次调用置 1。多个嵌套函数
|
||
# 定义共享同一堆(防重复 malloc + 二次重定向 VarEntry.Alloca)。
|
||
_nl_chain_done: t.CInt
|
||
|
||
# 泛型特化上下文:当前正在特化的类型参数名/实参名列表
|
||
# 由 _specialize_generic_class 设置,方法体翻译时用于将 T 替换为具体类型
|
||
# None 表示不在泛型特化上下文中
|
||
GenericTypeParamNames: list[str] | t.CPtr
|
||
GenericTypeArgs: list[str] | t.CPtr
|
||
|
||
# Phase 1a 声明模式标志:1=只注册 struct/enum/union 不翻译代码体,0=全量翻译
|
||
_declare_only: t.CInt
|
||
|
||
# Phase A 依赖未就绪标志:1=本文件翻译时依赖模块的 text.ll 尚未生成
|
||
# (同项目源文件按顺序翻译,main.vp 先于其 import 的 mbuddytest.vp),
|
||
# 跨模块函数返回类型无法精确解析。Phase A 多遍循环据此下遍重试。
|
||
_deps_pending: t.CInt
|
||
|
||
# 子 Handle 指针(每个 Handle 一个槽,通过 Mixin 回指针访问本结构体)
|
||
AssignH: HandlesAssign.AssignHandle | t.CPtr
|
||
ReturnH: HandlesReturn.ReturnHandle | t.CPtr
|
||
ImportsH: HandlesImports.ImportsHandle | t.CPtr
|
||
AnnAssignH: HandlesAnnAssign.AnnAssignHandle | t.CPtr
|
||
AugAssignH: HandlesAugAssign.AugAssignHandle | t.CPtr
|
||
IfH: HandlesIf.IfHandle | t.CPtr
|
||
WhileH: HandlesWhile.WhileHandle | t.CPtr
|
||
ForH: HandlesFor.ForHandle | t.CPtr
|
||
ExprH: HandlesExpr.ExprHandle | t.CPtr
|
||
ExprCallH: HandlesExprCall.ExprCallHandle | t.CPtr
|
||
MatchH: HandlesMatch.MatchHandle | t.CPtr
|
||
|
||
# 嵌套作用域符号表
|
||
SymTab: HandlesVar.SymbolTable | t.CPtr
|
||
|
||
def __init__(self):
|
||
self.Module = None
|
||
self.Pool = None
|
||
self._funcs = None
|
||
self._func_count = 0
|
||
self._cur_func = None
|
||
self._cur_builder = None
|
||
self._break_bb = None
|
||
self._continue_bb = None
|
||
self._label_counter = 0
|
||
self._imported_modules = None
|
||
self._from_imports = None
|
||
self._global_names = None
|
||
self._global_name_count = 0
|
||
self._nonlocal_names = None
|
||
self._nonlocal_name_count = 0
|
||
self._nonlocal_types = None
|
||
self._cur_func_name = None
|
||
self._va_list_ptr = None
|
||
self._vararg_name = None
|
||
self._stop_iter_flag_ptr = None
|
||
self._eh_dispatch_bb = None
|
||
self._eh_code_ptr = None
|
||
self._eh_msg_ptr = None
|
||
self._eh_msg_out_param = None
|
||
self._eh_code_out_param = None
|
||
self._cur_func_has_eh = 0
|
||
self.ModuleSha1 = None
|
||
self.CurrentPackage = None
|
||
self._closure_env_offsets = 0
|
||
self._closure_env_count = 0
|
||
self._lambda_count = 0
|
||
self._nl_chain_names = None
|
||
self._nl_chain_count = 0
|
||
self._nl_chain_done = 0
|
||
self.GenericTypeParamNames = None
|
||
self.GenericTypeArgs = None
|
||
self._declare_only = 0
|
||
self._deps_pending = 0
|
||
self.AssignH = None
|
||
self.ReturnH = None
|
||
self.ImportsH = None
|
||
self.AnnAssignH = None
|
||
self.AugAssignH = None
|
||
self.IfH = None
|
||
self.WhileH = None
|
||
self.ForH = None
|
||
self.ExprH = None
|
||
self.ExprCallH = None
|
||
self.MatchH = None
|
||
self.SymTab = None
|
||
|
||
# ============================================================
|
||
# 状态初始化
|
||
# ============================================================
|
||
def _init_state(self, pool: memhub.MemBuddy | t.CPtr):
|
||
"""初始化变量表、函数表和子 Handle"""
|
||
self.Pool = pool
|
||
if self._funcs is None:
|
||
self._funcs = ExprCallTable.init_func_table(pool, MAX_FUNCS)
|
||
# 嵌套作用域符号表(新版)
|
||
if self.SymTab is None:
|
||
self.SymTab = HandlesVar.init_symbol_table(pool)
|
||
# global/nonlocal 名称集合缓冲区(32 个 char* 指针 = 256 字节)
|
||
if self._global_names is None:
|
||
self._global_names = stdlib.malloc(MAX_GLOBAL_NAMES * 8)
|
||
if self._global_names is not None:
|
||
string.memset(self._global_names, 0, MAX_GLOBAL_NAMES * 8)
|
||
self._global_name_count = 0
|
||
if self._nonlocal_names is None:
|
||
self._nonlocal_names = stdlib.malloc(MAX_GLOBAL_NAMES * 8)
|
||
if self._nonlocal_names is not None:
|
||
string.memset(self._nonlocal_names, 0, MAX_GLOBAL_NAMES * 8)
|
||
self._nonlocal_name_count = 0
|
||
# nonlocal 变量类型数组(LLVMType 指针数组,与 _nonlocal_names 一一对应)
|
||
if self._nonlocal_types is None:
|
||
self._nonlocal_types = stdlib.malloc(MAX_GLOBAL_NAMES * 8)
|
||
if self._nonlocal_types is not None:
|
||
string.memset(self._nonlocal_types, 0, MAX_GLOBAL_NAMES * 8)
|
||
# 创建子 Handle(传入 self 作为 Mixin 回指针)
|
||
if self.AssignH is None:
|
||
self.AssignH = HandlesAssign.NewAssignHandle(pool, self)
|
||
if self.ReturnH is None:
|
||
self.ReturnH = HandlesReturn.NewReturnHandle(pool, self)
|
||
if self.ImportsH is None:
|
||
self.ImportsH = HandlesImports.NewImportsHandle(pool, self)
|
||
if self.AnnAssignH is None:
|
||
self.AnnAssignH = HandlesAnnAssign.NewAnnAssignHandle(pool, self)
|
||
if self.AugAssignH is None:
|
||
self.AugAssignH = HandlesAugAssign.NewAugAssignHandle(pool, self)
|
||
if self.IfH is None:
|
||
self.IfH = HandlesIf.NewIfHandle(pool, self)
|
||
if self.WhileH is None:
|
||
self.WhileH = HandlesWhile.NewWhileHandle(pool, self)
|
||
if self.ForH is None:
|
||
self.ForH = HandlesFor.NewForHandle(pool, self)
|
||
if self.MatchH is None:
|
||
self.MatchH = HandlesMatch.NewMatchHandle(pool, self)
|
||
if self.ExprH is None:
|
||
self.ExprH = HandlesExpr.NewExprHandle(pool, self)
|
||
if self.ExprCallH is None:
|
||
self.ExprCallH = ExprCallHandle.NewExprCallHandle(pool, self)
|
||
|
||
# ============================================================
|
||
# 主翻译入口
|
||
# ============================================================
|
||
def translate(self, tree: ast.AST | t.CPtr) -> int:
|
||
"""将 AST 翻译为 LLVM IR"""
|
||
if tree is None:
|
||
return 1
|
||
if _mbuddy is None:
|
||
return 1
|
||
|
||
pool: memhub.MemBuddy | t.CPtr = _mbuddy
|
||
|
||
# 初始化状态
|
||
self._init_state(pool)
|
||
|
||
# 创建 LLVM 模块
|
||
mod: llvmlite.LLVMModule | t.CPtr = llvmlite.new_module(pool, "main")
|
||
if mod is None:
|
||
VLogger.error("NewModule returned NULL", "TR")
|
||
return 1
|
||
self.Module = mod
|
||
|
||
# 设置目标(优先使用 project.vpj 中的配置)
|
||
triple: str = Config.TargetTriple
|
||
if triple is None:
|
||
triple = "x86_64-pc-windows-msvc"
|
||
llvmlite.module_set_target(mod, triple)
|
||
|
||
# 类型
|
||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||
|
||
# 声明 printf
|
||
printf_func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
|
||
pool, mod, "printf", i32_ty)
|
||
if printf_func is None:
|
||
VLogger.error("CreateDeclare printf returned NULL", "TR")
|
||
return 1
|
||
llvmlite.add_param(pool, printf_func, i8_ptr_ty, "fmt")
|
||
printf_func.IsVarArg = 1
|
||
# 诊断(builtins.vp dump 卡死根因排查):printf.fmt Param 创建后立即
|
||
# 校验其 Next——区分"创建即损坏"(create_declare/add_param 环节问题)
|
||
# 与"后续被越界写破坏"(dump 时遍历成环)。next=0 为正常。
|
||
dbg_p0: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(printf_func)
|
||
if dbg_p0 is not None:
|
||
dbg_p0n: llvmlite.Param | t.CPtr = llvmlite.param_get_next(dbg_p0)
|
||
stdio.printf("[DIAG] printf.fmt 创建后: param=%llu next=%llu\n",
|
||
t.CUInt64T(dbg_p0), t.CUInt64T(dbg_p0n))
|
||
|
||
# 声明 LLVM va_start/va_end intrinsic(供 *args 函数体内使用)
|
||
# declare void @llvm.va_start(i8*)
|
||
# declare void @llvm.va_end(i8*)
|
||
void_ty_decl: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool)
|
||
va_start_func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
|
||
pool, mod, "llvm.va_start", void_ty_decl)
|
||
if va_start_func is not None:
|
||
llvmlite.add_param(pool, va_start_func, i8_ptr_ty, "ap")
|
||
va_end_func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
|
||
pool, mod, "llvm.va_end", void_ty_decl)
|
||
if va_end_func is not None:
|
||
llvmlite.add_param(pool, va_end_func, i8_ptr_ty, "ap")
|
||
|
||
# 声明 malloc(闭包分配用)
|
||
malloc_func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
|
||
pool, mod, "malloc", i8_ptr_ty)
|
||
if malloc_func is not None:
|
||
i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool)
|
||
llvmlite.add_param(pool, malloc_func, i64_ty, "size")
|
||
stdio.printf("[DIAG] translate: 声明完成\n")
|
||
|
||
# 检查用户是否定义了 main 函数
|
||
has_user_main: int = 0
|
||
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
|
||
if ch is not None:
|
||
cn_count: t.CSizeT = len(ch)
|
||
for ci in range(cn_count):
|
||
child: ast.AST | t.CPtr = ch.get(ci)
|
||
if child is not None and child.kind() == ast.ASTKind.FunctionDef:
|
||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child)
|
||
if fd is not None and fd.name is not None:
|
||
if string.strcmp(fd.name, "main") == 0:
|
||
has_user_main = 1
|
||
break
|
||
stdio.printf("[DIAG] translate: main 检查完成(has_user_main=%d)\n", has_user_main)
|
||
|
||
if self._declare_only != 0:
|
||
# Phase 1a-pre(2=import扫描) / Phase 1a(1=struct注册): 只处理模块级,不创建 main 函数和 builder
|
||
self._translate_module_level(pool, mod, tree)
|
||
elif has_user_main == 0:
|
||
# 无用户 main → 只翻译模块级语句,不创建 wrapper main
|
||
# 修复:避免每个文件都生成 define i32 @main() 导致链接时 main 冲突
|
||
# 只有包含 def main() 的入口文件才会有 define i32 @main()
|
||
self._translate_module_level(pool, mod, tree)
|
||
else:
|
||
# 用户已定义 main → 委托 HandlesMain 翻译模块级
|
||
self._translate_module_level(pool, mod, tree)
|
||
|
||
return 0
|
||
|
||
# ============================================================
|
||
# 包装 main 函数(无用户 main 时)→ 委托 HandlesMain
|
||
# ============================================================
|
||
def _translate_wrapper_main(self, pool: memhub.MemBuddy | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
tree: ast.AST | t.CPtr,
|
||
i32_ty: llvmlite.LLVMType | t.CPtr):
|
||
"""委托 HandlesMain.create_wrapper_main() 创建包装 main(trans 单参)"""
|
||
added: int = HandlesMain.create_wrapper_main(self, tree, i32_ty)
|
||
|
||
# ============================================================
|
||
# 模块级翻译(用户已定义 main)→ 委托 HandlesMain
|
||
# ============================================================
|
||
def _translate_module_level(self, pool: memhub.MemBuddy | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
tree: ast.AST | t.CPtr):
|
||
"""委托 HandlesMain.translate_children() 翻译模块级语句(trans 单参)"""
|
||
# 全量翻译模式下,先处理导入语句,再创建前向声明,解决前向引用问题
|
||
if self._declare_only == 0:
|
||
stdio.printf("[DIAG] 模块级: 开始\n")
|
||
# 预处理导入语句,确保 _imported_modules 和 _from_imports 已填充
|
||
# (前向声明需要解析类型注解,如 t.CArray[str] 依赖 t 模块已导入)
|
||
# 记录最后处理的 import 行号,供 vpi 注入错误上下文帧定位
|
||
cur_imp_lineno: int = 0
|
||
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
|
||
if ch is not None:
|
||
cn_count: t.CSizeT = len(ch)
|
||
for ci in range(cn_count):
|
||
child: ast.AST | t.CPtr = ch.get(ci)
|
||
if child is None:
|
||
continue
|
||
kd: int = child.kind()
|
||
if kd == ast.ASTKind.Import:
|
||
cur_imp_lineno = child.lineno
|
||
self.ImportsH.HandleImport(child)
|
||
elif kd == ast.ASTKind.ImportFrom:
|
||
cur_imp_lineno = child.lineno
|
||
self.ImportsH.HandleImportFromModule(child)
|
||
self.ImportsH.HandleImportFromNames(child)
|
||
stdio.printf("[DIAG] 模块级: import 处理完成\n")
|
||
# 对齐 TPC _inject_auto_imports:检测源文件对 list/dict 容器的使用
|
||
# (裸名注解 d: dict / 构造 dict(...) / 下标 list[T]),自动把容器
|
||
# 类标记为可见结构体。背景:_list.vp/_dict.vp 定义内建容器类且已由
|
||
# Phase1 注册,但源文件不显式 import 它们(TPC 在翻译前自动注入
|
||
# import _list/_dict);TPV 用可见性机制等效替代——否则裸名
|
||
# `d: dict` 注解 resolve_annotation_type 时 is_struct_visible=0
|
||
# 解析失败(DictTest 的 "变量类型注解解析失败")。
|
||
self._inject_auto_container_visibility(pool, tree)
|
||
stdio.printf("[DIAG] 模块级: 容器可见性完成\n")
|
||
# 扫描当前模块的 CTypedef 声明(NAME: t.CTypedef = Type),
|
||
# 注册到动态 CTypedef 表,供 resolve_annotation_type 查询
|
||
HandlesType.ScanCTypedefDeclarations(pool, tree)
|
||
stdio.printf("[DIAG] 模块级: CTypedef 扫描完成\n")
|
||
# 跨模块 .vpi 注入:加载依赖模块的 .vpi 文件,
|
||
# 将函数 declare 声明注入到当前模块,解决跨模块函数调用找不到函数的问题
|
||
# 严格保证 declare_only == 0 时才注入(避免 Phase A-pre-inc 死锁)
|
||
if self._imported_modules is not None:
|
||
import lib.core.StubMerger as StubMerger
|
||
# 错误上下文帧:当前模块触发依赖 stub 加载的 import 位置
|
||
HandlesType.push_trace(HandlesType.get_current_file(), cur_imp_lineno)
|
||
StubMergerBuild.LoadDepVpiIntoModule(
|
||
pool, mod, self._imported_modules, self._from_imports,
|
||
HandlesType.get_temp_dir(), self)
|
||
HandlesType.pop_trace()
|
||
stdio.printf("[DIAG] 模块级: vpi 注入完成\n")
|
||
# 预注册模块级变量(AnnAssign/Assign)到 SymTab
|
||
# 解决时序问题:class Logger 的 __init__ 引用 _mbuddy 时,
|
||
# _mbuddy 的 AnnAssign 在 AST 中位于 class Logger 之后,
|
||
# 按 AST 顺序翻译时 _mbuddy 尚未注册 → lookup_var 返回 None → rhs_val is None
|
||
# 预处理先于 translate_children 注册所有模块级变量,
|
||
# 后续 translate_children 遍历到同一 AnnAssign 时 handle_module_level_var
|
||
# 通过 lookup_module_var 检测已存在并跳过(HandlesMain.py:206-209)
|
||
if ch is not None:
|
||
for ci in range(cn_count):
|
||
child: ast.AST | t.CPtr = ch.get(ci)
|
||
if child is None:
|
||
continue
|
||
kd_mv: int = child.kind()
|
||
if kd_mv == ast.ASTKind.AnnAssign or kd_mv == ast.ASTKind.Assign:
|
||
HandlesMain.handle_module_level_var(self, child)
|
||
stdio.printf("[DIAG] 模块级: 变量预注册完成\n")
|
||
# 创建前向声明
|
||
HandlesFunctions.forward_declare_functions(self, tree)
|
||
stdio.printf("[DIAG] 模块级: 前向声明完成\n")
|
||
added: int = HandlesMain.translate_children(self, tree)
|
||
stdio.printf("[DIAG] 模块级: translate_children 完成\n")
|
||
|
||
# ============================================================
|
||
# 容器模块自动可见性注入(对齐 TPC _inject_auto_imports)
|
||
#
|
||
# TPC 在翻译前自动注入 `import _list / import _dict (+json)` 到源文件,
|
||
# 使 list/dict 内建容器类在符号表中可见。TPV 用可见性机制等效替代:
|
||
# _list.vp/_dict.vp 已由 Phase1 注册(可达集合含它们),这里只需在
|
||
# 当前文件翻译时把容器类名标记为可见结构体,裸名注解/构造即可解析。
|
||
#
|
||
# 检测模式(与 TPC Phase2Translator._inject_auto_imports 一致):
|
||
# - AnnAssign 注解裸名 Name(list/dict):d: dict
|
||
# - 构造调用 func 裸名 Name(list/dict):dict(bd)
|
||
# - Subscript 的 value 裸名 Name(list/dict):list[int]
|
||
# ============================================================
|
||
def _inject_auto_container_visibility(self, pool: memhub.MemBuddy | t.CPtr,
|
||
tree: ast.AST | t.CPtr):
|
||
"""检测 list/dict 容器使用,注入容器类可见性"""
|
||
if tree is None or tree.children is None:
|
||
return
|
||
# 用栈式缓冲区传递检测结果(跨函数参数用 4 字节 int 指针)
|
||
need_list_box: t.CPtr = stdlib.malloc(4)
|
||
need_dict_box: t.CPtr = stdlib.malloc(4)
|
||
if need_list_box is None or need_dict_box is None:
|
||
if need_list_box is not None:
|
||
stdlib.free(need_list_box)
|
||
if need_dict_box is not None:
|
||
stdlib.free(need_dict_box)
|
||
return
|
||
need_list_box[0] = 0
|
||
need_dict_box[0] = 0
|
||
self._scan_container_usage(tree, need_list_box, need_dict_box)
|
||
if need_dict_box[0] != 0:
|
||
# dict 类可见 + _dict 模块导入(构造/方法调用的 SHA1 解析)
|
||
HandlesStruct.add_visible_struct(pool, "dict")
|
||
if self._imported_modules is None or \
|
||
HandlesImports.is_module_imported(self._imported_modules, "_dict") == 0:
|
||
self._imported_modules = HandlesImports.add_imported_module(
|
||
pool, self._imported_modules, "_dict")
|
||
if need_list_box[0] != 0:
|
||
HandlesStruct.add_visible_struct(pool, "list")
|
||
if self._imported_modules is None or \
|
||
HandlesImports.is_module_imported(self._imported_modules, "_list") == 0:
|
||
self._imported_modules = HandlesImports.add_imported_module(
|
||
pool, self._imported_modules, "_list")
|
||
stdlib.free(need_list_box)
|
||
stdlib.free(need_dict_box)
|
||
|
||
def _scan_container_usage(self, node: ast.AST | t.CPtr,
|
||
need_list_box: t.CPtr,
|
||
need_dict_box: t.CPtr):
|
||
"""递归扫描 AST 语句结构,检测 list/dict 容器使用"""
|
||
if node is None:
|
||
return
|
||
k: int = node.kind()
|
||
if k == ast.ASTKind.AnnAssign:
|
||
aa_s: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node)
|
||
if aa_s.annotation is not None:
|
||
self._check_container_type_node(aa_s.annotation, need_list_box, need_dict_box)
|
||
elif k == ast.ASTKind.Call:
|
||
cl_s: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node)
|
||
if cl_s.func is not None:
|
||
self._check_container_type_node(cl_s.func, need_list_box, need_dict_box)
|
||
elif k == ast.ASTKind.Subscript:
|
||
sub_s: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node)
|
||
if sub_s.value is not None:
|
||
self._check_container_type_node(sub_s.value, need_list_box, need_dict_box)
|
||
elif k == ast.ASTKind.List:
|
||
# [] 字面量:容器模板仍需注册
|
||
need_list_box[0] = 1
|
||
elif k == ast.ASTKind.Dict:
|
||
# {} 字面量:容器模板仍需注册
|
||
need_dict_box[0] = 1
|
||
# 递归语句块子节点
|
||
if node.children is not None:
|
||
ch_s: list[ast.AST | t.CPtr] | t.CPtr = node.children
|
||
n_s: t.CSizeT = len(ch_s)
|
||
for ci_s in range(n_s):
|
||
self._scan_container_usage(ch_s.get(ci_s), need_list_box, need_dict_box)
|
||
|
||
def _check_container_type_node(self, node: ast.AST | t.CPtr,
|
||
need_list_box: t.CPtr,
|
||
need_dict_box: t.CPtr):
|
||
"""检测类型位置节点是否为 list/dict(支持 Name 与 Subscript 外层)"""
|
||
if node is None:
|
||
return
|
||
k: int = node.kind()
|
||
if k == ast.ASTKind.Name:
|
||
nm_s: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
|
||
if nm_s.id is not None:
|
||
if string.strcmp(nm_s.id, "dict") == 0:
|
||
need_dict_box[0] = 1
|
||
elif string.strcmp(nm_s.id, "list") == 0:
|
||
need_list_box[0] = 1
|
||
elif k == ast.ASTKind.Subscript:
|
||
sub_s: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node)
|
||
if sub_s.value is not None:
|
||
self._check_container_type_node(sub_s.value, need_list_box, need_dict_box)
|
||
|
||
|
||
# ============================================================
|
||
# IR 输出
|
||
# ============================================================
|
||
def dump_ir(self, buf: bytes, size: t.CSizeT, mode: int):
|
||
"""将 LLVM IR 输出到缓冲区
|
||
|
||
mode: 0=完整, 1=stub(仅声明), 2=text(仅代码)
|
||
"""
|
||
if self.Module is None or buf is None:
|
||
return
|
||
if _mbuddy is None:
|
||
return
|
||
# 诊断(builtins.vp dump 卡死根因排查,仅 stub 模式打印一次):
|
||
# 模块函数清单 + 每个函数首个参数地址/Next 值(步数上限防成环死循环)。
|
||
# 确认 printf declare 的创建上下文与 Params 链损坏状态。
|
||
if mode == llvmlite.OUTPUT_STUB:
|
||
dbg_f: llvmlite.Function | t.CPtr = llvmlite.module_get_func_head(self.Module)
|
||
dbg_steps: int = 0
|
||
while dbg_f is not None:
|
||
dbg_steps += 1
|
||
if dbg_steps > 100000:
|
||
stdio.printf("[DIAG] 模块函数链遍历超限(dump_ir 诊断)\n")
|
||
stdlib.exit(1)
|
||
dbg_name: str = llvmlite.function_get_name(dbg_f)
|
||
dbg_p: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(dbg_f)
|
||
if dbg_p is not None:
|
||
dbg_pn: llvmlite.Param | t.CPtr = llvmlite.param_get_next(dbg_p)
|
||
stdio.printf("[DIAG] 模块函数: %s param0=%llu next=%llu\n",
|
||
dbg_name, t.CUInt64T(dbg_p), t.CUInt64T(dbg_pn))
|
||
else:
|
||
stdio.printf("[DIAG] 模块函数: %s (无参数)\n", dbg_name)
|
||
dbg_f = llvmlite.function_get_next(dbg_f)
|
||
buf[0] = '\0'
|
||
llvmlite.LLVMModulePrint(buf, size, self.Module, _mbuddy, mode)
|
||
|
||
|
||
# ============================================================
|
||
# global/nonlocal 名称管理(模块级辅助函数,委托到 gen 方法)
|
||
# ============================================================
|
||
def add_global_name(trans: HT.Translator | t.CPtr, name: str):
|
||
"""添加一个 global 变量名(委托到 gen.add_global_name)"""
|
||
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:
|
||
g.add_global_name(trans, name)
|
||
|
||
|
||
def is_global_name(trans: HT.Translator | t.CPtr, name: str) -> int:
|
||
"""检查 name 是否在当前函数的 global 集合中(委托到 gen.is_global_name)"""
|
||
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_global_name(trans, name)
|
||
return 0
|
||
|
||
|
||
def add_nonlocal_name(trans: HT.Translator | t.CPtr, name: str,
|
||
var_ty: llvmlite.LLVMType | t.CPtr = None):
|
||
"""添加一个 nonlocal 变量名(委托到 gen.add_nonlocal_name)
|
||
|
||
Args:
|
||
name: nonlocal 变量名
|
||
var_ty: 变量的 LLVM 类型(用于 env 指针数组方案的类型恢复,
|
||
None 时回退为 i32)
|
||
"""
|
||
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:
|
||
g.add_nonlocal_name(trans, name, var_ty)
|
||
|
||
|
||
def get_nonlocal_type(trans: HT.Translator | t.CPtr,
|
||
name: str) -> llvmlite.LLVMType | t.CPtr:
|
||
"""获取 nonlocal 变量的 LLVM 类型(委托到 gen.get_nonlocal_type)
|
||
|
||
Returns: 找到的类型指针,找不到返回 None
|
||
"""
|
||
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.get_nonlocal_type(trans, name)
|
||
return None
|
||
|
||
|
||
def is_nonlocal_name(trans: HT.Translator | t.CPtr, name: str) -> int:
|
||
"""检查 name 是否在当前函数的 nonlocal 集合中(委托到 gen.is_nonlocal_name)"""
|
||
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_nonlocal_name(trans, name)
|
||
return 0
|
||
|
||
|
||
def get_nonlocal_index(trans: HT.Translator | t.CPtr, name: str) -> int:
|
||
"""获取 nonlocal 变量在 env 中的索引(0-based),找不到返回 -1(委托到 gen.get_nonlocal_index)"""
|
||
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.get_nonlocal_index(trans, name)
|
||
return 0
|
||
|
||
|
||
def clear_scope_names(trans: HT.Translator | t.CPtr):
|
||
"""清空当前函数的 global/nonlocal 名称集合(进入新函数时调用)(委托到 gen.clear_scope_names)"""
|
||
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:
|
||
g.clear_scope_names(trans)
|
||
|
||
|
||
# 全局 mbuddy 指针
|
||
_mbuddy: memhub.MemBuddy | t.CPtr
|