Fixed some bugs and tried to maintain the bootstrap

This commit is contained in:
2026-07-28 21:10:05 +08:00
parent 03d0bba534
commit 68481a5a7f
28 changed files with 667 additions and 1491 deletions

View File

@@ -52,71 +52,36 @@ def Load_project_config(path: str) -> int:
global IncludesDir global IncludesDir
if path is None: if path is None:
stdio.printf("[CFG] FAIL: path is None\n")
stdio.fflush(0)
return 1 return 1
if _mbuddy is None: if _mbuddy is None:
stdio.printf("[CFG] FAIL: _mbuddy is None\n")
stdio.fflush(0)
return 1 return 1
# 打开文件 # 打开文件
stdio.printf("[CFG] before File ctor path=%s\n", path)
stdio.fflush(0)
f: fileio.File | t.CPtr = fileio.File(path, fileio.MODE.R) f: fileio.File | t.CPtr = fileio.File(path, fileio.MODE.R)
f_closed_flag: int = 1
if f is not None:
if f.closed:
f_closed_flag = 1
else:
f_closed_flag = 0
stdio.printf("[CFG] after File ctor f=%p closed=%d\n", f, f_closed_flag)
stdio.fflush(0)
if f is None: if f is None:
stdio.printf("[CFG] FAIL: File ctor returned None\n")
stdio.fflush(0)
return 1 return 1
if f.closed: if f.closed:
stdio.printf("[CFG] FAIL: f.closed is True\n")
stdio.fflush(0)
return 1 return 1
# 分配读取缓冲区 # 分配读取缓冲区
CFG_BUF_SIZE: t.CSizeT = 8192 CFG_BUF_SIZE: t.CSizeT = 8192
buf: bytes = _mbuddy.alloc(CFG_BUF_SIZE) buf: bytes = _mbuddy.alloc(CFG_BUF_SIZE)
if buf is None: if buf is None:
stdio.printf("[CFG] FAIL: alloc buf failed\n")
stdio.fflush(0)
f.close() f.close()
return 1 return 1
stdio.printf("[CFG] before read_all\n")
stdio.fflush(0)
bytes_read: t.CInt64T = f.read_all(buf, CFG_BUF_SIZE) bytes_read: t.CInt64T = f.read_all(buf, CFG_BUF_SIZE)
f.close() f.close()
stdio.printf("[CFG] after read_all bytes_read=%d\n", bytes_read)
stdio.fflush(0)
if bytes_read <= 0: if bytes_read <= 0:
stdio.printf("[CFG] FAIL: bytes_read <= 0\n")
stdio.fflush(0)
return 1 return 1
# 解析 JSON # 解析 JSON
stdio.printf("[CFG] before json_parse\n")
stdio.fflush(0)
root: JsonValue | t.CPtr = json_parse(_mbuddy, buf) root: JsonValue | t.CPtr = json_parse(_mbuddy, buf)
stdio.printf("[CFG] after json_parse root=%p\n", root)
stdio.fflush(0)
if root is None: if root is None:
stdio.printf("[CFG] FAIL: json_parse returned None\n")
stdio.fflush(0)
return 1 return 1
if not root.is_object(): if not root.is_object():
stdio.printf("[CFG] FAIL: root is not object\n")
stdio.fflush(0)
return 1 return 1
stdio.printf("[CFG] root is object OK\n")
stdio.fflush(0)
# 读取顶层字段(使用显式 __getitem__ 调用,兼容旧编译器二进制) # 读取顶层字段(使用显式 __getitem__ 调用,兼容旧编译器二进制)
sd_val: JsonValue | t.CPtr = root.__getitem__("source_dir") sd_val: JsonValue | t.CPtr = root.__getitem__("source_dir")

View File

@@ -16,7 +16,7 @@ import w32.win32base
# ============================================================ # ============================================================
# 全局 mbuddy 指针 # 全局 mbuddy 指针
_mbuddy: memhub.MemManager | t.CPtr _mbuddy: memhub.MemBuddy | t.CPtr
# ============================================================ # ============================================================

View File

@@ -9,14 +9,15 @@ import lib.core.VLogger as VLogger
# ============================================================ # ============================================================
# 全局 mbuddy 内存池指针(由 App/main.py 初始化后注入) # 全局 mbuddy 内存池指针(由 App/main.py 初始化后注入)
_mbuddy: memhub.MemManager | t.CPtr # 注意: 使用 MemBuddy 类型而非 MemManager避免虚函数分派不工作时调用父类 alloc 返回 None
_mbuddy: memhub.MemBuddy | t.CPtr
def InitLib(mb: memhub.MemManager | t.CPtr) -> int: def InitLib(mb: memhub.MemBuddy | t.CPtr) -> int:
"""初始化 lib 包的全局 _mbuddy 指针,并级联注入到所有子模块。 """初始化 lib 包的全局 _mbuddy 指针,并级联注入到所有子模块。
Args: Args:
mb: memhub.MemManager 实例指针MemBuddy 等子类通过多态传入) mb: memhub.MemBuddy 实例指针
Returns: Returns:
0 表示成功,非 0 表示失败 0 表示成功,非 0 表示失败

View File

