基本稳定可以编译 Test

This commit is contained in:
TermiNexus committed 2026-08-05 20:12:08 +08:00
1 parent a3b9bdc409
commit 8ad500c4da
12 files changed
+738 -119

No files matched your search

+1
View File
@@ -107,6 +107,7 @@ _g_pyi_cdefine_found: int = 0
def _lookup_cdefine_for_pyi(name: str) -> int: def _lookup_cdefine_for_pyi(name: str) -> int:
"""从本地 CDefine 表查找常量值(用于 .vpi 生成时的 BinOp 计算)""" """从本地 CDefine 表查找常量值(用于 .vpi 生成时的 BinOp 计算)"""
import lib.core.Handles.HandlesType as HandlesType import lib.core.Handles.HandlesType as HandlesType
global _g_pyi_cdefine_found
val: int = HandlesType.lookup_cdefine_constant(name) val: int = HandlesType.lookup_cdefine_constant(name)
if HandlesType.is_cdefine_found() != 0: if HandlesType.is_cdefine_found() != 0:
_g_pyi_cdefine_found = 1 _g_pyi_cdefine_found = 1
+1
View File
@@ -7,6 +7,7 @@ import stdio
import sys import sys
import memhub import memhub
import llvmlite import llvmlite
import viperlib
import w32.fileio as fileio import w32.fileio as fileio
import lib.core.VLogger as VLogger import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesType as HandlesType import lib.core.Handles.HandlesType as HandlesType
+298 -43
View File
@@ -5,6 +5,7 @@ import llvmlite
import memhub import memhub
import string import string
import stdio import stdio
import stdlib
import viperlib import viperlib
import lib.core.VLogger as VLogger import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesTranslator as HT import lib.core.Handles.HandlesTranslator as HT
@@ -1046,6 +1047,12 @@ def _translate_union_def(trans: HT.Translator | t.CPtr,
VLogger.error(fb, "UNION") VLogger.error(fb, "UNION")
return 0 return 0
# Phase 1b 新注册的 union struct_ty 深拷贝到 stdlib(跨文件 reset 存活)
if trans._declare_only == 0:
union_copy: llvmlite.LLVMType | t.CPtr = llvmlite.DeepCopyType(pool, union_ty)
if union_copy is not None:
union_ty = union_copy
# 注册命名结构体到模块 # 注册命名结构体到模块
llvmlite.module_add_named_type(trans.Module, pool, union_ty) llvmlite.module_add_named_type(trans.Module, pool, union_ty)
@@ -1332,6 +1339,13 @@ def _translate_renum_def(trans: HT.Translator | t.CPtr,
VLogger.error(fb4, "RENUM") VLogger.error(fb4, "RENUM")
return 0 return 0
# Phase 1b 新注册的 REnum struct_ty 深拷贝到 stdlib(跨文件 reset 存活,
# 与 entry.Ty 保持同一指针,find_struct_by_type 匹配不失效)
if trans._declare_only == 0:
renum_copy: llvmlite.LLVMType | t.CPtr = llvmlite.DeepCopyType(pool, renum_ty)
if renum_copy is not None:
renum_ty = renum_copy
# 注册命名结构体到模块 # 注册命名结构体到模块
llvmlite.module_add_named_type(trans.Module, pool, renum_ty) llvmlite.module_add_named_type(trans.Module, pool, renum_ty)
@@ -1450,11 +1464,14 @@ def _register_renum_variants(pool: memhub.MemBuddy | t.CPtr,
return return
# 懒初始化表(首次注册时分配) # 懒初始化表(首次注册时分配)
# 注意: 必须用 stdlib 分配——这些表在 1b 阶段(mark1 之后)首次分配,
# 若用 pool 会被 reset_to(mark1) 回收导致悬空(LLVMType 的 match 在
# parser.vp 等后续文件翻译时访问已回收的表 → 崩溃)。
if _renum_class_names is None: if _renum_class_names is None:
_renum_class_names = pool.alloc(8 * RENUM_CLASS_MAX) _renum_class_names = stdlib.malloc(8 * RENUM_CLASS_MAX)
_renum_class_variant_counts = pool.alloc(8 * RENUM_CLASS_MAX) _renum_class_variant_counts = stdlib.malloc(8 * RENUM_CLASS_MAX)
_renum_variant_names = pool.alloc(8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS) _renum_variant_names = stdlib.malloc(8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS)
_renum_variant_tags = pool.alloc(8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS) _renum_variant_tags = stdlib.malloc(8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS)
if (_renum_class_names is None or _renum_class_variant_counts is None if (_renum_class_names is None or _renum_class_variant_counts is None
or _renum_variant_names is None or _renum_variant_tags is None): or _renum_variant_names is None or _renum_variant_tags is None):
_renum_class_names = None _renum_class_names = None
@@ -1994,35 +2011,60 @@ def _clone_classdef_for_spec(pool: memhub.MemBuddy | t.CPtr,
# ============================================================ # ============================================================
# 泛型特化缓存(模块级) # 泛型特化缓存(模块级)
#
# 用扁平 stdlib 数组 + stdlib 深拷贝字符串,保证缓存条目
# 跨文件永久存活(1b 每文件 reset_to(mark1) 不会回收)。
# ============================================================ # ============================================================
_spec_keys: list[str] | t.CPtr = None SPEC_CACHE_MAX: t.CDefine = 512
_spec_names: list[str] | t.CPtr = None _spec_keys: t.CSizeT | t.CPtr = None
_spec_names: t.CSizeT | t.CPtr = None
_spec_count: int = 0
def _find_cached_spec(spec_key: str) -> str: def _find_cached_spec(spec_key: str) -> str:
"""查找已缓存的特化名,未找到返回 None""" """查找已缓存的特化名,未找到返回 None"""
if _spec_keys is None or spec_key is None: if _spec_keys is None or spec_key is None:
return None return None
n: t.CSizeT = _spec_keys.__len__() i: int
i: t.CSizeT for i in range(_spec_count):
for i in range(n): key_addr: t.CSizeT = _spec_keys[i]
k: str = _spec_keys.get(i) if key_addr != 0:
if k is not None and string.strcmp(k, spec_key) == 0: k: str = (str | t.CPtr)(t.CVoid(key_addr, t.CPtr))
# 用局部变量接收 list.get() 结果,触发旧编译器 inttoptr 类型转换 if k is not None and string.strcmp(k, spec_key) == 0:
spec_nm: str = _spec_names.get(i) name_addr: t.CSizeT = _spec_names[i]
return spec_nm if name_addr != 0:
return (str | t.CPtr)(t.CVoid(name_addr, t.CPtr))
return None return None
def _cache_spec(pool: memhub.MemBuddy | t.CPtr, spec_key: str, spec_name: str): def _cache_spec(pool: memhub.MemBuddy | t.CPtr, spec_key: str, spec_name: str):
"""缓存特化结果""" """缓存特化结果(stdlib 深拷贝存储,跨文件安全)"""
global _spec_keys, _spec_names global _spec_keys, _spec_names, _spec_count
if spec_key is None or spec_name is None:
return
if _spec_keys is None: if _spec_keys is None:
_spec_keys = list[str](pool, 8) _spec_keys = stdlib.malloc(SPEC_CACHE_MAX * 8)
_spec_names = list[str](pool, 8) _spec_names = stdlib.malloc(SPEC_CACHE_MAX * 8)
_spec_keys.append(spec_key) if _spec_keys is None or _spec_names is None:
_spec_names.append(spec_name) return
string.memset(_spec_keys, 0, SPEC_CACHE_MAX * 8)
string.memset(_spec_names, 0, SPEC_CACHE_MAX * 8)
_spec_count = 0
if _spec_count >= SPEC_CACHE_MAX:
return
# 深拷贝字符串到 stdlib 区
key_len: t.CSizeT = string.strlen(spec_key)
name_len: t.CSizeT = string.strlen(spec_name)
key_copy: t.CChar | t.CPtr = stdlib.malloc(key_len + 1)
name_copy: t.CChar | t.CPtr = stdlib.malloc(name_len + 1)
if key_copy is None or name_copy is None:
return
string.strcpy(key_copy, spec_key)
string.strcpy(name_copy, spec_name)
_spec_keys[_spec_count] = t.CSizeT(key_copy)
_spec_names[_spec_count] = t.CSizeT(name_copy)
_spec_count += 1
def _specialize_generic_class(trans: HT.Translator | t.CPtr, def _specialize_generic_class(trans: HT.Translator | t.CPtr,
@@ -2082,6 +2124,10 @@ def _specialize_generic_class(trans: HT.Translator | t.CPtr,
if trans._declare_only == 0: if trans._declare_only == 0:
pre_existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name) pre_existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name)
if pre_existing is not None and pre_existing.MethodsEmitted == 0: if pre_existing is not None and pre_existing.MethodsEmitted == 0:
# 防重入:先标记 MethodsEmitted=1,避免补译过程中方法体/返回类型注解
# 再次触发 _specialize_generic_class(如 __iter__ 返回 list[T]|t.CPtr)
# 导致无限递归补译 → OOM。补译完成后已设置,无需恢复。
pre_existing.MethodsEmitted = 1
tp_names_pre: list[str] | t.CPtr = template_cd.type_params tp_names_pre: list[str] | t.CPtr = template_cd.type_params
spec_cd_pre: ast.ClassDef | t.CPtr = _clone_classdef_for_spec( spec_cd_pre: ast.ClassDef | t.CPtr = _clone_classdef_for_spec(
pool, template_cd, spec_name, tp_names_pre, type_args) pool, template_cd, spec_name, tp_names_pre, type_args)
@@ -2215,6 +2261,9 @@ def translate_class_def(trans: HT.Translator | t.CPtr,
if cd is None or cd.name is None: if cd is None or cd.name is None:
return 0 return 0
stdio.printf("[VTDBG-STEP] class=%s translate_class_def enter (declare_only=%d)\n",
cd.name, (trans._declare_only if trans is not None else -1))
pool: memhub.MemBuddy | t.CPtr = trans.Pool pool: memhub.MemBuddy | t.CPtr = trans.Pool
class_name: str = cd.name class_name: str = cd.name
@@ -2244,6 +2293,9 @@ def translate_class_def(trans: HT.Translator | t.CPtr,
# 检查是否已注册(用 SHA1 区分跨模块同名类) # 检查是否已注册(用 SHA1 区分跨模块同名类)
existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
class_name, trans.ModuleSha1) class_name, trans.ModuleSha1)
stdio.printf("[VTDBG-STEP] class=%s find_struct_by_module returned\n", class_name)
stdio.printf("[VTDBG-STEP] class=%s existing_check done, entry=%p\n",
class_name, existing)
if existing is not None: if existing is not None:
# BUG 5 方案1修改点2:existing 时字段完整性检查 # BUG 5 方案1修改点2:existing 时字段完整性检查
# 结构体已注册,但需验证字段信息是否完整(防止 i32 回退残留或注册不完整) # 结构体已注册,但需验证字段信息是否完整(防止 i32 回退残留或注册不完整)
@@ -2255,6 +2307,22 @@ def translate_class_def(trans: HT.Translator | t.CPtr,
"InternalCompilerError") "InternalCompilerError")
# 结构体已注册(Phase A-pre 多遍扫描或 Phase B 重新翻译),但仍需在当前模块中翻译方法 # 结构体已注册(Phase A-pre 多遍扫描或 Phase B 重新翻译),但仍需在当前模块中翻译方法
if existing.Ty is not None: if existing.Ty is not None:
# Phase 1b(declare_only=0):existing.Ty 是 Phase 1a 注册的 struct_ty,
# 其 Name(如 "sha1.ClassName")指向 Phase 1a 的 pool 内存。虽然 mark1
# 之前分配不被 reset 回收,但 struct_ty 会被后续文件翻译引用(vtable/
# self 参数类型打印),部分实现下 pool 块被复用导致 Name 悬空崩溃。
# 保险起见:深拷贝 Name 到 stdlib,确保跨文件永久存活。
if trans._declare_only == 0:
old_name: t.CChar | t.CPtr = llvmlite.get_struct_name(existing.Ty)
if old_name is not None:
on_len: t.CSizeT = string.strlen(old_name)
on_copy: t.CChar | t.CPtr = stdlib.malloc(on_len + 1)
if on_copy is not None:
string.strcpy(on_copy, old_name)
c.DerefAs(existing.Ty, llvmlite.LLVMType.Struct(
llvmlite.get_struct_fields(existing.Ty),
llvmlite.get_struct_fcount(existing.Ty),
on_copy))
# Phase B: 将已存在的命名结构体注册到当前模块(输出类型定义行) # Phase B: 将已存在的命名结构体注册到当前模块(输出类型定义行)
llvmlite.module_add_named_type(trans.Module, pool, existing.Ty) llvmlite.module_add_named_type(trans.Module, pool, existing.Ty)
# Phase A-pre(declare_only=1)多遍扫描时,类已注册但不应翻译方法体 # Phase A-pre(declare_only=1)多遍扫描时,类已注册但不应翻译方法体
@@ -2272,11 +2340,14 @@ def translate_class_def(trans: HT.Translator | t.CPtr,
# 否则 find_struct_by_module("GSListNode[Value]") 返回 None # 否则 find_struct_by_module("GSListNode[Value]") 返回 None
# ============================================================ # ============================================================
_trigger_base_specialization(trans, cd) _trigger_base_specialization(trans, cd)
stdio.printf("[VTDBG-STEP] class=%s trigger_base_spec done\n", class_name)
# ============================================================ # ============================================================
# VTable 检测:判断是否启用虚表 # VTable 检测:判断是否启用虚表
# ============================================================ # ============================================================
has_vtable: int = _detect_vtable_status(cd, trans) has_vtable: int = _detect_vtable_status(cd, trans)
stdio.printf("[VTDBG-STEP] class=%s vtable_status done, has_vtable=%d\n",
class_name, has_vtable)
parent_name: str = _get_parent_class(cd, trans) parent_name: str = _get_parent_class(cd, trans)
is_novtable_deco: int = 0 is_novtable_deco: int = 0
if cd.decorator_list is not None: if cd.decorator_list is not None:
@@ -2302,7 +2373,11 @@ def translate_class_def(trans: HT.Translator | t.CPtr,
if parent_check is None: if parent_check is None:
parent_check = HandlesStruct.find_struct(parent_name) parent_check = HandlesStruct.find_struct(parent_name)
if parent_check is None: if parent_check is None:
stdio.printf("[VTDBG-STEP] class=%s parent %s not registered, defer\n",
class_name, parent_name)
return 0 return 0
stdio.printf("[VTDBG-STEP] class=%s parent_check done, parent=%s\n",
class_name, parent_name)
# ============================================================ # ============================================================
# 1. 遍历 class body,收集字段信息 # 1. 遍历 class body,收集字段信息
@@ -2325,6 +2400,7 @@ def translate_class_def(trans: HT.Translator | t.CPtr,
# ============================================================ # ============================================================
# 1.5 继承父类字段(字段展平) # 1.5 继承父类字段(字段展平)
# ============================================================
# #
# 父类字段排在子类字段之前,结构体布局: # 父类字段排在子类字段之前,结构体布局:
# [vtable_ptr?, parent_field1, ..., child_field1, ...] # [vtable_ptr?, parent_field1, ..., child_field1, ...]
@@ -2514,12 +2590,21 @@ def translate_class_def(trans: HT.Translator | t.CPtr,
prev_node = pnode prev_node = pnode
# 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName" # 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName"
# 注意: Phase 1b(declare_only=0)时 struct_ty 会注册到全局表并被后续
# 文件翻译引用(vtable/self 参数类型打印),其 Name 必须跨 1b 每文件
# reset_to(mark1) 存活 → 用 stdlib 深拷贝;Phase 1a 仍用 pool(无需跨文件)。
type_name: str = class_name type_name: str = class_name
if trans.ModuleSha1 is not None: if trans.ModuleSha1 is not None:
name_buf: t.CChar | t.CPtr = pool.alloc(64) name_buf: t.CChar | t.CPtr = pool.alloc(64)
if name_buf is not None: if name_buf is not None:
viperlib.snprintf(name_buf, 64, "%s.%s", trans.ModuleSha1, class_name) viperlib.snprintf(name_buf, 64, "%s.%s", trans.ModuleSha1, class_name)
type_name = name_buf type_name = name_buf
if trans._declare_only == 0 and type_name is not None:
tn_len: t.CSizeT = string.strlen(type_name)
tn_copy: t.CChar | t.CPtr = stdlib.malloc(tn_len + 1)
if tn_copy is not None:
string.strcpy(tn_copy, type_name)
type_name = tn_copy
# 创建 StructType(命名结构体) # 创建 StructType(命名结构体)
struct_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, first_node, total_field_count, type_name) struct_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, first_node, total_field_count, type_name)
@@ -2530,6 +2615,17 @@ def translate_class_def(trans: HT.Translator | t.CPtr,
VLogger.error(fb_st, "CLASS") VLogger.error(fb_st, "CLASS")
return 0 return 0
# Phase 1b(declare_only=0)新注册的 struct_ty 会被注册到全局表并被后续文件
# 翻译引用(vtable/self 参数类型打印/find_struct_by_type 指针匹配)。LLVMType
# 对象和 Fields 链是 pool 分配的,本文件 reset_to(mark1) 后悬空。深拷贝整棵树
# 到 stdlib,并替换 struct_ty 指针,保证 entry.Ty 与调用方持有的 struct_ty
# 指向同一个 stdlib 拷贝(指针匹配不失效)且跨文件永久存活。
if trans._declare_only == 0:
st_copy: llvmlite.LLVMType | t.CPtr = llvmlite.DeepCopyType(pool, struct_ty)
if st_copy is not None:
struct_ty = st_copy
type_name = llvmlite.get_struct_name(struct_ty)
# 注册命名结构体到模块(输出 %"name" = type { ... } 定义行) # 注册命名结构体到模块(输出 %"name" = type { ... } 定义行)
llvmlite.module_add_named_type(trans.Module, pool, struct_ty) llvmlite.module_add_named_type(trans.Module, pool, struct_ty)
@@ -2661,6 +2757,8 @@ def _format_func_type_str(pool: memhub.MemBuddy | t.CPtr,
return 0 return 0
buf[0] = '\0' buf[0] = '\0'
stdio.printf("[VTDBG-FMT] enter func=%p\n", func)
stdio.fflush(None)
# 打印返回类型(使用访问器函数避免跨模块直接字段访问) # 打印返回类型(使用访问器函数避免跨模块直接字段访问)
ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(func) ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(func)
ret_buf: t.CChar | t.CPtr = pool.alloc(128) ret_buf: t.CChar | t.CPtr = pool.alloc(128)
@@ -2669,23 +2767,42 @@ def _format_func_type_str(pool: memhub.MemBuddy | t.CPtr,
llvmlite.TypePrint(ret_buf, 128, ret_ty, pool) llvmlite.TypePrint(ret_buf, 128, ret_ty, pool)
_vtable_strcat(buf, buf_size, ret_buf) _vtable_strcat(buf, buf_size, ret_buf)
_vtable_strcat(buf, buf_size, " (") _vtable_strcat(buf, buf_size, " (")
stdio.printf("[VTDBG-FMT] ret done\n")
stdio.fflush(None)
# 遍历参数(使用访问器函数避免跨模块直接字段访问) # 遍历参数(使用访问器函数避免跨模块直接字段访问)
cur: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(func) cur: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(func)
first: int = 1 first: int = 1
param_buf: t.CChar | t.CPtr = pool.alloc(128) param_buf: t.CChar | t.CPtr = pool.alloc(128)
_pc: int = 0
while cur is not None: while cur is not None:
_pc += 1
stdio.printf("[VTDBG-FMT] p%d=%p\n", _pc, cur)
stdio.fflush(None)
if _pc > 100:
stdio.printf("[VTDBG-FUNC-LOOP] func=%p param_chain>100 stop\n", func)
break
if first == 0: if first == 0:
_vtable_strcat(buf, buf_size, ", ") _vtable_strcat(buf, buf_size, ", ")
if param_buf is not None: if param_buf is not None:
param_buf[0] = '\0' param_buf[0] = '\0'
stdio.printf("[VTDBG-FMT] p%d get_ty...\n", _pc)
stdio.fflush(None)
param_ty: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(cur) param_ty: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(cur)
stdio.printf("[VTDBG-FMT] p%d ty=%p\n", _pc, param_ty)
stdio.fflush(None)
if param_ty is not None: if param_ty is not None:
llvmlite.TypePrint(param_buf, 128, param_ty, pool) llvmlite.TypePrint(param_buf, 128, param_ty, pool)
stdio.printf("[VTDBG-FMT] p%d str=%s\n", _pc, param_buf)
stdio.fflush(None)
_vtable_strcat(buf, buf_size, param_buf) _vtable_strcat(buf, buf_size, param_buf)
stdio.printf("[VTDBG-FMT] p%d next...\n", _pc)
stdio.fflush(None)
cur = llvmlite.param_get_next(cur) cur = llvmlite.param_get_next(cur)
first = 0 first = 0
_vtable_strcat(buf, buf_size, ")") _vtable_strcat(buf, buf_size, ")")
stdio.printf("[VTDBG-FMT] done\n")
stdio.fflush(None)
return 1 return 1
@@ -2710,16 +2827,20 @@ def _generate_vtable(trans: HT.Translator | t.CPtr,
pool: memhub.MemBuddy | t.CPtr = trans.Pool pool: memhub.MemBuddy | t.CPtr = trans.Pool
mod: llvmlite.LLVMModule | t.CPtr = trans.Module mod: llvmlite.LLVMModule | t.CPtr = trans.Module
stdio.printf("[VTDBG-ENTER] class=%s\n", class_name)
children: list[ast.AST | t.CPtr] | t.CPtr = cd.children children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
if children is None: if children is None:
return 0 return 0
cn: t.CSizeT = children.__len__() cn: t.CSizeT = children.__len__()
# 1. 收集虚方法信息 # 1. 收集虚方法信息
full_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * VTBL_METHOD_MAX) # stdlib 分配:method_names_buf 存到 StructEntry.VTableMethods(跨文件永久存活),
method_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * VTBL_METHOD_MAX) # 必须迁出 mb 池 reset 区间,否则 1b 每文件 reset_to(mark1) 会回收导致悬空。
full_names_buf: t.CSizeT | t.CPtr = stdlib.malloc(8 * VTBL_METHOD_MAX)
method_names_buf: t.CSizeT | t.CPtr = stdlib.malloc(8 * VTBL_METHOD_MAX)
# 记录每个方法的父类 SHA1(非 0=继承方法用父模块 SHA1 mangling,0=当前类方法) # 记录每个方法的父类 SHA1(非 0=继承方法用父模块 SHA1 mangling,0=当前类方法)
method_parent_sha1s: t.CSizeT | t.CPtr = pool.alloc(8 * VTBL_METHOD_MAX) method_parent_sha1s: t.CSizeT | t.CPtr = stdlib.malloc(8 * VTBL_METHOD_MAX)
if full_names_buf is None or method_names_buf is None or method_parent_sha1s is None: if full_names_buf is None or method_names_buf is None or method_parent_sha1s is None:
return 0 return 0
string.memset(full_names_buf, 0, 8 * VTBL_METHOD_MAX) string.memset(full_names_buf, 0, 8 * VTBL_METHOD_MAX)
@@ -2750,6 +2871,10 @@ def _generate_vtable(trans: HT.Translator | t.CPtr,
parent_vt_count: int = 0 parent_vt_count: int = 0
if vt_parent_entry is not None: if vt_parent_entry is not None:
parent_vt_count = vt_parent_entry.VTableMethodCount parent_vt_count = vt_parent_entry.VTableMethodCount
stdio.printf("[VTDBG-PARENT] class=%s parent=%s parent_entry=%p vt_count=%d\n",
class_name, parent_name, vt_parent_entry, parent_vt_count)
stdio.printf("[VTDBG-STEP] class=%s collect-parent done, method_count=%d\n",
class_name, method_count)
if parent_vt_count > 0: if parent_vt_count > 0:
for pvi in range(parent_vt_count): for pvi in range(parent_vt_count):
if method_count >= VTBL_METHOD_MAX: if method_count >= VTBL_METHOD_MAX:
@@ -2789,7 +2914,7 @@ def _generate_vtable(trans: HT.Translator | t.CPtr,
full_names_buf[method_count] = t.CSizeT(pfname_buf) full_names_buf[method_count] = t.CSizeT(pfname_buf)
# 复制方法名(短名) # 复制方法名(短名)
pmname_len: t.CSizeT = string.strlen(pmethod_name) pmname_len: t.CSizeT = string.strlen(pmethod_name)
pmname_buf: t.CChar | t.CPtr = pool.alloc(pmname_len + 1) pmname_buf: t.CChar | t.CPtr = stdlib.malloc(pmname_len + 1)
if pmname_buf is not None: if pmname_buf is not None:
string.strcpy(pmname_buf, pmethod_name) string.strcpy(pmname_buf, pmethod_name)
method_names_buf[method_count] = t.CSizeT(pmname_buf) method_names_buf[method_count] = t.CSizeT(pmname_buf)
@@ -2846,7 +2971,7 @@ def _generate_vtable(trans: HT.Translator | t.CPtr,
# 复制方法名 # 复制方法名
mname_len: t.CSizeT = string.strlen(mname) mname_len: t.CSizeT = string.strlen(mname)
mname_buf: t.CChar | t.CPtr = pool.alloc(mname_len + 1) mname_buf: t.CChar | t.CPtr = stdlib.malloc(mname_len + 1)
if mname_buf is not None: if mname_buf is not None:
string.strcpy(mname_buf, mname) string.strcpy(mname_buf, mname)
method_names_buf[method_count] = t.CSizeT(mname_buf) method_names_buf[method_count] = t.CSizeT(mname_buf)
@@ -2854,9 +2979,12 @@ def _generate_vtable(trans: HT.Translator | t.CPtr,
method_count += 1 method_count += 1
if method_count == 0: if method_count == 0:
stdio.printf("[VTDBG-STEP] class=%s collect done, method_count=0 -> return\n", class_name)
return 0 return 0
# 2. 构造 VTable 类型: { i8*, i8*, ..., i8* } # 2. 构造 VTable 类型: { i8*, i8*, ..., i8* }
stdio.printf("[VTDBG-STEP] class=%s collect done, method_count=%d -> build vtable\n",
class_name, method_count)
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)
@@ -2875,19 +3003,23 @@ def _generate_vtable(trans: HT.Translator | t.CPtr,
return 0 return 0
# 3. 构造初始化字符串 # 3. 构造初始化字符串
init_buf: t.CChar | t.CPtr = pool.alloc(4096) # 大 vtable(如 MemBuddy 28+ 方法)每个方法 bitcast 约 100+ 字节,
# 4096 可能写满导致截断/strlen 越界,用 16384 预留足够空间。
init_buf: t.CChar | t.CPtr = pool.alloc(16384)
if init_buf is None: if init_buf is None:
return 0 return 0
init_buf[0] = '\0' init_buf[0] = '\0'
_vtable_strcat(init_buf, 4096, "{ ") stdio.printf("[VTDBG-STEP] class=%s build vtable-ty done, method_count=%d -> init str\n",
class_name, method_count)
_vtable_strcat(init_buf, 16384, "{ ")
for i in range(method_count): for i in range(method_count):
if i > 0: if i > 0:
_vtable_strcat(init_buf, 4096, ", ") _vtable_strcat(init_buf, 16384, ", ")
full_name_addr: t.CSizeT = full_names_buf[i] full_name_addr: t.CSizeT = full_names_buf[i]
if full_name_addr == 0: if full_name_addr == 0:
_vtable_strcat(init_buf, 4096, "i8* null") _vtable_strcat(init_buf, 16384, "i8* null")
continue continue
full_name: str = (str | t.CPtr)(t.CVoid(full_name_addr, t.CPtr)) full_name: str = (str | t.CPtr)(t.CVoid(full_name_addr, t.CPtr))
@@ -2909,31 +3041,71 @@ def _generate_vtable(trans: HT.Translator | t.CPtr,
if func is None: if func is None:
func = HandlesExprCall.find_func_global(full_name) func = HandlesExprCall.find_func_global(full_name)
if func is None: # func 可能已被 1b reset_to(mark1) 回收(跨模块继承方法在定义文件翻译后被 reset)。
_vtable_strcat(init_buf, 4096, "i8* null") # 悬空指针非 NULL 但内容已被复用,_format_func_type_str 解引用会沿垃圾 Next 链
# 指针追逐导致无限分配(TypePrint 每次 pool.alloc(512) → 单文件暴涨 900MB OOM)。
# 因此 func 非 NULL 时也须用 _is_valid_ptr 校验,失败回退到 TypeStr。
func_valid: int = 0
if func is not None:
if trans.Pool is not None:
# 继承方法(parent_sha1_addr != 0):func 来自其他模块,该模块 1b 翻译
# 后已被 reset_to(mark1) 回收,_is_valid_ptr 存在假阳性(块头复用后仍
# 看似有效),直接判定无效走 TypeStr 回退,避免解引用悬空 func 崩溃。
if parent_sha1_addr != 0:
func_valid = 0
elif trans.Pool._is_valid_ptr(func) != 0:
func_valid = 1
if func_valid == 0:
# 回退到全局表完整 entry 的 TypeStr(stdlib 深拷贝,跨文件永久存活)。
ge: HandlesExprCall.FuncEntry | t.CPtr = HandlesExprCall.find_func_entry_global(full_name)
stdio.printf("[VTDBG] vtable '%s' method '%s' func=%p valid=0 fallback_ge=%p\n",
class_name, full_name, func, ge)
if ge is not None and ge.TypeStr is not None:
_vtable_strcat(init_buf, 16384, "i8* bitcast (")
_vtable_strcat(init_buf, 16384, ge.TypeStr)
_vtable_strcat(init_buf, 16384, "* @")
if _vtable_name_needs_quote(mangled_name) != 0:
_vtable_strcat(init_buf, 16384, "\"")
_vtable_strcat(init_buf, 16384, mangled_name)
_vtable_strcat(init_buf, 16384, "\"")
else:
_vtable_strcat(init_buf, 16384, mangled_name)
_vtable_strcat(init_buf, 16384, " to i8*)")
continue
_vtable_strcat(init_buf, 16384, "i8* null")
continue continue
# 构造函数类型字符串 # 构造函数类型字符串
func_ty_buf: t.CChar | t.CPtr = pool.alloc(512) func_ty_buf: t.CChar | t.CPtr = pool.alloc(512)
if func_ty_buf is None: if func_ty_buf is None:
_vtable_strcat(init_buf, 4096, "i8* null") _vtable_strcat(init_buf, 16384, "i8* null")
continue continue
stdio.printf("[VTDBG-STEP] class=%s method[%d] %s valid func=%p -> format_func_type\n",
class_name, i, full_name, func)
_format_func_type_str(pool, func_ty_buf, 512, func) _format_func_type_str(pool, func_ty_buf, 512, func)
# 构造 bitcast 字符串: i8* bitcast (func_ty* @mangled to i8*) # 构造 bitcast 字符串: i8* bitcast (func_ty* @mangled to i8*)
_vtable_strcat(init_buf, 4096, "i8* bitcast (") stdio.printf("[VTDBG-STEP] class=%s method[%d] bitcast start, ftb=%p mn=%p\n",
_vtable_strcat(init_buf, 4096, func_ty_buf) class_name, i, func_ty_buf, mangled_name)
_vtable_strcat(init_buf, 4096, "* @") stdio.fflush(None)
_vtable_strcat(init_buf, 16384, "i8* bitcast (")
_vtable_strcat(init_buf, 16384, func_ty_buf)
_vtable_strcat(init_buf, 16384, "* @")
if _vtable_name_needs_quote(mangled_name) != 0: if _vtable_name_needs_quote(mangled_name) != 0:
_vtable_strcat(init_buf, 4096, "\"") _vtable_strcat(init_buf, 16384, "\"")
_vtable_strcat(init_buf, 4096, mangled_name) _vtable_strcat(init_buf, 16384, mangled_name)
_vtable_strcat(init_buf, 4096, "\"") _vtable_strcat(init_buf, 16384, "\"")
else: else:
_vtable_strcat(init_buf, 4096, mangled_name) _vtable_strcat(init_buf, 16384, mangled_name)
_vtable_strcat(init_buf, 4096, " to i8*)") _vtable_strcat(init_buf, 16384, " to i8*)")
stdio.printf("[VTDBG-STEP] class=%s method[%d] bitcast done\n", class_name, i)
stdio.fflush(None)
_vtable_strcat(init_buf, 4096, " }") _vtable_strcat(init_buf, 16384, " }")
stdio.printf("[VTDBG-STEP] class=%s vtable init str done, len=%d\n",
class_name, string.strlen(init_buf))
stdio.fflush(None)
# 4. 构造 VTable 全局变量名 # 4. 构造 VTable 全局变量名
vtable_name_buf: t.CChar | t.CPtr = pool.alloc(128) vtable_name_buf: t.CChar | t.CPtr = pool.alloc(128)
@@ -2941,10 +3113,16 @@ def _generate_vtable(trans: HT.Translator | t.CPtr,
return 0 return 0
viperlib.snprintf(vtable_name_buf, 128, "%s.vtable", class_name) viperlib.snprintf(vtable_name_buf, 128, "%s.vtable", class_name)
vtable_mangled: str = HandlesFunctions._mangle_name(trans, vtable_name_buf) vtable_mangled: str = HandlesFunctions._mangle_name(trans, vtable_name_buf)
stdio.printf("[VTDBG-STEP] class=%s vtable name done, mn=%p\n",
class_name, vtable_mangled)
stdio.fflush(None)
# 5. 创建全局变量 # 5. 创建全局变量
gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable( gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(
pool, vtable_mangled, vtable_ty) pool, vtable_mangled, vtable_ty)
stdio.printf("[VTDBG-STEP] class=%s new_global_variable done, gv=%p\n",
class_name, gv)
stdio.fflush(None)
if gv is None: if gv is None:
return 0 return 0
gv.Initializer = init_buf gv.Initializer = init_buf
@@ -2953,11 +3131,18 @@ def _generate_vtable(trans: HT.Translator | t.CPtr,
# 添加到模块 # 添加到模块
llvmlite.module_add_global(mod, gv) llvmlite.module_add_global(mod, gv)
stdio.printf("[VTDBG-STEP] class=%s module_add_global done\n", class_name)
stdio.fflush(None)
# 6. 存储虚方法名列表到 StructEntry(直接用 entry,规避跨模块同名 find_struct 找错) # 6. 存储虚方法名列表到 StructEntry(直接用 entry,规避跨模块同名 find_struct 找错)
stdio.printf("[VTDBG-STEP] class=%s store VTableMethods, entry=%p mnb=%p\n",
class_name, vt_self_entry, method_names_buf)
stdio.fflush(None)
if vt_self_entry is not None: if vt_self_entry is not None:
vt_self_entry.VTableMethods = method_names_buf vt_self_entry.VTableMethods = method_names_buf
vt_self_entry.VTableMethodCount = method_count vt_self_entry.VTableMethodCount = method_count
stdio.printf("[VTDBG-STEP] class=%s VTableMethods stored\n", class_name)
stdio.fflush(None)
return 0 return 0
@@ -3051,6 +3236,8 @@ def _translate_oop_methods(trans: HT.Translator | t.CPtr,
if stmt.kind() == ast.ASTKind.FunctionDef: if stmt.kind() == ast.ASTKind.FunctionDef:
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt) fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt)
if fd is not None and fd.name is not None: if fd is not None and fd.name is not None:
stdio.printf("[VTDBG-STEP] class=%s oop loop method: %s\n",
class_name, fd.name)
_translate_method(trans, fd, struct_ty, class_name) _translate_method(trans, fd, struct_ty, class_name)
# 如果有虚表,先生成 VTable 全局变量(设置 VTableMethodCount) # 如果有虚表,先生成 VTable 全局变量(设置 VTableMethodCount)
@@ -3070,6 +3257,7 @@ def _translate_oop_methods(trans: HT.Translator | t.CPtr,
if oop_entry is not None: if oop_entry is not None:
oop_entry.MethodsEmitted = 1 oop_entry.MethodsEmitted = 1
stdio.printf("[VTDBG-STEP] class=%s oop_methods done\n", class_name)
return 0 return 0
@@ -3108,6 +3296,8 @@ def _translate_method(trans: HT.Translator | t.CPtr,
self_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, struct_ty) self_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, struct_ty)
method_name: str = fd.name method_name: str = fd.name
stdio.printf("[VTDBG-STEP] class=%s translate_method enter: %s\n",
class_name, method_name)
# 构建方法全名: ClassName.method_name # 构建方法全名: ClassName.method_name
full_name_buf: t.CChar | t.CPtr = pool.alloc(128) full_name_buf: t.CChar | t.CPtr = pool.alloc(128)
@@ -3165,7 +3355,8 @@ def _translate_method(trans: HT.Translator | t.CPtr,
# 注册到函数表(用 ClassName.method_name 作为查找名,支持后缀匹配) # 注册到函数表(用 ClassName.method_name 作为查找名,支持后缀匹配)
max_funcs: int = 256 max_funcs: int = 256
if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, full_name, func, max_funcs, if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, full_name, func, max_funcs,
md_defaults, md_default_count, md_param_count) == 0: md_defaults, md_default_count, md_param_count,
pool) == 0:
trans._func_count = func_count + 1 trans._func_count = func_count + 1
# 添加 self 参数(Ptr(struct_ty)) # 添加 self 参数(Ptr(struct_ty))
@@ -3192,6 +3383,9 @@ def _translate_method(trans: HT.Translator | t.CPtr,
viperlib.snprintf(pname, 32, "%%%s", arg.arg) viperlib.snprintf(pname, 32, "%%%s", arg.arg)
llvmlite.add_param(pool, func, param_ty, pname) llvmlite.add_param(pool, func, param_ty, pname)
# 参数添加完成,补全全局函数表的 TypeStr(供 vtable 在 func 被 reset 后使用)
HandlesExprCall.update_global_func_typestr(pool, full_name, func)
# 创建 entry 块 # 创建 entry 块
entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry") entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry")
if entry_blk is None: if entry_blk is None:
@@ -3343,18 +3537,27 @@ def _generate_before_init(trans: HT.Translator | t.CPtr,
if trans is None or struct_ty is None or class_name is None: if trans is None or struct_ty is None or class_name is None:
return 0 return 0
stdio.printf("[VTDBG-STEP] class=%s -> before_init\n", class_name)
stdio.fflush(None)
import lib.core.Handles.HandlesFunctions as HandlesFunctions import lib.core.Handles.HandlesFunctions as HandlesFunctions
import lib.core.Handles.HandlesVar as HandlesVar import lib.core.Handles.HandlesVar as HandlesVar
import lib.core.Handles.HandlesExpr as HandlesExpr import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesExprCall as HandlesExprCall import lib.core.Handles.HandlesExprCall as HandlesExprCall
stdio.printf("[BI-DBG] step1 pool/mod/funcs ok, func_count=%d\n", trans._func_count)
stdio.fflush(None)
pool: memhub.MemBuddy | t.CPtr = trans.Pool pool: memhub.MemBuddy | t.CPtr = trans.Pool
mod: llvmlite.LLVMModule | t.CPtr = trans.Module mod: llvmlite.LLVMModule | t.CPtr = trans.Module
funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs
func_count: int = trans._func_count func_count: int = trans._func_count
stdio.printf("[BI-DBG] step2 pool=%p mod=%p funcs=%p ok\n", pool, mod, funcs_ptr)
stdio.fflush(None)
self_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, struct_ty) self_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, struct_ty)
void_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool) void_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool)
stdio.printf("[BI-DBG] step3 Ptr/Void ty ok self_ptr=%p\n", self_ptr_ty)
stdio.fflush(None)
# 构建函数名: ClassName.__before_init__ # 构建函数名: ClassName.__before_init__
full_name_buf: t.CChar | t.CPtr = pool.alloc(128) full_name_buf: t.CChar | t.CPtr = pool.alloc(128)
@@ -3362,46 +3565,82 @@ def _generate_before_init(trans: HT.Translator | t.CPtr,
return 0 return 0
viperlib.snprintf(full_name_buf, 128, "%s.__before_init__", class_name) viperlib.snprintf(full_name_buf, 128, "%s.__before_init__", class_name)
full_name: str = full_name_buf full_name: str = full_name_buf
stdio.printf("[BI-DBG] step4 full_name=%s\n", full_name)
stdio.fflush(None)
mangled_name: str = HandlesFunctions._mangle_name(trans, full_name) mangled_name: str = HandlesFunctions._mangle_name(trans, full_name)
stdio.printf("[BI-DBG] step5 mangled=%s\n", mangled_name)
stdio.fflush(None)
# 创建函数 # 创建函数
func: llvmlite.Function | t.CPtr = llvmlite.create_function( func: llvmlite.Function | t.CPtr = llvmlite.create_function(
pool, mod, mangled_name, void_ty) pool, mod, mangled_name, void_ty)
stdio.printf("[BI-DBG] step6 create_function done func=%p\n", func)
stdio.fflush(None)
if func is None: if func is None:
return 0 return 0
# 注册到函数表 # 注册到函数表
max_funcs: int = 256 max_funcs: int = 256
if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, full_name, func, max_funcs) == 0: rc_add: int = HandlesExprCall.add_func_to_table(funcs_ptr, func_count, full_name, func, max_funcs, None, 0, 0, pool)
stdio.printf("[BI-DBG] step7 add_func_to_table rc=%d\n", rc_add)
stdio.fflush(None)
if rc_add == 0:
trans._func_count = func_count + 1 trans._func_count = func_count + 1
# 添加 self 参数 # 添加 self 参数
llvmlite.add_param(pool, func, self_ptr_ty, "%self") llvmlite.add_param(pool, func, self_ptr_ty, "%self")
stdio.printf("[BI-DBG] step8 add_param done\n")
stdio.fflush(None)
# 参数添加完成,补全全局函数表的 TypeStr
rc_ut: int = HandlesExprCall.update_global_func_typestr(pool, full_name, func)
stdio.printf("[BI-DBG] step9 update_global_func_typestr rc=%d\n", rc_ut)
stdio.fflush(None)
# 创建 entry 块 + builder # 创建 entry 块 + builder
entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry") entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry")
stdio.printf("[BI-DBG] step10 create_block entry=%p\n", entry_blk)
stdio.fflush(None)
if entry_blk is None: if entry_blk is None:
return 0 return 0
func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func) func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func)
stdio.printf("[BI-DBG] step11 new_builder builder=%p\n", func_builder)
stdio.fflush(None)
if func_builder is None: if func_builder is None:
return 0 return 0
llvmlite.position_at_end(func_builder, entry_blk) llvmlite.position_at_end(func_builder, entry_blk)
# 注册 self 为 SSA 值 # 注册 self 为 SSA 值
self_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, self_ptr_ty, "%self") self_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, self_ptr_ty, "%self")
stdio.printf("[BI-DBG] step12 SSAValue self_val=%p\n", self_val)
stdio.fflush(None)
# 1. 零值填充: store zeroinitializer, Ptr(struct_ty)* %self # 1. 零值填充: store zeroinitializer, Ptr(struct_ty)* %self
zero: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, struct_ty) zero: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, struct_ty)
stdio.printf("[BI-DBG] step13 ConstZero zero=%p\n", zero)
stdio.fflush(None)
if zero is not None: if zero is not None:
llvmlite.build_store(func_builder, zero, self_val) llvmlite.build_store(func_builder, zero, self_val)
stdio.printf("[BI-DBG] step14 build_store zero done\n")
stdio.fflush(None)
# 1.5 如果有虚表,store vtable 全局地址到 __vtable__ 字段(索引 0) # 1.5 如果有虚表,store vtable 全局地址到 __vtable__ 字段(索引 0)
# 用 find_struct_by_type 定位 entry,规避跨模块同名 find_struct 找错 # 用 find_struct_by_type 定位 entry,规避跨模块同名 find_struct 找错
stdio.printf("[BI-DBG] step15 before find_struct_by_type, struct_ty=%p\n", struct_ty)
stdio.fflush(None)
bi_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type(struct_ty) bi_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type(struct_ty)
stdio.printf("[BI-DBG] step16 find_struct_by_type done, bi_entry=%p\n", bi_entry)
stdio.fflush(None)
bi_has_vt: int = 0 bi_has_vt: int = 0
if bi_entry is not None: if bi_entry is not None:
stdio.printf("[BI-DBG] step17 read bi_entry->HasVTable\n", None)
stdio.fflush(None)
bi_has_vt = bi_entry.HasVTable bi_has_vt = bi_entry.HasVTable
stdio.printf("[VTDBG-STEP] class=%s before_init: has_vt=%d vt_count=%d field_count=%d\n",
class_name, bi_has_vt,
(bi_entry.VTableMethodCount if bi_entry is not None else -1),
(bi_entry.FieldCount if bi_entry is not None else -1))
if bi_has_vt == 1: if bi_has_vt == 1:
vt_method_count: int = 0 vt_method_count: int = 0
if bi_entry is not None: if bi_entry is not None:
@@ -3460,16 +3699,31 @@ def _generate_before_init(trans: HT.Translator | t.CPtr,
# 2. 逐字段 store 默认值(用 bi_entry 直接访问,规避跨模块同名 find_struct 找错) # 2. 逐字段 store 默认值(用 bi_entry 直接访问,规避跨模块同名 find_struct 找错)
if bi_entry is not None: if bi_entry is not None:
stdio.printf("[VTDBG-STEP] class=%s before_init: store-defaults loop start, field_count=%d\n",
class_name, bi_entry.FieldCount)
for fi in range(bi_entry.FieldCount): for fi in range(bi_entry.FieldCount):
fe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry( fe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry(
bi_entry, fi) bi_entry, fi)
stdio.printf("[VTDBG-FIELD] class=%s fi=%d fe=%p index=%d default=%p ty=%p\n",
class_name, fi, fe,
(fe.Index if fe is not None else -1),
(fe.DefaultVal if fe is not None else None),
(fe.Ty if fe is not None else None))
if fe is None or fe.DefaultVal is None: if fe is None or fe.DefaultVal is None:
continue continue
# 打印 DefaultVal 的 AST kind(定位悬空/垃圾节点)
dk: int = fe.DefaultVal.kind()
stdio.printf("[VTDBG-FIELD] class=%s fi=%d translate default kind=%d\n",
class_name, fi, dk)
# 翻译默认值表达式 # 翻译默认值表达式
default_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( default_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
func_builder, pool, mod, fe.DefaultVal, None, 0, trans) func_builder, pool, mod, fe.DefaultVal, None, 0, trans)
if default_val is None: if default_val is None:
stdio.printf("[VTDBG-FIELD] class=%s fi=%d translate default -> None\n",
class_name, fi)
continue continue
stdio.printf("[VTDBG-STEP] class=%s before_init: field[%d] default translated\n",
class_name, fi)
# GEP 到字段 # GEP 到字段
field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
func_builder, struct_ty, fe.Ty, self_val, fe.Index) func_builder, struct_ty, fe.Ty, self_val, fe.Index)
@@ -3480,6 +3734,7 @@ def _generate_before_init(trans: HT.Translator | t.CPtr,
llvmlite.build_store(func_builder, default_val, field_ptr) llvmlite.build_store(func_builder, default_val, field_ptr)
# 3. ret void # 3. ret void
stdio.printf("[VTDBG-STEP] class=%s before_init: done, ret void\n", class_name)
llvmlite.build_ret_void(func_builder) llvmlite.build_ret_void(func_builder)
return 0 return 0
+10 -3
View File
@@ -935,9 +935,16 @@ def translate_compare(builder: llvmlite.IRBuilder | t.CPtr,
rhs_ptr_level: int = get_ptr_level(rhs.Ty) rhs_ptr_level: int = get_ptr_level(rhs.Ty)
if lhs_ptr_level != rhs_ptr_level: if lhs_ptr_level != rhs_ptr_level:
# 类型不匹配:数值vs指针 或 不同级指针 # 类型不匹配:数值vs指针 或 不同级指针
VLogger.error( # 用 fmt_buf 构造可读消息(Viper % 格式化在部分路径生成 null)
"比较类型不匹配: lhs 指针层级=%d, rhs 指针层级=%d (禁止数值与指针、不同级指针比较)" % (lhs_ptr_level, rhs_ptr_level), fmt_msg: t.CChar | t.CPtr = VLogger.fmt_buf()
"Compare") if fmt_msg is not None:
viperlib.snprintf(
fmt_msg, 1024,
"比较类型不匹配(行 %d): lhs 层级=%d (ty=%p), rhs 层级=%d (ty=%p)",
cmp.lineno, lhs_ptr_level, lhs.Ty, rhs_ptr_level, rhs.Ty)
VLogger.error(fmt_msg, "Compare")
else:
VLogger.error("比较类型不匹配: 数值与指针/不同级指针比较", "Compare")
return None return None
else: else:
# None 比较: None 被翻译为 i8* null(一级指针) # None 比较: None 被翻译为 i8* null(一级指针)
+255 -56
View File
@@ -2843,18 +2843,24 @@ def _call_method_on_ptr(pool: memhub.MemBuddy | t.CPtr,
if mdf_defaults is not None and mdf_default_count > 0 and mdf_pi >= mdf_offset: if mdf_defaults is not None and mdf_default_count > 0 and mdf_pi >= mdf_offset:
mdf_di: int = mdf_pi - mdf_offset mdf_di: int = mdf_pi - mdf_offset
if mdf_di < mdf_default_count: 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)) # 优先用 stdlib 常量快照重建(mdf_gd.Defaults 的 pool 内 AST 可能已被 reset 回收)
mdf_node: ast.AST | t.CPtr = mdf_defaults_list.get(mdf_di) mdf_val: llvmlite.Value | t.CPtr = None
if mdf_node is not None: if mdf_gd is not None:
mdf_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( mdf_val = _build_const_from_snapshot(
builder, pool, mod, mdf_node, None, 0, trans) pool, mod, mdf_gd, mdf_di, trans, builder)
if mdf_val is not None: if mdf_val is None:
llvmlite.value_set_next(mdf_val, None) 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))
llvmlite.value_set_next(tail, mdf_val) mdf_node: ast.AST | t.CPtr = mdf_defaults_list.get(mdf_di)
tail = mdf_val if mdf_node is not None:
total_count += 1 mdf_val = HandlesExpr.translate_value(
mdf_pi += 1 builder, pool, mod, mdf_node, None, 0, trans)
continue 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 获取参数类型) # 无默认值时用零值兜底(需要 found_func 获取参数类型)
if found_func is not None: if found_func is not None:
param_node_z: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(found_func) param_node_z: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(found_func)
@@ -3498,18 +3504,24 @@ def _translate_method_call(pool: memhub.MemBuddy | t.CPtr,
if mdf_defaults is not None and mdf_default_count > 0 and mdf_pi >= mdf_offset: if mdf_defaults is not None and mdf_default_count > 0 and mdf_pi >= mdf_offset:
mdf_di: int = mdf_pi - mdf_offset mdf_di: int = mdf_pi - mdf_offset
if mdf_di < mdf_default_count: 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)) # 优先用 stdlib 常量快照重建(mdf_gd.Defaults 的 pool 内 AST 可能已被 reset 回收)
mdf_node: ast.AST | t.CPtr = mdf_defaults_list.get(mdf_di) mdf_val: llvmlite.Value | t.CPtr = None
if mdf_node is not None: if mdf_gd is not None:
mdf_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( mdf_val = _build_const_from_snapshot(
builder, pool, mod, mdf_node, None, 0, trans) pool, mod, mdf_gd, mdf_di, trans, builder)
if mdf_val is not None: if mdf_val is None:
llvmlite.value_set_next(mdf_val, None) 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))
llvmlite.value_set_next(tail, mdf_val) mdf_node: ast.AST | t.CPtr = mdf_defaults_list.get(mdf_di)
tail = mdf_val if mdf_node is not None:
total_count += 1 mdf_val = HandlesExpr.translate_value(
mdf_pi += 1 builder, pool, mod, mdf_node, None, 0, trans)
continue 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 获取参数类型) # 无默认值时用零值兜底(需要 found_func 获取参数类型)
if found_func is not None: if found_func is not None:
param_node_z: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(found_func) param_node_z: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(found_func)
@@ -4947,18 +4959,24 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr,
while df_di < df_default_count: while df_di < df_default_count:
df_param_idx: int = df_offset + df_di df_param_idx: int = df_offset + df_di
if df_param_idx >= can: if df_param_idx >= can:
df_defaults_list: list[ast.AST | t.CPtr] | t.CPtr = (list[ast.AST | t.CPtr] | t.CPtr)(t.CVoid(t.CUInt64T(df_defaults), t.CPtr)) # 优先用 stdlib 常量快照重建(gd_entry.Defaults 的 pool 内 AST 可能已被 reset 回收)
df_default_node: ast.AST | t.CPtr = df_defaults_list.get(df_di) df_arg_val: llvmlite.Value | t.CPtr = None
if df_default_node is not None: if gd_entry is not None:
df_arg_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( df_arg_val = _build_const_from_snapshot(
builder, pool, mod, df_default_node, None, 0, trans) pool, mod, gd_entry, df_di, trans, builder)
if df_arg_val is not None: if df_arg_val is None:
df_arg_val.Next = None df_defaults_list: list[ast.AST | t.CPtr] | t.CPtr = (list[ast.AST | t.CPtr] | t.CPtr)(t.CVoid(t.CUInt64T(df_defaults), t.CPtr))
if head is None: df_default_node: ast.AST | t.CPtr = df_defaults_list.get(df_di)
head = df_arg_val if df_default_node is not None:
else: df_arg_val = HandlesExpr.translate_value(
tail.Next = df_arg_val builder, pool, mod, df_default_node, None, 0, trans)
tail = df_arg_val if df_arg_val is not None:
df_arg_val.Next = None
if head is None:
head = df_arg_val
else:
tail.Next = df_arg_val
tail = df_arg_val
df_di += 1 df_di += 1
# 使用模块中的实际函数名(可能带 SHA1 前缀,如 "83210a72e829a086.atoi") # 使用模块中的实际函数名(可能带 SHA1 前缀,如 "83210a72e829a086.atoi")
@@ -5569,6 +5587,10 @@ class FuncEntry:
Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr]),None=无默认值 Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr]),None=无默认值
DefaultCount: int # 默认值数量 DefaultCount: int # 默认值数量
ParamCount: int # 形参数量(不含 self) ParamCount: int # 形参数量(不含 self)
# TypeStr: 函数类型文本(stdlib 深拷贝,跨文件安全)
# 1b 每文件 reset_to(mark1) 回收 pool 内 Function 对象后,
# vtable 生成 find_func_global 读类型改用此文本,避免悬空。
TypeStr: t.CChar | t.CPtr
# ============================================================ # ============================================================
# 初始化函数表 # 初始化函数表
@@ -5610,13 +5632,15 @@ def add_func_to_table(funcs: FuncEntry | t.CPtr,
max_count: int, max_count: int,
defaults: t.CVoid | t.CPtr = None, defaults: t.CVoid | t.CPtr = None,
default_count: int = 0, default_count: int = 0,
param_count: int = 0) -> int: param_count: int = 0,
pool: memhub.MemBuddy | t.CPtr = None) -> int:
"""添加函数到函数表,返回 0 成功 """添加函数到函数表,返回 0 成功
Args: Args:
defaults: ast.Arguments.defaults 列表节点指针,None=无默认值 defaults: ast.Arguments.defaults 列表节点指针,None=无默认值
default_count: 默认值数量(len(defaults)) default_count: 默认值数量(len(defaults))
param_count: 形参数量(不含 self,len(args.args)) param_count: 形参数量(不含 self,len(args.args))
pool: 内存池(用于生成 TypeStr;None 时 TypeStr 为空,vtable 回退读 Func 对象)
""" """
if name is None or func is None or funcs is None: if name is None or func is None or funcs is None:
return 1 return 1
@@ -5631,7 +5655,7 @@ def add_func_to_table(funcs: FuncEntry | t.CPtr,
entry.DefaultCount = default_count entry.DefaultCount = default_count
entry.ParamCount = param_count entry.ParamCount = param_count
# 同时注册到全局函数表(供跨模块 vtable 初始化查找) # 同时注册到全局函数表(供跨模块 vtable 初始化查找)
_register_global_func(name, func) _register_global_func(name, func, pool)
# 同时注册到全局默认参数表(供跨模块调用时填充默认值) # 同时注册到全局默认参数表(供跨模块调用时填充默认值)
if default_count > 0: if default_count > 0:
_register_global_defaults(name, defaults, default_count, param_count) _register_global_defaults(name, defaults, default_count, param_count)
@@ -5662,10 +5686,64 @@ def _init_global_func_table() -> int:
_global_func_count = 0 _global_func_count = 0
return 1 return 1
def _register_global_func(name: str, func: llvmlite.Function | t.CPtr) -> int:
# _build_func_type_str — 从 Function 对象生成函数类型文本(stdlib 存储)
#
# 格式: ret_ty (param1_ty, param2_ty, ...),与 vtable bitcast 需要一致。
# 用 stdlib.malloc 分配返回,跨文件永久存活(1b reset 不回收)。
# 返回 None 表示失败。
def _build_func_type_str(pool: memhub.MemBuddy | t.CPtr,
func: llvmlite.Function | t.CPtr) -> t.CChar | t.CPtr:
"""生成函数类型文本(stdlib 分配)"""
if func is None:
return None
# 类型文本可能较长(SHA1 限定命名结构体 + 多参数),用 1024 缓冲
ty_buf: t.CChar | t.CPtr = pool.alloc(1024)
if ty_buf is None:
return None
ty_buf[0] = '\0'
# 返回类型
ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(func)
ret_part: t.CChar | t.CPtr = pool.alloc(512)
if ret_part is not None and ret_ty is not None:
ret_part[0] = '\0'
llvmlite.TypePrint(ret_part, 512, ret_ty, pool)
string.strcat(ty_buf, ret_part)
string.strcat(ty_buf, " (")
# 参数类型
cur: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(func)
first: int = 1
param_part: t.CChar | t.CPtr = pool.alloc(512)
while cur is not None:
if first == 0:
string.strcat(ty_buf, ", ")
if param_part is not None:
param_part[0] = '\0'
param_ty: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(cur)
if param_ty is not None:
llvmlite.TypePrint(param_part, 512, param_ty, pool)
string.strcat(ty_buf, param_part)
cur = llvmlite.param_get_next(cur)
first = 0
string.strcat(ty_buf, ")")
# 深拷贝到 stdlib 区(TypeStr 跨文件永久存活)
ts_len: t.CSizeT = string.strlen(ty_buf)
ts_copy: t.CChar | t.CPtr = stdlib.malloc(ts_len + 1)
if ts_copy is None:
return None
string.strcpy(ts_copy, ty_buf)
return ts_copy
def _register_global_func(name: str, func: llvmlite.Function | t.CPtr,
pool: memhub.MemBuddy | t.CPtr = None) -> int:
"""注册函数到全局表(已存在则跳过),返回 0 成功 """注册函数到全局表(已存在则跳过),返回 0 成功
直接操作全局表,不调用 add_func_to_table,避免递归。 直接操作全局表,不调用 add_func_to_table,避免递归。
pool 用于生成 TypeStr(None 时 TypeStr 为空)。
""" """
global _global_func_count global _global_func_count
if name is None or func is None: if name is None or func is None:
@@ -5681,11 +5759,38 @@ def _register_global_func(name: str, func: llvmlite.Function | t.CPtr) -> int:
entry_size: t.CSizeT = FuncEntry.__sizeof__() entry_size: t.CSizeT = FuncEntry.__sizeof__()
entry_addr: t.CUInt64T = t.CUInt64T(_global_funcs) + _global_func_count * entry_size entry_addr: t.CUInt64T = t.CUInt64T(_global_funcs) + _global_func_count * entry_size
entry: FuncEntry | t.CPtr = (FuncEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) entry: FuncEntry | t.CPtr = (FuncEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
entry.Name = name # Name 深拷贝到 stdlib 区:全局表跨文件永久存活,pool 内名字会被 1b 每文件
# reset_to(mark1) 回收导致悬空(vtable 生成 find_func_global 后 strcmp 崩溃)
name_len: t.CSizeT = string.strlen(name)
name_copy: t.CChar | t.CPtr = stdlib.malloc(name_len + 1)
if name_copy is None:
return 1
string.strcpy(name_copy, name)
entry.Name = name_copy
entry.Func = func entry.Func = func
# TypeStr 不在此生成:函数参数在 add_func_to_table 之后才添加,
# 需由调用方在参数添加完成后调用 update_global_func_typestr 补全。
_global_func_count += 1 _global_func_count += 1
return 0 return 0
def update_global_func_typestr(pool: memhub.MemBuddy | t.CPtr,
name: str,
func: llvmlite.Function | t.CPtr) -> int:
"""更新全局函数表的 TypeStr(在函数参数全部添加完成后调用)
调用时机:add_func_to_table 注册后、llvmlite.add_param 全部执行完。
生成 ret_ty (param1_ty, ...) 类型文本(stdlib 深拷贝),
供 vtable 生成在 func 被 1b reset 后使用。
"""
if name is None or func is None:
return 1
entry: FuncEntry | t.CPtr = find_func_entry_global(name)
if entry is None:
return 1
entry.TypeStr = _build_func_type_str(pool, func)
return 0
def find_func_global(name: str) -> llvmlite.Function | t.CPtr: def find_func_global(name: str) -> llvmlite.Function | t.CPtr:
"""在全局函数表中按名称查找,返回 Function 指针或 None""" """在全局函数表中按名称查找,返回 Function 指针或 None"""
if name is None or _global_funcs is None: if name is None or _global_funcs is None:
@@ -5693,6 +5798,20 @@ def find_func_global(name: str) -> llvmlite.Function | t.CPtr:
return find_func_in_table(_global_funcs, _global_func_count, name) return find_func_in_table(_global_funcs, _global_func_count, name)
def find_func_entry_global(name: str) -> FuncEntry | t.CPtr:
"""在全局函数表中按名称查找,返回完整 FuncEntry(含 TypeStr)或 None"""
if name is None or _global_funcs is None:
return None
entry_size: t.CSizeT = FuncEntry.__sizeof__()
for i in range(_global_func_count):
entry_addr: t.CUInt64T = t.CUInt64T(_global_funcs) + i * entry_size
entry: FuncEntry | t.CPtr = (FuncEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
if entry.Name is not None:
if string.strcmp(entry.Name, name) == 0:
return entry
return None
# ============================================================ # ============================================================
# 全局默认参数注册表(跨模块默认参数填充) # 全局默认参数注册表(跨模块默认参数填充)
# #
@@ -5705,9 +5824,15 @@ GLOBAL_DEFAULTS_MAX: t.CDefine = 4096
class FuncDefaultsEntry: class FuncDefaultsEntry:
"""默认参数表条目""" """默认参数表条目"""
Name: str Name: str
Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr]) Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr])(pool 内,可能被 reset)
DefaultCount: int DefaultCount: int
ParamCount: int # 形参数量(不含 self) ParamCount: int # 形参数量(不含 self)
# 常量快照(stdlib 分配,跨文件永久存活):
# 注册时提取每个默认值 Constant 的值,跨模块调用时优先用快照重建常量 IR,
# 避免读取已被 1b reset_to(mark1) 回收的 pool 内 AST。
ConstKinds: t.CInt | t.CPtr # const_kind 数组(DefaultCount 个 i32)
ConstInts: t.CInt64T | t.CPtr # int_val 数组(DefaultCount 个 i64)
ConstStrs: t.CSizeT | t.CPtr # str_val 指针数组(DefaultCount 个 i8*)
_global_defaults: FuncDefaultsEntry | t.CPtr = None _global_defaults: FuncDefaultsEntry | t.CPtr = None
_global_defaults_count: int = 0 _global_defaults_count: int = 0
@@ -5730,7 +5855,11 @@ def _register_global_defaults(name: str,
defaults: t.CVoid | t.CPtr, defaults: t.CVoid | t.CPtr,
default_count: int, default_count: int,
param_count: int) -> int: param_count: int) -> int:
"""注册函数默认参数到全局表,返回 0 成功""" """注册函数默认参数到全局表,返回 0 成功
注册时提取每个默认值 Constant 的常量快照到 stdlib(ConstKinds/ConstInts/ConstStrs),
跨模块调用时优先用快照重建常量 IR,避免读取被 reset 回收的 pool 内 AST。
"""
global _global_defaults_count global _global_defaults_count
if name is None or defaults is None: if name is None or defaults is None:
return 1 return 1
@@ -5744,26 +5873,96 @@ def _register_global_defaults(name: str,
entry_size: t.CSizeT = FuncDefaultsEntry.__sizeof__() entry_size: t.CSizeT = FuncDefaultsEntry.__sizeof__()
entry_addr: t.CUInt64T = t.CUInt64T(_global_defaults) + _global_defaults_count * entry_size entry_addr: t.CUInt64T = t.CUInt64T(_global_defaults) + _global_defaults_count * entry_size
entry: FuncDefaultsEntry | t.CPtr = (FuncDefaultsEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) entry: FuncDefaultsEntry | t.CPtr = (FuncDefaultsEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
entry.Name = name # Name 深拷贝到 stdlib(全局表跨文件永久存活)
nm_len: t.CSizeT = string.strlen(name)
nm_copy: t.CChar | t.CPtr = stdlib.malloc(nm_len + 1)
if nm_copy is None:
return 1
string.strcpy(nm_copy, name)
entry.Name = nm_copy
entry.Defaults = defaults entry.Defaults = defaults
entry.DefaultCount = default_count entry.DefaultCount = default_count
entry.ParamCount = param_count entry.ParamCount = param_count
# 提取常量快照到 stdlib
if default_count > 0:
kinds: t.CInt | t.CPtr = stdlib.malloc(default_count * 4)
ints: t.CInt64T | t.CPtr = stdlib.malloc(default_count * 8)
strs: t.CSizeT | t.CPtr = stdlib.malloc(default_count * 8)
if kinds is not None and ints is not None and strs is not None:
string.memset(kinds, 0, default_count * 4)
string.memset(ints, 0, default_count * 8)
string.memset(strs, 0, default_count * 8)
dl: list[ast.AST | t.CPtr] | t.CPtr = (list[ast.AST | t.CPtr] | t.CPtr)(t.CVoid(t.CUInt64T(defaults), t.CPtr))
di: int
for di in range(default_count):
dnode: ast.AST | t.CPtr = dl.get(di)
if dnode is not None and dnode.kind() == ast.ASTKind.Constant:
dcn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(dnode)
kinds[di] = dcn.const_kind
ints[di] = dcn.int_val
if dcn.const_kind == ast.CONST_STR and dcn.str_val is not None:
slen: t.CSizeT = string.strlen(dcn.str_val)
scopy: t.CChar | t.CPtr = stdlib.malloc(slen + 1)
if scopy is not None:
string.strcpy(scopy, dcn.str_val)
strs[di] = t.CSizeT(scopy)
entry.ConstKinds = kinds
entry.ConstInts = ints
entry.ConstStrs = strs
_global_defaults_count += 1 _global_defaults_count += 1
return 0 return 0
def find_func_defaults(name: str) -> FuncDefaultsEntry | t.CPtr: def find_func_defaults(name: str) -> FuncDefaultsEntry | t.CPtr:
"""按函数名查找默认参数信息,返回 FuncDefaultsEntry 或 None""" """按函数名查找默认参数信息,返回 FuncDefaultsEntry 或 None"""
if name is None or _global_defaults is None: if name is None or _global_defaults is None:
return None return None
entry_size: t.CSizeT = FuncDefaultsEntry.__sizeof__() entry_size: t.CSizeT = FuncDefaultsEntry.__sizeof__()
i: int = 0 i: int = 0
while i < _global_defaults_count: while i < _global_defaults_count:
entry_addr: t.CUInt64T = t.CUInt64T(_global_defaults) + i * entry_size entry_addr: t.CUInt64T = t.CUInt64T(_global_defaults) + i * entry_size
entry: FuncDefaultsEntry | t.CPtr = (FuncDefaultsEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) entry: FuncDefaultsEntry | t.CPtr = (FuncDefaultsEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
if entry.Name is not None: if entry.Name is not None:
if string.strcmp(entry.Name, name) == 0: if string.strcmp(entry.Name, name) == 0:
return entry return entry
i += 1 i += 1
return None
# _build_const_from_snapshot — 从常量快照重建常量 IR 值
#
# 用于跨模块默认参数填充:gd_entry.Defaults(pool 内 AST)可能已被 reset 回收,
# 改用注册时提取的 stdlib 常量快照(ConstKinds/ConstInts/ConstStrs)重建常量 IR。
# 返回 llvmlite.Value*,失败返回 None。
def _build_const_from_snapshot(pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
gd_entry: FuncDefaultsEntry | t.CPtr,
di: int,
trans: HT.Translator | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr) -> llvmlite.Value | t.CPtr:
"""从快照重建第 di 个默认值常量 IR"""
if gd_entry is None or gd_entry.ConstKinds is None or gd_entry.ConstInts is None:
return None
if di < 0 or di >= gd_entry.DefaultCount:
return None
kind: t.CInt = gd_entry.ConstKinds[di]
ival: t.CInt64T = gd_entry.ConstInts[di]
if kind == ast.CONST_INT:
if ival > 2147483647 or ival < -2147483648:
return llvmlite.const_int64(pool, ival)
return llvmlite.const_int32(pool, ival)
elif kind == ast.CONST_BOOL:
if ival != 0:
return llvmlite.const_int32(pool, 1)
return llvmlite.const_int32(pool, 0)
elif kind == ast.CONST_NONE:
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
return llvmlite.ConstNull(pool, i8_ptr_ty, "null")
elif kind == ast.CONST_STR:
if gd_entry.ConstStrs is not None and gd_entry.ConstStrs[di] != 0:
sv: str = (str | t.CPtr)(t.CVoid(gd_entry.ConstStrs[di], t.CPtr))
return HandlesExpr.create_global_string(builder, pool, mod, sv, trans)
# 无法重建的(如 CONST_FLOAT/复杂表达式)返回 None,调用方回退到 AST
return None return None
def find_func_entry_in_table(funcs: FuncEntry | t.CPtr, def find_func_entry_in_table(funcs: FuncEntry | t.CPtr,
+14 -3
View File
@@ -373,7 +373,8 @@ def forward_declare_functions(trans: HT.Translator | t.CPtr,
max_funcs: int = 256 max_funcs: int = 256
cur_count: int = trans._func_count cur_count: int = trans._func_count
if HandlesExprCall.add_func_to_table(funcs_ptr, cur_count, fd.name, func, max_funcs, if HandlesExprCall.add_func_to_table(funcs_ptr, cur_count, fd.name, func, max_funcs,
fd_defaults, fd_default_count, fd_param_count) == 0: fd_defaults, fd_default_count, fd_param_count,
trans.Pool) == 0:
trans._func_count = cur_count + 1 trans._func_count = cur_count + 1
# 注册 CExport 函数到全局表 # 注册 CExport 函数到全局表
@@ -410,6 +411,9 @@ def forward_declare_functions(trans: HT.Translator | t.CPtr,
if ags.vararg is not None: if ags.vararg is not None:
func.IsVarArg = 1 func.IsVarArg = 1
# 参数添加完成,补全全局函数表的 TypeStr(供 vtable 在 func 被 reset 后使用)
HandlesExprCall.update_global_func_typestr(trans.Pool, fd.name, func)
return 0 return 0
@@ -497,7 +501,7 @@ def translate_function_def(trans: HT.Translator | t.CPtr,
# 注册到函数表 # 注册到函数表
max_funcs_extern: int = 256 max_funcs_extern: int = 256
if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, fd.name, func, max_funcs_extern) == 0: if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, fd.name, func, max_funcs_extern, None, 0, 0, pool) == 0:
trans._func_count = func_count + 1 trans._func_count = func_count + 1
# 添加参数(支持类型注解) # 添加参数(支持类型注解)
@@ -530,6 +534,9 @@ def translate_function_def(trans: HT.Translator | t.CPtr,
if func_attrs_e is not None: if func_attrs_e is not None:
llvmlite.function_set_attrs(func, func_attrs_e) llvmlite.function_set_attrs(func, func_attrs_e)
# 参数添加完成,补全全局函数表的 TypeStr
HandlesExprCall.update_global_func_typestr(pool, fd.name, func)
return 0 return 0
# args_node 用于后续 alloca 创建,提前赋值 # args_node 用于后续 alloca 创建,提前赋值
@@ -576,7 +583,8 @@ def translate_function_def(trans: HT.Translator | t.CPtr,
# 注册到函数表 # 注册到函数表
max_funcs: int = 256 max_funcs: int = 256
if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, fd.name, func, max_funcs, if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, fd.name, func, max_funcs,
tfd_defaults, tfd_default_count, tfd_param_count) == 0: tfd_defaults, tfd_default_count, tfd_param_count,
trans.Pool) == 0:
trans._func_count = func_count + 1 trans._func_count = func_count + 1
# 添加参数(支持类型注解) # 添加参数(支持类型注解)
@@ -607,6 +615,9 @@ def translate_function_def(trans: HT.Translator | t.CPtr,
if ags.vararg is not None: if ags.vararg is not None:
func.IsVarArg = 1 func.IsVarArg = 1
# 参数添加完成,补全全局函数表的 TypeStr
HandlesExprCall.update_global_func_typestr(trans.Pool, fd.name, func)
# 创建 entry 块 # 创建 entry 块
entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry") entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry")
if entry_blk is None: if entry_blk is None:
+6
View File
@@ -87,6 +87,12 @@ def translate_children(trans: HT.Translator | t.CPtr,
child: ast.AST | t.CPtr = ch.get(ci) child: ast.AST | t.CPtr = ch.get(ci)
if child is None: continue if child is None: continue
kd: int = child.kind() kd: int = child.kind()
if kd == ast.ASTKind.ClassDef:
stdio.printf("[MAIN-DBG] module child[%d] kind=%d ClassDef\n", ci, kd)
elif kd == ast.ASTKind.FunctionDef:
stdio.printf("[MAIN-DBG] module child[%d] kind=%d FunctionDef\n", ci, kd)
elif kd == ast.ASTKind.AnnAssign:
stdio.printf("[MAIN-DBG] module child[%d] kind=%d AnnAssign\n", ci, kd)
# _declare_only == 0 时,_translate_module_level 已预处理导入语句, # _declare_only == 0 时,_translate_module_level 已预处理导入语句,
# 此处跳过避免重复处理(from_imports 条目重复) # 此处跳过避免重复处理(from_imports 条目重复)
+48 -14
View File
@@ -66,6 +66,16 @@ class StructEntry:
_struct_table: StructEntry | t.CPtr = None _struct_table: StructEntry | t.CPtr = None
_struct_count: int = 0 _struct_count: int = 0
# OOM 回收标志:1=后续 register_struct/add_field 的新分配用 stdlib(跨文件永久存活),
# 0=用 pool(mark1 前阶段,会被保留)。Phase1 在 1b 开始前设为 1。
_g_stdlib_alloc: int = 0
def set_stdlib_alloc(flag: int):
"""设置 OOM 回收分配模式:1=1b 阶段(新条目用 stdlib),0=注册阶段(用 pool)"""
global _g_stdlib_alloc
_g_stdlib_alloc = flag
# ============================================================ # ============================================================
# 跨模块命名空间隔离:per-file 结构体可见性 # 跨模块命名空间隔离:per-file 结构体可见性
@@ -193,10 +203,12 @@ def register_struct(pool: memhub.MemBuddy | t.CPtr,
return None return None
# 用类型指针去重(同一类型不重复注册,支持跨模块同名类) # 用类型指针去重(同一类型不重复注册,支持跨模块同名类)
# 用 t.CUInt64T 指针值比较(is 比较会触发类型安全检查解引用悬空 Ty)
st_dedup: t.CUInt64T = t.CUInt64T(struct_ty)
for i in range(_struct_count): for i in range(_struct_count):
existing: StructEntry | t.CPtr = _get_struct_entry(i) existing: StructEntry | t.CPtr = _get_struct_entry(i)
if existing is not None and existing.Ty is not None: if existing is not None and existing.Ty is not None:
if existing.Ty is struct_ty: if t.CUInt64T(existing.Ty) == st_dedup:
return existing return existing
if _struct_count >= STRUCT_MAX: if _struct_count >= STRUCT_MAX:
@@ -210,16 +222,22 @@ def register_struct(pool: memhub.MemBuddy | t.CPtr,
if entry is None: if entry is None:
return None return None
# 分配字段数组 # 分配字段数组(1b 阶段用 stdlib,避免 reset 回收后 Fields 悬空)
field_size: t.CSizeT = FieldEntry.__sizeof__() field_size: t.CSizeT = FieldEntry.__sizeof__()
entry.Fields = pool.alloc(field_size * FIELD_MAX) if _g_stdlib_alloc != 0:
entry.Fields = stdlib.malloc(field_size * FIELD_MAX)
else:
entry.Fields = pool.alloc(field_size * FIELD_MAX)
if entry.Fields is None: if entry.Fields is None:
return None return None
string.memset(entry.Fields, 0, field_size * FIELD_MAX) string.memset(entry.Fields, 0, field_size * FIELD_MAX)
# 复制类名 # 复制类名(1b 阶段用 stdlib)
name_len: t.CSizeT = string.strlen(name) name_len: t.CSizeT = string.strlen(name)
name_buf: t.CChar | t.CPtr = pool.alloc(name_len + 1) if _g_stdlib_alloc != 0:
name_buf: t.CChar | t.CPtr = stdlib.malloc(name_len + 1)
else:
name_buf: t.CChar | t.CPtr = pool.alloc(name_len + 1)
if name_buf is not None: if name_buf is not None:
string.strcpy(name_buf, name) string.strcpy(name_buf, name)
entry.Name = name_buf entry.Name = name_buf
@@ -230,7 +248,10 @@ def register_struct(pool: memhub.MemBuddy | t.CPtr,
# 注册时直接设置 SHA1(避免 set_struct_sha1 跨模块同名时找错 entry) # 注册时直接设置 SHA1(避免 set_struct_sha1 跨模块同名时找错 entry)
if sha1 is not None: if sha1 is not None:
sha1_len: t.CSizeT = string.strlen(sha1) sha1_len: t.CSizeT = string.strlen(sha1)
sha1_buf: t.CChar | t.CPtr = pool.alloc(sha1_len + 1) if _g_stdlib_alloc != 0:
sha1_buf: t.CChar | t.CPtr = stdlib.malloc(sha1_len + 1)
else:
sha1_buf: t.CChar | t.CPtr = pool.alloc(sha1_len + 1)
if sha1_buf is not None: if sha1_buf is not None:
string.strcpy(sha1_buf, sha1) string.strcpy(sha1_buf, sha1)
entry.ModuleSha1 = sha1_buf entry.ModuleSha1 = sha1_buf
@@ -308,9 +329,12 @@ def add_field(pool: memhub.MemBuddy | t.CPtr,
if fe is None: if fe is None:
return -1 return -1
# 复制字段名 # 复制字段名(1b 阶段用 stdlib,避免 reset 回收后 fe.Name 悬空)
name_len: t.CSizeT = string.strlen(field_name) name_len: t.CSizeT = string.strlen(field_name)
name_buf: t.CChar | t.CPtr = pool.alloc(name_len + 1) if _g_stdlib_alloc != 0:
name_buf: t.CChar | t.CPtr = stdlib.malloc(name_len + 1)
else:
name_buf: t.CChar | t.CPtr = pool.alloc(name_len + 1)
if name_buf is not None: if name_buf is not None:
string.strcpy(name_buf, field_name) string.strcpy(name_buf, field_name)
fe.Name = name_buf fe.Name = name_buf
@@ -399,13 +423,20 @@ def find_struct_by_module(name: str, sha1: str) -> StructEntry | t.CPtr:
# 直接用指针身份定位 entry,规避跨模块同名类 find_struct 找错的问题。 # 直接用指针身份定位 entry,规避跨模块同名类 find_struct 找错的问题。
# ============================================================ # ============================================================
def find_struct_by_type(struct_ty: llvmlite.LLVMType | t.CPtr) -> StructEntry | t.CPtr: def find_struct_by_type(struct_ty: llvmlite.LLVMType | t.CPtr) -> StructEntry | t.CPtr:
"""按类型指针查找结构体(is 比较),返回 StructEntry 或 None""" """按类型指针查找结构体(指针值比较),返回 StructEntry 或 None
注意: 不能用 `entry.Ty is struct_ty` 的 is 比较——TPV 编译 is 时会触发
translate_compare 的类型安全检查(is_ptr_type/TypePrint 递归打印),
对悬空 entry.Ty(1b 泛型特化类注册后被 reset 回收的 pool 指针)解引用崩溃。
改用 t.CUInt64T 纯指针值比较,不解引用任何内容。
"""
if struct_ty is None or _struct_table is None: if struct_ty is None or _struct_table is None:
return None return None
st_val: t.CUInt64T = t.CUInt64T(struct_ty)
for i in range(_struct_count): for i in range(_struct_count):
entry: StructEntry | t.CPtr = _get_struct_entry(i) entry: StructEntry | t.CPtr = _get_struct_entry(i)
if entry is not None and entry.Ty is not None: if entry is not None and entry.Ty is not None:
if entry.Ty is struct_ty: if t.CUInt64T(entry.Ty) == st_val:
return entry return entry
return None return None
@@ -436,11 +467,12 @@ def lookup_field(struct_ty: llvmlite.LLVMType | t.CPtr,
# - 名称匹配但字段未找到时 continue(继续检查其他同名 entry) # - 名称匹配但字段未找到时 continue(继续检查其他同名 entry)
# ============================================================ # ============================================================
# 第一遍: is 身份比较 # 第一遍: is 身份比较(用 t.CUInt64T 指针值比较,避免 is 编译路径解引用悬空 Ty)
st_lk: t.CUInt64T = t.CUInt64T(struct_ty)
for i in range(_struct_count): for i in range(_struct_count):
entry: StructEntry | t.CPtr = _get_struct_entry(i) entry: StructEntry | t.CPtr = _get_struct_entry(i)
if entry is not None and entry.Ty is not None: if entry is not None and entry.Ty is not None:
if entry.Ty is struct_ty: if t.CUInt64T(entry.Ty) == st_lk:
# is 匹配,查找字段 # is 匹配,查找字段
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)
@@ -666,11 +698,12 @@ def is_union_by_type(struct_ty: llvmlite.LLVMType | t.CPtr) -> int:
if struct_ty is None or _struct_table is None: if struct_ty is None or _struct_table is None:
return 0 return 0
ty_name: str = _extract_struct_name(struct_ty) ty_name: str = _extract_struct_name(struct_ty)
st_iu: t.CUInt64T = t.CUInt64T(struct_ty)
for i in range(_struct_count): for i in range(_struct_count):
entry: StructEntry | t.CPtr = _get_struct_entry(i) entry: StructEntry | t.CPtr = _get_struct_entry(i)
if entry is not None and entry.Ty is not None: if entry is not None and entry.Ty is not None:
matched: int = 0 matched: int = 0
if entry.Ty is struct_ty: if t.CUInt64T(entry.Ty) == st_iu:
matched = 1 matched = 1
elif ty_name is not None and entry.Name is not None: elif ty_name is not None and entry.Name is not None:
if string.strcmp(entry.Name, ty_name) == 0: if string.strcmp(entry.Name, ty_name) == 0:
@@ -778,10 +811,11 @@ def get_class_name_by_type(pool: memhub.MemBuddy | t.CPtr,
"""按类型指针查找类名,返回类名字符串或 None""" """按类型指针查找类名,返回类名字符串或 None"""
if struct_ty is None or _struct_table is None: if struct_ty is None or _struct_table is None:
return None return None
st_cn: t.CUInt64T = t.CUInt64T(struct_ty)
for i in range(_struct_count): for i in range(_struct_count):
entry: StructEntry | t.CPtr = _get_struct_entry(i) entry: StructEntry | t.CPtr = _get_struct_entry(i)
if entry is not None and entry.Ty is not None: if entry is not None and entry.Ty is not None:
if entry.Ty is struct_ty: if t.CUInt64T(entry.Ty) == st_cn:
return entry.Name return entry.Name
# 回退: 类型指针比较失败时,遍历所有注册的结构体按名称匹配 # 回退: 类型指针比较失败时,遍历所有注册的结构体按名称匹配
# 提取 struct_ty 的 Name 字段(可能是 "SHA1.ClassName" 格式) # 提取 struct_ty 的 Name 字段(可能是 "SHA1.ClassName" 格式)
+34
View File
@@ -232,10 +232,16 @@ class Translator:
pool: memhub.MemBuddy | t.CPtr = _mbuddy pool: memhub.MemBuddy | t.CPtr = _mbuddy
# 初始化状态 # 初始化状态
stdio.printf("[TRDBG] translate enter, declare_only=%d\n", self._declare_only)
stdio.fflush(None)
self._init_state(pool) self._init_state(pool)
stdio.printf("[TRDBG] after _init_state, funcs=%p\n", self._funcs)
stdio.fflush(None)
# 创建 LLVM 模块 # 创建 LLVM 模块
mod: llvmlite.LLVMModule | t.CPtr = llvmlite.new_module(pool, "main") mod: llvmlite.LLVMModule | t.CPtr = llvmlite.new_module(pool, "main")
stdio.printf("[TRDBG] after new_module, mod=%p\n", mod)
stdio.fflush(None)
if mod is None: if mod is None:
VLogger.error("NewModule returned NULL", "TR") VLogger.error("NewModule returned NULL", "TR")
return 1 return 1
@@ -246,15 +252,21 @@ class Translator:
if triple is None: if triple is None:
triple = "x86_64-pc-windows-msvc" triple = "x86_64-pc-windows-msvc"
llvmlite.module_set_target(mod, triple) llvmlite.module_set_target(mod, triple)
stdio.printf("[TRDBG] after module_set_target\n")
stdio.fflush(None)
# 类型 # 类型
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(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)
stdio.printf("[TRDBG] after types i32=%p i8=%p i8ptr=%p\n", i32_ty, i8_ty, i8_ptr_ty)
stdio.fflush(None)
# 声明 printf # 声明 printf
printf_func: llvmlite.Function | t.CPtr = llvmlite.create_declare( printf_func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
pool, mod, "printf", i32_ty) pool, mod, "printf", i32_ty)
stdio.printf("[TRDBG] after create_declare printf=%p\n", printf_func)
stdio.fflush(None)
if printf_func is None: if printf_func is None:
VLogger.error("CreateDeclare printf returned NULL", "TR") VLogger.error("CreateDeclare printf returned NULL", "TR")
return 1 return 1
@@ -273,6 +285,8 @@ class Translator:
pool, mod, "llvm.va_end", void_ty_decl) pool, mod, "llvm.va_end", void_ty_decl)
if va_end_func is not None: if va_end_func is not None:
llvmlite.add_param(pool, va_end_func, i8_ptr_ty, "ap") llvmlite.add_param(pool, va_end_func, i8_ptr_ty, "ap")
stdio.printf("[TRDBG] after va_start/va_end decl\n")
stdio.fflush(None)
# 声明 malloc(闭包分配用) # 声明 malloc(闭包分配用)
malloc_func: llvmlite.Function | t.CPtr = llvmlite.create_declare( malloc_func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
@@ -280,12 +294,18 @@ class Translator:
if malloc_func is not None: if malloc_func is not None:
i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool) i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool)
llvmlite.add_param(pool, malloc_func, i64_ty, "size") llvmlite.add_param(pool, malloc_func, i64_ty, "size")
stdio.printf("[TRDBG] after malloc decl\n")
stdio.fflush(None)
# 检查用户是否定义了 main 函数 # 检查用户是否定义了 main 函数
has_user_main: int = 0 has_user_main: int = 0
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
stdio.printf("[TRDBG] tree.children=%p\n", ch)
stdio.fflush(None)
if ch is not None: if ch is not None:
cn_count: t.CSizeT = ch.__len__() cn_count: t.CSizeT = ch.__len__()
stdio.printf("[TRDBG] children count=%d\n", cn_count)
stdio.fflush(None)
for ci in range(cn_count): for ci in range(cn_count):
child: ast.AST | t.CPtr = ch.get(ci) child: ast.AST | t.CPtr = ch.get(ci)
if child is not None and child.kind() == ast.ASTKind.FunctionDef: if child is not None and child.kind() == ast.ASTKind.FunctionDef:
@@ -294,6 +314,8 @@ class Translator:
if string.strcmp(fd.name, "main") == 0: if string.strcmp(fd.name, "main") == 0:
has_user_main = 1 has_user_main = 1
break break
stdio.printf("[TRDBG] main check done, has_user_main=%d\n", has_user_main)
stdio.fflush(None)
if self._declare_only != 0: if self._declare_only != 0:
# Phase 1a-pre(2=import扫描) / Phase 1a(1=struct注册): 只处理模块级,不创建 main 函数和 builder # Phase 1a-pre(2=import扫描) / Phase 1a(1=struct注册): 只处理模块级,不创建 main 函数和 builder
@@ -343,9 +365,13 @@ class Translator:
elif kd == ast.ASTKind.ImportFrom: elif kd == ast.ASTKind.ImportFrom:
self.ImportsH.HandleImportFromModule(child) self.ImportsH.HandleImportFromModule(child)
self.ImportsH.HandleImportFromNames(child) self.ImportsH.HandleImportFromNames(child)
stdio.printf("[MLDBG] after import preprocess\n")
stdio.fflush(None)
# 扫描当前模块的 CTypedef 声明(NAME: t.CTypedef = Type), # 扫描当前模块的 CTypedef 声明(NAME: t.CTypedef = Type),
# 注册到动态 CTypedef 表,供 resolve_annotation_type 查询 # 注册到动态 CTypedef 表,供 resolve_annotation_type 查询
HandlesType.ScanCTypedefDeclarations(pool, tree) HandlesType.ScanCTypedefDeclarations(pool, tree)
stdio.printf("[MLDBG] after ScanCTypedefDeclarations\n")
stdio.fflush(None)
# 跨模块 .vpi 注入:加载依赖模块的 .vpi 文件, # 跨模块 .vpi 注入:加载依赖模块的 .vpi 文件,
# 将函数 declare 声明注入到当前模块,解决跨模块函数调用找不到函数的问题 # 将函数 declare 声明注入到当前模块,解决跨模块函数调用找不到函数的问题
# 严格保证 declare_only == 0 时才注入(避免 Phase A-pre-inc 死锁) # 严格保证 declare_only == 0 时才注入(避免 Phase A-pre-inc 死锁)
@@ -354,6 +380,8 @@ class Translator:
StubMerger.LoadDepVpiIntoModule( StubMerger.LoadDepVpiIntoModule(
pool, mod, self._imported_modules, self._from_imports, pool, mod, self._imported_modules, self._from_imports,
HandlesExprCall._g_temp_dir, self) HandlesExprCall._g_temp_dir, self)
stdio.printf("[MLDBG] after LoadDepVpiIntoModule\n")
stdio.fflush(None)
# 预注册模块级变量(AnnAssign/Assign)到 SymTab # 预注册模块级变量(AnnAssign/Assign)到 SymTab
# 解决时序问题:class Logger 的 __init__ 引用 _mbuddy 时, # 解决时序问题:class Logger 的 __init__ 引用 _mbuddy 时,
# _mbuddy 的 AnnAssign 在 AST 中位于 class Logger 之后, # _mbuddy 的 AnnAssign 在 AST 中位于 class Logger 之后,
@@ -369,9 +397,15 @@ class Translator:
kd_mv: int = child.kind() kd_mv: int = child.kind()
if kd_mv == ast.ASTKind.AnnAssign or kd_mv == ast.ASTKind.Assign: if kd_mv == ast.ASTKind.AnnAssign or kd_mv == ast.ASTKind.Assign:
HandlesMain.handle_module_level_var(self, child) HandlesMain.handle_module_level_var(self, child)
stdio.printf("[MLDBG] after module-level var pre-reg\n")
stdio.fflush(None)
# 创建前向声明 # 创建前向声明
HandlesFunctions.forward_declare_functions(self, tree) HandlesFunctions.forward_declare_functions(self, tree)
stdio.printf("[MLDBG] after forward_declare_functions\n")
stdio.fflush(None)
added: int = HandlesMain.translate_children(self, tree) added: int = HandlesMain.translate_children(self, tree)
stdio.printf("[MLDBG] after translate_children\n")
stdio.fflush(None)
# ============================================================ # ============================================================
# IR 输出 # IR 输出
+7
View File
@@ -172,6 +172,7 @@ def compute_file_sha1(pool: memhub.MemBuddy | t.CPtr,
bytes_read: t.CInt64T = f.read_all(buf, BUF_SIZE) bytes_read: t.CInt64T = f.read_all(buf, BUF_SIZE)
f.close() f.close()
if bytes_read <= 0: if bytes_read <= 0:
stdlib.free(buf)
return None return None
# 原地去除 \r(CRLF → LF),与 Projectrans.py 文本模式读取一致 # 原地去除 \r(CRLF → LF),与 Projectrans.py 文本模式读取一致
@@ -190,17 +191,21 @@ def compute_file_sha1(pool: memhub.MemBuddy | t.CPtr,
# 计算 SHA1 # 计算 SHA1
ctx: hashlib.sha1 | t.CPtr = hashlib.sha1() ctx: hashlib.sha1 | t.CPtr = hashlib.sha1()
if ctx is None: if ctx is None:
stdlib.free(buf)
return None return None
ctx.update(buf) ctx.update(buf)
digest: bytes = stdlib.malloc(hashlib.SHA1_DIGEST_LEN) digest: bytes = stdlib.malloc(hashlib.SHA1_DIGEST_LEN)
if digest is None: if digest is None:
stdlib.free(buf)
return None return None
ctx.final(digest) ctx.final(digest)
# 转为十六进制字符串(取前 8 字节 = 16 个十六进制字符) # 转为十六进制字符串(取前 8 字节 = 16 个十六进制字符)
hex_buf: str = stdlib.malloc(17) hex_buf: str = stdlib.malloc(17)
if hex_buf is None: if hex_buf is None:
stdlib.free(buf)
stdlib.free(digest)
return None return None
for i in range(8): for i in range(8):
hi: int = (digest[i] >> 4) & 0xF hi: int = (digest[i] >> 4) & 0xF
@@ -214,6 +219,8 @@ def compute_file_sha1(pool: memhub.MemBuddy | t.CPtr,
else: else:
hex_buf[i * 2 + 1] = 'a' + (lo - 10) hex_buf[i * 2 + 1] = 'a' + (lo - 10)
hex_buf[16] = '\0' hex_buf[16] = '\0'
stdlib.free(buf)
stdlib.free(digest)
return hex_buf return hex_buf
+63
View File
@@ -546,6 +546,8 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
# 初始化 AST 表(只需一次) # 初始化 AST 表(只需一次)
ast._init_tables(mb) ast._init_tables(mb)
stdio.printf("[MEM-DBG] 扫描完成后: total=%zu used=%zu free=%zu free_blocks=%zu\n",
mb.usable_size, mb.used_bytes(), mb.free_bytes(), mb.free_count())
# FileEntry 结构体大小(Phase 1a 和 1b 共用) # FileEntry 结构体大小(Phase 1a 和 1b 共用)
entry_size: t.CSizeT = IncludesScanner.FileEntry.__sizeof__() entry_size: t.CSizeT = IncludesScanner.FileEntry.__sizeof__()
@@ -561,6 +563,9 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
p1a_skipped: int = 0 p1a_skipped: int = 0
p1a_failed: int = 0 p1a_failed: int = 0
stdio.printf("[MEM-DBG] Phase 1a-pre 扫描 import 前: total=%zu used=%zu free=%zu free_blocks=%zu\n",
mb.usable_size, mb.used_bytes(), mb.free_bytes(), mb.free_count())
for i in range(result.Count): for i in range(result.Count):
entry_addr_a: t.CUInt64T = t.CUInt64T(result.Entries) + i * entry_size entry_addr_a: t.CUInt64T = t.CUInt64T(result.Entries) + i * entry_size
entry_a: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(entry_addr_a, t.CPtr)) entry_a: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(entry_addr_a, t.CPtr))
@@ -577,6 +582,9 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
p1a_skipped += 1 p1a_skipped += 1
continue continue
stdio.printf("[MEM-DBG] Phase 1a-pre 翻译前: total=%zu used=%zu free=%zu free_blocks=%zu\n",
mb.usable_size, mb.used_bytes(), mb.free_bytes(), mb.free_count())
# 读取文件内容 # 读取文件内容
file_path_a: str = entry_a.Path file_path_a: str = entry_a.Path
f_a: fileio.File | t.CPtr = fileio.File(file_path_a, fileio.MODE.R) f_a: fileio.File | t.CPtr = fileio.File(file_path_a, fileio.MODE.R)
@@ -660,6 +668,9 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
stdlib.free(src_buf_a) stdlib.free(src_buf_a)
stdio.printf("[MEM-DBG] Phase 1a-pre 扫描 import 完成: total=%zu used=%zu free=%zu free_blocks=%zu\n",
mb.usable_size, mb.used_bytes(), mb.free_bytes(), mb.free_count())
# ============================================================ # ============================================================
# 依赖图按需翻译:构建可达 SHA1 集合 # 依赖图按需翻译:构建可达 SHA1 集合
# #
@@ -776,6 +787,9 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
viperlib.snprintf(fb_gpre, 1024, "预注册 %d 个泛型类模板文件", generic_file_count) viperlib.snprintf(fb_gpre, 1024, "预注册 %d 个泛型类模板文件", generic_file_count)
VLogger.info(fb_gpre, "Phase1") VLogger.info(fb_gpre, "Phase1")
stdio.printf("[MEM-DBG] 泛型模板预注册前: total=%zu used=%zu free=%zu free_blocks=%zu\n",
mb.usable_size, mb.used_bytes(), mb.free_bytes(), mb.free_count())
for gi in range(generic_file_count): for gi in range(generic_file_count):
gi_addr_p: t.CUInt64T = t.CUInt64T(generic_file_indices) + gi * 4 gi_addr_p: t.CUInt64T = t.CUInt64T(generic_file_indices) + gi * 4
gi_ptr_p: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(gi_addr_p, t.CPtr)) gi_ptr_p: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(gi_addr_p, t.CPtr))
@@ -839,6 +853,9 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
stdlib.free(gen_tr._nonlocal_names) stdlib.free(gen_tr._nonlocal_names)
stdlib.free(gen_src) stdlib.free(gen_src)
stdio.printf("[MEM-DBG] 泛型模板预注册完成: total=%zu used=%zu free=%zu free_blocks=%zu\n",
mb.usable_size, mb.used_bytes(), mb.free_bytes(), mb.free_count())
# 遍历文件:优先使用拓扑顺序,回退到字母序 # 遍历文件:优先使用拓扑顺序,回退到字母序
iter_count: int = topo_count if topo_count > 0 else result.Count iter_count: int = topo_count if topo_count > 0 else result.Count
for i in range(iter_count): for i in range(iter_count):
@@ -924,6 +941,8 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
HandlesType.clear_cdefine_constants() HandlesType.clear_cdefine_constants()
HandlesType.clear_ctypedefs() HandlesType.clear_ctypedefs()
HandlesStruct.reset_visible_structs(mb, 0) HandlesStruct.reset_visible_structs(mb, 0)
stdio.printf("[MEM-DBG] Phase 1a struct 注册前: total=%zu used=%zu free=%zu free_blocks=%zu\n",
mb.usable_size, mb.used_bytes(), mb.free_bytes(), mb.free_count())
ret_r: int = tr_r.translate(tree_r) ret_r: int = tr_r.translate(tree_r)
if ret_r != 0: if ret_r != 0:
p1a_fl += 1 p1a_fl += 1
@@ -956,6 +975,18 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
# ============================================================ # ============================================================
# Phase 1b: 全量翻译(struct 已注册,走 existing 路径翻译方法体) # Phase 1b: 全量翻译(struct 已注册,走 existing 路径翻译方法体)
# ============================================================ # ============================================================
# OOM 回收:1a-pre/泛型预注册/1a 全部结束后打 mark1,
# 所有跨文件持久表(_struct_table/_enum_table/_generic_class_nodes/
# _renum_*/关键字表等)都落在 mark1 之前。
# 1b 每文件翻译完后 reset_to(mark1) 回收该文件的 AST/IR/Handler/dump 临时,
# 避免 90 文件累积导致 1GB 池 OOM。
mark1: t.CSizeT = mb.mark()
stdio.printf("[MEM-DBG] Phase 1b 打点 mark1=%zu: total=%zu used=%zu free=%zu free_blocks=%zu\n",
mark1, mb.usable_size, mb.used_bytes(), mb.free_bytes(), mb.free_count())
# 1b 阶段新注册的 struct/enum 条目改 stdlib 分配(跨文件永久存活,不被 reset 回收)
HandlesStruct.set_stdlib_alloc(1)
# 遍历每个文件 # 遍历每个文件
translated: int = 0 translated: int = 0
skipped: int = 0 skipped: int = 0
@@ -1020,7 +1051,14 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
viperlib.snprintf(fb, 1024, "翻译: %s (sha1=%s)", rp, sha1) viperlib.snprintf(fb, 1024, "翻译: %s (sha1=%s)", rp, sha1)
VLogger.info(fb, "Phase1") VLogger.info(fb, "Phase1")
stdio.printf("[MEM-DBG] Phase 1b 翻译前: total=%zu used=%zu free=%zu free_blocks=%zu\n",
mb.usable_size, mb.used_bytes(), mb.free_bytes(), mb.free_count())
stdio.printf("[STDBG] stepA before free(stub_path)\n")
stdio.fflush(None)
stdlib.free(stub_path) stdlib.free(stub_path)
stdio.printf("[STDBG] stepB after free(stub_path)\n")
stdio.fflush(None)
# 读取文件内容 # 读取文件内容
file_path: str = entry.Path file_path: str = entry.Path
@@ -1060,6 +1098,8 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
src_buf[bytes_read] = 0 src_buf[bytes_read] = 0
else: else:
src_buf[SRC_BUF_SIZE - 1] = 0 src_buf[SRC_BUF_SIZE - 1] = 0
stdio.printf("[STDBG] stepC after file read, bytes_read=%d\n", bytes_read)
stdio.fflush(None)
# 解析 AST # 解析 AST
lx: ast.Lexer | t.CPtr = ast.new_lexer(mb) lx: ast.Lexer | t.CPtr = ast.new_lexer(mb)
@@ -1068,8 +1108,14 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
failed += 1 failed += 1
continue continue
ast._lexer_init(lx, src_buf, mb) ast._lexer_init(lx, src_buf, mb)
stdio.printf("[STDBG] stepD before tokenize\n")
stdio.fflush(None)
tokens: ast.Token | t.CPtr = ast.tokenize(lx) tokens: ast.Token | t.CPtr = ast.tokenize(lx)
stdio.printf("[STDBG] stepE after tokenize\n")
stdio.fflush(None)
tree: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens) tree: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens)
stdio.printf("[STDBG] stepF after parse_tokens, tree=%p\n", tree)
stdio.fflush(None)
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:
@@ -1083,6 +1129,8 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
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)
stdio.printf("[STDBG] stepG after _GeneratePyiFromAst, pyi_pos=%d\n", pyi_pos)
stdio.fflush(None)
if pyi_pos > 0: if pyi_pos > 0:
pyi_path: str = StubMerger._sliced_path(temp_dir, dir_len, sha1, "vpi") pyi_path: str = StubMerger._sliced_path(temp_dir, dir_len, sha1, "vpi")
if pyi_path is not None: if pyi_path is not None:
@@ -1106,7 +1154,11 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
HandlesType.clear_cdefine_constants() HandlesType.clear_cdefine_constants()
HandlesType.clear_ctypedefs() HandlesType.clear_ctypedefs()
HandlesStruct.reset_visible_structs(mb, 0) HandlesStruct.reset_visible_structs(mb, 0)
stdio.printf("[STDBG] stepH before tr.translate\n")
stdio.fflush(None)
ret: int = tr.translate(tree) ret: int = tr.translate(tree)
stdio.printf("[STDBG] stepI after tr.translate, ret=%d\n", ret)
stdio.fflush(None)
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:
@@ -1133,6 +1185,8 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
continue continue
tr.dump_ir(stub_buf, PHASE1_IR_SIZE, llvmlite.OUTPUT_STUB) tr.dump_ir(stub_buf, PHASE1_IR_SIZE, llvmlite.OUTPUT_STUB)
stub_len: t.CSizeT = string.strlen(stub_buf) stub_len: t.CSizeT = string.strlen(stub_buf)
stdio.printf("[MEM-DBG] Phase 1b dump_ir(stub) done, len=%d used=%zu\n",
stub_len, mb.used_bytes())
# save stub.ll # save stub.ll
dir_len_p1: t.CSizeT = string.strlen(temp_dir) dir_len_p1: t.CSizeT = string.strlen(temp_dir)
@@ -1157,6 +1211,8 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
continue continue
tr.dump_ir(text_buf, PHASE1_IR_SIZE, llvmlite.OUTPUT_TEXT) tr.dump_ir(text_buf, PHASE1_IR_SIZE, llvmlite.OUTPUT_TEXT)
text_len: t.CSizeT = string.strlen(text_buf) text_len: t.CSizeT = string.strlen(text_buf)
stdio.printf("[MEM-DBG] Phase 1b dump_ir(text) done, len=%d used=%zu\n",
text_len, mb.used_bytes())
# save text.ll # save text.ll
text_path_p1: str = StubMerger._sliced_path(temp_dir, dir_len_p1, sha1, "text.ll") text_path_p1: str = StubMerger._sliced_path(temp_dir, dir_len_p1, sha1, "text.ll")
@@ -1190,6 +1246,13 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
translated += 1 translated += 1
# OOM 回收:回收本文件翻译产生的瞬时数据(AST/tokens/lexer/IR/Handler/dump 临时)
# 持久表(struct/enum/REnum/spec 缓存/全局函数名等)已迁出 reset 区间(stdlib),
# reset_to(mark1) 只回收 mark1 之后分配、未被单独 free 的块。
stdio.printf("[MEM-DBG] Phase 1b 翻译后 reset 前: used=%zu\n", mb.used_bytes())
mb.reset_to(mark1)
stdio.printf("[MEM-DBG] Phase 1b reset 完成: used=%zu\n", mb.used_bytes())
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 失败=%d", translated, skipped, failed) viperlib.snprintf(fb, 1024, "完成: 翻译=%d 跳过=%d 失败=%d", translated, skipped, failed)
+1
View File
@@ -177,6 +177,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
return 1 return 1
# === 栈金丝雀检查(全局变量,不影响栈布局)=== # === 栈金丝雀检查(全局变量,不影响栈布局)===
global _g_canary
_g_canary = 305419896 _g_canary = 305419896
fb: t.CChar | t.CPtr = VLogger.fmt_buf() fb: t.CChar | t.CPtr = VLogger.fmt_buf()