Files
TransPyV/App/lib/core/Handles/HandlesTranslator.py

457 lines
19 KiB
Python
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 stdlib
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.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesFunctions as HandlesFunctions
import lib.Projectrans.Config as Config
# ============================================================
# 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*
# ============================================================
# 常量
MAX_VARS: t.CDefine = 256
MAX_FUNCS: t.CDefine = 256
MAX_GLOBAL_NAMES: t.CDefine = 32
@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
# 循环控制流目标break/continue
_break_bb: llvmlite.BasicBlock | t.CPtr
_continue_bb: llvmlite.BasicBlock | t.CPtr
# 独立标签计数器(不与 builder.Counter 共享,避免 SSA 编号非单调)
_label_counter: t.CInt
# global 声明的变量名集合(当前函数内)
_global_names: str
_global_name_count: t.CInt
# nonlocal 声明的变量名集合(当前函数内)
_nonlocal_names: str
_nonlocal_name_count: t.CInt
# 闭包相关:当前函数名(用于嵌套函数提升命名)
_cur_func_name: str
# 模块 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
# 泛型特化上下文:当前正在特化的类型参数名/实参名列表
# 由 _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
# 子 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
# 嵌套作用域符号表
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._cur_func_name = None
self.ModuleSha1 = None
self.CurrentPackage = None
self._closure_env_offsets = 0
self._closure_env_count = 0
self.GenericTypeParamNames = None
self.GenericTypeArgs = None
self._declare_only = 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.SymTab = None
# ============================================================
# 状态初始化
# ============================================================
def _init_state(self, pool: memhub.MemBuddy | t.CPtr):
"""初始化变量表、函数表和子 Handle"""
self.Pool = pool
if self._funcs is None:
self._funcs = HandlesExprCall.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
# 创建子 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.ExprH is None:
self.ExprH = HandlesExpr.NewExprHandle(pool, self)
if self.ExprCallH is None:
self.ExprCallH = HandlesExprCall.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
stdio.printf("[TR] step1 _init_state 前\n")
stdio.fflush(0)
# 初始化状态
self._init_state(pool)
stdio.printf("[TR] step1 _init_state 后\n")
stdio.fflush(0)
# 创建 LLVM 模块
stdio.printf("[TR] step2 new_module 前\n")
stdio.fflush(0)
mod: llvmlite.LLVMModule | t.CPtr = llvmlite.new_module(pool, "main")
stdio.printf("[TR] step2 new_module 后=%d\n", mod)
stdio.fflush(0)
if mod is None:
stdio.printf("[TR] NewModule returned NULL\n")
return 1
self.Module = mod
# 设置目标(优先使用 project.vpj 中的配置)
triple: str = Config.TargetTriple
if triple is None:
triple = "x86_64-pc-windows-msvc"
stdio.printf("[TR] step3 module_set_target 前\n")
stdio.fflush(0)
llvmlite.module_set_target(mod, triple)
stdio.printf("[TR] step3 module_set_target 后\n")
stdio.fflush(0)
# 类型
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
stdio.printf("[TR] step4 create_declare printf 前\n")
stdio.fflush(0)
printf_func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
pool, mod, "printf", i32_ty)
stdio.printf("[TR] step4 create_declare printf 后=%d\n", printf_func)
stdio.fflush(0)
if printf_func is None:
stdio.printf("[TR] CreateDeclare printf returned NULL\n")
return 1
llvmlite.add_param(pool, printf_func, i8_ptr_ty, "fmt")
printf_func.IsVarArg = 1
# 声明 malloc闭包分配用
stdio.printf("[TR] step5 create_declare malloc 前\n")
stdio.fflush(0)
malloc_func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
pool, mod, "malloc", i8_ptr_ty)
stdio.printf("[TR] step5 create_declare malloc 后\n")
stdio.fflush(0)
if malloc_func is not None:
i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool)
llvmlite.add_param(pool, malloc_func, i64_ty, "size")
# 检查用户是否定义了 main 函数
stdio.printf("[TR] step6 检查 user main 前\n")
stdio.fflush(0)
has_user_main: int = 0
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
if ch is not None:
cn_count: t.CSizeT = ch.__len__()
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("[TR] step6 检查 user main 后=%d\n", has_user_main)
stdio.fflush(0)
stdio.printf("[TR] step7 _translate_module_level 前\n")
stdio.fflush(0)
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)
stdio.printf("[TR] step7 _translate_module_level 后\n")
stdio.fflush(0)
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() 创建包装 maintrans 单参)"""
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("[TR._translate_module_level] _declare_only==0, 预处理 imports\n")
stdio.fflush(0)
# 预处理导入语句,确保 _imported_modules 和 _from_imports 已填充
# (前向声明需要解析类型注解,如 t.CArray[str] 依赖 t 模块已导入)
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
if ch is not None:
cn_count: t.CSizeT = ch.__len__()
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:
self.ImportsH.HandleImport(child)
elif kd == ast.ASTKind.ImportFrom:
self.ImportsH.HandleImportFromModule(child)
self.ImportsH.HandleImportFromNames(child)
stdio.printf("[TR._translate_module_level] 预处理 imports 完成\n")
stdio.fflush(0)
# 创建前向声明
stdio.printf("[TR._translate_module_level] forward_declare_functions 前\n")
stdio.fflush(0)
HandlesFunctions.forward_declare_functions(self, tree)
stdio.printf("[TR._translate_module_level] forward_declare_functions 后\n")
stdio.fflush(0)
stdio.printf("[TR._translate_module_level] translate_children 前\n")
stdio.fflush(0)
added: int = HandlesMain.translate_children(self, tree)
stdio.printf("[TR._translate_module_level] translate_children 后=%d\n", added)
stdio.fflush(0)
# ============================================================
# 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
buf[0] = '\0'
llvmlite.LLVMModulePrint(buf, size, self.Module, _mbuddy, mode)
# ============================================================
# global/nonlocal 名称管理(模块级辅助函数)
# ============================================================
def add_global_name(trans: HT.Translator | t.CPtr, name: str):
"""添加一个 global 变量名"""
if trans is None or name is None:
return
if trans._global_name_count >= MAX_GLOBAL_NAMES:
return
if trans._global_names is None:
return
# 检查是否已存在
if is_global_name(trans, name) != 0:
return
entry_addr: t.CUInt64T = t.CUInt64T(trans._global_names) + trans._global_name_count * 8
slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr)
slot_ptr[0] = name
trans._global_name_count += 1
def is_global_name(trans: HT.Translator | t.CPtr, name: str) -> int:
"""检查 name 是否在当前函数的 global 集合中"""
if trans is None or name is None or trans._global_names is None:
return 0
for i in range(trans._global_name_count):
entry_addr: t.CUInt64T = t.CUInt64T(trans._global_names) + i * 8
slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr)
entry: str = slot_ptr[0]
if entry is not None:
if string.strcmp(entry, name) == 0:
return 1
return 0
def add_nonlocal_name(trans: HT.Translator | t.CPtr, name: str):
"""添加一个 nonlocal 变量名"""
if trans is None or name is None:
return
if trans._nonlocal_name_count >= MAX_GLOBAL_NAMES:
return
if trans._nonlocal_names is None:
return
if is_nonlocal_name(trans, name) != 0:
return
entry_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_names) + trans._nonlocal_name_count * 8
slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr)
slot_ptr[0] = name
trans._nonlocal_name_count += 1
trans._closure_env_count += 1
def is_nonlocal_name(trans: HT.Translator | t.CPtr, name: str) -> int:
"""检查 name 是否在当前函数的 nonlocal 集合中"""
if trans is None or name is None or trans._nonlocal_names is None:
return 0
for i in range(trans._nonlocal_name_count):
entry_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_names) + i * 8
slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr)
entry: str = slot_ptr[0]
if entry is not None:
if string.strcmp(entry, name) == 0:
return 1
return 0
def get_nonlocal_index(trans: HT.Translator | t.CPtr, name: str) -> int:
"""获取 nonlocal 变量在 env 中的索引0-based找不到返回 -1"""
if trans is None or name is None or trans._nonlocal_names is None:
return -1
for i in range(trans._nonlocal_name_count):
entry_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_names) + i * 8
slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr)
entry: str = slot_ptr[0]
if entry is not None:
if string.strcmp(entry, name) == 0:
return i
return -1
def clear_scope_names(trans: HT.Translator | t.CPtr):
"""清空当前函数的 global/nonlocal 名称集合(进入新函数时调用)"""
if trans is None:
return
trans._global_name_count = 0
trans._nonlocal_name_count = 0
trans._closure_env_count = 0
# 全局 mbuddy 指针
_mbuddy: memhub.MemBuddy | t.CPtr