@@ -27,7 +27,7 @@ import lib.Projectrans.Config as Config
# ============================================================ # ============================================================
# 全局 mbuddy 指针 # 全局 mbuddy 指针
_mbuddy: memhub.MemManager | t.CPtr _mbuddy: memhub.MemBuddy | t.CPtr
# 源代码缓冲区大小1MB # 源代码缓冲区大小1MB
SRC_BUF_SIZE: t.CDefine = 1048576 SRC_BUF_SIZE: t.CDefine = 1048576
@@ -270,26 +270,11 @@ def compile_ll_to_obj(ir_path: str, output_dir: str, module_name: str, cc_cmd: s
return 1 return 1
viperlib.snprintf(cmd, cmd_len, "%s %s -o %s %s", cc_cmd, cc_flags, obj_path, ir_path) viperlib.snprintf(cmd, cmd_len, "%s %s -o %s %s", cc_cmd, cc_flags, obj_path, ir_path)
result: subprocess.CompletedProcess | t.CPtr = subprocess.run(cmd, True, True) # 用 stdlib.system() 直接在控制台运行,输出直接显示
if result is None: # 避免 subprocess 管道捕获丢失输出
sys_ret: int = stdlib.system(cmd)
if sys_ret != 0:
fb: t.CChar | t.CPtr = VLogger.fmt_buf() fb: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb is not None:
viperlib.snprintf(fb, 1024, "subprocess.run 返回 None: %s", module_name)
VLogger.error(fb, "LLC")
return 1
if result.returncode != 0:
# 先直接输出 llc 的具体错误信息VLogger.error 会 sys.exit必须先输出
# 注意: subprocess 在 Windows 下将 stderr 合并到 stdoutsi.hStdError = stdout_write
# 因此 result.stderr 总是 None错误信息在 result.stdout 中
# stdout 通常已含换行符,不再额外加 \n
if result.stdout is not None:
stdio.printf("%s", result.stdout)
stdio.fflush(0)
if result.stderr is not None:
stdio.printf("%s", result.stderr)
stdio.fflush(0)
# 最后输出编译失败摘要VLogger.error 会 sys.exit
fb = VLogger.fmt_buf()
if fb is not None: if fb is not None:
viperlib.snprintf(fb, 1024, "编译失败 (module=%s, cmd=%s)", module_name, cmd) viperlib.snprintf(fb, 1024, "编译失败 (module=%s, cmd=%s)", module_name, cmd)
VLogger.error(fb, "LLC") VLogger.error(fb, "LLC")
@@ -524,23 +509,13 @@ def link_objs_to_exe(obj_paths: str, obj_paths_len: t.CSizeT,
viperlib.snprintf(cmd, cmd_len, "%s %s -o %s %s", viperlib.snprintf(cmd, cmd_len, "%s %s -o %s %s",
linker_cmd, obj_paths, linker_output, linker_flags) linker_cmd, obj_paths, linker_output, linker_flags)
result: subprocess.CompletedProcess | t.CPtr = subprocess.run(cmd, True, True) # 用 stdlib.system() 直接在控制台运行链接,输出直接显示
if result is None: # 避免 subprocess 管道捕获丢失输出TransPyV 标准句柄可能无效)
VLogger.error("subprocess.run 返回 None", "link") sys_ret: int = stdlib.system(cmd)
return 1 if sys_ret != 0:
if result.returncode != 0:
# 先直接输出 linker 的具体错误信息VLogger.error 会 sys.exit必须先输出
# stdout/stderr 通常已含换行符,不再额外加 \n
if result.stdout is not None:
stdio.printf("%s", result.stdout)
stdio.fflush(0)
if result.stderr is not None:
stdio.printf("%s", result.stderr)
stdio.fflush(0)
# 最后输出链接失败摘要VLogger.error 会 sys.exit
fb: t.CChar | t.CPtr = VLogger.fmt_buf() fb: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb is not None: if fb is not None:
viperlib.snprintf(fb, 1024, "链接失败,返回码: %d, 命令: %s", result.returncode, cmd) viperlib.snprintf(fb, 1024, "链接失败,返回码: %d, 命令: %s", sys_ret, cmd)
VLogger.error(fb, "link") VLogger.error(fb, "link")
return 1 return 1
return 0 return 0

View File

@@ -4,6 +4,7 @@ import ast
import llvmlite import llvmlite
import memhub import memhub
import string import string
import stdio
import lib.core.Handles.HandlesBase as HandlesBase import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesVar as HandlesVar import lib.core.Handles.HandlesVar as HandlesVar
@@ -49,19 +50,73 @@ def is_cdefine_annotation(annot: ast.AST | t.CPtr) -> int:
# ============================================================ # ============================================================
# extract_cdefine_int_value - 从 AnnAssign.value 提取整数常量(模块级函数) # extract_cdefine_int_value - 从 AnnAssign.value 提取整数常量(模块级函数)
# #
# 支持 ast.Constant(INT),其他形式返回 0 # 支持的表达式形式:
# 1. Constant(INT) — 如 0x0002, 42
# 2. BinOp(BitOr/BitAnd) — 如 FOREGROUND_RED | FOREGROUND_GREEN
# 3. Name — 引用已注册的 CDefine 常量
# 4. Call — 如 t.CUnsignedLong(-11) → 取第一个参数
# 5. UnaryOp(USub/UAdd/Invert) — 如 -11
# ============================================================ # ============================================================
def extract_cdefine_int_value(val_node: ast.AST | t.CPtr) -> int: def extract_cdefine_int_value(val_node: ast.AST | t.CPtr) -> int:
"""从值节点提取整数常量(支持 Constant INT""" """从值节点提取整数常量(支持 Constant/BinOp/Name/Call/UnaryOp"""
if val_node is None: if val_node is None:
return 0 return 0
if val_node.kind() != ast.ASTKind.Constant: k: int = val_node.kind()
return 0
# Case 1: Constant(INT) — 如 0x0002
if k == ast.ASTKind.Constant:
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(val_node) cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(val_node)
if cn.const_kind != ast.CONST_INT: if cn.const_kind != ast.CONST_INT:
return 0 return 0
return cn.int_val return cn.int_val
# Case 2: BinOp — 如 FOREGROUND_RED | FOREGROUND_GREEN
if k == ast.ASTKind.BinOp:
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(val_node)
left_val: int = extract_cdefine_int_value(bop.left)
right_val: int = extract_cdefine_int_value(bop.right)
if bop.op == ast.OpKind.BitOr:
return left_val | right_val
if bop.op == ast.OpKind.BitAnd:
return left_val & right_val
if bop.op == ast.OpKind.Add:
return left_val + right_val
if bop.op == ast.OpKind.Sub:
return left_val - right_val
return 0
# Case 3: Name — 引用已注册的 CDefine 常量
if k == ast.ASTKind.Name:
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(val_node)
if nm.id is not None:
looked_up: int = HandlesType.lookup_cdefine_constant(nm.id)
if HandlesType.is_cdefine_found() != 0:
return looked_up
return 0
# Case 4: Call — 如 t.CUnsignedLong(-11)
if k == ast.ASTKind.Call:
cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(val_node)
if cl.args is not None and cl.args.__len__() > 0:
first_arg: ast.AST | t.CPtr = cl.args.get(0)
arg_val: int = extract_cdefine_int_value(first_arg)
return arg_val
return 0
# Case 5: UnaryOp — 如 -11
if k == ast.ASTKind.UnaryOp:
uop: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(val_node)
operand_val: int = extract_cdefine_int_value(uop.operand)
if uop.op == ast.OpKind.USub:
return -operand_val
if uop.op == ast.OpKind.UAdd:
return operand_val
if uop.op == ast.OpKind.Invert:
return ~operand_val
return 0
return 0
# ============================================================ # ============================================================
# _annotation_contains_name - 递归检查注解中是否包含指定名称 # _annotation_contains_name - 递归检查注解中是否包含指定名称

View File

@@ -238,8 +238,6 @@ class AssignHandle(HandlesBase.Mixin):
setitem_done = 1 setitem_done = 1
if setitem_done == 0: if setitem_done == 0:
sub_vk: int = sub_asgn.value.kind() sub_vk: int = sub_asgn.value.kind()
stdio.printf("[ASGN-SUB] fallback failed: val_kind=%d\n", sub_vk)
stdio.fflush(0)
if setitem_done == 0: if setitem_done == 0:
HandlesType.fatal_error(target, "subscript ptr is None") HandlesType.fatal_error(target, "subscript ptr is None")
continue continue
@@ -249,25 +247,14 @@ class AssignHandle(HandlesBase.Mixin):
field_ptr: llvmlite.Value | t.CPtr = HandlesExpr.get_attribute_ptr( field_ptr: llvmlite.Value | t.CPtr = HandlesExpr.get_attribute_ptr(
builder, pool, mod, target, self.Trans) builder, pool, mod, target, self.Trans)
if field_ptr is not None: if field_ptr is not None:
stdio.printf("[ASGN-ATTR] field_ptr ok ty_not_null=%d\n",
1 if field_ptr.Ty is not None else 0)
stdio.fflush(0)
# 获取字段类型,对 rhs_val 进行类型转换(如 i32 → i64 # 获取字段类型,对 rhs_val 进行类型转换(如 i32 → i64
store_val: llvmlite.Value | t.CPtr = rhs_val store_val: llvmlite.Value | t.CPtr = rhs_val
if field_ptr.Ty is not None: if field_ptr.Ty is not None:
field_ty: llvmlite.LLVMType | t.CPtr = field_ptr.Ty.Pointee field_ty: llvmlite.LLVMType | t.CPtr = field_ptr.Ty.Pointee
if field_ty is not None: if field_ty is not None:
stdio.printf("[ASGN-ATTR] coerce rhs_ty=%d field_ty=%d\n",
HandlesExpr.get_llvm_type_bits(rhs_val.Ty),
HandlesExpr.get_llvm_type_bits(field_ty))
stdio.fflush(0)
store_val = HandlesExpr.coerce_to_type( store_val = HandlesExpr.coerce_to_type(
builder, rhs_val, field_ty) builder, rhs_val, field_ty)
stdio.printf("[ASGN-ATTR] pre_store\n")
stdio.fflush(0)
llvmlite.build_store(builder, store_val, field_ptr) llvmlite.build_store(builder, store_val, field_ptr)
stdio.printf("[ASGN-ATTR] post_store\n")
stdio.fflush(0)
else: else:
# 构造详细错误信息 # 构造详细错误信息
attr_node: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(target) attr_node: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(target)

View File

@@ -69,7 +69,7 @@ class TypeInfo:
# ============================================================ # ============================================================
class TypeRegistry: class TypeRegistry:
_ht: hashtable.HashTable | t.CPtr _ht: hashtable.HashTable | t.CPtr
__mbuddy__: memhub.MemManager | t.CPtr __mbuddy__: memhub.MemBuddy | t.CPtr
def Register(self, ti: TypeInfo | t.CPtr) -> int: def Register(self, ti: TypeInfo | t.CPtr) -> int:
"""注册一个 TypeInfo。ti.Name 字段必须已设置。 """注册一个 TypeInfo。ti.Name 字段必须已设置。
@@ -106,7 +106,7 @@ class TypeRegistry:
# #
# 默认值Kind=Basic, IsSigned=-1, 其余=0/None # 默认值Kind=Basic, IsSigned=-1, 其余=0/None
# ============================================================ # ============================================================
def NewTypeInfo(pool: memhub.MemManager | t.CPtr) -> TypeInfo | t.CPtr: def NewTypeInfo(pool: memhub.MemBuddy | t.CPtr) -> TypeInfo | t.CPtr:
ptr: TypeInfo | t.CPtr = pool.alloc(TypeInfo.__sizeof__()) ptr: TypeInfo | t.CPtr = pool.alloc(TypeInfo.__sizeof__())
if ptr is None: if ptr is None:
return None return None
@@ -119,7 +119,7 @@ def NewTypeInfo(pool: memhub.MemManager | t.CPtr) -> TypeInfo | t.CPtr:
# ============================================================ # ============================================================
# NewTypeRegistry - 工厂函数:创建类型注册表 # NewTypeRegistry - 工厂函数:创建类型注册表
# ============================================================ # ============================================================
def NewTypeRegistry(pool: memhub.MemManager | t.CPtr) -> TypeRegistry | t.CPtr: def NewTypeRegistry(pool: memhub.MemBuddy | t.CPtr) -> TypeRegistry | t.CPtr:
ptr: TypeRegistry | t.CPtr = pool.alloc(TypeRegistry.__sizeof__()) ptr: TypeRegistry | t.CPtr = pool.alloc(TypeRegistry.__sizeof__())
if ptr is None: if ptr is None:
return None return None

View File

@@ -818,7 +818,7 @@ def _translate_enum_def(trans: HT.Translator | t.CPtr,
# 用于联合体确定最大字段大小 # 用于联合体确定最大字段大小
# ============================================================ # ============================================================
def _get_type_size(ty: llvmlite.LLVMType | t.CPtr) -> int: def _get_type_size(ty: llvmlite.LLVMType | t.CPtr) -> int:
"""计算 LLVM 类型的字节大小""" """计算 LLVM 类型的字节大小(含对齐 padding"""
if ty is None: if ty is None:
return 0 return 0
match ty: match ty:
@@ -831,20 +831,79 @@ def _get_type_size(ty: llvmlite.LLVMType | t.CPtr) -> int:
case llvmlite.LLVMType.Array(elem_ty, count): case llvmlite.LLVMType.Array(elem_ty, count):
return _get_type_size(elem_ty) * count return _get_type_size(elem_ty) * count
case llvmlite.LLVMType.Struct(fields, fcount, name): case llvmlite.LLVMType.Struct(fields, fcount, name):
# 计算结构体大小,考虑字段对齐 padding
# 规则: 每个字段的对齐 = 该字段类型的自然对齐
# 指针/i64 → 8, i32 → 4, i16 → 2, i8 → 1
# 结构体总大小需对齐到最大字段对齐的倍数
total: int = 0 total: int = 0
max_align: int = 1
cur: llvmlite.ParamNode | t.CPtr = fields cur: llvmlite.ParamNode | t.CPtr = fields
i: int = 0 i: int = 0
while cur is not None and i < fcount: while cur is not None and i < fcount:
if cur.Ty is not None: if cur.Ty is not None:
fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(cur.Ty) fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(cur.Ty)
total += _get_type_size(fty) fsize: int = _get_type_size(fty)
falign: int = _get_type_align(fty)
# 对齐当前偏移到字段对齐边界
if falign > 0:
rem: int = total % falign
if rem != 0:
total += falign - rem
total += fsize
if falign > max_align:
max_align = falign
cur = cur.Next cur = cur.Next
i += 1 i += 1
# 结构体总大小对齐到最大字段对齐的倍数
rem2: int = total % max_align
if rem2 != 0:
total += max_align - rem2
return total return total
case _: case _:
return 8 return 8
def _get_type_align(ty: llvmlite.LLVMType | t.CPtr) -> int:
"""返回类型的自然对齐(字节)"""
if ty is None:
return 1
match ty:
case llvmlite.LLVMType.Int(bits):
if bits <= 8:
return 1
elif bits <= 16:
return 2
elif bits <= 32:
return 4
else:
return 8
case llvmlite.LLVMType.Float(bits):
if bits <= 32:
return 4
else:
return 8
case llvmlite.LLVMType.Ptr(pointee):
return 8
case llvmlite.LLVMType.Array(elem_ty, count):
return _get_type_align(elem_ty)
case llvmlite.LLVMType.Struct(fields, fcount, name):
# 结构体的对齐 = 最大字段对齐
max_align: int = 1
cur: llvmlite.ParamNode | t.CPtr = fields
i: int = 0
while cur is not None and i < fcount:
if cur.Ty is not None:
fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(cur.Ty)
fa: int = _get_type_align(fty)
if fa > max_align:
max_align = fa
cur = cur.Next
i += 1
return max_align
case _:
return 8
# ============================================================ # ============================================================
# _translate_union_def — 翻译联合体定义 # _translate_union_def — 翻译联合体定义
# #
@@ -3003,6 +3062,8 @@ def _translate_method(trans: HT.Translator | t.CPtr,
return 0 return 0
# 提取默认参数信息(方法的 args[0] 是 self不含在 param_count 中) # 提取默认参数信息(方法的 args[0] 是 self不含在 param_count 中)
# 注意: 必须先把属性赋给显式类型为 list[...] | t.CPtr 的局部变量再调用 __len__()
# 否则编译器无法识别属性返回的 list 类型GEP base 会变成 i32 0 导致 llc 报错
md_defaults: t.CVoid | t.CPtr = None md_defaults: t.CVoid | t.CPtr = None
md_default_count: int = 0 md_default_count: int = 0
md_param_count: int = 0 md_param_count: int = 0
@@ -3010,10 +3071,12 @@ def _translate_method(trans: HT.Translator | t.CPtr,
if md_args_node is not None: if md_args_node is not None:
md_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(md_args_node) md_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(md_args_node)
if md_ags.args is not None: if md_ags.args is not None:
md_param_count = md_ags.args.__len__() - 1 md_alist: list[ast.AST | t.CPtr] | t.CPtr = md_ags.args
md_param_count = md_alist.__len__() - 1
if md_ags.defaults is not None: if md_ags.defaults is not None:
md_defaults = md_ags.defaults md_dlist: list[ast.AST | t.CPtr] | t.CPtr = md_ags.defaults
md_default_count = md_ags.defaults.__len__() md_defaults = md_dlist
md_default_count = md_dlist.__len__()
# 注册到函数表(用 ClassName.method_name 作为查找名,支持后缀匹配) # 注册到函数表(用 ClassName.method_name 作为查找名,支持后缀匹配)
max_funcs: int = 256 max_funcs: int = 256
@@ -3059,12 +3122,16 @@ def _translate_method(trans: HT.Translator | t.CPtr,
# 进入函数作用域 # 进入函数作用域
HandlesVar.enter_scope(trans.SymTab, SCOPE_FUNCTION) HandlesVar.enter_scope(trans.SymTab, SCOPE_FUNCTION)
# 注册 self 为 SSA 值(不创建 alloca,不 store # self 创建 alloca store(与其他参数一致
# 这样 self.field 通过 lookup_var 获取 Ptr(struct_ty) 后直接 GEP # 修复: 之前 self 注册为 SSA 值导致 translate_name_value 错误地 load 一次
self_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, self_ptr_ty, "%self") # 将 Ptr(struct_ty) 变成 struct 值,引发变参函数 ABI 不匹配崩溃
HandlesVar.define_var(trans.SymTab, "self", self_val) self_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, self_ptr_ty)
if self_alloca is not None:
HandlesVar.define_var(trans.SymTab, "self", self_alloca)
# 设置 self 的类型注解类名(属性访问 lookup_field 回退查找用) # 设置 self 的类型注解类名(属性访问 lookup_field 回退查找用)
HandlesVar.set_var_annot_class_name(trans.SymTab, "self", class_name) HandlesVar.set_var_annot_class_name(trans.SymTab, "self", class_name)
self_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, self_ptr_ty, "%self")
llvmlite.build_store(func_builder, self_val, self_alloca)
# 为其他参数创建 alloca 并 store与普通函数一致跳过索引 0 的 self 参数) # 为其他参数创建 alloca 并 store与普通函数一致跳过索引 0 的 self 参数)
if args_node is not None: if args_node is not None:

View File

@@ -238,7 +238,10 @@ def coerce_to_type(builder: llvmlite.IRBuilder | t.CPtr,
if val_bits != 0 and is_ptr_type(target_ty) != 0: if val_bits != 0 and is_ptr_type(target_ty) != 0:
return llvmlite.build_inttoptr(builder, val, target_ty) return llvmlite.build_inttoptr(builder, val, target_ty)
# 指针 → 整数: ptrtoint当目标明确是整数而非指针时 # 指针 → 整数: ptrtoint当目标明确是整数而非指针时
if is_ptr_type(val.Ty) != 0 and target_bits != 0 and is_ptr_type(target_ty) == 0: # 注意: target_bits == 8 时跳过 ptrtoint走后面的 build_load 解引用首字符
# 修复: buf[idx] = '\0' 中 '\0' 是 CONST_STR → i8* 指针,
# ptrtoint 会截断地址低 8 位(非 0应 load 解引用取首字符 0
if is_ptr_type(val.Ty) != 0 and target_bits != 0 and target_bits != 8 and is_ptr_type(target_ty) == 0:
return llvmlite.build_ptrtoint(builder, val, target_ty) return llvmlite.build_ptrtoint(builder, val, target_ty)
if val_bits != 0 and target_bits != 0: if val_bits != 0 and target_bits != 0:
if val_bits == target_bits: if val_bits == target_bits:
@@ -284,8 +287,6 @@ def create_global_string(builder: llvmlite.IRBuilder | t.CPtr,
"""创建全局字符串常量并返回 i8* bitcast""" """创建全局字符串常量并返回 i8* bitcast"""
escaped: t.CChar | t.CPtr = escape_llvm_string(pool, str_val) escaped: t.CChar | t.CPtr = escape_llvm_string(pool, str_val)
if escaped is None: if escaped is None:
stdio.printf("[CGS] escape_llvm_string None\n")
stdio.fflush(0)
return None return None
slen: t.CSizeT = string.strlen(str_val) slen: t.CSizeT = string.strlen(str_val)
@@ -301,8 +302,6 @@ def create_global_string(builder: llvmlite.IRBuilder | t.CPtr,
# 字符串名加 SHA1 前缀,和函数导出规则一致,避免跨模块重名 # 字符串名加 SHA1 前缀,和函数导出规则一致,避免跨模块重名
gv_name: t.CChar | t.CPtr = pool.alloc(48) gv_name: t.CChar | t.CPtr = pool.alloc(48)
if gv_name is None: if gv_name is None:
stdio.printf("[CGS] gv_name alloc None\n")
stdio.fflush(0)
return None return None
if trans.ModuleSha1 is not None: if trans.ModuleSha1 is not None:
viperlib.snprintf(gv_name, 48, ".str.%s.%d", trans.ModuleSha1, str_idx) viperlib.snprintf(gv_name, 48, ".str.%s.%d", trans.ModuleSha1, str_idx)
@@ -311,8 +310,6 @@ def create_global_string(builder: llvmlite.IRBuilder | t.CPtr,
gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, gv_name, arr_ty) gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, gv_name, arr_ty)
if gv is None: if gv is None:
stdio.printf("[CGS] new_global_variable None name=%s\n", gv_name)
stdio.fflush(0)
return None return None
llvmlite.module_add_global(mod, gv) llvmlite.module_add_global(mod, gv)
@@ -324,8 +321,6 @@ def create_global_string(builder: llvmlite.IRBuilder | t.CPtr,
arr_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, arr_ty) arr_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, arr_ty)
gv_ref_name: t.CChar | t.CPtr = pool.alloc(64) gv_ref_name: t.CChar | t.CPtr = pool.alloc(64)
if gv_ref_name is None: if gv_ref_name is None:
stdio.printf("[CGS] gv_ref_name alloc None\n")
stdio.fflush(0)
return None return None
viperlib.snprintf(gv_ref_name, 64, "@%s", gv.Name) viperlib.snprintf(gv_ref_name, 64, "@%s", gv.Name)
gv_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, arr_ptr_ty, gv_ref_name) gv_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, arr_ptr_ty, gv_ref_name)
@@ -333,9 +328,6 @@ def create_global_string(builder: llvmlite.IRBuilder | t.CPtr,
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
bc: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, gv_ref, i8_ptr_ty) bc: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, gv_ref, i8_ptr_ty)
if bc is None:
stdio.printf("[CGS] build_bitcast None\n")
stdio.fflush(0)
return bc return bc
@@ -350,12 +342,8 @@ def translate_constant(builder: llvmlite.IRBuilder | t.CPtr,
"""翻译常量int/str/bool""" """翻译常量int/str/bool"""
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
if cn is None: if cn is None:
stdio.printf("[TC] cn is None\n")
stdio.fflush(0)
return None return None
ck: int = cn.const_kind ck: int = cn.const_kind
stdio.printf("[TC] const_kind=%d\n", ck)
stdio.fflush(0)
if cn.const_kind == ast.CONST_INT: if cn.const_kind == ast.CONST_INT:
# 超出 i32 范围则用 i64避免常量创建时被截断 # 超出 i32 范围则用 i64避免常量创建时被截断
iv: t.CInt64T = cn.int_val iv: t.CInt64T = cn.int_val
@@ -366,18 +354,15 @@ def translate_constant(builder: llvmlite.IRBuilder | t.CPtr,
# 浮点常量默认创建为 double64 位),赋值时由 coerce_to_type 自动 fptrunc # 浮点常量默认创建为 double64 位),赋值时由 coerce_to_type 自动 fptrunc
double_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Double(pool) double_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Double(pool)
return llvmlite.ConstFloat(pool, double_ty, cn.float_val) return llvmlite.ConstFloat(pool, double_ty, cn.float_val)
elif cn.const_kind == ast.CONST_CHAR:
# 单引号单字符 → i32 值(字符 ASCII 码coerce_to_type 会 trunc 为 i8
cv: t.CInt64T = cn.int_val
return llvmlite.const_int32(pool, cv)
elif cn.const_kind == ast.CONST_STR: elif cn.const_kind == ast.CONST_STR:
sv: str = cn.str_val sv: str = cn.str_val
if sv is None: if sv is None:
stdio.printf("[TC] CONST_STR but str_val is None\n")
stdio.fflush(0)
return None return None
stdio.printf("[TC] CONST_STR sv[0]=%d\n", sv[0])
stdio.fflush(0)
r: llvmlite.Value | t.CPtr = create_global_string(builder, pool, mod, sv, trans) r: llvmlite.Value | t.CPtr = create_global_string(builder, pool, mod, sv, trans)
if r is None:
stdio.printf("[TC] create_global_string returned None\n")
stdio.fflush(0)
return r return r
elif cn.const_kind == ast.CONST_BOOL: elif cn.const_kind == ast.CONST_BOOL:
if cn.int_val != 0: if cn.int_val != 0:
@@ -385,32 +370,14 @@ def translate_constant(builder: llvmlite.IRBuilder | t.CPtr,
return llvmlite.const_int32(pool, 0) return llvmlite.const_int32(pool, 0)
elif cn.const_kind == ast.CONST_NONE: elif cn.const_kind == ast.CONST_NONE:
# None → i8* null空指针常量用于 `p is None` / `p is not None` 比较 # None → i8* null空指针常量用于 `p is None` / `p is not None` 比较
stdio.printf("[TC] NONE step1 Int8\n")
stdio.fflush(0)
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
if i8_ty is None: if i8_ty is None:
stdio.printf("[TC] NONE Int8 alloc None\n")
stdio.fflush(0)
return None return None
stdio.printf("[TC] NONE step2 Ptr\n")
stdio.fflush(0)
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
if i8_ptr_ty is None: if i8_ptr_ty is None:
stdio.printf("[TC] NONE Ptr alloc None\n")
stdio.fflush(0)
return None return None
stdio.printf("[TC] NONE step3 ConstNull\n")
stdio.fflush(0)
rv_none: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, i8_ptr_ty, "null") rv_none: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, i8_ptr_ty, "null")
if rv_none is None:
stdio.printf("[TC] NONE ConstNull None\n")
stdio.fflush(0)
else:
stdio.printf("[TC] NONE ok\n")
stdio.fflush(0)
return rv_none return rv_none
stdio.printf("[TC] unknown const_kind=%d\n", ck)
stdio.fflush(0)
return None return None
@@ -632,12 +599,6 @@ def translate_value(builder: llvmlite.IRBuilder | t.CPtr,
k: int = node.kind() k: int = node.kind()
if k == ast.ASTKind.Constant: if k == ast.ASTKind.Constant:
rv: llvmlite.Value | t.CPtr = translate_constant(builder, pool, mod, node, trans) rv: llvmlite.Value | t.CPtr = translate_constant(builder, pool, mod, node, trans)
if rv is None:
stdio.printf("[TV] Constant returned None\n")
stdio.fflush(0)
else:
stdio.printf("[TV] Constant ok\n")
stdio.fflush(0)
return rv return rv
elif k == ast.ASTKind.Name: elif k == ast.ASTKind.Name:
return translate_name_value(builder, pool, node, trans) return translate_name_value(builder, pool, node, trans)
@@ -686,21 +647,22 @@ def translate_ifexp(builder: llvmlite.IRBuilder | t.CPtr,
func: llvmlite.Function | t.CPtr = trans._cur_func func: llvmlite.Function | t.CPtr = trans._cur_func
if func is None: if func is None:
stdio.printf("[IFEXP] func=None\n")
stdio.fflush(0)
return None return None
# 1. 求值条件 # 1. 求值条件
cond_val: llvmlite.Value | t.CPtr = translate_value( cond_val: llvmlite.Value | t.CPtr = translate_value(
builder, pool, mod, ie.test, None, 0, trans) builder, pool, mod, ie.test, None, 0, trans)
if cond_val is None: if cond_val is None:
stdio.printf("[IFEXP] cond_val=None\n")
stdio.fflush(0)
return None return None
# 转换为 i1 # 转换为 i1
cond_bits: int = get_llvm_type_bits(cond_val.Ty) cond_bits: int = get_llvm_type_bits(cond_val.Ty)
if cond_bits == 1: if cond_bits == 1:
cond_i1: llvmlite.Value | t.CPtr = cond_val cond_i1: llvmlite.Value | t.CPtr = cond_val
else:
if is_ptr_type(cond_val.Ty) != 0:
# 指针类型:与 null 比较
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: else:
zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0) zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
cond_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, cond_val, zero) cond_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, cond_val, zero)
@@ -818,14 +780,10 @@ def translate_compare(builder: llvmlite.IRBuilder | t.CPtr,
comparators: list[ast.AST | t.CPtr] | t.CPtr = cmp.comparators comparators: list[ast.AST | t.CPtr] | t.CPtr = cmp.comparators
if comparators is None or comparators.__len__() == 0: if comparators is None or comparators.__len__() == 0:
stdio.printf("[CMP] comparators empty\n")
stdio.fflush(0)
return None return None
rhs: llvmlite.Value | t.CPtr = translate_value( rhs: llvmlite.Value | t.CPtr = translate_value(
builder, pool, mod, comparators.get(0), None, 0, trans) builder, pool, mod, comparators.get(0), None, 0, trans)
if rhs is None: if rhs is None:
stdio.printf("[CMP] rhs=None\n")
stdio.fflush(0)
return None return None
# === 比较运算符重载路径 1: lhs 是 Name 且对应结构体变量 === # === 比较运算符重载路径 1: lhs 是 Name 且对应结构体变量 ===
@@ -846,8 +804,6 @@ def translate_compare(builder: llvmlite.IRBuilder | t.CPtr,
lhs: llvmlite.Value | t.CPtr = translate_value( lhs: llvmlite.Value | t.CPtr = translate_value(
builder, pool, mod, cmp.left, None, 0, trans) builder, pool, mod, cmp.left, None, 0, trans)
if lhs is None: if lhs is None:
stdio.printf("[CMP] lhs=None\n")
stdio.fflush(0)
return None return None
# === 比较运算符重载路径 2: lhs 是 Ptr(Struct) === # === 比较运算符重载路径 2: lhs 是 Ptr(Struct) ===
@@ -933,7 +889,11 @@ def translate_unaryop(builder: llvmlite.IRBuilder | t.CPtr,
# +x = x # +x = x
return operand return operand
elif uo.op == ast.OpKind.Not: elif uo.op == ast.OpKind.Not:
# not x = (x == 0),返回 i1 # not x = (x == 0/null),返回 i1
if is_ptr_type(operand.Ty) != 0:
# 指针类型:与 null 比较
null_op: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, operand.Ty, "null")
return llvmlite.build_icmp(builder, llvmlite.ICMP_EQ, operand, null_op)
operand_bits_not: int = get_llvm_type_bits(operand.Ty) operand_bits_not: int = get_llvm_type_bits(operand.Ty)
zero = llvmlite.const_int32(pool, 0) zero = llvmlite.const_int32(pool, 0)
if operand_bits_not == 64: if operand_bits_not == 64:
@@ -1009,10 +969,15 @@ def translate_boolop(builder: llvmlite.IRBuilder | t.CPtr,
if val is None: if val is None:
return None return None
# 转为 i1已经是 i1 的直接用,否则与 0 比较) # 转为 i1已经是 i1 的直接用,否则与 0/null 比较)
val_bits: int = get_llvm_type_bits(val.Ty) val_bits: int = get_llvm_type_bits(val.Ty)
val_i1: llvmlite.Value | t.CPtr = val val_i1: llvmlite.Value | t.CPtr = val
if val_bits != 1: if val_bits != 1:
if is_ptr_type(val.Ty) != 0:
# 指针类型:与 null 比较(避免 i8* 与 i32 类型不匹配)
null_val: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, val.Ty, "null")
val_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, val, null_val)
else:
zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0) zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
val_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, val, zero) val_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, val, zero)
@@ -1051,6 +1016,11 @@ def translate_boolop(builder: llvmlite.IRBuilder | t.CPtr,
last_bits: int = get_llvm_type_bits(last_val.Ty) last_bits: int = get_llvm_type_bits(last_val.Ty)
last_i1: llvmlite.Value | t.CPtr = last_val last_i1: llvmlite.Value | t.CPtr = last_val
if last_bits != 1: if last_bits != 1:
if is_ptr_type(last_val.Ty) != 0:
# 指针类型:与 null 比较(避免 i8* 与 i32 类型不匹配)
null_val2: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, last_val.Ty, "null")
last_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, last_val, null_val2)
else:
zero = llvmlite.const_int32(pool, 0) zero = llvmlite.const_int32(pool, 0)
last_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, last_val, zero) last_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, last_val, zero)
@@ -1147,33 +1117,27 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
name: str, name: str,
from_imports: str) -> int: from_imports: str) -> int:
"""跨模块查找 CDefine 常量,返回值或 -1未找到""" """跨模块查找 CDefine 常量,返回值或 -1未找到"""
# [XMOD-CD] 诊断:记录跨模块 CDefine 查找入口
_xmod_log_buf: str = pool.alloc(512)
if _xmod_log_buf is not None:
viperlib.snprintf(_xmod_log_buf, 512, "[XMOD-CD] enter name=%s from_imports=%s\n", name, from_imports)
_xmod_lf: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf.closed:
_xmod_lf.write_str(_xmod_log_buf)
_xmod_lf.close()
if name is None or from_imports is None: if name is None or from_imports is None:
stdio.printf("[XMCD] FAIL name=%s reason=from_imports_is_none\n", name)
return -1 return -1
# 1. 从 from_imports 查找名称对应的模块名 # 1. 从 from_imports 查找名称对应的模块名
# allow_star_fallback=1: CDefine 常量(如 INVALID_HANDLE_VALUE通过 # 先尝试精确匹配(allow_star_fallback=0避免 CDefine 常量被 star import 误导
# from w32.win32base import * 导入,不会作为精确条目出现在 from_imports 中, mod_name_raw: str = HandlesImports.lookup_from_import(from_imports, name, 0)
# 而是作为 *:w32.win32base 条目。必须启用 star import 回退才能找到源模块。
mod_name_raw: str = HandlesImports.lookup_from_import(from_imports, name, 1)
if mod_name_raw is None: if mod_name_raw is None:
if _xmod_log_buf is not None: # 精确匹配失败:尝试 star import 回退
viperlib.snprintf(_xmod_log_buf, 512, "[XMOD-CD] FAIL step1 mod=None name=%s\n", name) # CDefine 常量(如 INVALID_HANDLE_VALUE通过 from w32.win32base import * 导入,
_xmod_lf2: fileio.File | t.CPtr = fileio.File( # 不会作为精确条目出现在 from_imports 中,而是作为 *:w32.win32base 条目。
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A) mod_name_raw = HandlesImports.lookup_from_import(from_imports, name, 1)
if not _xmod_lf2.closed: if mod_name_raw is None:
_xmod_lf2.write_str(_xmod_log_buf) stdio.printf("[XMCD] FAIL name=%s reason=lookup_from_import_returned_none\n", name)
_xmod_lf2.close()
return -1 return -1
stdio.printf("[XMCD] star_fallback name=%s mod=%s\n", name, mod_name_raw)
# 打印 from_imports 用于诊断精确匹配失败原因
fi_len: t.CSizeT = string.strlen(from_imports)
stdio.printf("[XMCD] from_imports (len=%d): %s\n", fi_len, from_imports)
else:
stdio.printf("[XMCD] exact_match name=%s mod=%s\n", name, mod_name_raw)
# 2. 复制模块名到新缓冲区lookup_from_import 返回的是内部指针) # 2. 复制模块名到新缓冲区lookup_from_import 返回的是内部指针)
# 截断于空格、null、或 ':'(别名格式的分隔符) # 截断于空格、null、或 ':'(别名格式的分隔符)
@@ -1197,29 +1161,9 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
if sha1 is None: if sha1 is None:
sha1 = HandlesExprCall._lookup_module_sha1_suffix(base_mod) sha1 = HandlesExprCall._lookup_module_sha1_suffix(base_mod)
if sha1 is None: if sha1 is None:
if _xmod_log_buf is not None: stdio.printf("[XMCD] FAIL name=%s base_mod=%s reason=sha1_not_found\n", name, base_mod)
viperlib.snprintf(_xmod_log_buf, 512, "[XMOD-CD] FAIL step4 sha1=None base_mod=%s\n", base_mod)
_xmod_lf3: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf3.closed:
_xmod_lf3.write_str(_xmod_log_buf)
_xmod_lf3.close()
return -1 return -1
# [XMOD-CD] 诊断:记录 SHA1 查找成功
if _xmod_log_buf is not None:
viperlib.snprintf(_xmod_log_buf, 512, "[XMOD-CD] ok step4 base_mod=%s sha1=%s\n", base_mod, sha1)
_xmod_lf4: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf4.closed:
_xmod_lf4.write_str(_xmod_log_buf)
_xmod_lf4.close()
# 4.5 优先查全局跨模块 CDefine 表(编译期注册,无需文件 I/O
gcdef_val: int = HandlesType.lookup_global_cdefine(sha1, name)
if HandlesType.is_cdefine_found() != 0:
return gcdef_val
# 5. 获取 temp_dir # 5. 获取 temp_dir
temp_dir: str = HandlesType.get_temp_dir() temp_dir: str = HandlesType.get_temp_dir()
if temp_dir is None: if temp_dir is None:
@@ -1271,44 +1215,14 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
VLogger.error(err_buf, "XMOD-CD") VLogger.error(err_buf, "XMOD-CD")
stdlib.free(pyi_buf) stdlib.free(pyi_buf)
return -1 return -1
# [XMOD-CD] 诊断:记录 src_path
_xmod_dbg_sp2: str = pool.alloc(512)
if _xmod_dbg_sp2 is not None:
viperlib.snprintf(_xmod_dbg_sp2, 512,
"[XMOD-CD] py-fallback src_path=%s sha1=%s\n", src_path, sha1)
_xmod_lf_sp2: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf_sp2.closed:
_xmod_lf_sp2.write_str(_xmod_dbg_sp2)
_xmod_lf_sp2.close()
pf = fileio.File(src_path, fileio.MODE.R) pf = fileio.File(src_path, fileio.MODE.R)
stdlib.free(src_path) stdlib.free(src_path)
if pf.closed: if pf.closed:
# [XMOD-CD] 诊断:文件打开失败
_xmod_dbg_fc: str = pool.alloc(512)
if _xmod_dbg_fc is not None:
viperlib.snprintf(_xmod_dbg_fc, 512,
"[XMOD-CD] FAIL file-closed sha1=%s\n", sha1)
_xmod_lf_fc: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf_fc.closed:
_xmod_lf_fc.write_str(_xmod_dbg_fc)
_xmod_lf_fc.close()
stdlib.free(pyi_buf) stdlib.free(pyi_buf)
return -1 return -1
bytes_read = pf.read_all(pyi_buf, PYI_READ_BUF_SIZE) bytes_read = pf.read_all(pyi_buf, PYI_READ_BUF_SIZE)
pf.close() pf.close()
if bytes_read <= 0: if bytes_read <= 0:
# [XMOD-CD] 诊断:文件读取失败
_xmod_dbg_br: str = pool.alloc(512)
if _xmod_dbg_br is not None:
viperlib.snprintf(_xmod_dbg_br, 512,
"[XMOD-CD] FAIL bytes_read=%d sha1=%s\n", bytes_read, sha1)
_xmod_lf_br: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf_br.closed:
_xmod_lf_br.write_str(_xmod_dbg_br)
_xmod_lf_br.close()
stdlib.free(pyi_buf) stdlib.free(pyi_buf)
return -1 return -1
if bytes_read < PYI_READ_BUF_SIZE: if bytes_read < PYI_READ_BUF_SIZE:
@@ -1320,25 +1234,6 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
# 格式: NAME: t.CDefine = value # 格式: NAME: t.CDefine = value
name_len: t.CSizeT = string.strlen(name) name_len: t.CSizeT = string.strlen(name)
total_len: t.CSizeT = string.strlen(pyi_buf) total_len: t.CSizeT = string.strlen(pyi_buf)
# [XMOD-CD] 诊断:记录文件读取结果和 total_len
_xmod_dbg1: str = pool.alloc(512)
if _xmod_dbg1 is not None:
_dbg_first80: str = pool.alloc(81)
if _dbg_first80 is not None:
_dbg_n: int = 0
while _dbg_n < 80 and _dbg_n < total_len:
_dbg_first80[_dbg_n] = pyi_buf[_dbg_n]
_dbg_n += 1
_dbg_first80[_dbg_n] = '\0'
else:
_dbg_first80 = "<alloc-fail>"
viperlib.snprintf(_xmod_dbg1, 512, "[XMOD-CD] file-read name=%s bytes_read=%d total_len=%d first80=%.80s\n",
name, bytes_read, total_len, _dbg_first80)
_xmod_lf_d1: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf_d1.closed:
_xmod_lf_d1.write_str(_xmod_dbg1)
_xmod_lf_d1.close()
pos: t.CSizeT = 0 pos: t.CSizeT = 0
result_val: int = 0 result_val: int = 0
result_found: int = 0 result_found: int = 0
@@ -1393,7 +1288,29 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ': while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ':
eq_pos += 1 eq_pos += 1
# 解析整数值(支持十六进制 0x 前缀) # 检查是否是 t.CUnsignedLong(...) / t.CLong(...) / t.CInt(...) 等类型构造函数
# 格式: t.CUnsignedLong(-11) / t.CUnsignedLong(0xFFFFFFFF)
# 如果是,跳过 "t.CXxx(" 前缀,解析括号内的值,忽略结尾 ')'
is_type_ctor: int = 0
if eq_pos + 2 < line_start + line_len:
if pyi_buf[eq_pos] == 't' and pyi_buf[eq_pos + 1] == '.':
# 找到 '(' 的位置
paren_pos: t.CSizeT = eq_pos + 2
while paren_pos < line_start + line_len and pyi_buf[paren_pos] != '(':
paren_pos += 1
if paren_pos < line_start + line_len and pyi_buf[paren_pos] == '(':
is_type_ctor = 1
eq_pos = paren_pos + 1 # 跳过 '('
# 跳过括号内可能的前导空格
while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ':
eq_pos += 1
# 解析整数值(支持十六进制 0x 前缀和负号)
# 负号标记
is_neg: int = 0
if eq_pos < line_start + line_len and pyi_buf[eq_pos] == '-':
is_neg = 1
eq_pos += 1
val_str_start: t.CSizeT = eq_pos val_str_start: t.CSizeT = eq_pos
val_str_len: t.CSizeT = 0 val_str_len: t.CSizeT = 0
is_hex: int = 0 is_hex: int = 0
@@ -1447,9 +1364,13 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
break break
hex_result = hex_result * 16 + hd hex_result = hex_result * 16 + hd
result_val = hex_result result_val = hex_result
# 十六进制负值(如 0xFFFFFFFF保持原样由 32 位截断处理
result_found = 1 result_found = 1
else: else:
result_val = string.atoi(val_buf) result_val = string.atoi(val_buf)
# 应用负号(如 t.CUnsignedLong(-11) → -11
if is_neg != 0:
result_val = -result_val
result_found = 1 result_found = 1
break break
@@ -1488,26 +1409,6 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
if rc_sub_len == 0: if rc_sub_len == 0:
continue continue
# [XMOD-CD] 诊断:记录找到的 from . 行和子模块名
_xmod_dbg_rc: str = pool.alloc(512)
if _xmod_dbg_rc is not None:
_rc_sub_buf_dbg: str = pool.alloc(rc_sub_len + 1)
if _rc_sub_buf_dbg is not None:
_rc_si2: t.CSizeT
for _rc_si2 in range(rc_sub_len):
_rc_sub_buf_dbg[_rc_si2] = pyi_buf[rc_sub_start + _rc_si2]
_rc_sub_buf_dbg[rc_sub_len] = '\0'
else:
_rc_sub_buf_dbg = "<alloc-fail>"
viperlib.snprintf(_xmod_dbg_rc, 512,
"[XMOD-CD] rc-from-line name=%s sub=%s rc_line_start=%d rc_line_len=%d\n",
name, _rc_sub_buf_dbg, rc_line_start, rc_line_len)
_xmod_lf_rc: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf_rc.closed:
_xmod_lf_rc.write_str(_xmod_dbg_rc)
_xmod_lf_rc.close()
# 检查行是否包含 "import" # 检查行是否包含 "import"
rc_has_import: int = 0 rc_has_import: int = 0
rc_ipos: t.CSizeT = rc_sub_end rc_ipos: t.CSizeT = rc_sub_end
@@ -1594,18 +1495,6 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
rc_name_match = 1 rc_name_match = 1
rc_cpos += 1 rc_cpos += 1
# [XMOD-CD] 诊断:记录 NAME 匹配结果
_xmod_dbg_match: str = pool.alloc(512)
if _xmod_dbg_match is not None:
viperlib.snprintf(_xmod_dbg_match, 512,
"[XMOD-CD] rc-match name=%s star=%d name_match=%d has_paren=%d rc_scan_end=%d rc_imp_start=%d\n",
name, rc_star, rc_name_match, rc_has_paren, rc_scan_end, rc_imp_start)
_xmod_lf_m: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf_m.closed:
_xmod_lf_m.write_str(_xmod_dbg_match)
_xmod_lf_m.close()
if rc_star == 0 and rc_name_match == 0: if rc_star == 0 and rc_name_match == 0:
continue continue
@@ -1632,18 +1521,6 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
continue continue
viperlib.snprintf(rc_fi, rc_fi_len, "%s:%s", name, rc_full_mod) viperlib.snprintf(rc_fi, rc_fi_len, "%s:%s", name, rc_full_mod)
# [XMOD-CD] 诊断:记录递归调用前的状态
_xmod_dbg_recurse: str = pool.alloc(512)
if _xmod_dbg_recurse is not None:
viperlib.snprintf(_xmod_dbg_recurse, 512,
"[XMOD-CD] rc-recurse name=%s full_mod=%s fi=%s star=%d name_match=%d has_paren=%d scan_end=%d\n",
name, rc_full_mod, rc_fi, rc_star, rc_name_match, rc_has_paren, rc_scan_end)
_xmod_lf_rec: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf_rec.closed:
_xmod_lf_rec.write_str(_xmod_dbg_recurse)
_xmod_lf_rec.close()
# 递归调用查找子模块 # 递归调用查找子模块
rc_sub_val: int = _lookup_cross_module_cdefine(pool, name, rc_fi) rc_sub_val: int = _lookup_cross_module_cdefine(pool, name, rc_fi)
if HandlesType.is_cdefine_found() != 0: if HandlesType.is_cdefine_found() != 0:
@@ -1659,21 +1536,37 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
else: else:
HandlesType.set_cdefine_found(0) HandlesType.set_cdefine_found(0)
# [XMOD-CD] 诊断:记录查找结果
if _xmod_log_buf is not None:
if result_found != 0:
viperlib.snprintf(_xmod_log_buf, 512, "[XMOD-CD] FOUND name=%s val=%d base_mod=%s\n", name, result_val, base_mod)
else:
viperlib.snprintf(_xmod_log_buf, 512, "[XMOD-CD] NOTFOUND name=%s base_mod=%s sha1=%s\n", name, base_mod, sha1)
_xmod_lf5: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf5.closed:
_xmod_lf5.write_str(_xmod_log_buf)
_xmod_lf5.close()
return result_val return result_val
# ============================================================
# _is_cdefine_name_pattern - 检查名字是否符合 CDefine 命名约定
#
# CDefine 常量(如 FOREGROUND_GREEN, STD_OUTPUT_HANDLE, SCOPE_MODULE
# 都遵循 ALL_CAPS 约定:仅含大写字母 A-Z、数字 0-9、下划线 _
# 且至少含一个大写字母。
#
# Python 关键字match, if, for和变量名self, pool, builder
# 都含小写字母,不会匹配,从而避免 fail-fast 误报。
#
# 返回: 1=符合 CDefine 命名约定, 0=不符合
# ============================================================
def _is_cdefine_name_pattern(name: str) -> int:
"""检查名字是否符合 CDefine 命名约定(全大写+下划线+数字)"""
if name is None:
return 0
has_upper: int = 0
i: t.CSizeT = 0
while name[i] != '\0':
c: t.CChar = name[i]
if c >= 'a' and c <= 'z':
return 0
if c >= 'A' and c <= 'Z':
has_upper = 1
i += 1
return has_upper
# ============================================================ # ============================================================
# 翻译变量引用Name 节点)→ load # 翻译变量引用Name 节点)→ load
# ============================================================ # ============================================================
@@ -1690,27 +1583,21 @@ def translate_name_value(builder: llvmlite.IRBuilder | t.CPtr,
return None return None
# CDefine 编译期常量: 直接返回整数常量值(不生成运行时代码) # CDefine 编译期常量: 直接返回整数常量值(不生成运行时代码)
# NAME: t.CDefine = value 形式定义的常量在编译期已注册到全局 # NAME: t.CDefine = value 形式定义的常量在编译期已注册到本地
cdef_val: int = HandlesType.lookup_cdefine_constant(nm_id) cdef_val: int = HandlesType.lookup_cdefine_constant(nm_id)
if HandlesType.is_cdefine_found() != 0: if HandlesType.is_cdefine_found() != 0:
return llvmlite.const_int32(pool, cdef_val) return llvmlite.const_int32(pool, cdef_val)
# 本地 CDefine 表未找到:尝试跨模块查找 # 本地表未找到:尝试跨模块 .pyi 查找(保证多模块查表存表一致)
# 对于 from w32.win32base import * 导入的 INVALID_HANDLE_VALUE 等常量 # 仅对符合 CDefine 命名约定ALL_CAPS的名字触发跨模块查找
# CDefine 表在模块切换时被清空,需要从 from_imports 查找来源模块并读取 .pyi # 避免对普通变量名mb/name/ptr/pool/self 等)误触发,造成严重性能损耗
if trans is not None: if _is_cdefine_name_pattern(nm_id) != 0:
if trans._from_imports is not None: if trans is not None and trans._from_imports is not None:
cdef_val = _lookup_cross_module_cdefine(pool, nm_id, trans._from_imports) cdef_val = _lookup_cross_module_cdefine(pool, nm_id, trans._from_imports)
if HandlesType.is_cdefine_found() != 0: if HandlesType.is_cdefine_found() != 0:
return llvmlite.const_int32(pool, cdef_val) return llvmlite.const_int32(pool, cdef_val)
# 模块别名检查:如果 nm_id 是已导入模块名(如 win32file, fileio # global 变量从模块作用域查找global 声明优先级最高)
# 不应被当作普通变量或全局变量,返回 None 让上层处理
if trans is not None and trans._imported_modules is not None:
if HandlesImports.is_module_imported(trans._imported_modules, nm_id) != 0:
return None
# global 变量:从模块作用域查找
if trans is not None: if trans is not None:
if HT.is_global_name(trans, nm_id) != 0: if HT.is_global_name(trans, nm_id) != 0:
mod_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_module_var( mod_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_module_var(
@@ -1727,17 +1614,11 @@ def translate_name_value(builder: llvmlite.IRBuilder | t.CPtr,
if HT.is_nonlocal_name(trans, nm_id) != 0: if HT.is_nonlocal_name(trans, nm_id) != 0:
return HandlesNonlocal.load_nonlocal_var(trans, nm_id) return HandlesNonlocal.load_nonlocal_var(trans, nm_id)
# 局部变量查找(必须先于模块别名检查)
# 否则与模块同名的局部变量(如 `import t, c` 后的局部变量 c会被误判为模块别名
# 导致 SymTab 已注册的局部变量查找不到rhs_val is None bug 根因)
alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, nm_id) alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, nm_id)
if alloca is None: if alloca is not None:
# 跨模块 CDefine 查找(仅当 Name 不是任何变量时才尝试):
# 从 from_imports 解析源模块,再从该模块的 pyi 文件中解析 CDefine 常量值
# (如 FLAG_IS_ASYNC 从 base.py 导入)
if trans is not None and trans._from_imports is not None:
cross_val: int = _lookup_cross_module_cdefine(pool, nm_id, trans._from_imports)
if cross_val >= 0:
return llvmlite.const_int32(pool, cross_val)
return None
load_ty: llvmlite.LLVMType | t.CPtr = None load_ty: llvmlite.LLVMType | t.CPtr = None
if alloca.Ty is not None: if alloca.Ty is not None:
load_ty = alloca.Ty.Pointee load_ty = alloca.Ty.Pointee
@@ -1745,6 +1626,29 @@ def translate_name_value(builder: llvmlite.IRBuilder | t.CPtr,
load_ty = llvmlite.Int32(pool) load_ty = llvmlite.Int32(pool)
return llvmlite.build_load(builder, load_ty, alloca) return llvmlite.build_load(builder, load_ty, alloca)
# 模块别名检查SymTab 查找失败后才检查
# 如果 nm_id 是已导入模块名(如 win32file, fileio且未被声明为局部变量
# 返回 None 让上层处理(用于属性访问 win32file.CreateFileA
if trans is not None and trans._imported_modules is not None:
if HandlesImports.is_module_imported(trans._imported_modules, nm_id) != 0:
return None
# 所有查找路径均失败
# fail-fast: 仅对符合 CDefine 命名约定ALL_CAPS的名字报错
# 避免对 match/self/pool 等关键字和变量名误报
# 跨模块 CDefine 查找已在上方完成,此处不重复
if _is_cdefine_name_pattern(nm_id) != 0:
err_buf2: str = pool.alloc(256)
if err_buf2 is not None:
cur_sha1: str = "(unknown)"
if trans is not None and trans.ModuleSha1 is not None:
cur_sha1 = trans.ModuleSha1
viperlib.snprintf(err_buf2, 256,
"[CD] FATAL: Name '%s' NOT found (CDefine local+cross + global + nonlocal + alloca + module alias) in module sha1=%s\n",
nm_id, cur_sha1)
VLogger.error(err_buf2, "CD")
return None
# ============================================================ # ============================================================
# ExprHandle - 表达式处理器Mixin 继承模式) # ExprHandle - 表达式处理器Mixin 继承模式)
@@ -1989,22 +1893,11 @@ def translate_subscript(builder: llvmlite.IRBuilder | t.CPtr,
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value) nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value)
if nm.id is not None and trans is not None: if nm.id is not None and trans is not None:
alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, nm.id) alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, nm.id)
if alloca is None:
stdio.printf("[TS] alloca=None var=%s\n", nm.id)
stdio.fflush(0)
elif alloca.Ty is None:
stdio.printf("[TS] alloca.Ty=None var=%s\n", nm.id)
stdio.fflush(0)
if alloca is not None and alloca.Ty is not None: if alloca is not None and alloca.Ty is not None:
if is_ptr_type(alloca.Ty) != 0: if is_ptr_type(alloca.Ty) != 0:
pointee: llvmlite.LLVMType | t.CPtr = alloca.Ty.Pointee pointee: llvmlite.LLVMType | t.CPtr = alloca.Ty.Pointee
if pointee is None:
stdio.printf("[TS] pointee=None var=%s\n", nm.id)
stdio.fflush(0)
if pointee is not None: if pointee is not None:
# 不调用 pointee.kind() 避免跨模块引用 LLVMType.kind 符号 # 不调用 pointee.kind() 避免跨模块引用 LLVMType.kind 符号
stdio.printf("[TS] var=%s pointee_not_null\n", nm.id)
stdio.fflush(0)
# 单层 match避免嵌套 match 的编译器 bug # 单层 match避免嵌套 match 的编译器 bug
match pointee: match pointee:
case llvmlite.LLVMType.Array(elem_ty, count): case llvmlite.LLVMType.Array(elem_ty, count):
@@ -2015,8 +1908,6 @@ def translate_subscript(builder: llvmlite.IRBuilder | t.CPtr,
return llvmlite.build_load(builder, elem_ty, elem_ptr) return llvmlite.build_load(builder, elem_ty, elem_ptr)
return None return None
case llvmlite.LLVMType.Ptr(inner_ty): case llvmlite.LLVMType.Ptr(inner_ty):
stdio.printf("[TS] matched Ptr var=%s\n", nm.id)
stdio.fflush(0)
# 检查 inner_ty 是否是 list[T] 类型(泛型类不注册 struct # 检查 inner_ty 是否是 list[T] 类型(泛型类不注册 struct
# list 的 subscript 应该走 __getitem__ 内联路径,而非指针遍历 # list 的 subscript 应该走 __getitem__ 内联路径,而非指针遍历
list_struct_name: str = None list_struct_name: str = None
@@ -2064,32 +1955,16 @@ def translate_subscript(builder: llvmlite.IRBuilder | t.CPtr,
# 自定义结构体 (如 HashTable|t.CPtr, JsonValue|t.CPtr): # 自定义结构体 (如 HashTable|t.CPtr, JsonValue|t.CPtr):
# 优先转发到 __getitem__避免 IsPtrElement 误判为指针遍历 # 优先转发到 __getitem__避免 IsPtrElement 误判为指针遍历
cls_nm_rd_ptr: str = _get_custom_struct_cls_nm(pool, inner_ty) cls_nm_rd_ptr: str = _get_custom_struct_cls_nm(pool, inner_ty)
if cls_nm_rd_ptr is None:
stdio.printf("[TS] cls_nm=None var=%s\n", nm.id)
stdio.fflush(0)
if not (cls_nm_rd_ptr is None): if not (cls_nm_rd_ptr is None):
stdio.printf("[TS] cls_nm=%s var=%s\n", cls_nm_rd_ptr, nm.id)
stdio.fflush(0)
stdio.printf("[TS] pre_getitem cls=%s\n", cls_nm_rd_ptr)
stdio.fflush(0)
obj_ptr_rd: llvmlite.Value | t.CPtr = llvmlite.build_load( obj_ptr_rd: llvmlite.Value | t.CPtr = llvmlite.build_load(
builder, pointee, alloca) builder, pointee, alloca)
if obj_ptr_rd is None:
stdio.printf("[TS] __getitem__ build_load=None\n")
stdio.fflush(0)
if not (obj_ptr_rd is None): if not (obj_ptr_rd is None):
arg_vals_rd_p: t.CSizeT | t.CPtr = pool.alloc(8) arg_vals_rd_p: t.CSizeT | t.CPtr = pool.alloc(8)
if arg_vals_rd_p is None:
stdio.printf("[TS] __getitem__ alloc=None\n")
stdio.fflush(0)
if not (arg_vals_rd_p is None): if not (arg_vals_rd_p is None):
arg_vals_rd_p[0] = t.CSizeT(idx_val) arg_vals_rd_p[0] = t.CSizeT(idx_val)
ret_rd_p: llvmlite.Value | t.CPtr = HandlesExprCall._call_method_on_ptr( ret_rd_p: llvmlite.Value | t.CPtr = HandlesExprCall._call_method_on_ptr(
pool, builder, mod, cls_nm_rd_ptr, "__getitem__", pool, builder, mod, cls_nm_rd_ptr, "__getitem__",
obj_ptr_rd, arg_vals_rd_p, 1, trans) obj_ptr_rd, arg_vals_rd_p, 1, trans)
if ret_rd_p is None:
stdio.printf("[TS] __getitem__ call=None cls=%s\n", cls_nm_rd_ptr)
stdio.fflush(0)
if not (ret_rd_p is None): if not (ret_rd_p is None):
return ret_rd_p return ret_rd_p
return None return None
@@ -2493,11 +2368,6 @@ def translate_attribute(builder: llvmlite.IRBuilder | t.CPtr,
obj_ptr = translate_value(builder, pool, mod, at.value, None, 0, trans) obj_ptr = translate_value(builder, pool, mod, at.value, None, 0, trans)
if obj_ptr is None or obj_ptr.Ty is None: if obj_ptr is None or obj_ptr.Ty is None:
if at.value.kind() == ast.ASTKind.Name:
nm_d: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
if nm_d.id is not None:
stdio.printf("[TA-DIAG] obj_ptr=None attr=%s name=%s\n",
at.attr, nm_d.id)
return None return None
# 如果 obj_ptr 是 Ptr(Ptr(Struct))X|t.CPtr 变量的 alloca # 如果 obj_ptr 是 Ptr(Ptr(Struct))X|t.CPtr 变量的 alloca
@@ -2540,29 +2410,15 @@ def translate_attribute(builder: llvmlite.IRBuilder | t.CPtr,
var_entry: HandlesVar.VarEntry | t.CPtr = HandlesVar.lookup_var_entry( var_entry: HandlesVar.VarEntry | t.CPtr = HandlesVar.lookup_var_entry(
trans.SymTab, nm_fb.id) trans.SymTab, nm_fb.id)
if var_entry is not None and var_entry.AnnotClassName is not None: if var_entry is not None and var_entry.AnnotClassName is not None:
stdio.printf("[TA-DIAG] fallback annot=%s attr=%s\n",
var_entry.AnnotClassName, at.attr)
cur_sha1: str = trans.ModuleSha1 cur_sha1: str = trans.ModuleSha1
field_info = HandlesStruct.lookup_field_by_class( field_info = HandlesStruct.lookup_field_by_class(
var_entry.AnnotClassName, at.attr, cur_sha1) var_entry.AnnotClassName, at.attr, cur_sha1)
if field_info is None:
stdio.printf("[TA-DIAG] lfbc_failed annot=%s attr=%s\n",
var_entry.AnnotClassName, at.attr)
stdio.fflush(0)
else:
stdio.printf("[TA-DIAG] lfbc_ok annot=%s attr=%s idx=%d\n",
var_entry.AnnotClassName, at.attr, field_info.Index)
stdio.fflush(0)
# 回退 1 成功bitcast obj_ptr 到 AnnotClassName 对应的结构体类型 # 回退 1 成功bitcast obj_ptr 到 AnnotClassName 对应的结构体类型
# 原始 struct_ty 可能是 i8X|t.CPtr 简化为 Ptr(i8) # 原始 struct_ty 可能是 i8X|t.CPtr 简化为 Ptr(i8)
# 需用实际结构体类型做 GEP否则 GEP i8 失败 # 需用实际结构体类型做 GEP否则 GEP i8 失败
if field_info is not None: if field_info is not None:
annot_se: HandlesStruct.StructEntry | t.CPtr = \ annot_se: HandlesStruct.StructEntry | t.CPtr = \
HandlesStruct.find_struct(var_entry.AnnotClassName) HandlesStruct.find_struct(var_entry.AnnotClassName)
if annot_se is None:
stdio.printf("[TA-DIAG] fb1 find_struct None annot=%s\n",
var_entry.AnnotClassName)
stdio.fflush(0)
if annot_se is not None and annot_se.Ty is not None: if annot_se is not None and annot_se.Ty is not None:
annot_ptr_ty: llvmlite.LLVMType | t.CPtr = \ annot_ptr_ty: llvmlite.LLVMType | t.CPtr = \
llvmlite.Ptr(pool, annot_se.Ty) llvmlite.Ptr(pool, annot_se.Ty)
@@ -2576,11 +2432,6 @@ def translate_attribute(builder: llvmlite.IRBuilder | t.CPtr,
# (原始 struct_ty 可能是 i8ensure 无效) # (原始 struct_ty 可能是 i8ensure 无效)
HandlesStruct.ensure_struct_def_in_module( HandlesStruct.ensure_struct_def_in_module(
pool, mod, annot_se.Ty) pool, mod, annot_se.Ty)
stdio.printf("[TA-DIAG] fb1 struct_ty updated\n")
stdio.fflush(0)
else:
stdio.printf("[TA-DIAG] fb1 bitcast None\n")
stdio.fflush(0)
# 回退 2: 子类搜索 — 注解类型是基类但实际值是派生类 # 回退 2: 子类搜索 — 注解类型是基类但实际值是派生类
# 如 node: AST | t.CPtr = If(...),访问 node.orelse # 如 node: AST | t.CPtr = If(...),访问 node.orelse
if field_info is None: if field_info is None:
@@ -2615,29 +2466,14 @@ def translate_attribute(builder: llvmlite.IRBuilder | t.CPtr,
return None return None
# 普通结构体GEP + load # 普通结构体GEP + load
field_idx: int = field_info.Index field_idx: int = field_info.Index
stdio.printf("[TA-DIAG] gep_try idx=%d struct_is_ptr=%d\n",
field_idx, is_ptr_type(struct_ty))
stdio.fflush(0)
field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
builder, struct_ty, field_ty, obj_ptr, field_idx) builder, struct_ty, field_ty, obj_ptr, field_idx)
if field_ptr is None:
stdio.printf("[TA-DIAG] gep_failed idx=%d\n", field_idx)
stdio.fflush(0)
if field_ptr is not None: if field_ptr is not None:
stdio.printf("[TA-DIAG] gep_ok idx=%d is_array=%d\n",
field_idx, is_array_type(field_ty))
stdio.fflush(0)
# 数组类型字段不能 load 为 SSA value直接返回字段指针 # 数组类型字段不能 load 为 SSA value直接返回字段指针
# 用于后续下标访问: self.state[0] → GEP state 字段 → GEP 数组元素 # 用于后续下标访问: self.state[0] → GEP state 字段 → GEP 数组元素
if is_array_type(field_ty) != 0: if is_array_type(field_ty) != 0:
return field_ptr return field_ptr
stdio.printf("[TA-DIAG] pre_load idx=%d field_ty_not_null=%d\n",
field_idx, 1 if field_ty is not None else 0)
stdio.fflush(0)
loaded_val: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, field_ty, field_ptr) loaded_val: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, field_ty, field_ptr)
stdio.printf("[TA-DIAG] post_load idx=%d loaded=%d\n",
field_idx, 1 if loaded_val is not None else 0)
stdio.fflush(0)
# 联合类型字段(如 Token | t.CPtr被编译为 i8* # 联合类型字段(如 Token | t.CPtr被编译为 i8*
# 若 AnnotClassName 指示了具体结构体类型bitcast 为正确的结构体指针 # 若 AnnotClassName 指示了具体结构体类型bitcast 为正确的结构体指针
if loaded_val is not None and field_info.AnnotClassName is not None: if loaded_val is not None and field_info.AnnotClassName is not None:
@@ -2647,17 +2483,8 @@ def translate_attribute(builder: llvmlite.IRBuilder | t.CPtr,
annot_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, annot_struct.Ty) annot_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, annot_struct.Ty)
return llvmlite.build_bitcast(builder, loaded_val, annot_ptr_ty) return llvmlite.build_bitcast(builder, loaded_val, annot_ptr_ty)
return loaded_val return loaded_val
# 诊断:所有字段查找路径失败
sn_diag: str = HandlesStruct._extract_struct_name(struct_ty)
if sn_diag is not None:
stdio.printf("[TA-DIAG] field=None attr=%s sname=%s\n",
at.attr, sn_diag)
else:
stdio.printf("[TA-DIAG] field=None attr=%s sname=(null)\n",
at.attr)
return None return None
case _: case _:
stdio.printf("[TA-DIAG] type_mismatch attr=%s\n", at.attr)
return None return None
# ============================================================ # ============================================================
@@ -2686,34 +2513,17 @@ def get_subscript_ptr(builder: llvmlite.IRBuilder | t.CPtr,
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value) nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value)
if nm.id is not None and trans is not None: if nm.id is not None and trans is not None:
alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, nm.id) alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, nm.id)
if alloca is None:
stdio.printf("[GSP] alloca=None var=%s\n", nm.id)
stdio.fflush(0)
elif alloca.Ty is None:
stdio.printf("[GSP] alloca.Ty=None var=%s\n", nm.id)
stdio.fflush(0)
if alloca is not None and alloca.Ty is not None: if alloca is not None and alloca.Ty is not None:
if is_ptr_type(alloca.Ty) != 0: if is_ptr_type(alloca.Ty) != 0:
pointee: llvmlite.LLVMType | t.CPtr = alloca.Ty.Pointee pointee: llvmlite.LLVMType | t.CPtr = alloca.Ty.Pointee
if pointee is None:
stdio.printf("[GSP] pointee=None var=%s\n", nm.id)
stdio.fflush(0)
if pointee is not None: if pointee is not None:
pe_arr: int = is_array_type(pointee)
pe_ptr: int = is_ptr_type(pointee)
stdio.printf("[GSP] var=%s pe_arr=%d pe_ptr=%d\n", nm.id, pe_arr, pe_ptr)
stdio.fflush(0)
# 单层 match避免嵌套 match 的编译器 bug # 单层 match避免嵌套 match 的编译器 bug
match pointee: match pointee:
case llvmlite.LLVMType.Array(elem_ty, count): case llvmlite.LLVMType.Array(elem_ty, count):
stdio.printf("[GSP] matched Array\n")
stdio.fflush(0)
# 数组遍历 # 数组遍历
return llvmlite.build_gep_array( return llvmlite.build_gep_array(
builder, pointee, elem_ty, alloca, idx_val) builder, pointee, elem_ty, alloca, idx_val)
case llvmlite.LLVMType.Ptr(inner_ty): case llvmlite.LLVMType.Ptr(inner_ty):
stdio.printf("[GSP] matched Ptr\n")
stdio.fflush(0)
# inner_ty 是 Ptr 说明 alloca.Ty 是三重指针, # inner_ty 是 Ptr 说明 alloca.Ty 是三重指针,
# 即 X|t.CPtr 当 X 本身是指针类型 (如 T=AST|t.CPtr, T|t.CPtr=AST**)。 # 即 X|t.CPtr 当 X 本身是指针类型 (如 T=AST|t.CPtr, T|t.CPtr=AST**)。
# 此时 [i]=val 应该是指针解引用赋值, 而非调用 __setitem__。 # 此时 [i]=val 应该是指针解引用赋值, 而非调用 __setitem__。
@@ -2731,9 +2541,6 @@ def get_subscript_ptr(builder: llvmlite.IRBuilder | t.CPtr,
if cls_nm_ptr_chk is None: if cls_nm_ptr_chk is None:
pass pass
if not (cls_nm_ptr_chk is None): if not (cls_nm_ptr_chk is None):
stdio.printf("[GSP] custom struct %s, defer to __setitem__\n",
cls_nm_ptr_chk)
stdio.fflush(0)
return None return None
# bytes|t.CPtr / str|t.CPtr: alloca 是 i8** # bytes|t.CPtr / str|t.CPtr: alloca 是 i8**
# 直接 GEP 按 i8* 步长8 字节),不 load # 直接 GEP 按 i8* 步长8 字节),不 load
@@ -2742,39 +2549,26 @@ def get_subscript_ptr(builder: llvmlite.IRBuilder | t.CPtr,
ve_pe: HandlesVar.VarEntry | t.CPtr = \ ve_pe: HandlesVar.VarEntry | t.CPtr = \
HandlesVar.lookup_var_entry(trans.SymTab, nm.id) HandlesVar.lookup_var_entry(trans.SymTab, nm.id)
if ve_pe is not None and ve_pe.IsPtrElement == 1: if ve_pe is not None and ve_pe.IsPtrElement == 1:
stdio.printf("[GSP] IsPtrElement=1, gep direct\n")
stdio.fflush(0)
return llvmlite.build_gep( return llvmlite.build_gep(
builder, pointee, alloca, idx_val) builder, pointee, alloca, idx_val)
# 普通指针遍历: 先 load 指针值,再 GEP # 普通指针遍历: 先 load 指针值,再 GEP
ptr_val: llvmlite.Value | t.CPtr = llvmlite.build_load( ptr_val: llvmlite.Value | t.CPtr = llvmlite.build_load(
builder, pointee, alloca) builder, pointee, alloca)
if ptr_val is None: if ptr_val is None:
stdio.printf("[GSP] build_load=None\n")
stdio.fflush(0)
return None return None
gep_r: llvmlite.Value | t.CPtr = llvmlite.build_gep( gep_r: llvmlite.Value | t.CPtr = llvmlite.build_gep(
builder, inner_ty, ptr_val, idx_val) builder, inner_ty, ptr_val, idx_val)
if gep_r is None:
stdio.printf("[GSP] build_gep=None\n")
stdio.fflush(0)
return gep_r return gep_r
case _: case _:
# pointee 是普通标量类型 (如 i64, i32, i8): # pointee 是普通标量类型 (如 i64, i32, i8):
# alloca 是 Ptr(标量), 直接 GEP 获取第 idx 个元素指针 # alloca 是 Ptr(标量), 直接 GEP 获取第 idx 个元素指针
# 支持 arg_vals[i] = val 这类参数数组下标赋值 # 支持 arg_vals[i] = val 这类参数数组下标赋值
stdio.printf("[GSP] matched scalar, gep direct\n")
stdio.fflush(0)
return llvmlite.build_gep(builder, pointee, alloca, idx_val) return llvmlite.build_gep(builder, pointee, alloca, idx_val)
# 通用路径 # 通用路径
stdio.printf("[GSP] fallback to generic path\n")
stdio.fflush(0)
ptr_val: llvmlite.Value | t.CPtr = translate_value( ptr_val: llvmlite.Value | t.CPtr = translate_value(
builder, pool, mod, sub.value, None, 0, trans) builder, pool, mod, sub.value, None, 0, trans)
if ptr_val is None or ptr_val.Ty is None: if ptr_val is None or ptr_val.Ty is None:
stdio.printf("[GSP] generic: ptr_val=None\n")
stdio.fflush(0)
return None return None
if is_ptr_type(ptr_val.Ty) != 0: if is_ptr_type(ptr_val.Ty) != 0:
elem_ty2: llvmlite.LLVMType | t.CPtr = ptr_val.Ty.Pointee elem_ty2: llvmlite.LLVMType | t.CPtr = ptr_val.Ty.Pointee
@@ -2792,9 +2586,6 @@ def get_subscript_ptr(builder: llvmlite.IRBuilder | t.CPtr,
if cls_nm_gen is None: if cls_nm_gen is None:
pass pass
if not (cls_nm_gen is None): if not (cls_nm_gen is None):
stdio.printf("[GSP] generic custom struct %s, defer to __setitem__\n",
cls_nm_gen)
stdio.fflush(0)
return None return None
# 指针类型: 单索引 GEP (getelementptr ty, ptr, idx) # 指针类型: 单索引 GEP (getelementptr ty, ptr, idx)
return llvmlite.build_gep(builder, elem_ty2, ptr_val, idx_val) return llvmlite.build_gep(builder, elem_ty2, ptr_val, idx_val)

View File

@@ -362,29 +362,49 @@ def _ensure_c_lib_declare(pool: memhub.MemBuddy | t.CPtr,
# ============================================================ # ============================================================
def _infer_external_func_ret_ty(pool: memhub.MemBuddy | t.CPtr, def _infer_external_func_ret_ty(pool: memhub.MemBuddy | t.CPtr,
func_name: str) -> llvmlite.LLVMType | t.CPtr: func_name: str) -> llvmlite.LLVMType | t.CPtr:
"""根据函数名推断外部 includes 函数的返回类型""" """根据函数名推断外部 includes 函数的返回类型
支持三种函数名形式:
1. 裸名: "parse", "strlen"
2. 别名: "json_parse"from X import parse as json_parse
3. 带 SHA1 前缀: "240a9a4157959a9f.parse"(跨模块调用 mangled name
"""
if pool is None or func_name is None: if pool is None or func_name is None:
return llvmlite.Int32(pool) return llvmlite.Int32(pool)
# 提取裸函数名:去掉 SHA1 前缀(如 "240a9a4157959a9f.parse" → "parse"
# SHA1 前缀是 16 位十六进制 + '.',检查是否有 '.' 分隔
bare_name: str = func_name
dot_pos: str = string.strrchr(func_name, 46) # 46 = ord('.')
if dot_pos is not None:
# '.' 后的部分是裸函数名
bare_name = dot_pos + 1
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool))
# 返回 i8* 的函数(指针返回值,截断会导致错误) # 返回 i8* 的函数(指针返回值,截断会导致错误)
if func_name == "strchr": if bare_name == "strchr" or func_name == "strchr":
return llvmlite.Ptr(pool, llvmlite.Int8(pool)) return i8_ptr_ty
if func_name == "strrchr": if bare_name == "strrchr" or func_name == "strrchr":
return llvmlite.Ptr(pool, llvmlite.Int8(pool)) return i8_ptr_ty
if func_name == "strstr": if bare_name == "strstr" or func_name == "strstr":
return llvmlite.Ptr(pool, llvmlite.Int8(pool)) return i8_ptr_ty
if func_name == "strcpy": if bare_name == "strcpy" or func_name == "strcpy":
return llvmlite.Ptr(pool, llvmlite.Int8(pool)) return i8_ptr_ty
if func_name == "strncpy": if bare_name == "strncpy" or func_name == "strncpy":
return llvmlite.Ptr(pool, llvmlite.Int8(pool)) return i8_ptr_ty
if func_name == "memset": if bare_name == "memset" or func_name == "memset":
return llvmlite.Ptr(pool, llvmlite.Int8(pool)) return i8_ptr_ty
if func_name == "memset32": if bare_name == "memset32" or func_name == "memset32":
return llvmlite.Ptr(pool, llvmlite.Int8(pool)) return i8_ptr_ty
if func_name == "memcpy": if bare_name == "memcpy" or func_name == "memcpy":
return llvmlite.Ptr(pool, llvmlite.Int8(pool)) return i8_ptr_ty
if func_name == "memmove": if bare_name == "memmove" or func_name == "memmove":
return llvmlite.Ptr(pool, llvmlite.Int8(pool)) return i8_ptr_ty
# JSON 解析函数返回 JsonValue*(指针)
# from json.__parser import parse as json_parse → 别名 json_parse 也需覆盖
if bare_name == "parse" or func_name == "parse" or func_name == "json_parse":
return i8_ptr_ty
# MemBuddy 方法(当类型信息丢失时可能走外部函数路径) # MemBuddy 方法(当类型信息丢失时可能走外部函数路径)
if func_name == "alloc": if func_name == "alloc":
return llvmlite.Ptr(pool, llvmlite.Int8(pool)) return llvmlite.Ptr(pool, llvmlite.Int8(pool))
@@ -394,6 +414,14 @@ def _infer_external_func_ret_ty(pool: memhub.MemBuddy | t.CPtr,
return llvmlite.Ptr(pool, llvmlite.Int8(pool)) return llvmlite.Ptr(pool, llvmlite.Int8(pool))
if func_name == "alloc_buf": if func_name == "alloc_buf":
return llvmlite.Ptr(pool, llvmlite.Int8(pool)) return llvmlite.Ptr(pool, llvmlite.Int8(pool))
# VLogger 模块函数(跨模块调用时 stub 未注入,返回指针被截断为 i32 导致崩溃)
if func_name == "get_logger":
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
if func_name == "fmt_buf":
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
# Config 模块函数(跨模块调用时 stub 未注入,返回 i8* 被 inttoptr i32 截断导致路径损坏)
if func_name == "get_includes_binary_dir":
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
# 返回 i64 的函数 # 返回 i64 的函数
if func_name == "strlen": if func_name == "strlen":
@@ -442,6 +470,17 @@ def _infer_external_func_ret_ty(pool: memhub.MemBuddy | t.CPtr,
return i8_ptr_ty return i8_ptr_ty
if func_name == "LoadLibraryW": if func_name == "LoadLibraryW":
return i8_ptr_ty return i8_ptr_ty
# Win32 Handle 返回函数HANDLE = void* = i8*
if func_name == "GetStdHandle":
return i8_ptr_ty
if func_name == "CreateFileA":
return i8_ptr_ty
if func_name == "CreateFileW":
return i8_ptr_ty
if func_name == "FindFirstFileA":
return i8_ptr_ty
if func_name == "FindFirstFileW":
return i8_ptr_ty
# Win32 API 返回 i64 (SIZE_T) 的函数 # Win32 API 返回 i64 (SIZE_T) 的函数
if func_name == "VirtualQuery": if func_name == "VirtualQuery":
@@ -486,7 +525,11 @@ def _infer_external_func_ret_ty(pool: memhub.MemBuddy | t.CPtr,
func_name == "function_get_param_head" or func_name == "param_get_next": func_name == "function_get_param_head" or func_name == "param_get_next":
return llvmlite.Ptr(pool, llvmlite.Int8(pool)) return llvmlite.Ptr(pool, llvmlite.Int8(pool))
# 默认 i32 # 默认 i32整数与本模块函数定义的默认返回类型一致HandlesFunctions.py line 324
# 已知返回指针的函数在上方显式列出(返回 i8*),已知返回 i64 的函数也显式列出
# 避免使用 i64 导致 stub 声明declare i64与实际定义define i32类型不匹配
# x86-64 ABI 中 i32 返回值在 rax 低 32 位,与 define i32 完全一致
# 与 _infer_method_ret_ty 的默认策略保持一致
return llvmlite.Int32(pool) return llvmlite.Int32(pool)
# ============================================================ # ============================================================
@@ -2154,6 +2197,29 @@ def _translate_struct_ctor(pool: memhub.MemBuddy | t.CPtr,
if ctor_entry is not None: if ctor_entry is not None:
is_oop = ctor_entry.IsOOP is_oop = ctor_entry.IsOOP
# 跨模块 OOP 类推断IsOOP 可能未设置Phase1 缓存跳过 _translate_oop_methods
# 方案1: 检查当前模块是否有 ClassName.__init__ 的声明stub 注入)
# 方案2: 检查全局默认参数表是否有 ClassName.__init__ 的条目(翻译时填充,更可靠)
if is_oop == 0 and class_name is not None:
init_lookup_name: t.CChar | t.CPtr = pool.alloc(128)
if init_lookup_name is not None:
viperlib.snprintf(init_lookup_name, 128, "%s.__init__", class_name)
# 方案1: 检查当前模块的函数声明
init_found_func: llvmlite.Function | t.CPtr = find_func_in_module(mod, init_lookup_name)
if init_found_func is not None:
is_oop = 1
if ctor_entry is not None:
ctor_entry.IsOOP = 1
ctor_entry.HasInit = 1
else:
# 方案2: 检查全局默认参数表(翻译时填充,不依赖 stub 注入)
init_defaults_entry: FuncDefaultsEntry | t.CPtr = find_func_defaults(init_lookup_name)
if init_defaults_entry is not None:
is_oop = 1
if ctor_entry is not None:
ctor_entry.IsOOP = 1
ctor_entry.HasInit = 1
if is_oop != 0: if is_oop != 0:
# 存储指针:默认用 alloca如果有 __new__ 则用 __new__ 返回的指针 # 存储指针:默认用 alloca如果有 __new__ 则用 __new__ 返回的指针
storage_ptr: llvmlite.Value | t.CPtr = tmp storage_ptr: llvmlite.Value | t.CPtr = tmp
@@ -2773,7 +2839,13 @@ def _ensure_method_declare(pool: memhub.MemBuddy | t.CPtr,
ret_ty: llvmlite.LLVMType | t.CPtr, ret_ty: llvmlite.LLVMType | t.CPtr,
param_head: llvmlite.ParamNode | t.CPtr, param_head: llvmlite.ParamNode | t.CPtr,
param_count: int): param_count: int):
"""为跨模块方法调用创建 declare 声明""" """为跨模块方法调用创建 declare 声明
若模块中已存在同名 declare 且参数数量较少(例如 File.__init__ 的
stub 仅 3 个参数,而实际调用传入 4 个),则向现有 declare 追加缺失
参数,避免 llc 报 `argument invalid for parameter type` 之类的错误。
已存在的 define 不修改(其参数由定义决定)。
"""
if pool is None or mod is None or call_name is None: if pool is None or mod is None or call_name is None:
return return
# 检查模块中是否已有同名函数declare 或 define # 检查模块中是否已有同名函数declare 或 define
@@ -2781,7 +2853,32 @@ def _ensure_method_declare(pool: memhub.MemBuddy | t.CPtr,
while existing is not None: while existing is not None:
if existing.Name is not None: if existing.Name is not None:
if string.strcmp(existing.Name, call_name) == 0: if string.strcmp(existing.Name, call_name) == 0:
return # 已存在,无需重复声明 # 已存在:仅当是 declare 且参数数量不足时追加缺失参数
if existing.IsDeclared == 1:
# 遍历现有参数链表计数(避免依赖 GSList.Count 字段的类型推断)
cur_count: int = 0
cur_p: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(existing)
while cur_p is not None:
cur_count += 1
cur_p = cur_p.Next
# 只追加缺失的参数cur_count < param_count 时)
if cur_count < param_count:
# 定位到 param_head 的第 cur_count 个节点开始追加
pnode2: llvmlite.ParamNode | t.CPtr = param_head
pi2: int = 0
# 跳过已有的 cur_count 个参数
while pnode2 is not None and pi2 < cur_count:
pnode2 = pnode2.Next
pi2 += 1
# 追加剩余参数
while pnode2 is not None and pi2 < param_count:
if pnode2.Ty is not None:
param2: llvmlite.Param | t.CPtr = llvmlite.new_param(pool, pnode2.Ty, None)
if param2 is not None:
llvmlite.function_add_param(existing, param2)
pnode2 = pnode2.Next
pi2 += 1
return
existing = existing.Next existing = existing.Next
# 创建函数声明 # 创建函数声明
func: llvmlite.Function | t.CPtr = llvmlite.new_function(pool, call_name, ret_ty) func: llvmlite.Function | t.CPtr = llvmlite.new_function(pool, call_name, ret_ty)
@@ -2832,18 +2929,35 @@ def _infer_method_ret_ty(pool: memhub.MemBuddy | t.CPtr,
return i8_ptr_ty return i8_ptr_ty
if string.strcmp(method_name, "__enter__") == 0: if string.strcmp(method_name, "__enter__") == 0:
return i8_ptr_ty return i8_ptr_ty
# 工厂方法:返回对象指针(截断会导致后续方法调用崩溃)
if string.strcmp(method_name, "parse_args") == 0:
return i8_ptr_ty
# 魔术方法:返回对象指针(如 JsonValue.__getitem__ 返回 JsonValue*
if string.strcmp(method_name, "__getitem__") == 0:
return i8_ptr_ty
# 返回 i8* 的方法(返回字符串/类型名/描述) # 返回 i8* 的方法(返回字符串/类型名/描述)
if string.strcmp(method_name, "type_name") == 0: if string.strcmp(method_name, "type_name") == 0:
return i8_ptr_ty return i8_ptr_ty
if string.strcmp(method_name, "get_name") == 0: if string.strcmp(method_name, "get_name") == 0:
return i8_ptr_ty return i8_ptr_ty
if string.strcmp(method_name, "get_str") == 0:
return i8_ptr_ty
if string.strcmp(method_name, "get_path") == 0:
return i8_ptr_ty
if string.strcmp(method_name, "get_buf") == 0:
return i8_ptr_ty
if string.strcmp(method_name, "to_string") == 0: if string.strcmp(method_name, "to_string") == 0:
return i8_ptr_ty return i8_ptr_ty
if string.strcmp(method_name, "as_string") == 0:
return i8_ptr_ty
if string.strcmp(method_name, "__repr__") == 0: if string.strcmp(method_name, "__repr__") == 0:
return i8_ptr_ty return i8_ptr_ty
if string.strcmp(method_name, "__str__") == 0: if string.strcmp(method_name, "__str__") == 0:
return i8_ptr_ty return i8_ptr_ty
# 返回 i8* 的方法(返回对象指针,如 JsonValue.get_item → JsonValue*
if string.strcmp(method_name, "get_item") == 0:
return i8_ptr_ty
# 返回 void 的方法 # 返回 void 的方法
if string.strcmp(method_name, "__before_init__") == 0: if string.strcmp(method_name, "__before_init__") == 0:
@@ -2853,10 +2967,12 @@ def _infer_method_ret_ty(pool: memhub.MemBuddy | t.CPtr,
if string.strcmp(method_name, "__exit__") == 0: if string.strcmp(method_name, "__exit__") == 0:
return llvmlite.Void(pool) return llvmlite.Void(pool)
# 默认 i64(整数):既可安全截断为 i32trunc也可转换为指针inttoptr # 默认 i32(整数):与本模块函数定义的默认返回类型一致HandlesFunctions.py line 324
# 避免使用指针类型i8*)导致 coerce_to_type 生成 load解引用造成崩溃 # 已知返回指针的方法在上方显式列出(返回 i8*),已知返回 void 的方法也显式列出
# x86-64 ABI 中 i32 返回值在 rax 低 32 位i64 读取后 trunc 取低 32 位是安全的 # 避免使用 i64 导致 stub 声明declare i64与实际定义define i32类型不匹配
return llvmlite.Int64(pool) # x86-64 ABI 中 i32 返回值在 rax 低 32 位,与 define i32 完全一致
# 与 _infer_external_func_ret_ty 的默认策略保持一致
return llvmlite.Int32(pool)
# ============================================================ # ============================================================
# _translate_method_call - 翻译方法调用 obj.method(args) # _translate_method_call - 翻译方法调用 obj.method(args)
@@ -2981,6 +3097,65 @@ def _translate_method_call(pool: memhub.MemBuddy | t.CPtr,
total_count: int = 1 + can total_count: int = 1 + can
# 默认参数填充:如果调用点参数少于函数定义参数,用默认值填充缺失参数
# 查找函数的 defaults 信息
mdf_defaults: t.CVoid | t.CPtr = None
mdf_default_count: int = 0
mdf_param_count: int = 0
if trans is not None and trans._funcs is not None:
mdf_entry: FuncEntry | t.CPtr = find_func_entry_in_table(
trans._funcs, trans._func_count, lookup_name)
if mdf_entry is not None:
mdf_defaults = mdf_entry.Defaults
mdf_default_count = mdf_entry.DefaultCount
mdf_param_count = mdf_entry.ParamCount
if mdf_defaults is None:
mdf_gd: FuncDefaultsEntry | t.CPtr = find_func_defaults(lookup_name)
if mdf_gd is not None:
mdf_defaults = mdf_gd.Defaults
mdf_default_count = mdf_gd.DefaultCount
mdf_param_count = mdf_gd.ParamCount
# 计算需要填充的参数(不含 self
# can = 已提供的非 self 参数数量
# mdf_param_count = 函数定义的非 self 参数数量
if mdf_param_count > can:
mdf_offset: int = mdf_param_count - mdf_default_count
mdf_pi: int = can
while mdf_pi < mdf_param_count:
# 优先用默认值
if mdf_defaults is not None and mdf_default_count > 0 and mdf_pi >= mdf_offset:
mdf_di: int = mdf_pi - mdf_offset
if mdf_di < mdf_default_count:
mdf_defaults_list: list[ast.AST | t.CPtr] | t.CPtr = (list[ast.AST | t.CPtr] | t.CPtr)(t.CVoid(t.CUInt64T(mdf_defaults), t.CPtr))
mdf_node: ast.AST | t.CPtr = mdf_defaults_list.get(mdf_di)
if mdf_node is not None:
mdf_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
builder, pool, mod, mdf_node, None, 0, trans)
if mdf_val is not None:
llvmlite.value_set_next(mdf_val, None)
llvmlite.value_set_next(tail, mdf_val)
tail = mdf_val
total_count += 1
mdf_pi += 1
continue
# 无默认值时用零值兜底(需要 found_func 获取参数类型)
if found_func is not None:
param_node_z: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(found_func)
skip_z: int = 0
while skip_z <= mdf_pi and param_node_z is not None:
param_node_z = llvmlite.param_get_next(param_node_z)
skip_z += 1
if param_node_z is not None:
zero_ty: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(param_node_z)
zero_val: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, zero_ty)
if zero_val is not None:
llvmlite.value_set_next(zero_val, None)
llvmlite.value_set_next(tail, zero_val)
tail = zero_val
total_count += 1
mdf_pi += 1
# 虚方法分发:如果类有虚表且该方法在虚表中,走间接调用 # 虚方法分发:如果类有虚表且该方法在虚表中,走间接调用
# (不依赖 found_func — 继承的虚方法可能没有子类实现) # (不依赖 found_func — 继承的虚方法可能没有子类实现)
# 复用前面已获取的 mc_entryfind_struct_by_type 规避跨模块同名找错) # 复用前面已获取的 mc_entryfind_struct_by_type 规避跨模块同名找错)
@@ -3061,6 +3236,30 @@ def _translate_struct_ctor_kw(pool: memhub.MemBuddy | t.CPtr,
is_oop: int = 0 is_oop: int = 0
if kw_entry is not None: if kw_entry is not None:
is_oop = kw_entry.IsOOP is_oop = kw_entry.IsOOP
# 跨模块 OOP 类推断IsOOP 可能未设置Phase1 缓存跳过 _translate_oop_methods
# 方案1: 检查当前模块是否有 ClassName.__init__ 的声明stub 注入)
# 方案2: 检查全局默认参数表是否有 ClassName.__init__ 的条目(翻译时填充,更可靠)
if is_oop == 0 and class_name is not None:
kw_init_lookup: t.CChar | t.CPtr = pool.alloc(128)
if kw_init_lookup is not None:
viperlib.snprintf(kw_init_lookup, 128, "%s.__init__", class_name)
# 方案1: 检查当前模块的函数声明
kw_init_found: llvmlite.Function | t.CPtr = find_func_in_module(mod, kw_init_lookup)
if kw_init_found is not None:
is_oop = 1
if kw_entry is not None:
kw_entry.IsOOP = 1
kw_entry.HasInit = 1
else:
# 方案2: 检查全局默认参数表(翻译时填充,不依赖 stub 注入)
kw_init_defaults: FuncDefaultsEntry | t.CPtr = find_func_defaults(kw_init_lookup)
if kw_init_defaults is not None:
is_oop = 1
if kw_entry is not None:
kw_entry.IsOOP = 1
kw_entry.HasInit = 1
if is_oop != 0: if is_oop != 0:
_call_method_on_ptr(pool, builder, mod, class_name, _call_method_on_ptr(pool, builder, mod, class_name,
"__before_init__", tmp, None, 0, trans) "__before_init__", tmp, None, 0, trans)
@@ -3693,13 +3892,27 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr,
# 检测 obj.__len__() — 返回 list 对象的 __count__ 字段(偏移 8i64 # 检测 obj.__len__() — 返回 list 对象的 __count__ 字段(偏移 8i64
# __len__ 是 list[T] 的内置方法list 是泛型类不注册 struct # __len__ 是 list[T] 的内置方法list 是泛型类不注册 struct
# 注意: 必须用 translate_value 而非 translate_name_value因为 len_at.value
# 可能是 Attribute 节点(如 md_ags.argstranslate_name_value 只处理 Name 节点,
# 对 Attribute 会错误返回 i32 0导致 GEP base 不是指针base of getelementptr must be a pointer
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
len_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) len_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func)
if len_at.attr is not None and string.strcmp(len_at.attr, "__len__") == 0: if len_at.attr is not None and string.strcmp(len_at.attr, "__len__") == 0:
if len_at.value is not None and can == 0: if len_at.value is not None and can == 0:
obj_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_name_value( obj_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
builder, pool, len_at.value, trans) builder, pool, mod, len_at.value, funcs_ptr, func_count, trans)
if obj_val is not None: if obj_val is not None and obj_val.Ty is not None:
# 防御性类型检查: obj_val 必须是指针类型才能做 GEP
# 如果 translate_value 返回 i32 (如 CDefine 常量被误解析、
# 模块属性前向引用回退为 i32)GEP base 会是 i32 而非指针,
# 导致 llc 报错 "base of getelementptr must be a pointer"
if HandlesExpr.is_ptr_type(obj_val.Ty) == 0:
# 诊断: 输出节点类型信息帮助定位根本原因
len_node_kind: int = len_at.value.kind()
stdio.printf(
"[LEN-DIAG] __len__ on non-ptr (kind=%d), fallback to 0\n",
len_node_kind)
return llvmlite.const_int64(pool, 0)
i64_ty_len: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool) i64_ty_len: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool)
# 注意: 必须用 const_int64 而非 ConstInt(...,"0") # 注意: 必须用 const_int64 而非 ConstInt(...,"0")
# ConstInt 的 name 参数 "0" 会被当作 IR 文本值输出 i64 0 # ConstInt 的 name 参数 "0" 会被当作 IR 文本值输出 i64 0
@@ -3917,6 +4130,20 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr,
lm_obj: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( lm_obj: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
builder, pool, mod, lm_at.value, funcs_ptr, func_count, trans) builder, pool, mod, lm_at.value, funcs_ptr, func_count, trans)
if lm_obj is not None: if lm_obj is not None:
# 防御性类型检查: lm_obj 必须是指针类型才能做 GEP
# translate_value 对某些 Attribute 节点(如 ast.Arguments 的属性)
# 可能返回 i32 0 (非指针),直接 GEP 会导致
# "base of getelementptr must be a pointer" 错误
if lm_obj.Ty is None or HandlesExpr.is_ptr_type(lm_obj.Ty) == 0:
lm_node_kind: int = lm_at.value.kind()
fb_lm: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb_lm is not None:
viperlib.snprintf(fb_lm, 1024,
"list 方法 '%s' 的目标对象非指针 (node kind=%d)"
"translate_value 类型推断失败",
lm_name, lm_node_kind)
VLogger.critical(fb_lm, "LIST-METHOD")
return None
i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool) i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool)
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
@@ -4245,6 +4472,9 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr,
# 旧逻辑IsDeclared==1 时用 func_name 裸名是错误的stub 注入的 declare Name 已带 SHA1 前缀, # 旧逻辑IsDeclared==1 时用 func_name 裸名是错误的stub 注入的 declare Name 已带 SHA1 前缀,
# 用裸名会导致 call @_PathToModuleName 而 define 是 @"sha1._PathToModuleName",链接报 undefined reference # 用裸名会导致 call @_PathToModuleName 而 define 是 @"sha1._PathToModuleName",链接报 undefined reference
call_name: str = func_name call_name: str = func_name
# 原始函数名(别名导入时记录,如 from X import parse as json_parse → orig_func_name="parse"
# 用于在别名处理后重新推断返回类型,避免 _infer_external_func_ret_ty 用别名匹配失败
orig_func_name: str = None
if found_func is not None: if found_func is not None:
found_name: t.CChar | t.CPtr = llvmlite.function_get_name(found_func) found_name: t.CChar | t.CPtr = llvmlite.function_get_name(found_func)
if found_name is not None: if found_name is not None:
@@ -4357,6 +4587,11 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr,
bo_buf[bo_i] = bare_orig[bo_i] bo_buf[bo_i] = bare_orig[bo_i]
bo_buf[bo_len] = '\0' bo_buf[bo_len] = '\0'
bare_func_name = bo_buf bare_func_name = bo_buf
# 记录原始函数名,供后续重新推断返回类型
# 例如 from json.__parser import parse as json_parse
# func_name="json_parse", bare_func_name="parse"
# _infer_external_func_ret_ty 用 "parse" 能正确匹配,用 "json_parse" 则返回默认 i32
orig_func_name = bare_func_name
if is_cexport_func(bare_sha1, bare_func_name) != 0: if is_cexport_func(bare_sha1, bare_func_name) != 0:
call_name = bare_func_name call_name = bare_func_name
else: else:
@@ -4382,6 +4617,14 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr,
# memcpy → @llvm.memcpy 内联函数(避免 monomorphization 跨模块 @memcpy 声明缺失) # memcpy → @llvm.memcpy 内联函数(避免 monomorphization 跨模块 @memcpy 声明缺失)
if func_name == "memcpy" and can >= 3: if func_name == "memcpy" and can >= 3:
return _emit_llvm_memcpy_intrinsic(pool, builder, mod, mc_dst2, mc_src2, mc_num2) return _emit_llvm_memcpy_intrinsic(pool, builder, mod, mc_dst2, mc_src2, mc_num2)
# 别名导入重新推断返回类型:
# from X import parse as json_parse → func_name="json_parse" 时 _infer_external_func_ret_ty 返回默认 i32
# 用 orig_func_name="parse" 重新推断,能正确匹配返回 i8*JsonValue*
# 避免指针被截断为 i32 后 inttoptr 丢失高 32 位导致崩溃
if orig_func_name is not None and orig_func_name != func_name:
re_inferred_ty: llvmlite.LLVMType | t.CPtr = _infer_external_func_ret_ty(pool, orig_func_name)
if re_inferred_ty is not None:
call_ret_ty = re_inferred_ty
# 跨模块调用:创建 declare 声明,避免 llc 报 undefined value # 跨模块调用:创建 declare 声明,避免 llc 报 undefined value
_ensure_method_declare(pool, mod, call_name, call_ret_ty, head, can) _ensure_method_declare(pool, mod, call_name, call_ret_ty, head, can)
return llvmlite.build_call(builder, call_name, head, can, call_ret_ty, 0) return llvmlite.build_call(builder, call_name, head, can, call_ret_ty, 0)

