Fixed some bugs and tried to maintain the bootstrap
This commit is contained in:
@@ -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")
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import w32.win32base
|
|||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
# 全局 mbuddy 指针
|
# 全局 mbuddy 指针
|
||||||
_mbuddy: memhub.MemManager | t.CPtr
|
_mbuddy: memhub.MemBuddy | t.CPtr
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|||||||
@@ -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 表示失败
|
||||||
|
|||||||
@@ -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 合并到 stdout(si.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
|
||||||
|
|||||||
@@ -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 - 递归检查注解中是否包含指定名称
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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,
|
|||||||
# 浮点常量默认创建为 double(64 位),赋值时由 coerce_to_type 自动 fptrunc
|
# 浮点常量默认创建为 double(64 位),赋值时由 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 可能是 i8(X|t.CPtr 简化为 Ptr(i8)),
|
# 原始 struct_ty 可能是 i8(X|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 可能是 i8,ensure 无效)
|
# (原始 struct_ty 可能是 i8,ensure 无效)
|
||||||
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)
|
||||||
|
|||||||
@@ -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(整数):既可安全截断为 i32(trunc),也可转换为指针(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_entry(find_struct_by_type 规避跨模块同名找错)
|
# 复用前面已获取的 mc_entry(find_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__ 字段(偏移 8,i64)
|
# 检测 obj.__len__() — 返回 list 对象的 __count__ 字段(偏移 8,i64)
|
||||||
# __len__ 是 list[T] 的内置方法,list 是泛型类不注册 struct
|
# __len__ 是 list[T] 的内置方法,list 是泛型类不注册 struct
|
||||||
|
# 注意: 必须用 translate_value 而非 translate_name_value,因为 len_at.value
|
||||||
|
# 可能是 Attribute 节点(如 md_ags.args),translate_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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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=2(import扫描模式)时跳过,只处理 import 依赖
|
# _declare_only=2(import扫描模式)时跳过,只处理 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 分派
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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 索引,跨模块持久化)
|
# 当前模块 SHA1(Phase1 在模块开始翻译前设置,供报错使用)
|
||||||
#
|
|
||||||
# 本地表在模块切换时被 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 跨模块 typedef(win32base.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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
105
App/main.py
105
App/main.py
@@ -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 完成")
|
||||||
|
|||||||
@@ -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
|
|
||||||
241
test_stdout.log
241
test_stdout.log
@@ -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
|
|
||||||
Reference in New Issue
Block a user