refactor(TransPyV): 统一自举写法(字段默认值/novirtual/define/enum/指针注解)

- CallGenBase:字段声明处直接给默认值,InitCallGen 不再逐字段赋值
- CallGenFd/CallGenDispatch:@t.NoVTable 改 novirtual,清理过时注释
- VLogger:LogLevel 改 enum、t.CDefine 改 define 关键字、Logger|t.CPtr 改 Logger*、longjmp 用 rawptr
- Generator:_g_gen 由 Generator|t.CPtr 改为 Generator*
- CallGenProp:合并续行
This commit is contained in:
TermiNexus committed 2026-09-30 19:09:22 +08:00
1 parent 849001ae9e
commit f3c708613f
6 files changed
+74 -158

No files matched your search

+34 -74
View File
@@ -59,123 +59,89 @@ novirtual class CallGenBase:
# --- c.cexport 注册表(原 _g_cexport_sha1_arr/_g_cexport_func_arr/_g_cexport_count) ---
Gen: Generator.Generator*
CexportSha1Arr: bytes
CexportFuncArr: bytes
CexportCount: int
CexportSha1Arr: bytes = None
CexportFuncArr: bytes = None
CexportCount: int = 0
# --- static 符号注册表(`static` 修饰符 / @t.CStatic / t.CStatic 标记的符号 →
# 定义模块 SHA1)。语义 = 禁止跨模块使用(C 的 internal linkage):定义侧登记,
# 跨模块引用侧(mod.name 取值 / mod.fn() 调用 / from mod import name)拦截报错。
# 与 CexportSha1Arr 同款 PermPool 定长槽(跨 mark/reset 存活)。
StaticSha1Arr: bytes
StaticNameArr: bytes
StaticCount: int
StaticSha1Arr: bytes = None
StaticNameArr: bytes = None
StaticCount: int = 0
# --- LLVMIR 寄存器序号 ---
LLVMIRRegSeq: int
LLVMIRRegSeq: int = 0
# --- temp 目录 ---
TempDir: str
TempDirLen: sizet
TempDir: str = None
TempDirLen: sizet = 0
# --- 闭包名表(原 _g_closure_names/_g_closure_count) ---
ClosureNames: str
ClosureCount: int
ClosureNames: str = None
ClosureCount: int = 0
# --- 函数指针签名表(原 _g_funcptr_names/_g_funcptr_rets/_g_funcptr_count) ---
FuncptrNames: str
FuncptrRets: uint64*
FuncptrCount: int
FuncptrNames: str = None
FuncptrRets: uint64* = None
FuncptrCount: int = 0
# --- 全局函数注册表(原 _global_funcs/_global_func_count) ---
GlobalFuncs: GenTypes.FuncEntry*
GlobalFuncCount: int
GlobalFuncs: GenTypes.FuncEntry* = None
GlobalFuncCount: int = 0
# --- 全局函数表"名 → 槽下标"索引(开放寻址 | 线性探测;槽存 index+1,0=空槽) ---
# GlobalFuncs 只追加不重排 ⇒ 槽下标稳定;Built == GlobalFuncCount 才可信,否则回退线性扫描。
GlobalFuncNameIdx: sizet*
GlobalFuncNameIdxCap: int
GlobalFuncNameIdxBuilt: int
GlobalFuncNameIdx: sizet* = None
GlobalFuncNameIdxCap: int = 0
GlobalFuncNameIdxBuilt: int = -1
# --- 全局默认参数表(原 _global_defaults/_global_defaults_count) ---
GlobalDefaults: GenTypes.FuncDefaultsEntry*
GlobalDefaultsCount: int
GlobalDefaults: GenTypes.FuncDefaultsEntry* = None
GlobalDefaultsCount: int = 0
# --- 依赖模块 text.ll「方法返回类型文本」缓存(_LookupMethodRetTyFromTextLL 性能优化) ---
# key = define 的完整 mangled 函数名("{sha1}.{后缀}"),值只存文本(绝不存 LLVMType*,其分配在每文件 reset 失效的 pool 中);表与键/值均 PermPool 分配,命中后用调用方 pool 重建类型,建表失败即不缓存并回退原扫描。
MethodRetTyMap: hashtable.HashTable*
MethodRetTyMap: hashtable.HashTable* = None
def InitCallGen(self) -> int:
"""初始化调用 Mixin 字段(子类构造时内联调用,规避 NoVTable 继承符号不转发)"""
if self is None: return 1
self.CexportSha1Arr = None
self.CexportFuncArr = None
self.CexportCount = 0
self.LLVMIRRegSeq = 0
self.TempDir = None
self.TempDirLen = 0
self.ClosureNames = None
self.ClosureCount = 0
self.FuncptrNames = None
self.FuncptrRets = None
self.FuncptrCount = 0
self.GlobalFuncs = None
self.GlobalFuncCount = 0
self.GlobalFuncNameIdx = None
self.GlobalFuncNameIdxCap = 0
self.GlobalFuncNameIdxBuilt = -1
self.GlobalDefaults = None
self.GlobalDefaultsCount = 0
self.MethodRetTyMap = None
return 0
# P4 簇 1+2 迁移方法:模块 SHA1 查询 / CExport 注册表 / c.* 系列 / 内联汇编 / LLVMIR
def _lookup_module_sha1(self, mod_name: str) -> str:
"""查找模块名对应的 SHA1,找不到返回 None
委托给 StubMerger.LookupSha1ByModName(精确匹配 + 包名回退)。
"""
return StubMergerStore.LookupSha1ByModName(mod_name)
def _lookup_module_sha1_suffix(self, mod_suffix: str) -> str:
"""后缀匹配查找模块 SHA1,如 mod_suffix="__types" 匹配 "llvmlite.__types"
用于 from .X import Y 的相对导入:impf.module 是 ".X"(带前导点),
去掉前导点后为 "X",SHA1 映射表中键是 "pkg.X",需要后缀匹配。
委托给 StubMerger.LookupSha1ByModNameSuffix(精确 + 后缀 + 反向后缀)。
"""
return StubMergerStore.LookupSha1ByModNameSuffix(mod_suffix)
def _module_package_from_sha1(self, pool: memhub.MemBuddy*,
mod_sha1: str) -> str:
def _module_package_from_sha1(self, pool: memhub.MemBuddy*, mod_sha1: str) -> str:
"""从 SHA1 存储器的 rel_path 计算模块所属包名(目录部分,'/' → '.')"""
if pool is None or mod_sha1 is None:
return None
if pool is None or mod_sha1 is None: return None
rel_arr_ptr: bytes = StubMergerStore.GetSha1StoreRelArrPtr()
sha1_arr_ptr: bytes = StubMergerStore.GetSha1StoreArrPtr()
count: int = StubMergerStore.GetSha1StoreCount()
if rel_arr_ptr is None or sha1_arr_ptr is None or count <= 0:
return None
if rel_arr_ptr is None or sha1_arr_ptr is None or count <= 0: return None
for i in range(count):
sidx: sizet = sizet(i) * 17
if string.strcmp(sha1_arr_ptr + sidx, mod_sha1) != 0:
continue
if string.strcmp(sha1_arr_ptr + sidx, mod_sha1) != 0: continue
ridx: sizet = sizet(i) * StubMerger.MAX_REL_PATH_LEN
rel: str = rel_arr_ptr + ridx
last_slash: str = string.strrchr(rel, 47) # 47 = ord('/')
if last_slash is None:
return None
if last_slash is None: return None
pkg_len: sizet = sizet(uint64(last_slash) - uint64(rel))
if pkg_len == 0:
return None
if pkg_len == 0: return None
pkg_buf: str = pool.alloc(pkg_len + 1)
if pkg_buf is None:
return None
if pkg_buf is None: return None
for pi in range(pkg_len):
if rel[pi] == '/':
pkg_buf[pi] = '.'
@@ -186,28 +152,23 @@ novirtual class CallGenBase:
return None
def _lookup_reexport_from_vpi(self, pool: memhub.MemBuddy*,
mod_sha1: str, func_name: str) -> str:
def _lookup_reexport_from_vpi(self, pool: memhub.MemBuddy*, mod_sha1: str, func_name: str) -> str:
"""re-export 表未命中时,从模块 .vpi 按需解析 from-import 定位定义模块
includes 模块(如 llvmlite/__init__)的 stub/text 已存在时不会被按需
全量翻译(Phase2 3.5 仅在 stub/text 缺失时翻译),而 re-export 表只在
declare_only=0 的全量翻译中注册(HandleImportFromNames),因此表可能为空。
本函数解析该模块 .vpi 的 "from .X import ... func_name ..." 语句,
返回定义模块名(如 llvmlite/__init__ 的 .__builder → "llvmlite.__builder")。
"""
if pool is None or mod_sha1 is None or func_name is None:
return None
if pool is None or mod_sha1 is None or func_name is None: return None
# star import 候选模块累积(空格分隔):from X import * 无法确定归属,收集全部候选由调用方逐个验证
star_cands: str = None
star_cands_len: sizet = 0
temp_dir: str = self.Gen.TypeGenBase.get_temp_dir()
if temp_dir is None:
return None
if temp_dir is None: return None
td_len: sizet = string.strlen(temp_dir)
vpi_path: str = StubMergerCollect._sliced_path(temp_dir, td_len, mod_sha1, "vpi")
if vpi_path is None:
return None
if vpi_path is None: return None
READ_SZ: sizet = 1048576
buf: bytes = stdlib.malloc(READ_SZ)
if buf is None:
@@ -414,8 +375,7 @@ novirtual class CallGenBase:
误用 @1fdad1c76fb116bc.malloc 而非裸名 @malloc → ld.lld undefined
symbol: 1fdad1c76fb116bc.malloc)。
"""
if self.Gen is None or sha1 is None or func_name is None:
return 0
if self.Gen is None or sha1 is None or func_name is None: return 0
if self.Gen.CallGenBase.CexportSha1Arr is not None:
for i in range(self.Gen.CallGenBase.CexportCount):
idx: sizet = sizet(i) * 17
-4
View File
@@ -23,10 +23,6 @@ import lib.core.Gen.GenApi as GenApi
# ============================================================
# CallGenDispatch - CallGenMixin 拆分(阶段 C):translate_call 检测段
#
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 每个 helper 返回 Value|CPtr,None = 未命中(translate_call 继续)。
# @t.NoVTable:静态绑定。
# ============================================================
novirtual class CallGenDispatch(CallGenBase.CallGenBase):
"""translate_call 前置检测 helper(继承 Base)"""
+12 -32
View File
@@ -14,18 +14,9 @@ from . import CallGenBase
# ============================================================
# CallGenFd - CallGenMixin 拆分(阶段 B):FakeDuck / requires 字段注入 / provider 栈
#
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class CallGenFd(CallGenBase.CallGenBase):
novirtual class CallGenFd(CallGenBase.CallGenBase):
"""FakeDuck / requires 字段注入 / provider 栈"""
# _translate_fakeduck_call:FakeDuck str 变量方法调用 → 扩展类 _Type/_str(对齐 TPC HandlesExprCall.py L2841-2880)。对象是 Name 且有影子({var}__meta__)时 self=影子;否则在入口创建临时影子(__data__=obj 值、__mbuddy__=NULL)后作 self,避免 bitcast i8* → _str* 读垃圾指针
# ============================================================
def _translate_fakeduck_call(self, pool: memhub.MemBuddy*,
builder: llvmlite.IRBuilder*,
mod: llvmlite.LLVMModule*,
@@ -34,21 +25,15 @@ class CallGenFd(CallGenBase.CallGenBase):
cl: ast.Call*,
trans: HT.Translator*) -> llvmlite.Value*:
"""FakeDuck: str 变量方法调用解析到扩展类 _Type/_str,返回 call 结果或 None"""
if pool is None or builder is None or cl is None or trans is None:
return None
if method_name is None:
return None
if pool is None or builder is None or cl is None or trans is None: return None
if method_name is None: return None
# 仅对 str 类型触发(AnnotClassName == "str",对象是 char*);
# cls_name 为 None(表达式接收者解析失败)时也尝试
if cls_name is not None and string.strcmp(cls_name, "str") != 0:
return None
if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute:
return None
if cls_name is not None and string.strcmp(cls_name, "str") != 0: return None
if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute: return None
fd_at: ast.Attribute* = ast.Attribute*(cl.func)
if fd_at is None or fd_at.value is None or fd_at.attr is None:
return None
if string.strcmp(fd_at.attr, method_name) != 0:
return None
if fd_at is None or fd_at.value is None or fd_at.attr is None: return None
if string.strcmp(fd_at.attr, method_name) != 0: return None
# 候选扩展类:先 _Type(a.type_id())后 _str(a.upper() 等)
fd_func: llvmlite.Function* = None
fd_cls: str = None
@@ -63,12 +48,10 @@ class CallGenFd(CallGenBase.CallGenBase):
if fd_func is not None:
fd_cls = fd_cn
break
if fd_func is None or fd_cls is None:
return None
if fd_func is None or fd_cls is None: return None
# 扩展类结构体必须已注册(GEP/临时影子需要类型)
fd_sty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(fd_cls)
if fd_sty is None:
return None
if fd_sty is None: return None
# 扩展类字段数:有字段(_str)时 self 用影子结构体指针;
# 无字段(_Type)时 self 用对象值 bitcast 到扩展类指针(对齐 TPC L2856-2876)
fd_entry_fd: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_type(fd_sty)
@@ -93,8 +76,7 @@ class CallGenFd(CallGenBase.CallGenBase):
# 先确保 _str 完整定义(跨模块结构体默认 opaque,alloca 报 unsized)
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, fd_sty)
fd_self = self.Gen.VarGen._alloca_at_entry(builder, fd_sty)
if fd_self is None:
return None
if fd_self is None: return None
fd_obj_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fd_at.value, None, 0, trans)
if fd_obj_val is not None:
fd_dfe: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(fd_sty, "__data__")
@@ -102,8 +84,7 @@ class CallGenFd(CallGenBase.CallGenBase):
fd_dp: llvmlite.Value* = llvmlite.build_gep_struct(builder, fd_sty, fd_dfe.Ty, fd_self, fd_dfe.Index)
if fd_dp is not None:
llvmlite.build_store(builder, fd_obj_val, fd_dp)
fd_bfe: GenTypes.FieldEntry* = \
self.Gen.StructGen.lookup_field(fd_sty, "__mbuddy__")
fd_bfe: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(fd_sty, "__mbuddy__")
if fd_bfe is not None and fd_bfe.Ty is not None:
fd_bp: llvmlite.Value* = llvmlite.build_gep_struct(builder, fd_sty, fd_bfe.Ty, fd_self, fd_bfe.Index)
fd_null: llvmlite.Value* = llvmlite.ConstNull(pool, fd_bfe.Ty, "null")
@@ -149,8 +130,7 @@ class CallGenFd(CallGenBase.CallGenBase):
if fd_ret_ty is None:
fd_ret_ty = llvmlite.Int32(pool)
fd_fname: str = llvmlite.function_get_name(fd_func)
if fd_fname is None:
return None
if fd_fname is None: return None
# 返回类型精确化:跨模块 declare 的 list[T] 特化返回类型可能被简化为 Ptr(i8),调用方变量 alloca 类型随之退化 → parts[0] 走字符下标路径而非 list 内联 __getitem__(printf %s 崩溃)。从定义模块 text.ll 读取精确返回类型;仅当函数名确为 "{16hex}.{func}"(判定走唯一真源 GenApi.sha1_prefix_len)才提取模块 sha1
if GenApi.sha1_prefix_len(fd_fname) != 0:
fd_sha1: str = pool.alloc(17)
+1 -2
View File
@@ -431,8 +431,7 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
method_name: str,
cl: ast.Call*) -> int:
"""基于接收者实际类型判定 list 内建方法(实际类型不可得回退注解名)"""
sty: llvmlite.LLVMType* = \
self.Gen.StructGen.get_struct_type_from_value(recv_val)
sty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(recv_val)
if sty is not None:
ty_nm: str = llvmlite.get_struct_name(sty)
if ty_nm is not None and ty_nm[0] != '\0':
+1 -1
View File
@@ -459,4 +459,4 @@ novirtual class Generator:
# ============================================================
# 全局生成器单例(组合架构兼容层)
# ============================================================
_g_gen: Generator | t.CPtr = None
_g_gen: Generator* = None
+26 -45
View File
@@ -17,7 +17,7 @@ import w32.win32base as win32base
# 错误恢复(REPL/JIT 模式):error 打印后 longjmp 跳回 REPL 的 setjmp 点。
# mingw-w64 x86_64:longjmp 原型为 void longjmp(jmp_buf, int);setjmp 宏展开为
# _setjmp(buf, NULL)(jmp_buf 实为 _JBTYPE[16],见 Repl.vp 的 _REPL_JMPBUF_SIZE)。
extern def longjmp(buf: t.CPtr, val: int)
extern def longjmp(buf: rawptr, val: int)
# REPL 恢复点指针(由 Repl 在会话开始时注册、会话结束时清除)。
@@ -25,7 +25,7 @@ extern def longjmp(buf: t.CPtr, val: int)
# Repl.ReplExecFragment 入口重注册),故它覆盖整条片段流水线(翻译 → 写 .ll →
# llc → clang++ → LoadLibrary → GetProcAddress → 调用 → 回显),而不只是翻译期。
# 批处理路径从不调用 set_repl_jmpbuf ⇒ 恒为 None ⇒ 所有出口退回 sys.exit(1)。
_repl_jmpbuf: t.CPtr = None
_repl_jmpbuf: rawptr = None
# ============================================================
@@ -62,35 +62,29 @@ def clear_repl_jmpbuf() -> int:
return 0
# 日志级别
class LogLevel(t.CEnum):
DEBUG = 0
INFO = 1
WARNING = 2
ERROR = 3
SUCCESS = 4
CRITICAL = 5
enum LogLevel:
DEBUG, INFO, WARNING, ERROR, SUCCESS, CRITICAL
# Win32 控制台前景色属性
FOREGROUND_BLUE: t.CDefine = 0x0001
FOREGROUND_GREEN: t.CDefine = 0x0002
FOREGROUND_RED: t.CDefine = 0x0004
FOREGROUND_INTENSITY: t.CDefine = 0x0008
FOREGROUND_WHITE: t.CDefine = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
FOREGROUND_CYAN: t.CDefine = FOREGROUND_BLUE | FOREGROUND_GREEN
FOREGROUND_YELLOW: t.CDefine = FOREGROUND_RED | FOREGROUND_GREEN
FOREGROUND_MAGENTA: t.CDefine = FOREGROUND_RED | FOREGROUND_BLUE
define FOREGROUND_BLUE = 0x0001
define FOREGROUND_GREEN = 0x0002
define FOREGROUND_RED = 0x0004
define FOREGROUND_INTENSITY = 0x0008
define FOREGROUND_WHITE = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
define FOREGROUND_CYAN = FOREGROUND_BLUE | FOREGROUND_GREEN
define FOREGROUND_YELLOW = FOREGROUND_RED | FOREGROUND_GREEN
define FOREGROUND_MAGENTA = FOREGROUND_RED | FOREGROUND_BLUE
# Win32 控制台背景色属性
BACKGROUND_RED: t.CDefine = 0x0040
BACKGROUND_GREEN: t.CDefine = 0x0020
BACKGROUND_BLUE: t.CDefine = 0x0010
BACKGROUND_INTENSITY: t.CDefine = 0x0080
BACKGROUND_WHITE: t.CDefine = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
define BACKGROUND_RED = 0x0040
define BACKGROUND_GREEN = 0x0020
define BACKGROUND_BLUE = 0x0010
define BACKGROUND_INTENSITY = 0x0080
define BACKGROUND_WHITE = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
@t.NoVTable
class Logger:
novirtual class Logger:
_level: int
_console_handle: win32base.HANDLE
_use_color: int
@@ -138,25 +132,17 @@ class Logger:
return 0
def debug(self, msg: str, category: str = "") -> int:
return self._log(LogLevel.DEBUG, "├", "DEBUG", msg,
FOREGROUND_INTENSITY, FOREGROUND_INTENSITY, category)
return self._log(LogLevel.DEBUG, "├", "DEBUG", msg, FOREGROUND_INTENSITY, FOREGROUND_INTENSITY, category)
def info(self, msg: str, category: str = "") -> int:
ret: int = self._log(LogLevel.INFO, "├", "INFO", msg,
FOREGROUND_GREEN,
FOREGROUND_GREEN | FOREGROUND_INTENSITY, category)
ret: int = self._log(LogLevel.INFO, "├", "INFO", msg, FOREGROUND_GREEN, FOREGROUND_GREEN | FOREGROUND_INTENSITY, category)
return ret
def warning(self, msg: str, category: str = "") -> int:
return self._log(LogLevel.WARNING, "├", "WARN", msg,
FOREGROUND_YELLOW,
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
category)
return self._log(LogLevel.WARNING, "├", "WARN", msg, FOREGROUND_YELLOW, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY, category)
def error(self, msg: str, category: str = "") -> int:
ret: int = self._log(LogLevel.ERROR, "├", "ERROR", msg,
FOREGROUND_RED,
FOREGROUND_RED | FOREGROUND_INTENSITY, category)
ret: int = self._log(LogLevel.ERROR, "├", "ERROR", msg, FOREGROUND_RED, FOREGROUND_RED | FOREGROUND_INTENSITY, category)
# JIT/REPL 模式:诊断已打印,经统一出口跳回 REPL 循环(未武装时该出口仍终止进程)
if self.jit_flag:
repl_abort()
@@ -166,16 +152,11 @@ class Logger:
return ret
def success(self, msg: str, category: str = "") -> int:
return self._log(LogLevel.SUCCESS, "├", "SUCCESS", msg,
FOREGROUND_GREEN,
FOREGROUND_GREEN | FOREGROUND_INTENSITY, category)
return self._log(LogLevel.SUCCESS, "├", "SUCCESS", msg, FOREGROUND_GREEN, FOREGROUND_GREEN | FOREGROUND_INTENSITY, category)
def critical(self, msg: str, category: str = "") -> int:
# CRITICAL 使用 ╠ 前缀(红底白字标签,对齐 TPC critical 风格)
return self._log(LogLevel.CRITICAL, "╠", "CRITICAL", msg,
FOREGROUND_RED,
BACKGROUND_RED | FOREGROUND_WHITE | FOREGROUND_INTENSITY,
category)
return self._log(LogLevel.CRITICAL, "╠", "CRITICAL", msg, FOREGROUND_RED, BACKGROUND_RED | FOREGROUND_WHITE | FOREGROUND_INTENSITY, category)
def set_level(self, level: int) -> int:
self._level = level
@@ -232,8 +213,8 @@ class Logger:
_mbuddy: memhub.MemBuddy*
# 全局 logger 指针
logger: Logger | t.CPtr
log: Logger | t.CPtr
logger: Logger*
log: Logger*
def init_logger():
"""初始化全局 logger 实例。"""