View File

@@ -353,6 +353,8 @@ def forward_declare_functions(trans: HT.Translator | t.CPtr,
continue continue
# 提取默认参数信息 # 提取默认参数信息
# 注意: 必须先把属性赋给显式类型为 list[...] | t.CPtr 的局部变量再调用 __len__()
# 否则编译器无法识别属性返回的 list 类型GEP base 会变成 i32 0 导致 llc 报错
fd_args_node: ast.Arguments | t.CPtr = fd.args fd_args_node: ast.Arguments | t.CPtr = fd.args
fd_defaults: t.CVoid | t.CPtr = None fd_defaults: t.CVoid | t.CPtr = None
fd_default_count: int = 0 fd_default_count: int = 0
@@ -360,10 +362,12 @@ def forward_declare_functions(trans: HT.Translator | t.CPtr,
if fd_args_node is not None: if fd_args_node is not None:
fd_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(fd_args_node) fd_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(fd_args_node)
if fd_ags.args is not None: if fd_ags.args is not None:
fd_param_count = fd_ags.args.__len__() fd_alist: list[ast.AST | t.CPtr] | t.CPtr = fd_ags.args
fd_param_count = fd_alist.__len__()
if fd_ags.defaults is not None: if fd_ags.defaults is not None:
fd_defaults = fd_ags.defaults fd_dlist: list[ast.AST | t.CPtr] | t.CPtr = fd_ags.defaults
fd_default_count = fd_ags.defaults.__len__() fd_defaults = fd_dlist
fd_default_count = fd_dlist.__len__()
# 注册到函数表(用裸名 fd.name不是 mangled_name # 注册到函数表(用裸名 fd.name不是 mangled_name
max_funcs: int = 256 max_funcs: int = 256
@@ -558,10 +562,12 @@ def translate_function_def(trans: HT.Translator | t.CPtr,
if args_node is not None: if args_node is not None:
tfd_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) tfd_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
if tfd_ags.args is not None: if tfd_ags.args is not None:
tfd_param_count = tfd_ags.args.__len__() tfd_alist: list[ast.AST | t.CPtr] | t.CPtr = tfd_ags.args
tfd_param_count = tfd_alist.__len__()
if tfd_ags.defaults is not None: if tfd_ags.defaults is not None:
tfd_defaults = tfd_ags.defaults tfd_dlist: list[ast.AST | t.CPtr] | t.CPtr = tfd_ags.defaults
tfd_default_count = tfd_ags.defaults.__len__() tfd_defaults = tfd_dlist
tfd_default_count = tfd_dlist.__len__()
# 注册到函数表 # 注册到函数表
max_funcs: int = 256 max_funcs: int = 256
@@ -668,8 +674,6 @@ def translate_function_def(trans: HT.Translator | t.CPtr,
for bi2 in range(bn2): for bi2 in range(bn2):
stmt2: ast.AST | t.CPtr = body.get(bi2) stmt2: ast.AST | t.CPtr = body.get(bi2)
if stmt2 is not None: if stmt2 is not None:
stdio.printf("[DBG] TR body stmt=%d kind=%d\n", bi2, stmt2.kind())
stdio.fflush(0)
HandlesBody.translate_stmt(trans, stmt2) HandlesBody.translate_stmt(trans, stmt2)
# 如果函数体最后一条语句不是 Return添加隐式 ret # 如果函数体最后一条语句不是 Return添加隐式 ret

View File

@@ -559,6 +559,21 @@ class ImportsHandle(HandlesBase.Mixin):
resolved: str = _resolve_relative_module( resolved: str = _resolve_relative_module(
self.Trans.Pool, self.Trans.CurrentPackage, self.Trans.Pool, self.Trans.CurrentPackage,
impf.level, impf.module) impf.level, impf.module)
# [IFD] 诊断 from-import 名称处理
mod_dbg: str = "(null)"
if impf.module is not None:
mod_dbg = impf.module
pkg_dbg: str = "(null)"
if self.Trans.CurrentPackage is not None:
pkg_dbg = self.Trans.CurrentPackage
res_dbg: str = "(null)"
if resolved is not None:
res_dbg = resolved
names_dbg: t.CSizeT = 0
if impf.names is not None:
names_dbg = impf.names.__len__()
stdio.printf("[IFD] level=%d module=%s pkg=%s resolved=%s names=%d\n",
impf.level, mod_dbg, pkg_dbg, res_dbg, names_dbg)
if resolved is not None: if resolved is not None:
names: list[ast.AST | t.CPtr] | t.CPtr = impf.names names: list[ast.AST | t.CPtr] | t.CPtr = impf.names
if names is not None: if names is not None:

View File

@@ -88,6 +88,10 @@ def translate_children(trans: HT.Translator | t.CPtr,
if child is None: continue if child is None: continue
kd: int = child.kind() kd: int = child.kind()
# _declare_only == 0 时_translate_module_level 已预处理导入语句,
# 此处跳过避免重复处理from_imports 条目重复)
if trans._declare_only == 0 and (kd == ast.ASTKind.Import or kd == ast.ASTKind.ImportFrom):
continue
if kd == ast.ASTKind.Import: if kd == ast.ASTKind.Import:
trans.ImportsH.HandleImport(child) trans.ImportsH.HandleImport(child)
elif kd == ast.ASTKind.ImportFrom: elif kd == ast.ASTKind.ImportFrom:
@@ -97,10 +101,6 @@ def translate_children(trans: HT.Translator | t.CPtr,
# Phase 1a 声明模式:只注册 CExport/State 函数到全局表(解决翻译顺序依赖) # Phase 1a 声明模式:只注册 CExport/State 函数到全局表(解决翻译顺序依赖)
# Phase 1b 全量翻译:正常翻译函数体 # Phase 1b 全量翻译:正常翻译函数体
if trans._declare_only == 0: if trans._declare_only == 0:
fd_dbg: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child)
if fd_dbg is not None and fd_dbg.name is not None:
stdio.printf("[DBG] TR func=%s\n", fd_dbg.name)
stdio.fflush(0)
added: int = HandlesFunctions.translate_function_def(trans, child) added: int = HandlesFunctions.translate_function_def(trans, child)
added_total += added added_total += added
elif trans._declare_only == 1: elif trans._declare_only == 1:
@@ -109,10 +109,6 @@ def translate_children(trans: HT.Translator | t.CPtr,
# ClassDef 在模块级直接处理(不需要 builder # ClassDef 在模块级直接处理(不需要 builder
# _declare_only=2import扫描模式时跳过只处理 import 依赖 # _declare_only=2import扫描模式时跳过只处理 import 依赖
if trans._declare_only != 2: if trans._declare_only != 2:
cd_dbg: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(child)
if cd_dbg is not None and cd_dbg.name is not None:
stdio.printf("[DBG] TR class=%s\n", cd_dbg.name)
stdio.fflush(0)
HandlesClassDef.translate_class_def(trans, child) HandlesClassDef.translate_class_def(trans, child)
elif trans._declare_only == 0 and trans._cur_builder is not None: elif trans._declare_only == 0 and trans._cur_builder is not None:
# 有 builder → 委托 HandlesBody 分派 # 有 builder → 委托 HandlesBody 分派

View File

@@ -522,16 +522,8 @@ def lookup_field_by_class(class_name: str,
entry = find_struct(class_name) entry = find_struct(class_name)
if entry is None: if entry is None:
# 诊断:遍历打印所有已注册结构体名,确认目标类是否在注册表中 # 诊断:遍历打印所有已注册结构体名,确认目标类是否在注册表中
stdio.printf("[LFBC-DIAG] FAIL class=%s field=%s sha1=%s count=%d\n",
class_name, field_name,
sha1 if sha1 is not None else "(null)", _struct_count)
for diag_i in range(_struct_count): for diag_i in range(_struct_count):
diag_entry: StructEntry | t.CPtr = _get_struct_entry(diag_i) diag_entry: StructEntry | t.CPtr = _get_struct_entry(diag_i)
if diag_entry is not None and diag_entry.Name is not None:
stdio.printf("[LFBC-DIAG] [%d] %s sha1=%s fc=%d\n",
diag_i, diag_entry.Name,
diag_entry.ModuleSha1 if diag_entry.ModuleSha1 is not None else "(null)",
diag_entry.FieldCount)
return None return None
for fi in range(entry.FieldCount): for fi in range(entry.FieldCount):
fe: FieldEntry | t.CPtr = _get_field_entry(entry, fi) fe: FieldEntry | t.CPtr = _get_field_entry(entry, fi)
@@ -539,8 +531,6 @@ def lookup_field_by_class(class_name: str,
if string.strcmp(fe.Name, field_name) == 0: if string.strcmp(fe.Name, field_name) == 0:
return fe return fe
# 诊断:找到结构体但字段未找到 # 诊断:找到结构体但字段未找到
stdio.printf("[LFBC-DIAG] NOFIELD class=%s field=%s sname=%s fc=%d\n",
class_name, field_name, entry.Name, entry.FieldCount)
return None return None

View File

@@ -68,22 +68,8 @@ _g_cdefine_names: list[str] | t.CPtr = None
_g_cdefine_values: list[str] | t.CPtr = None _g_cdefine_values: list[str] | t.CPtr = None
# ============================================================ # ============================================================
# 全局跨模块 CDefine 表(按模块 SHA1 索引,跨模块持久化 # 当前模块 SHA1Phase1 在模块开始翻译前设置,供报错使用
#
# 本地表在模块切换时被 clear_cdefine_constants 清空,
# 导致跨模块引用(如 HandlesVar.SCOPE_FUNCTION找不到常量。
# 全局表在模块切换时不清空,跨模块查找直接查表,无需文件 I/O。
#
# 数据布局:
# _g_gcdef_sha1s: 每条 17 字节(模块 SHA1 16字符 + null
# _g_gcdef_names: 每条 64 字节(常量名 + null
# _g_gcdef_values: 每条 32 字节(值字符串 + null
# ============================================================ # ============================================================
MAX_GLOBAL_CDEFINE: t.CDefine = 1024
_g_gcdef_sha1s: bytes = None
_g_gcdef_names: bytes = None
_g_gcdef_values: bytes = None
_g_gcdef_count: int = 0
_g_current_module_sha1: str = None _g_current_module_sha1: str = None
@@ -93,29 +79,14 @@ def set_current_module_sha1(sha1: str) -> None:
_g_current_module_sha1 = sha1 _g_current_module_sha1 = sha1
def _global_cdefine_init(pool: memhub.MemBuddy | t.CPtr) -> int:
"""懒初始化全局 CDefine 表"""
global _g_gcdef_sha1s, _g_gcdef_names, _g_gcdef_values
if _g_gcdef_sha1s is None:
_g_gcdef_sha1s = stdlib.malloc(MAX_GLOBAL_CDEFINE * 17)
_g_gcdef_names = stdlib.malloc(MAX_GLOBAL_CDEFINE * 64)
_g_gcdef_values = stdlib.malloc(MAX_GLOBAL_CDEFINE * 32)
if _g_gcdef_sha1s is None or _g_gcdef_names is None or _g_gcdef_values is None:
return 1
string.memset(_g_gcdef_sha1s, 0, MAX_GLOBAL_CDEFINE * 17)
string.memset(_g_gcdef_names, 0, MAX_GLOBAL_CDEFINE * 64)
string.memset(_g_gcdef_values, 0, MAX_GLOBAL_CDEFINE * 32)
return 0
def register_cdefine_constant(pool: memhub.MemBuddy | t.CPtr, def register_cdefine_constant(pool: memhub.MemBuddy | t.CPtr,
name: str, value: int) -> None: name: str, value: int) -> None:
"""注册 CDefine 编译期常量到本地表和全局表 """注册 CDefine 编译期常量到本地表
值以十进制字符串存储。注意value 是 32 位有符号整数, 值以十进制字符串存储。注意value 是 32 位有符号整数,
0xFFFFFFFF 会存储为 "-1"lookup 时用 found 标志区分"未找到"和值为 -1。 0xFFFFFFFF 会存储为 "-1"lookup 时用 found 标志区分"未找到"和值为 -1。
""" """
global _g_cdefine_names, _g_cdefine_values, _g_gcdef_count global _g_cdefine_names, _g_cdefine_values
if _g_cdefine_names is None: if _g_cdefine_names is None:
_g_cdefine_names = list[str](pool, 64) _g_cdefine_names = list[str](pool, 64)
_g_cdefine_values = list[str](pool, 64) _g_cdefine_values = list[str](pool, 64)
@@ -126,41 +97,6 @@ def register_cdefine_constant(pool: memhub.MemBuddy | t.CPtr,
_g_cdefine_values.append(val_buf) _g_cdefine_values.append(val_buf)
else: else:
_g_cdefine_values.append("0") _g_cdefine_values.append("0")
# 同时注册到全局跨模块表(用当前模块 SHA1 索引)
if _g_current_module_sha1 is not None and _g_gcdef_count < MAX_GLOBAL_CDEFINE:
if _global_cdefine_init(pool) == 0:
sidx: t.CSizeT = t.CSizeT(_g_gcdef_count) * 17
nidx: t.CSizeT = t.CSizeT(_g_gcdef_count) * 64
vidx: t.CSizeT = t.CSizeT(_g_gcdef_count) * 32
string.strcpy(_g_gcdef_sha1s + sidx, _g_current_module_sha1)
string.strcpy(_g_gcdef_names + nidx, name)
vbuf: str = _g_gcdef_values + vidx
viperlib.snprintf(vbuf, 32, "%d", value)
_g_gcdef_count += 1
def lookup_global_cdefine(module_sha1: str, name: str) -> int:
"""从全局跨模块表查找 CDefine 常量
用 module_sha1 + name 精确匹配。
找到时设置 _g_cdefine_found=1 并返回值;未找到返回 0。
"""
global _g_cdefine_found
if module_sha1 is None or name is None:
return 0
if _g_gcdef_sha1s is None or _g_gcdef_count <= 0:
return 0
i: t.CSizeT = 0
while i < _g_gcdef_count:
sidx: t.CSizeT = t.CSizeT(i) * 17
nidx: t.CSizeT = t.CSizeT(i) * 64
vidx: t.CSizeT = t.CSizeT(i) * 32
if string.strcmp(_g_gcdef_sha1s + sidx, module_sha1) == 0:
if string.strcmp(_g_gcdef_names + nidx, name) == 0:
_g_cdefine_found = 1
return string.atoi(_g_gcdef_values + vidx)
i += 1
return 0
def lookup_cdefine_constant(name: str) -> int: def lookup_cdefine_constant(name: str) -> int:
@@ -645,6 +581,14 @@ def map_t_type(pool: memhub.MemBuddy | t.CPtr,
return llvmlite.Ptr(pool, llvmlite.Int8(pool)) return llvmlite.Ptr(pool, llvmlite.Int8(pool))
elif string.strcmp(type_name, "VOIDPTR") == 0: elif string.strcmp(type_name, "VOIDPTR") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool)) return llvmlite.Ptr(pool, llvmlite.Int8(pool))
# Windows API 跨模块 typedefwin32base.py 中定义)
# HANDLE = VOIDPTR = i8*LPCSTR = const char* = i8*LPCWSTR = const wchar_t* = i16*
elif string.strcmp(type_name, "HANDLE") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
elif string.strcmp(type_name, "LPCSTR") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
elif string.strcmp(type_name, "LPCWSTR") == 0:
return llvmlite.Ptr(pool, llvmlite.Int16(pool))
elif string.strcmp(type_name, "INT8PTR") == 0: elif string.strcmp(type_name, "INT8PTR") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool)) return llvmlite.Ptr(pool, llvmlite.Int8(pool))
elif string.strcmp(type_name, "INT16PTR") == 0: elif string.strcmp(type_name, "INT16PTR") == 0:

View File

@@ -22,7 +22,7 @@ import lib.core.VLogger as VLogger
# ============================================================ # ============================================================
# 全局 mbuddy 指针 # 全局 mbuddy 指针
_mbuddy: memhub.MemManager | t.CPtr _mbuddy: memhub.MemBuddy | t.CPtr
# 文件路径最大长度 # 文件路径最大长度
MAX_PATH_LEN: t.CDefine = 512 MAX_PATH_LEN: t.CDefine = 512

View File

@@ -24,7 +24,7 @@ import lib.Projectrans.Config as Config
import lib.StubGen.Converter as StubConverter import lib.StubGen.Converter as StubConverter
# 全局 mbuddy 指针 # 全局 mbuddy 指针
_mbuddy: memhub.MemManager | t.CPtr _mbuddy: memhub.MemBuddy | t.CPtr
# 源代码缓冲区大小1MB # 源代码缓冲区大小1MB
SRC_BUF_SIZE: t.CDefine = 1048576 SRC_BUF_SIZE: t.CDefine = 1048576
@@ -944,7 +944,6 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
src_buf[SRC_BUF_SIZE - 1] = 0 src_buf[SRC_BUF_SIZE - 1] = 0
# 解析 AST # 解析 AST
stdio.printf("[P1B-1] parse %s\n", entry.RelPath)
lx: ast.Lexer | t.CPtr = ast.new_lexer(mb) lx: ast.Lexer | t.CPtr = ast.new_lexer(mb)
if lx is None: if lx is None:
stdlib.free(src_buf) stdlib.free(src_buf)
@@ -953,7 +952,6 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
ast._lexer_init(lx, src_buf, mb) ast._lexer_init(lx, src_buf, mb)
tokens: ast.Token | t.CPtr = ast.tokenize(lx) tokens: ast.Token | t.CPtr = ast.tokenize(lx)
tree: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens) tree: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens)
stdio.printf("[P1B-1a] parse-done %s\n", entry.RelPath)
if tree is None: if tree is None:
fb: t.CChar | t.CPtr = VLogger.fmt_buf() fb: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb is not None: if fb is not None:
@@ -964,7 +962,6 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
continue continue
# 生成 .pyi 存根文件(直接遍历 AST不依赖 PythonToStubConverter # 生成 .pyi 存根文件(直接遍历 AST不依赖 PythonToStubConverter
stdio.printf("[P1B-2] pyi %s\n", entry.RelPath)
pyi_buf: bytes = stdlib.malloc(PYI_BUF_SIZE) pyi_buf: bytes = stdlib.malloc(PYI_BUF_SIZE)
if pyi_buf is not None: if pyi_buf is not None:
pyi_pos: t.CSizeT = StubConverter._GeneratePyiFromAst(mb, tree, entry.RelPath, pyi_buf, PYI_BUF_SIZE) pyi_pos: t.CSizeT = StubConverter._GeneratePyiFromAst(mb, tree, entry.RelPath, pyi_buf, PYI_BUF_SIZE)
@@ -979,7 +976,6 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
stdlib.free(pyi_buf) stdlib.free(pyi_buf)
# 翻译 AST → LLVM IR # 翻译 AST → LLVM IR
stdio.printf("[P1B-3] translate %s\n", entry.RelPath)
tr: HandlesTranslator.Translator | t.CPtr = HandlesTranslator.Translator() tr: HandlesTranslator.Translator | t.CPtr = HandlesTranslator.Translator()
if tr is None: if tr is None:
stdlib.free(src_buf) stdlib.free(src_buf)
@@ -992,7 +988,6 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
HandlesType.clear_cdefine_constants() HandlesType.clear_cdefine_constants()
HandlesStruct.reset_visible_structs(mb, 0) HandlesStruct.reset_visible_structs(mb, 0)
ret: int = tr.translate(tree) ret: int = tr.translate(tree)
stdio.printf("[P1B-3a] translate-done %s ret=%d\n", entry.RelPath, ret)
if ret != 0: if ret != 0:
fb: t.CChar | t.CPtr = VLogger.fmt_buf() fb: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb is not None: if fb is not None:
@@ -1007,7 +1002,6 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
continue continue
# dump stub IR (declarations only) # dump stub IR (declarations only)
stdio.printf("[P1B-4] stub %s\n", entry.RelPath)
PHASE1_IR_SIZE: t.CSizeT = 1048576 PHASE1_IR_SIZE: t.CSizeT = 1048576
stub_buf: bytes = stdlib.malloc(PHASE1_IR_SIZE) stub_buf: bytes = stdlib.malloc(PHASE1_IR_SIZE)
if stub_buf is None: if stub_buf is None:
@@ -1033,7 +1027,6 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
stdlib.free(stub_buf) stdlib.free(stub_buf)
# dump text IR (definitions only) # dump text IR (definitions only)
stdio.printf("[P1B-5] text %s\n", entry.RelPath)
text_buf: bytes = stdlib.malloc(PHASE1_IR_SIZE) text_buf: bytes = stdlib.malloc(PHASE1_IR_SIZE)
if text_buf is None: if text_buf is None:
stdlib.free(src_buf) stdlib.free(src_buf)

View File

@@ -24,7 +24,7 @@ import lib.Projectrans.Utils as Utils
import lib.Projectrans.Config as Config import lib.Projectrans.Config as Config
# 全局 mbuddy 指针 # 全局 mbuddy 指针
_mbuddy: memhub.MemManager | t.CPtr _mbuddy: memhub.MemBuddy | t.CPtr
# 源代码缓冲区大小1MB # 源代码缓冲区大小1MB
SRC_BUF_SIZE: t.CDefine = 1048576 SRC_BUF_SIZE: t.CDefine = 1048576
@@ -32,6 +32,9 @@ SRC_BUF_SIZE: t.CDefine = 1048576
# 最大源文件数(递归扫描子目录后文件数增多,增大到 64 # 最大源文件数(递归扫描子目录后文件数增多,增大到 64
MAX_SRC_FILES: t.CDefine = 64 MAX_SRC_FILES: t.CDefine = 64
# 全局栈金丝雀(避免局部变量改变栈布局)
_g_canary: t.CUInt32T
@t.NoVTable @t.NoVTable
class SrcFileEntry: class SrcFileEntry:
@@ -172,8 +175,8 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
VLogger.error("source_dir 为空", "project") VLogger.error("source_dir 为空", "project")
return 1 return 1
stdio.printf("[DBG] RunMultiFileProject enter src=%s\n", source_dir) # === 栈金丝雀检查(全局变量,不影响栈布局)===
stdio.fflush(0) _g_canary = 305419896
fb: t.CChar | t.CPtr = VLogger.fmt_buf() fb: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb is not None: if fb is not None:
@@ -188,8 +191,6 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
string.memset(entries, 0, MAX_SRC_FILES * entry_size) string.memset(entries, 0, MAX_SRC_FILES * entry_size)
file_count: int = _ScanDirForPyFiles(mb, source_dir, entries, entry_size, 0, MAX_SRC_FILES) file_count: int = _ScanDirForPyFiles(mb, source_dir, entries, entry_size, 0, MAX_SRC_FILES)
stdio.printf("[DBG] scan done file_count=%d\n", file_count)
stdio.fflush(0)
fb: t.CChar | t.CPtr = VLogger.fmt_buf() fb: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb is not None: if fb is not None:
viperlib.snprintf(fb, 1024, "%d 个源文件", file_count) viperlib.snprintf(fb, 1024, "%d 个源文件", file_count)
@@ -296,8 +297,6 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
# === 2. Phase A: 为每个文件生成 stub + text === # === 2. Phase A: 为每个文件生成 stub + text ===
if do_phase1 != 0: if do_phase1 != 0:
stdio.printf("[DBG] before Phase A\n")
stdio.fflush(0)
if log is not None: if log is not None:
log.banner("Phase A: 生成 stub + text") log.banner("Phase A: 生成 stub + text")
@@ -311,8 +310,6 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
PHASE_A_PRE_MAX_PASSES: t.CInt = 3 PHASE_A_PRE_MAX_PASSES: t.CInt = 3
for pass_i in range(PHASE_A_PRE_MAX_PASSES): for pass_i in range(PHASE_A_PRE_MAX_PASSES):
struct_count_before: int = HandlesStruct.get_struct_count() struct_count_before: int = HandlesStruct.get_struct_count()
stdio.printf("[DBG] PhaseA-pre pass=%d struct_count_before=%d\n", pass_i, struct_count_before)
stdio.fflush(0)
for i in range(file_count): for i in range(file_count):
ea_pre: t.CUInt64T = t.CUInt64T(entries) + i * entry_size ea_pre: t.CUInt64T = t.CUInt64T(entries) + i * entry_size
ent_pre: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea_pre, t.CPtr)) ent_pre: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea_pre, t.CPtr))
@@ -322,8 +319,6 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
if string.strlen(ent_pre.Path) > src_dir_len_pre + 1: if string.strlen(ent_pre.Path) > src_dir_len_pre + 1:
rel_path_pre: str = ent_pre.Path + src_dir_len_pre + 1 rel_path_pre: str = ent_pre.Path + src_dir_len_pre + 1
pkg_pre = HandlesImports.compute_package_from_relpath(mb, rel_path_pre) pkg_pre = HandlesImports.compute_package_from_relpath(mb, rel_path_pre)
stdio.printf("[DBG] PhaseA-pre pass=%d file=%s\n", pass_i, ent_pre.Path)
stdio.fflush(0)
tr_pre: HandlesTranslator.Translator | t.CPtr = BuildPipeline.TranslateFileGetTrans(mb, ent_pre.Path, ent_pre.Sha1, pkg_pre, 1) tr_pre: HandlesTranslator.Translator | t.CPtr = BuildPipeline.TranslateFileGetTrans(mb, ent_pre.Path, ent_pre.Sha1, pkg_pre, 1)
if tr_pre is None: if tr_pre is None:
fb: t.CChar | t.CPtr = VLogger.fmt_buf() fb: t.CChar | t.CPtr = VLogger.fmt_buf()
@@ -331,8 +326,6 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
viperlib.snprintf(fb, 1024, "预注册失败: %s", ent_pre.Path) viperlib.snprintf(fb, 1024, "预注册失败: %s", ent_pre.Path)
VLogger.warning(fb, "PhaseA") VLogger.warning(fb, "PhaseA")
struct_count_after: int = HandlesStruct.get_struct_count() struct_count_after: int = HandlesStruct.get_struct_count()
stdio.printf("[DBG] PhaseA-pre pass=%d done struct_count_after=%d\n", pass_i, struct_count_after)
stdio.fflush(0)
# 收敛检查:本遍没有新结构体注册 → 所有类已注册 # 收敛检查:本遍没有新结构体注册 → 所有类已注册
if struct_count_after == struct_count_before: if struct_count_after == struct_count_before:
break break
@@ -341,16 +334,11 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
PHASE_A_IR_SIZE: t.CSizeT = 1048576 PHASE_A_IR_SIZE: t.CSizeT = 1048576
td_len_pa: t.CSizeT = string.strlen(temp_dir) td_len_pa: t.CSizeT = string.strlen(temp_dir)
stdio.printf("[DBG] PhaseA full-translate start\n")
stdio.fflush(0)
for i in range(file_count): for i in range(file_count):
ea: t.CUInt64T = t.CUInt64T(entries) + i * entry_size ea: t.CUInt64T = t.CUInt64T(entries) + i * entry_size
ent: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea, t.CPtr)) ent: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea, t.CPtr))
if ent is None or ent.Path is None: if ent is None or ent.Path is None:
continue continue
stdio.printf("[DBG] PhaseA file=%s\n", ent.Path)
stdio.fflush(0)
# 计算源文件的包名(相对 source_dir 的目录部分) # 计算源文件的包名(相对 source_dir 的目录部分)
src_dir_len_pa: t.CSizeT = string.strlen(source_dir) src_dir_len_pa: t.CSizeT = string.strlen(source_dir)
pkg_pa: str = None pkg_pa: str = None
@@ -413,8 +401,6 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
# === 3. Phase B: 编译每个文件为 .obj === # === 3. Phase B: 编译每个文件为 .obj ===
if do_phase2 != 0: if do_phase2 != 0:
stdio.printf("[DBG] before Phase B\n")
stdio.fflush(0)
if log is not None: if log is not None:
log.banner("Phase B: 编译 .obj") log.banner("Phase B: 编译 .obj")
@@ -441,12 +427,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
ent: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea, t.CPtr)) ent: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea, t.CPtr))
if ent is None or ent.Path is None or ent.Sha1 is None: if ent is None or ent.Path is None or ent.Sha1 is None:
continue continue
stdio.printf("[DBG] PhaseB file=%s\n", ent.Path)
stdio.fflush(0)
# 组合本地 stub + 所有依赖 stub + 本地 text → 完整 IR # 组合本地 stub + 所有依赖 stub + 本地 text → 完整 IR
stdio.printf("[DBG] PhaseB step=alloc combined_ir\n")
stdio.fflush(0)
combined_ir: bytes = stdlib.malloc(COMBINED_IR_SIZE) combined_ir: bytes = stdlib.malloc(COMBINED_IR_SIZE)
if combined_ir is None: if combined_ir is None:
fb: t.CChar | t.CPtr = VLogger.fmt_buf() fb: t.CChar | t.CPtr = VLogger.fmt_buf()
@@ -454,11 +435,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
viperlib.snprintf(fb, 1024, "combined_ir 分配失败: %s", ent.Path) viperlib.snprintf(fb, 1024, "combined_ir 分配失败: %s", ent.Path)
VLogger.error(fb, "PhaseB") VLogger.error(fb, "PhaseB")
continue continue
stdio.printf("[DBG] PhaseB step=BuildCombinedIR sha1=%s\n", ent.Sha1)
stdio.fflush(0)
combined_len: t.CSizeT = StubMerger.BuildCombinedIR(temp_dir, ent.Sha1, combined_ir, COMBINED_IR_SIZE) combined_len: t.CSizeT = StubMerger.BuildCombinedIR(temp_dir, ent.Sha1, combined_ir, COMBINED_IR_SIZE)
stdio.printf("[DBG] PhaseB step=BuildCombinedIR done len=%d\n", combined_len)
stdio.fflush(0)
if combined_len == 0: if combined_len == 0:
fb: t.CChar | t.CPtr = VLogger.fmt_buf() fb: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb is not None: if fb is not None:
@@ -468,13 +445,9 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
continue continue
# 编译为 .obj # 编译为 .obj
stdio.printf("[DBG] PhaseB step=compile_module_to_obj\n")
stdio.fflush(0)
cret: int = BuildPipeline.compile_module_to_obj( cret: int = BuildPipeline.compile_module_to_obj(
combined_ir, combined_len, temp_dir, output_dir, ent.Sha1, combined_ir, combined_len, temp_dir, output_dir, ent.Sha1,
cc_cmd, cc_flags) cc_cmd, cc_flags)
stdio.printf("[DBG] PhaseB step=compile_module_to_obj done cret=%d\n", cret)
stdio.fflush(0)
stdlib.free(combined_ir) stdlib.free(combined_ir)
if cret != 0: if cret != 0:
fb: t.CChar | t.CPtr = VLogger.fmt_buf() fb: t.CChar | t.CPtr = VLogger.fmt_buf()
@@ -484,9 +457,6 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
sys.exit(1) sys.exit(1)
compiled_count += 1 compiled_count += 1
stdio.printf("[DBG] PhaseB step=obj_path construct\n")
stdio.fflush(0)
# 构造 .obj 路径,检测是否是 main 模块test_main.py 或 main.py # 构造 .obj 路径,检测是否是 main 模块test_main.py 或 main.py
od_len: t.CSizeT = string.strlen(output_dir) od_len: t.CSizeT = string.strlen(output_dir)
is_main_mod: int = 0 is_main_mod: int = 0
@@ -517,11 +487,6 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
else: else:
VLogger.warning(".obj 路径缓冲区不足", "PhaseB") VLogger.warning(".obj 路径缓冲区不足", "PhaseB")
stdlib.free(obj_path_sliced) stdlib.free(obj_path_sliced)
stdio.printf("[DBG] PhaseB step=obj_path done\n")
stdio.fflush(0)
stdio.printf("[DBG] PhaseB loop done compiled_count=%d\n", compiled_count)
stdio.fflush(0)
fb: t.CChar | t.CPtr = VLogger.fmt_buf() fb: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb is not None: if fb is not None:
viperlib.snprintf(fb, 1024, "编译完成: %d/%d", compiled_count, file_count) viperlib.snprintf(fb, 1024, "编译完成: %d/%d", compiled_count, file_count)
@@ -538,27 +503,18 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
# 检测并编译缺失的 includes 文件到 output_dir加入链接命令。 # 检测并编译缺失的 includes 文件到 output_dir加入链接命令。
# 数据来源StubMerger 全局内存存储器(不读取 _sha1_map.txt 文件) # 数据来源StubMerger 全局内存存储器(不读取 _sha1_map.txt 文件)
if includes_dir is not None and includes_binary_dir is not None: if includes_dir is not None and includes_binary_dir is not None:
stdio.printf("[DBG] PhaseB+ start\n")
stdio.fflush(0)
inc_compiled: int = 0 inc_compiled: int = 0
td_len_mi: t.CSizeT = string.strlen(temp_dir) td_len_mi: t.CSizeT = string.strlen(temp_dir)
# 从全局存储器获取 SHA1/模块名/rel_path 数组(直接访问器,避免 box 解引用问题) # 从全局存储器获取 SHA1/模块名/rel_path 数组(直接访问器,避免 box 解引用问题)
store_count_mi: int = StubMerger.GetSha1StoreCount() store_count_mi: int = StubMerger.GetSha1StoreCount()
stdio.printf("[DBG] PhaseB+ store_count=%d\n", store_count_mi)
stdio.fflush(0)
if store_count_mi > 0: if store_count_mi > 0:
store_sha1_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreArrPtr() store_sha1_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreArrPtr()
store_mod_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreModArrPtr() store_mod_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreModArrPtr()
store_rel_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreRelArrPtr() store_rel_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreRelArrPtr()
stdio.printf("[DBG] PhaseB+ arrs ok sha1=%p mod=%p rel=%p\n", store_sha1_arr_mi, store_mod_arr_mi, store_rel_arr_mi)
stdio.fflush(0)
for si_mi in range(store_count_mi): for si_mi in range(store_count_mi):
# 获取当前条目的 SHA1 和 rel_path # 获取当前条目的 SHA1 和 rel_path
inc_sha1_mi: str = store_sha1_arr_mi + t.CSizeT(si_mi) * 17 inc_sha1_mi: str = store_sha1_arr_mi + t.CSizeT(si_mi) * 17
inc_rel_mi: str = store_rel_arr_mi + t.CSizeT(si_mi) * StubMerger.MAX_REL_PATH_LEN inc_rel_mi: str = store_rel_arr_mi + t.CSizeT(si_mi) * StubMerger.MAX_REL_PATH_LEN
stdio.printf("[DBG] PhaseB+ iter=%d sha1=%s rel=%s\n", si_mi, inc_sha1_mi, inc_rel_mi)
stdio.fflush(0)
# 检查 .obj 是否已存在于 includes.binary # 检查 .obj 是否已存在于 includes.binary
ibd_len_mi: t.CSizeT = string.strlen(includes_binary_dir) ibd_len_mi: t.CSizeT = string.strlen(includes_binary_dir)
check_pat_mi: bytes = stdlib.malloc(ibd_len_mi + 35) check_pat_mi: bytes = stdlib.malloc(ibd_len_mi + 35)
@@ -719,8 +675,6 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
VLogger.info(fb, "PhaseB+") VLogger.info(fb, "PhaseB+")
# === 4. Phase C: 链接所有 .obj → .exe === # === 4. Phase C: 链接所有 .obj → .exe ===
stdio.printf("[DBG] PhaseC start\n")
stdio.fflush(0)
if log is not None: if log is not None:
log.banner("Phase C: 链接") log.banner("Phase C: 链接")
@@ -754,14 +708,10 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
final_obj_paths[fop_pos] = '\0' final_obj_paths[fop_pos] = '\0'
obj_paths_len: t.CSizeT = fop_pos obj_paths_len: t.CSizeT = fop_pos
stdio.printf("[DBG] PhaseC before link_objs_to_exe len=%d\n", obj_paths_len)
stdio.fflush(0)
lret: int = BuildPipeline.link_objs_to_exe( lret: int = BuildPipeline.link_objs_to_exe(
final_obj_paths, obj_paths_len, final_obj_paths, obj_paths_len,
linker_cmd, linker_flags, exe_path, linker_cmd, linker_flags, exe_path,
includes_binary_dir) includes_binary_dir)
stdio.printf("[DBG] PhaseC link_objs_to_exe done lret=%d\n", lret)
stdio.fflush(0)
if lret == 0: if lret == 0:
fb: t.CChar | t.CPtr = VLogger.fmt_buf() fb: t.CChar | t.CPtr = VLogger.fmt_buf()

View File

@@ -35,7 +35,7 @@ import lib.Projectrans.Config as Config
# ============================================================ # ============================================================
# 全局 mbuddy 指针 # 全局 mbuddy 指针
_mbuddy: memhub.MemManager | t.CPtr _mbuddy: memhub.MemBuddy | t.CPtr
# 最大 includes SHA1 数(用于过滤) # 最大 includes SHA1 数(用于过滤)
MAX_INCLUDES_SHA1: t.CDefine = 256 MAX_INCLUDES_SHA1: t.CDefine = 256

View File

@@ -54,11 +54,12 @@ BACKGROUND_INTENSITY: t.CDefine = 0x0080
BACKGROUND_WHITE: t.CDefine = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE BACKGROUND_WHITE: t.CDefine = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
@t.NoVTable
class Logger: class Logger:
_level: int _level: int
_console_handle: w32base.HANDLE _console_handle: win32base.HANDLE
_use_color: int _use_color: int
__mbuddy__: memhub.MemManager | t.CPtr __mbuddy__: memhub.MemBuddy | t.CPtr
def __init__(self, level: int = 1): def __init__(self, level: int = 1):
self._level = level self._level = level
@@ -67,8 +68,11 @@ class Logger:
self.__mbuddy__ = _mbuddy self.__mbuddy__ = _mbuddy
def _set_color(self, attr: WORD) -> int: def _set_color(self, attr: WORD) -> int:
if self._use_color: uc: int = self._use_color
return w32cmd.SetConsoleTextAttribute(self._console_handle, attr) if uc:
ch: win32base.HANDLE = self._console_handle
ret: int = w32cmd.SetConsoleTextAttribute(ch, attr)
return ret
return 0 return 0
def _reset_color(self) -> int: def _reset_color(self) -> int:
@@ -88,23 +92,17 @@ class Logger:
def _log(self, level: int, prefix_sym: str, level_str: str, msg: str, def _log(self, level: int, prefix_sym: str, level_str: str, msg: str,
sym_color: WORD, level_color: WORD, sym_color: WORD, level_color: WORD,
category: str = "") -> int: category: str = "") -> int:
if level < self._level: # 前缀符号着色
return 0
# 前缀符号(如 ├)
self._set_color(sym_color) self._set_color(sym_color)
stdio.printf("%s ", prefix_sym) stdio.printf("%s ", prefix_sym)
# LEVEL 标签(亮色) # LEVEL 标签着色
self._set_color(level_color) self._set_color(level_color)
if category is not None: stdio.printf("%s", level_str)
if category[0] != 0:
stdio.printf("%s[%s]: ", level_str, category)
else:
stdio.printf("%s: ", level_str)
else:
stdio.printf("%s: ", level_str)
# 消息内容(默认色)
self._reset_color() self._reset_color()
stdio.printf("%s\n", msg) # category 可选
if category is not None and category[0] != 0:
stdio.printf("[%s]", category)
stdio.printf(": %s\n", msg)
return 0 return 0
def debug(self, msg: str, category: str = "") -> int: def debug(self, msg: str, category: str = "") -> int:
@@ -112,9 +110,10 @@ class Logger:
FOREGROUND_INTENSITY, FOREGROUND_INTENSITY, category) FOREGROUND_INTENSITY, FOREGROUND_INTENSITY, category)
def info(self, msg: str, category: str = "") -> int: def info(self, msg: str, category: str = "") -> int:
return self._log(LogLevel.INFO, "", "INFO", msg, ret: int = self._log(LogLevel.INFO, "", "INFO", msg,
FOREGROUND_GREEN, FOREGROUND_GREEN,
FOREGROUND_GREEN | FOREGROUND_INTENSITY, category) FOREGROUND_GREEN | FOREGROUND_INTENSITY, category)
return ret
def warning(self, msg: str, category: str = "") -> int: def warning(self, msg: str, category: str = "") -> int:
return self._log(LogLevel.WARNING, "", "WARN", msg, return self._log(LogLevel.WARNING, "", "WARN", msg,
@@ -189,7 +188,7 @@ class Logger:
# 全局 mbuddy 指针(由 lib.InitLib 注入) # 全局 mbuddy 指针(由 lib.InitLib 注入)
_mbuddy: memhub.MemManager | t.CPtr _mbuddy: memhub.MemBuddy | t.CPtr
# 全局 logger 指针 # 全局 logger 指针
_g_logger: Logger | t.CPtr _g_logger: Logger | t.CPtr
@@ -223,10 +222,8 @@ def get_logger() -> Logger | t.CPtr:
if raw is None: if raw is None:
return None return None
_g_logger = raw _g_logger = raw
_g_logger._level = LogLevel.INFO _g_logger.__before_init__()
_g_logger._console_handle = w32file.GetStdHandle(w32file.STD_OUTPUT_HANDLE) _g_logger.__init__(LogLevel.INFO)
_g_logger._use_color = 1
_g_logger.__mbuddy__ = _mbuddy
return _g_logger return _g_logger

View File

@@ -49,127 +49,70 @@ SRC_BUF_SIZE: t.CDefine = 1048576
def main() -> int: def main() -> int:
w32cmd.SetConsoleOutputCP(CODE_PAGE) w32cmd.SetConsoleOutputCP(CODE_PAGE)
w32cmd.SetConsoleCP(CODE_PAGE) w32cmd.SetConsoleCP(CODE_PAGE)
# 用 fflush(0) 刷新所有流确保崩溃前输出可见0=NULL 刷新所有输出流)
stdio.printf("[DBG] main enter\n")
stdio.fflush(0)
# 初始化 mbuddy 内存池 # 初始化 mbuddy 内存池
stdio.printf("[DBG] before malloc\n")
stdio.fflush(0)
arena: bytes = stdlib.malloc(POOL_SIZE) arena: bytes = stdlib.malloc(POOL_SIZE)
stdio.printf("[DBG] after malloc arena=%p\n", arena)
stdio.fflush(0)
if arena is None: if arena is None:
stdio.printf("FAIL: malloc for arena failed\n") stdio.printf("FAIL: malloc for arena failed\n")
return 1 return 1
stdio.printf("[DBG] before MemBuddy\n")
stdio.fflush(0)
mb: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, POOL_SIZE) mb: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, POOL_SIZE)
stdio.printf("[DBG] after MemBuddy mb=%p\n", mb)
stdio.fflush(0)
if mb is None: if mb is None:
stdio.printf("FAIL: MemBuddy init failed\n") stdio.printf("FAIL: MemBuddy init failed\n")
return 1 return 1
# 设置全局 mbuddy 指针sys 和 argparse 都需要) # 设置全局 mbuddy 指针sys 和 argparse 都需要)
stdio.printf("[DBG] before _mbuddy setup\n")
stdio.fflush(0)
sys._mbuddy = mb sys._mbuddy = mb
stdio.printf("[DBG] sys._mbuddy ok\n")
stdio.fflush(0)
argparse._mbuddy = mb argparse._mbuddy = mb
ast._mbuddy = mb ast._mbuddy = mb
lib._mbuddy = (memhub.MemManager | t.CPtr)(mb) lib._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
Config._mbuddy = (memhub.MemManager | t.CPtr)(mb) Config._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
Utils._mbuddy = (memhub.MemManager | t.CPtr)(mb) Utils._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
HandlesTranslator._mbuddy = mb HandlesTranslator._mbuddy = mb
BuildPipeline._mbuddy = (memhub.MemManager | t.CPtr)(mb) BuildPipeline._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
IncludesScanner._mbuddy = (memhub.MemManager | t.CPtr)(mb) IncludesScanner._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
StubMerger._mbuddy = (memhub.MemManager | t.CPtr)(mb) StubMerger._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
Phase1._mbuddy = (memhub.MemManager | t.CPtr)(mb) Phase1._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
Phase2._mbuddy = (memhub.MemManager | t.CPtr)(mb) Phase2._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
subprocess._mbuddy = mb subprocess._mbuddy = mb
hashlib._mbuddy = (memhub.MemManager | t.CPtr)(mb) hashlib._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
VLogger._mbuddy = (memhub.MemManager | t.CPtr)(mb) VLogger._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
stdio.printf("[DBG] before InitLib\n") lib.InitLib((memhub.MemBuddy | t.CPtr)(mb))
stdio.fflush(0)
lib.InitLib((memhub.MemManager | t.CPtr)(mb))
stdio.printf("[DBG] after InitLib\n")
stdio.fflush(0)
# 初始化 VLogger 并打印启动日志 # 初始化 VLogger 并打印启动日志
log: VLogger.Logger | t.CPtr = VLogger.get_logger() log: VLogger.Logger | t.CPtr = VLogger.get_logger()
stdio.printf("[DBG] after get_logger log=%p\n", log)
stdio.fflush(0)
if log is not None: if log is not None:
log.info("TransPyV 启动") log.info("TransPyV 启动")
stdio.printf("[DBG] after log.info\n")
stdio.fflush(0)
# 初始化命令行参数Windows: GetCommandLineA, POSIX: /proc/self/cmdline # 初始化命令行参数Windows: GetCommandLineA, POSIX: /proc/self/cmdline
stdio.printf("[DBG] before _init_argv\n")
stdio.fflush(0)
sys._init_argv() sys._init_argv()
stdio.printf("[DBG] after _init_argv\n")
stdio.fflush(0)
# 创建参数解析器 # 创建参数解析器
stdio.printf("[DBG] before ArgumentParser\n")
stdio.fflush(0)
parser: argparse.ArgumentParser | t.CPtr = argparse.ArgumentParser( parser: argparse.ArgumentParser | t.CPtr = argparse.ArgumentParser(
"TransPyV", "TransPyV 命令行参数解析", pool=mb) "TransPyV", "TransPyV 命令行参数解析", pool=mb)
stdio.printf("[DBG] after ArgumentParser parser=%p\n", parser)
stdio.fflush(0)
# 注册参数(与 Projectrans.py main() 一致) # 注册参数(与 Projectrans.py main() 一致)
stdio.printf("[DBG] before add_argument --project\n")
stdio.fflush(0)
parser.add_argument("--project", None, argparse.STRING, 0, None, False, parser.add_argument("--project", None, argparse.STRING, 0, None, False,
argparse.STORE, "project.json 路径(默认查找当前目录)") argparse.STORE, "project.json 路径(默认查找当前目录)")
stdio.printf("[DBG] after add_argument --project\n")
stdio.fflush(0)
parser.add_argument("--src", None, argparse.STRING, 0, None, False, parser.add_argument("--src", None, argparse.STRING, 0, None, False,
argparse.STORE, "源文件目录(覆盖 project.json") argparse.STORE, "源文件目录(覆盖 project.json")
stdio.printf("[DBG] after --src\n")
stdio.fflush(0)
parser.add_argument("--temp", None, argparse.STRING, 0, None, False, parser.add_argument("--temp", None, argparse.STRING, 0, None, False,
argparse.STORE, "声明接口临时目录(覆盖 project.json") argparse.STORE, "声明接口临时目录(覆盖 project.json")
stdio.printf("[DBG] after --temp\n")
stdio.fflush(0)
parser.add_argument("--output", None, argparse.STRING, 0, None, False, parser.add_argument("--output", None, argparse.STRING, 0, None, False,
argparse.STORE, "输出目录(覆盖 project.json") argparse.STORE, "输出目录(覆盖 project.json")
stdio.printf("[DBG] after --output\n")
stdio.fflush(0)
parser.add_argument("--phase", None, argparse.STRING, 0, None, False, parser.add_argument("--phase", None, argparse.STRING, 0, None, False,
argparse.STORE, "阶段: 1=生成声明, 2=翻译+编译, all=全部") argparse.STORE, "阶段: 1=生成声明, 2=翻译+编译, all=全部")
stdio.printf("[DBG] after --phase\n")
stdio.fflush(0)
parser.add_argument("--cc", None, argparse.STRING, 0, None, False, parser.add_argument("--cc", None, argparse.STRING, 0, None, False,
argparse.STORE, "LLVM 编译器命令(覆盖 project.json") argparse.STORE, "LLVM 编译器命令(覆盖 project.json")
stdio.printf("[DBG] after --cc\n")
stdio.fflush(0)
parser.add_argument("--clean", None, argparse.BOOL, 0, None, False, parser.add_argument("--clean", None, argparse.BOOL, 0, None, False,
argparse.STORE_TRUE, "清理 output 和 temp 目录") argparse.STORE_TRUE, "清理 output 和 temp 目录")
stdio.printf("[DBG] after --clean\n")
stdio.fflush(0)
parser.add_argument("--run", None, argparse.BOOL, 0, None, False, parser.add_argument("--run", None, argparse.BOOL, 0, None, False,
argparse.STORE_TRUE, "编译成功后立即执行生成的可执行文件") argparse.STORE_TRUE, "编译成功后立即执行生成的可执行文件")
stdio.printf("[DBG] after --run\n")
stdio.fflush(0)
parser.add_argument("--rebuild-includes", None, argparse.BOOL, 0, None, False, parser.add_argument("--rebuild-includes", None, argparse.BOOL, 0, None, False,
argparse.STORE_TRUE, "删除 includes.binary 预编译缓存并重新编译所有 includes") argparse.STORE_TRUE, "删除 includes.binary 预编译缓存并重新编译所有 includes")
stdio.printf("[DBG] after --rebuild-includes\n")
stdio.fflush(0)
parser.add_argument("--clear-cache", None, argparse.BOOL, 0, None, False, parser.add_argument("--clear-cache", None, argparse.BOOL, 0, None, False,
argparse.STORE_TRUE, "清除 .transpyc_cache 全局缓存") argparse.STORE_TRUE, "清除 .transpyc_cache 全局缓存")
stdio.printf("[DBG] after --clear-cache\n")
stdio.fflush(0)
# 解析命令行参数 # 解析命令行参数
stdio.printf("[DBG] before parse_args\n")
stdio.fflush(0)
args: argparse.ParsedArgs | t.CPtr = parser.parse_args(sys._argc, sys._argv) args: argparse.ParsedArgs | t.CPtr = parser.parse_args(sys._argc, sys._argv)
stdio.printf("[DBG] after parse_args args=%p\n", args)
stdio.fflush(0)
if args is None: if args is None:
if log is not None: if log is not None:
log.error("参数解析失败", "argparse") log.error("参数解析失败", "argparse")
@@ -244,13 +187,10 @@ def main() -> int:
proj_loaded: int = 0 proj_loaded: int = 0
proj_path: str = project proj_path: str = project
if proj_path is not None: if proj_path is not None:
stdio.printf("[DBG] before Load_project_config path=%s\n", proj_path)
stdio.fflush(0)
if log is not None: if log is not None:
log.banner("工程配置") log.banner("工程配置")
if Config.Load_project_config(proj_path) == 0: cfg_ret: int = Config.Load_project_config(proj_path)
stdio.printf("[DBG] Load_project_config OK\n") if cfg_ret == 0:
stdio.fflush(0)
proj_loaded = 1 proj_loaded = 1
else: else:
if log is not None: if log is not None:
@@ -284,14 +224,8 @@ def main() -> int:
if proj_dir is not None: if proj_dir is not None:
string.memcpy(proj_dir, proj_path, slash_pos) string.memcpy(proj_dir, proj_path, slash_pos)
proj_dir[slash_pos] = '\0' proj_dir[slash_pos] = '\0'
stdio.printf("[DBG] before resolve_paths dir=%s\n", proj_dir)
stdio.fflush(0)
Config.resolve_paths(proj_dir) Config.resolve_paths(proj_dir)
stdio.printf("[DBG] resolve_paths OK\n")
stdio.fflush(0)
Config.print_config() Config.print_config()
stdio.printf("[DBG] print_config OK\n")
stdio.fflush(0)
# === --clean: 清理 temp 和 output 目录 === # === --clean: 清理 temp 和 output 目录 ===
if _gb_clean: if _gb_clean:
@@ -321,9 +255,10 @@ def main() -> int:
phase_mode = "all" phase_mode = "all"
do_phase1: int = 0 do_phase1: int = 0
do_phase2: int = 0 do_phase2: int = 0
if phase_mode == "1" or phase_mode == "all": # 注意: 使用 string.strcmp 而非 ==,避免编译器 == 语义 bug
if string.strcmp(phase_mode, "1") == 0 or string.strcmp(phase_mode, "all") == 0:
do_phase1 = 1 do_phase1 = 1
if phase_mode == "2" or phase_mode == "all": if string.strcmp(phase_mode, "2") == 0 or string.strcmp(phase_mode, "all") == 0:
do_phase2 = 1 do_phase2 = 1
if log is not None: if log is not None:
fb3: t.CChar | t.CPtr = VLogger.fmt_buf() fb3: t.CChar | t.CPtr = VLogger.fmt_buf()
@@ -337,11 +272,7 @@ def main() -> int:
ph1_temp: str = Config.TempDir ph1_temp: str = Config.TempDir
if ph1_temp is None: if ph1_temp is None:
ph1_temp = "." ph1_temp = "."
stdio.printf("[DBG] before Phase1.RunPhase1 inc=%s temp=%s\n", Config.IncludesDir, ph1_temp)
stdio.fflush(0)
Phase1.RunPhase1(mb, Config.IncludesDir, ph1_temp, log) Phase1.RunPhase1(mb, Config.IncludesDir, ph1_temp, log)
stdio.printf("[DBG] Phase1.RunPhase1 OK\n")
stdio.fflush(0)
# 如果仅 Phase1不执行 Phase2直接退出 # 如果仅 Phase1不执行 Phase2直接退出
if do_phase2 == 0: if do_phase2 == 0:
if log is not None: if log is not None:
@@ -363,14 +294,10 @@ def main() -> int:
mf_linker_out: str = Config.LinkerOutput if Config.LinkerOutput is not None else "app.exe" mf_linker_out: str = Config.LinkerOutput if Config.LinkerOutput is not None else "app.exe"
mf_includes_bin: str = Config.get_includes_binary_dir() mf_includes_bin: str = Config.get_includes_binary_dir()
stdio.printf("[DBG] before Phase2.RunMultiFileProject src=%s temp=%s out=%s\n", Config.SourceDir, mf_temp, mf_output)
stdio.fflush(0)
mf_ret: int = Phase2.RunMultiFileProject( mf_ret: int = Phase2.RunMultiFileProject(
mb, Config.SourceDir, mf_temp, mf_output, mb, Config.SourceDir, mf_temp, mf_output,
mf_cc, mf_cc_flags, mf_linker, mf_linker_flags, mf_linker_out, mf_cc, mf_cc_flags, mf_linker, mf_linker_flags, mf_linker_out,
mf_includes_bin, Config.IncludesDir, do_phase1, do_phase2, log, args) mf_includes_bin, Config.IncludesDir, do_phase1, do_phase2, log, args)
stdio.printf("[DBG] Phase2.RunMultiFileProject OK ret=%d\n", mf_ret)
stdio.fflush(0)
argparse.release(args) argparse.release(args)
if log is not None: if log is not None:
log.success("TransPyV 完成") log.success("TransPyV 完成")

View File

View File

View File

View File

View File

@@ -1,483 +0,0 @@
[DBG] main enter
├ INFO: TransPyV 启动
=== TransPyV 参数解析结果 ===
--project: TransPyV/Test/project.vpj
--src: (未指定)
--temp: (未指定)
--output: (未指定)
--phase: (未指定,默认 all)
--cc: (未指定)
--clean: True
--run: False
--rebuild-includes: False
--clear-cache: False
参数解析完成。
[DBG] before Load_project_config path=TransPyV/Test/project.vpj
=== 工程配置 ===
[DBG] Load_project_config OK
[DBG] before resolve_paths dir=TransPyV/Test
[DBG] resolve_paths OK
├ INFO[config]: project: AstTest v1.0.0
├ INFO[config]: source_dir: TransPyV/Test/App
├ INFO[config]: build_dir: TransPyV/Test/.tpv_build
├ INFO[config]: temp_dir: TransPyV/Test/.tpv_build/temp
├ INFO[config]: output_dir: TransPyV/Test/.tpv_build/output
├ INFO[config]: compiler: llc
├ INFO[config]: linker: clang++ -> app.exe
├ INFO[config]: includes: TransPyV/Test/../../includes
├ INFO[config]: sha1_slice_level: 1
[DBG] print_config OK
├ INFO[clean]: 清理临时目录...
├ INFO[clean]: TransPyV/Test/.tpv_build/temp: 删除 1 个文件
├ INFO[clean]: TransPyV/Test/.tpv_build/output: 删除 0 个文件
├ INFO[phase]: 模式: all (phase1=1 phase2=1)
[DBG] before Phase1.RunPhase1 inc=TransPyV/Test/../../includes temp=TransPyV/Test/.tpv_build/temp
=== Phase1: 扫描 includes按需翻译 ===
├ INFO[Phase1]: 拓扑排序: 25 个类, 15 个文件按依赖顺序处理
├ INFO[Phase1]: 完成: 翻译=0 跳过=78 失败=0
[DBG] Phase1.RunPhase1 OK
[DBG] before Phase2.RunMultiFileProject src=TransPyV/Test/App temp=TransPyV/Test/.tpv_build/temp out=TransPyV/Test/.tpv_build/output
[DBG] RunMultiFileProject enter src=TransPyV/Test/App
├ INFO[project]: 多文件项目编译: TransPyV/Test/App
├ INFO[project]: asm_test.py (sha1=80241c7d6f357bd1)
├ INFO[project]: attr_test.py (sha1=17c0dfbcebfa3a0e)
├ INFO[project]: augassign_test.py (sha1=0eccc2393466d940)
├ INFO[project]: circ_a.py (sha1=ac47a9dc68e6834c)
├ INFO[project]: circ_b.py (sha1=04d33c721a603632)
├ INFO[project]: circ_test.py (sha1=5314f09055045035)
├ INFO[project]: closure_test.py (sha1=9d8e1c9631c28b1b)
├ INFO[project]: deco_test.py (sha1=b7bbe6a1c1e75ad8)
├ INFO[project]: deref_min_test.py (sha1=6f5e876273093314)
├ INFO[project]: deref_test.py (sha1=eb252050d92f8fb9)
├ INFO[project]: eq_test.py (sha1=b8cbe044a10adcca)
├ INFO[project]: float_test.py (sha1=e74870eba3e6d774)
├ INFO[project]: flow_test.py (sha1=969c589035910845)
├ INFO[project]: for_test.py (sha1=1eb1c9fc7e85d9f8)
├ INFO[project]: func_test.py (sha1=3c2fbc9e35ad3bf2)
├ INFO[project]: func_vtable_test.py (sha1=a9df037d9178888f)
├ INFO[project]: inherit_test.py (sha1=97043f0d52da437f)
├ INFO[project]: llvmir_test.py (sha1=c39f3e540adb7b4e)
├ INFO[project]: namespace_defs.py (sha1=b7eeff93aa63e70f)
├ INFO[project]: namespace_test.py (sha1=ef45adce81bf5b2d)
├ INFO[project]: new_test.py (sha1=9d798d964b9d3411)
├ INFO[project]: oop_test.py (sha1=1b9ab264a942c56b)
├ INFO[project]: opovl_test.py (sha1=a7cf0ce4066332ae)
├ INFO[project]: ptr_only_test.py (sha1=ed1c124f3cb787c9)
├ INFO[project]: ptr_test.py (sha1=07f7da85af876124)
├ INFO[project]: simple_test.py (sha1=b078e9c9c74a2a0c)
├ INFO[project]: string_min_test.py (sha1=74ca31446cac2107)
├ INFO[project]: string_test.py (sha1=e0009679269c6b63)
├ INFO[project]: struct_test.py (sha1=33a854a5c4f67d74)
├ INFO[project]: testcheck_test.py (sha1=d7662500f1c2c0ff)
├ INFO[project]: test_main.py (sha1=ff744980c190e9b0)
├ INFO[project]: type_bit_test.py (sha1=55cbbb5dec4fef2c)
├ INFO[project]: virtual_dispatch_test.py (sha1=cc3ad7f3bc880326)
├ INFO[project]: vtable_test.py (sha1=2769dee537308b00)
[DBG] scan done file_count=34
├ INFO[project]: 共 34 个源文件
├ INFO[project]: 已追加 34 个 App 文件到 _sha1_map.txt
[DBG] before Phase A
=== Phase A: 生成 stub + text ===
├ INFO[PhaseA]: 预注册 struct/enum/union...
[DBG] PhaseA-pre pass=0 struct_count_before=24
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/asm_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/attr_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/augassign_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/circ_a.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/circ_b.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/circ_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/closure_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/deco_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/deref_min_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/deref_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/eq_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/float_test.py
├ INFO[UNION]: registered DataUnion with 3 fields, max_size=8
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/flow_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/for_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/func_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/func_vtable_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/inherit_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/llvmir_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/namespace_defs.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/namespace_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/new_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/oop_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/opovl_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/ptr_only_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/ptr_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/simple_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/string_min_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/string_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/struct_test.py
├ INFO[ENUM]: registered State with 3 members, base_bits=32
├ INFO[ENUM]: registered Color with 4 members, base_bits=32
├ INFO[ENUM]: registered MixedType with 3 members, base_bits=64
├ INFO[UNION]: registered DataUnion with 3 fields, max_size=8
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/testcheck_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/test_main.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/type_bit_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/virtual_dispatch_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/vtable_test.py
[DBG] PhaseA-pre pass=0 done struct_count_after=51
[DBG] PhaseA-pre pass=1 struct_count_before=51
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/asm_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/attr_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/augassign_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/circ_a.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/circ_b.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/circ_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/closure_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/deco_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/deref_min_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/deref_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/eq_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/float_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/flow_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/for_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/func_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/func_vtable_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/inherit_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/llvmir_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/namespace_defs.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/namespace_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/new_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/oop_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/opovl_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/ptr_only_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/ptr_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/simple_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/string_min_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/string_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/struct_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/testcheck_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/test_main.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/type_bit_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/virtual_dispatch_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/vtable_test.py
[DBG] PhaseA-pre pass=1 done struct_count_after=51
├ INFO[PhaseA]: 预注册完成
[DBG] PhaseA full-translate start
[DBG] PhaseA file=TransPyV/Test/App/asm_test.py
[DBG] PhaseA file=TransPyV/Test/App/attr_test.py
[DBG] PhaseA file=TransPyV/Test/App/augassign_test.py
[DBG] PhaseA file=TransPyV/Test/App/circ_a.py
[DBG] PhaseA file=TransPyV/Test/App/circ_b.py
[DBG] PhaseA file=TransPyV/Test/App/circ_test.py
[DBG] PhaseA file=TransPyV/Test/App/closure_test.py
[DBG] PhaseA file=TransPyV/Test/App/deco_test.py
[DBG] PhaseA file=TransPyV/Test/App/deref_min_test.py
[DBG] PhaseA file=TransPyV/Test/App/deref_test.py
[DBG] PhaseA file=TransPyV/Test/App/eq_test.py
[DBG] PhaseA file=TransPyV/Test/App/float_test.py
[DBG] PhaseA file=TransPyV/Test/App/flow_test.py
[DBG] PhaseA file=TransPyV/Test/App/for_test.py
[DBG] PhaseA file=TransPyV/Test/App/func_test.py
[DBG] PhaseA file=TransPyV/Test/App/func_vtable_test.py
[DBG] PhaseA file=TransPyV/Test/App/inherit_test.py
[DBG] PhaseA file=TransPyV/Test/App/llvmir_test.py
[DBG] PhaseA file=TransPyV/Test/App/namespace_defs.py
[DBG] PhaseA file=TransPyV/Test/App/namespace_test.py
[DBG] PhaseA file=TransPyV/Test/App/new_test.py
[DBG] PhaseA file=TransPyV/Test/App/oop_test.py
[DBG] PhaseA file=TransPyV/Test/App/opovl_test.py
[DBG] PhaseA file=TransPyV/Test/App/ptr_only_test.py
[DBG] PhaseA file=TransPyV/Test/App/ptr_test.py
[DBG] PhaseA file=TransPyV/Test/App/simple_test.py
[DBG] PhaseA file=TransPyV/Test/App/string_min_test.py
[DBG] PhaseA file=TransPyV/Test/App/string_test.py
[DBG] PhaseA file=TransPyV/Test/App/struct_test.py
[DBG] PhaseA file=TransPyV/Test/App/testcheck_test.py
[DBG] PhaseA file=TransPyV/Test/App/test_main.py
[DBG] PhaseA file=TransPyV/Test/App/type_bit_test.py
[DBG] PhaseA file=TransPyV/Test/App/virtual_dispatch_test.py
[DBG] PhaseA file=TransPyV/Test/App/vtable_test.py
[DBG] before Phase B
=== Phase B: 编译 .obj ===
[DBG] PhaseB file=TransPyV/Test/App/asm_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=80241c7d6f357bd1
[DBG] PhaseB step=BuildCombinedIR done len=51574
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/attr_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=17c0dfbcebfa3a0e
[DBG] PhaseB step=BuildCombinedIR done len=72070
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/augassign_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=0eccc2393466d940
[DBG] PhaseB step=BuildCombinedIR done len=53827
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/circ_a.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=ac47a9dc68e6834c
[DBG] PhaseB step=BuildCombinedIR done len=51031
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/circ_b.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=04d33c721a603632
[DBG] PhaseB step=BuildCombinedIR done len=51025
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/circ_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=5314f09055045035
[DBG] PhaseB step=BuildCombinedIR done len=56407
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/closure_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=9d8e1c9631c28b1b
[DBG] PhaseB step=BuildCombinedIR done len=52838
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/deco_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=b7bbe6a1c1e75ad8
[DBG] PhaseB step=BuildCombinedIR done len=68777
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/deref_min_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=6f5e876273093314
[DBG] PhaseB step=BuildCombinedIR done len=50111
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/deref_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=eb252050d92f8fb9
[DBG] PhaseB step=BuildCombinedIR done len=50661
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/eq_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=b8cbe044a10adcca
[DBG] PhaseB step=BuildCombinedIR done len=67044
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/float_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=e74870eba3e6d774
[DBG] PhaseB step=BuildCombinedIR done len=57074
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/flow_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=969c589035910845
[DBG] PhaseB step=BuildCombinedIR done len=51773
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/for_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=1eb1c9fc7e85d9f8
[DBG] PhaseB step=BuildCombinedIR done len=50124
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/func_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=3c2fbc9e35ad3bf2
[DBG] PhaseB step=BuildCombinedIR done len=54695
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/func_vtable_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=a9df037d9178888f
[DBG] PhaseB step=BuildCombinedIR done len=60040
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/inherit_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=97043f0d52da437f
[DBG] PhaseB step=BuildCombinedIR done len=63006
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/llvmir_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=c39f3e540adb7b4e
[DBG] PhaseB step=BuildCombinedIR done len=72025
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/namespace_defs.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=b7eeff93aa63e70f
[DBG] PhaseB step=BuildCombinedIR done len=52547
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/namespace_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=ef45adce81bf5b2d
[DBG] PhaseB step=BuildCombinedIR done len=63978
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/new_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=9d798d964b9d3411
[DBG] PhaseB step=BuildCombinedIR done len=59175
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/oop_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=1b9ab264a942c56b
[DBG] PhaseB step=BuildCombinedIR done len=62087
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/opovl_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=a7cf0ce4066332ae
[DBG] PhaseB step=BuildCombinedIR done len=82295
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/ptr_only_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=ed1c124f3cb787c9
[DBG] PhaseB step=BuildCombinedIR done len=52176
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/ptr_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=07f7da85af876124
[DBG] PhaseB step=BuildCombinedIR done len=59942
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/simple_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=b078e9c9c74a2a0c
[DBG] PhaseB step=BuildCombinedIR done len=49754
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/string_min_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=74ca31446cac2107
[DBG] PhaseB step=BuildCombinedIR done len=54019
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/string_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=e0009679269c6b63
[DBG] PhaseB step=BuildCombinedIR done len=65173
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/struct_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=33a854a5c4f67d74
[DBG] PhaseB step=BuildCombinedIR done len=71825
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/testcheck_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=d7662500f1c2c0ff
[DBG] PhaseB step=BuildCombinedIR done len=58573
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/test_main.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=ff744980c190e9b0
[DBG] PhaseB step=BuildCombinedIR done len=57150
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/type_bit_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=55cbbb5dec4fef2c
[DBG] PhaseB step=BuildCombinedIR done len=52348
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/virtual_dispatch_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=cc3ad7f3bc880326
[DBG] PhaseB step=BuildCombinedIR done len=59792
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB file=TransPyV/Test/App/vtable_test.py
[DBG] PhaseB step=alloc combined_ir
[DBG] PhaseB step=BuildCombinedIR sha1=2769dee537308b00
[DBG] PhaseB step=BuildCombinedIR done len=56517
[DBG] PhaseB step=compile_module_to_obj
[DBG] PhaseB step=compile_module_to_obj done cret=0
[DBG] PhaseB step=obj_path construct
[DBG] PhaseB step=obj_path done
[DBG] PhaseB loop done compiled_count=34
├ SUCCESS[PhaseB]: 编译完成: 34/34
[DBG] PhaseB+ start
[DBG] PhaseB+ store_count=93

View File

View File

@@ -1,241 +0,0 @@
[DBG] main enter
├ INFO: TransPyV 启动
=== TransPyV 参数解析结果 ===
--project: TransPyV/Test/project.vpj
--src: (未指定)
--temp: (未指定)
--output: (未指定)
--phase: (未指定,默认 all)
--cc: (未指定)
--clean: True
--run: False
--rebuild-includes: False
--clear-cache: False
参数解析完成。
[DBG] before Load_project_config path=TransPyV/Test/project.vpj
=== 工程配置 ===
[DBG] Load_project_config OK
[DBG] before resolve_paths dir=TransPyV/Test
[DBG] resolve_paths OK
├ INFO[config]: project: AstTest v1.0.0
├ INFO[config]: source_dir: TransPyV/Test/App
├ INFO[config]: build_dir: TransPyV/Test/.tpv_build
├ INFO[config]: temp_dir: TransPyV/Test/.tpv_build/temp
├ INFO[config]: output_dir: TransPyV/Test/.tpv_build/output
├ INFO[config]: compiler: llc
├ INFO[config]: linker: clang++ -> app.exe
├ INFO[config]: includes: TransPyV/Test/../../includes
├ INFO[config]: sha1_slice_level: 1
[DBG] print_config OK
├ INFO[clean]: 清理临时目录...
├ INFO[clean]: TransPyV/Test/.tpv_build/temp: 删除 1 个文件
├ INFO[clean]: TransPyV/Test/.tpv_build/output: 删除 0 个文件
├ INFO[phase]: 模式: all (phase1=1 phase2=1)
[DBG] before Phase1.RunPhase1 inc=TransPyV/Test/../../includes temp=TransPyV/Test/.tpv_build/temp
=== Phase1: 扫描 includes按需翻译 ===
├ INFO[Phase1]: 拓扑排序: 25 个类, 15 个文件按依赖顺序处理
├ INFO[Phase1]: 完成: 翻译=0 跳过=78 失败=0
[DBG] Phase1.RunPhase1 OK
[DBG] before Phase2.RunMultiFileProject src=TransPyV/Test/App temp=TransPyV/Test/.tpv_build/temp out=TransPyV/Test/.tpv_build/output
[DBG] RunMultiFileProject enter src=TransPyV/Test/App
├ INFO[project]: 多文件项目编译: TransPyV/Test/App
├ INFO[project]: asm_test.py (sha1=80241c7d6f357bd1)
├ INFO[project]: attr_test.py (sha1=17c0dfbcebfa3a0e)
├ INFO[project]: augassign_test.py (sha1=0eccc2393466d940)
├ INFO[project]: circ_a.py (sha1=ac47a9dc68e6834c)
├ INFO[project]: circ_b.py (sha1=04d33c721a603632)
├ INFO[project]: circ_test.py (sha1=5314f09055045035)
├ INFO[project]: closure_test.py (sha1=9d8e1c9631c28b1b)
├ INFO[project]: deco_test.py (sha1=b7bbe6a1c1e75ad8)
├ INFO[project]: deref_min_test.py (sha1=6f5e876273093314)
├ INFO[project]: deref_test.py (sha1=eb252050d92f8fb9)
├ INFO[project]: eq_test.py (sha1=b8cbe044a10adcca)
├ INFO[project]: float_test.py (sha1=e74870eba3e6d774)
├ INFO[project]: flow_test.py (sha1=969c589035910845)
├ INFO[project]: for_test.py (sha1=1eb1c9fc7e85d9f8)
├ INFO[project]: func_test.py (sha1=3c2fbc9e35ad3bf2)
├ INFO[project]: func_vtable_test.py (sha1=a9df037d9178888f)
├ INFO[project]: inherit_test.py (sha1=97043f0d52da437f)
├ INFO[project]: llvmir_test.py (sha1=c39f3e540adb7b4e)
├ INFO[project]: namespace_defs.py (sha1=b7eeff93aa63e70f)
├ INFO[project]: namespace_test.py (sha1=ef45adce81bf5b2d)
├ INFO[project]: new_test.py (sha1=9d798d964b9d3411)
├ INFO[project]: oop_test.py (sha1=1b9ab264a942c56b)
├ INFO[project]: opovl_test.py (sha1=a7cf0ce4066332ae)
├ INFO[project]: ptr_only_test.py (sha1=ed1c124f3cb787c9)
├ INFO[project]: ptr_test.py (sha1=07f7da85af876124)
├ INFO[project]: simple_test.py (sha1=b078e9c9c74a2a0c)
├ INFO[project]: string_min_test.py (sha1=74ca31446cac2107)
├ INFO[project]: string_test.py (sha1=e0009679269c6b63)
├ INFO[project]: struct_test.py (sha1=33a854a5c4f67d74)
├ INFO[project]: testcheck_test.py (sha1=d7662500f1c2c0ff)
├ INFO[project]: test_main.py (sha1=ff744980c190e9b0)
├ INFO[project]: type_bit_test.py (sha1=55cbbb5dec4fef2c)
├ INFO[project]: virtual_dispatch_test.py (sha1=cc3ad7f3bc880326)
├ INFO[project]: vtable_test.py (sha1=2769dee537308b00)
[DBG] scan done file_count=34
├ INFO[project]: 共 34 个源文件
├ INFO[project]: 已追加 34 个 App 文件到 _sha1_map.txt
[DBG] before Phase A
=== Phase A: 生成 stub + text ===
├ INFO[PhaseA]: 预注册 struct/enum/union...
[DBG] PhaseA-pre pass=0 struct_count_before=24
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/asm_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/attr_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/augassign_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/circ_a.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/circ_b.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/circ_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/closure_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/deco_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/deref_min_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/deref_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/eq_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/float_test.py
├ INFO[UNION]: registered DataUnion with 3 fields, max_size=8
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/flow_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/for_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/func_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/func_vtable_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/inherit_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/llvmir_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/namespace_defs.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/namespace_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/new_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/oop_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/opovl_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/ptr_only_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/ptr_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/simple_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/string_min_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/string_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/struct_test.py
├ INFO[ENUM]: registered State with 3 members, base_bits=32
├ INFO[ENUM]: registered Color with 4 members, base_bits=32
├ INFO[ENUM]: registered MixedType with 3 members, base_bits=64
├ INFO[UNION]: registered DataUnion with 3 fields, max_size=8
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/testcheck_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/test_main.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/type_bit_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/virtual_dispatch_test.py
[DBG] PhaseA-pre pass=0 file=TransPyV/Test/App/vtable_test.py
[DBG] PhaseA-pre pass=0 done struct_count_after=51
[DBG] PhaseA-pre pass=1 struct_count_before=51
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/asm_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/attr_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/augassign_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/circ_a.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/circ_b.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/circ_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/closure_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/deco_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/deref_min_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/deref_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/eq_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/float_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/flow_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/for_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/func_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/func_vtable_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/inherit_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/llvmir_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/namespace_defs.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/namespace_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/new_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/oop_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/opovl_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/ptr_only_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/ptr_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/simple_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/string_min_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/string_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/struct_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/testcheck_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/test_main.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/type_bit_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/virtual_dispatch_test.py
[DBG] PhaseA-pre pass=1 file=TransPyV/Test/App/vtable_test.py
[DBG] PhaseA-pre pass=1 done struct_count_after=51
├ INFO[PhaseA]: 预注册完成
[DBG] PhaseA full-translate start
[DBG] PhaseA file=TransPyV/Test/App/asm_test.py
[DBG] PhaseA file=TransPyV/Test/App/attr_test.py
[DBG] PhaseA file=TransPyV/Test/App/augassign_test.py
[DBG] PhaseA file=TransPyV/Test/App/circ_a.py
[DBG] PhaseA file=TransPyV/Test/App/circ_b.py
[DBG] PhaseA file=TransPyV/Test/App/circ_test.py
[DBG] PhaseA file=TransPyV/Test/App/closure_test.py
[DBG] PhaseA file=TransPyV/Test/App/deco_test.py
[DBG] PhaseA file=TransPyV/Test/App/deref_min_test.py
[DBG] PhaseA file=TransPyV/Test/App/deref_test.py
[DBG] PhaseA file=TransPyV/Test/App/eq_test.py
[DBG] PhaseA file=TransPyV/Test/App/float_test.py
[DBG] PhaseA file=TransPyV/Test/App/flow_test.py
[DBG] PhaseA file=TransPyV/Test/App/for_test.py
[DBG] PhaseA file=TransPyV/Test/App/func_test.py
[DBG] PhaseA file=TransPyV/Test/App/func_vtable_test.py
[DBG] PhaseA file=TransPyV/Test/App/inherit_test.py
[DBG] PhaseA file=TransPyV/Test/App/llvmir_test.py
[DBG] PhaseA file=TransPyV/Test/App/namespace_defs.py
[DBG] PhaseA file=TransPyV/Test/App/namespace_test.py
[DBG] PhaseA file=TransPyV/Test/App/new_test.py
[DBG] PhaseA file=TransPyV/Test/App/oop_test.py
[DBG] PhaseA file=TransPyV/Test/App/opovl_test.py
[DBG] PhaseA file=TransPyV/Test/App/ptr_only_test.py
[DBG] PhaseA file=TransPyV/Test/App/ptr_test.py
[DBG] PhaseA file=TransPyV/Test/App/simple_test.py
[DBG] PhaseA file=TransPyV/Test/App/string_min_test.py
[DBG] PhaseA file=TransPyV/Test/App/string_test.py
[DBG] PhaseA file=TransPyV/Test/App/struct_test.py
[DBG] PhaseA file=TransPyV/Test/App/testcheck_test.py
[DBG] PhaseA file=TransPyV/Test/App/test_main.py
[DBG] PhaseA file=TransPyV/Test/App/type_bit_test.py
[DBG] PhaseA file=TransPyV/Test/App/virtual_dispatch_test.py
[DBG] PhaseA file=TransPyV/Test/App/vtable_test.py
[DBG] before Phase B
=== Phase B: 编译 .obj ===
[DBG] PhaseB file=TransPyV/Test/App/asm_test.py
[DBG] PhaseB file=TransPyV/Test/App/attr_test.py
[DBG] PhaseB file=TransPyV/Test/App/augassign_test.py
[DBG] PhaseB file=TransPyV/Test/App/circ_a.py
[DBG] PhaseB file=TransPyV/Test/App/circ_b.py
[DBG] PhaseB file=TransPyV/Test/App/circ_test.py
[DBG] PhaseB file=TransPyV/Test/App/closure_test.py
[DBG] PhaseB file=TransPyV/Test/App/deco_test.py
[DBG] PhaseB file=TransPyV/Test/App/deref_min_test.py
[DBG] PhaseB file=TransPyV/Test/App/deref_test.py
[DBG] PhaseB file=TransPyV/Test/App/eq_test.py
[DBG] PhaseB file=TransPyV/Test/App/float_test.py
[DBG] PhaseB file=TransPyV/Test/App/flow_test.py
[DBG] PhaseB file=TransPyV/Test/App/for_test.py
[DBG] PhaseB file=TransPyV/Test/App/func_test.py
[DBG] PhaseB file=TransPyV/Test/App/func_vtable_test.py
[DBG] PhaseB file=TransPyV/Test/App/inherit_test.py
[DBG] PhaseB file=TransPyV/Test/App/llvmir_test.py
[DBG] PhaseB file=TransPyV/Test/App/namespace_defs.py
[DBG] PhaseB file=TransPyV/Test/App/namespace_test.py
[DBG] PhaseB file=TransPyV/Test/App/new_test.py
[DBG] PhaseB file=TransPyV/Test/App/oop_test.py
[DBG] PhaseB file=TransPyV/Test/App/opovl_test.py
[DBG] PhaseB file=TransPyV/Test/App/ptr_only_test.py
[DBG] PhaseB file=TransPyV/Test/App/ptr_test.py
[DBG] PhaseB file=TransPyV/Test/App/simple_test.py
[DBG] PhaseB file=TransPyV/Test/App/string_min_test.py
[DBG] PhaseB file=TransPyV/Test/App/string_test.py
[DBG] PhaseB file=TransPyV/Test/App/struct_test.py
[DBG] PhaseB file=TransPyV/Test/App/testcheck_test.py
[DBG] PhaseB file=TransPyV/Test/App/test_main.py
[DBG] PhaseB file=TransPyV/Test/App/type_bit_test.py
[DBG] PhaseB file=TransPyV/Test/App/virtual_dispatch_test.py
[DBG] PhaseB file=TransPyV/Test/App/vtable_test.py