基本稳定可以编译 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:
"""从本地 CDefine 表查找常量值(用于 .vpi 生成时的 BinOp 计算)"""
import lib.core.Handles.HandlesType as HandlesType
global _g_pyi_cdefine_found
val: int = HandlesType.lookup_cdefine_constant(name)
if HandlesType.is_cdefine_found() != 0:
_g_pyi_cdefine_found = 1
+1
View File
@@ -7,6 +7,7 @@ import stdio
import sys
import memhub
import llvmlite
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesType as HandlesType
+298 -43
View File
@@ -5,6 +5,7 @@ import llvmlite
import memhub
import string
import stdio
import stdlib
import viperlib
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesTranslator as HT
@@ -1046,6 +1047,12 @@ def _translate_union_def(trans: HT.Translator | t.CPtr,
VLogger.error(fb, "UNION")
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)
@@ -1332,6 +1339,13 @@ def _translate_renum_def(trans: HT.Translator | t.CPtr,
VLogger.error(fb4, "RENUM")
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)
@@ -1450,11 +1464,14 @@ def _register_renum_variants(pool: memhub.MemBuddy | t.CPtr,
return
# 懒初始化表(首次注册时分配)
# 注意: 必须用 stdlib 分配——这些表在 1b 阶段(mark1 之后)首次分配,
# 若用 pool 会被 reset_to(mark1) 回收导致悬空(LLVMType 的 match 在
# parser.vp 等后续文件翻译时访问已回收的表 → 崩溃)。
if _renum_class_names is None:
_renum_class_names = pool.alloc(8 * RENUM_CLASS_MAX)
_renum_class_variant_counts = pool.alloc(8 * RENUM_CLASS_MAX)
_renum_variant_names = pool.alloc(8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS)
_renum_variant_tags = pool.alloc(8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS)
_renum_class_names = stdlib.malloc(8 * RENUM_CLASS_MAX)
_renum_class_variant_counts = stdlib.malloc(8 * RENUM_CLASS_MAX)
_renum_variant_names = stdlib.malloc(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
or _renum_variant_names is None or _renum_variant_tags is 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_names: list[str] | t.CPtr = None
SPEC_CACHE_MAX: t.CDefine = 512
_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:
"""查找已缓存的特化名,未找到返回 None"""
if _spec_keys is None or spec_key is None:
return None
n: t.CSizeT = _spec_keys.__len__()
i: t.CSizeT
for i in range(n):
k: str = _spec_keys.get(i)
if k is not None and string.strcmp(k, spec_key) == 0:
# 用局部变量接收 list.get() 结果,触发旧编译器 inttoptr 类型转换
spec_nm: str = _spec_names.get(i)
return spec_nm
i: int
for i in range(_spec_count):
key_addr: t.CSizeT = _spec_keys[i]
if key_addr != 0:
k: str = (str | t.CPtr)(t.CVoid(key_addr, t.CPtr))
if k is not None and string.strcmp(k, spec_key) == 0:
name_addr: t.CSizeT = _spec_names[i]
if name_addr != 0:
return (str | t.CPtr)(t.CVoid(name_addr, t.CPtr))
return None
def _cache_spec(pool: memhub.MemBuddy | t.CPtr, spec_key: str, spec_name: str):
"""缓存特化结果"""
global _spec_keys, _spec_names
"""缓存特化结果(stdlib 深拷贝存储,跨文件安全)"""
global _spec_keys, _spec_names, _spec_count
if spec_key is None or spec_name is None:
return
if _spec_keys is None:
_spec_keys = list[str](pool, 8)
_spec_names = list[str](pool, 8)
_spec_keys.append(spec_key)
_spec_names.append(spec_name)
_spec_keys = stdlib.malloc(SPEC_CACHE_MAX * 8)
_spec_names = stdlib.malloc(SPEC_CACHE_MAX * 8)
if _spec_keys is None or _spec_names is None:
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,
@@ -2082,6 +2124,10 @@ def _specialize_generic_class(trans: HT.Translator | t.CPtr,
if trans._declare_only == 0:
pre_existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name)
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
spec_cd_pre: ast.ClassDef | t.CPtr = _clone_classdef_for_spec(
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:
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
class_name: str = cd.name
@@ -2244,6 +2293,9 @@ def translate_class_def(trans: HT.Translator | t.CPtr,
# 检查是否已注册(用 SHA1 区分跨模块同名类)
existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
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:
# BUG 5 方案1修改点2:existing 时字段完整性检查
# 结构体已注册,但需验证字段信息是否完整(防止 i32 回退残留或注册不完整)
@@ -2255,6 +2307,22 @@ def translate_class_def(trans: HT.Translator | t.CPtr,
"InternalCompilerError")
# 结构体已注册(Phase A-pre 多遍扫描或 Phase B 重新翻译),但仍需在当前模块中翻译方法
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: 将已存在的命名结构体注册到当前模块(输出类型定义行)
llvmlite.module_add_named_type(trans.Module, pool, existing.Ty)
# 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
# ============================================================
_trigger_base_specialization(trans, cd)
stdio.printf("[VTDBG-STEP] class=%s trigger_base_spec done\n", class_name)
# ============================================================
# VTable 检测:判断是否启用虚表
# ============================================================
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)
is_novtable_deco: int = 0
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:
parent_check = HandlesStruct.find_struct(parent_name)
if parent_check is None:
stdio.printf("[VTDBG-STEP] class=%s parent %s not registered, defer\n",
class_name, parent_name)
return 0
stdio.printf("[VTDBG-STEP] class=%s parent_check done, parent=%s\n",
class_name, parent_name)
# ============================================================
# 1. 遍历 class body,收集字段信息
@@ -2325,6 +2400,7 @@ def translate_class_def(trans: HT.Translator | t.CPtr,
# ============================================================
# 1.5 继承父类字段(字段展平)
# ============================================================
#
# 父类字段排在子类字段之前,结构体布局:
# [vtable_ptr?, parent_field1, ..., child_field1, ...]
@@ -2514,12 +2590,21 @@ def translate_class_def(trans: HT.Translator | t.CPtr,
prev_node = pnode
# 构造命名结构体类型名: "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
if trans.ModuleSha1 is not None:
name_buf: t.CChar | t.CPtr = pool.alloc(64)
if name_buf is not None:
viperlib.snprintf(name_buf, 64, "%s.%s", trans.ModuleSha1, class_name)
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(命名结构体)
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")
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 { ... } 定义行)
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
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_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)
_vtable_strcat(buf, buf_size, ret_buf)
_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)
first: int = 1
param_buf: t.CChar | t.CPtr = pool.alloc(128)
_pc: int = 0
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:
_vtable_strcat(buf, buf_size, ", ")
if param_buf is not None:
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)
stdio.printf("[VTDBG-FMT] p%d ty=%p\n", _pc, param_ty)
stdio.fflush(None)
if param_ty is not None:
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)
stdio.printf("[VTDBG-FMT] p%d next...\n", _pc)
stdio.fflush(None)
cur = llvmlite.param_get_next(cur)
first = 0
_vtable_strcat(buf, buf_size, ")")
stdio.printf("[VTDBG-FMT] done\n")
stdio.fflush(None)
return 1
@@ -2710,16 +2827,20 @@ def _generate_vtable(trans: HT.Translator | t.CPtr,
pool: memhub.MemBuddy | t.CPtr = trans.Pool
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
if children is None:
return 0
cn: t.CSizeT = children.__len__()
# 1. 收集虚方法信息
full_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * VTBL_METHOD_MAX)
method_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * VTBL_METHOD_MAX)
# stdlib 分配:method_names_buf 存到 StructEntry.VTableMethods(跨文件永久存活),
# 必须迁出 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=当前类方法)
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:
return 0
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
if vt_parent_entry is not None:
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:
for pvi in range(parent_vt_count):
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)
# 复制方法名(短名)
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:
string.strcpy(pmname_buf, pmethod_name)
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_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:
string.strcpy(mname_buf, mname)
method_names_buf[method_count] = t.CSizeT(mname_buf)
@@ -2854,9 +2979,12 @@ def _generate_vtable(trans: HT.Translator | t.CPtr,
method_count += 1
if method_count == 0:
stdio.printf("[VTDBG-STEP] class=%s collect done, method_count=0 -> return\n", class_name)
return 0
# 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_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
# 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:
return 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):
if i > 0:
_vtable_strcat(init_buf, 4096, ", ")
_vtable_strcat(init_buf, 16384, ", ")
full_name_addr: t.CSizeT = full_names_buf[i]
if full_name_addr == 0:
_vtable_strcat(init_buf, 4096, "i8* null")
_vtable_strcat(init_buf, 16384, "i8* null")
continue
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:
func = HandlesExprCall.find_func_global(full_name)
if func is None:
_vtable_strcat(init_buf, 4096, "i8* null")
# func 可能已被 1b reset_to(mark1) 回收(跨模块继承方法在定义文件翻译后被 reset)。
# 悬空指针非 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
# 构造函数类型字符串
func_ty_buf: t.CChar | t.CPtr = pool.alloc(512)
if func_ty_buf is None:
_vtable_strcat(init_buf, 4096, "i8* null")
_vtable_strcat(init_buf, 16384, "i8* null")
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)
# 构造 bitcast 字符串: i8* bitcast (func_ty* @mangled to i8*)
_vtable_strcat(init_buf, 4096, "i8* bitcast (")
_vtable_strcat(init_buf, 4096, func_ty_buf)
_vtable_strcat(init_buf, 4096, "* @")
stdio.printf("[VTDBG-STEP] class=%s method[%d] bitcast start, ftb=%p mn=%p\n",
class_name, i, func_ty_buf, mangled_name)
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:
_vtable_strcat(init_buf, 4096, "\"")
_vtable_strcat(init_buf, 4096, mangled_name)
_vtable_strcat(init_buf, 4096, "\"")
_vtable_strcat(init_buf, 16384, "\"")
_vtable_strcat(init_buf, 16384, mangled_name)
_vtable_strcat(init_buf, 16384, "\"")
else:
_vtable_strcat(init_buf, 4096, mangled_name)
_vtable_strcat(init_buf, 4096, " to i8*)")
_vtable_strcat(init_buf, 16384, mangled_name)
_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 全局变量名
vtable_name_buf: t.CChar | t.CPtr = pool.alloc(128)
@@ -2941,10 +3113,16 @@ def _generate_vtable(trans: HT.Translator | t.CPtr,
return 0
viperlib.snprintf(vtable_name_buf, 128, "%s.vtable", class_name)
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. 创建全局变量
gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(
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:
return 0
gv.Initializer = init_buf
@@ -2953,11 +3131,18 @@ def _generate_vtable(trans: HT.Translator | t.CPtr,
# 添加到模块
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 找错)
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:
vt_self_entry.VTableMethods = method_names_buf
vt_self_entry.VTableMethodCount = method_count
stdio.printf("[VTDBG-STEP] class=%s VTableMethods stored\n", class_name)
stdio.fflush(None)
return 0
@@ -3051,6 +3236,8 @@ def _translate_oop_methods(trans: HT.Translator | t.CPtr,
if stmt.kind() == ast.ASTKind.FunctionDef:
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt)
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)
# 如果有虚表,先生成 VTable 全局变量(设置 VTableMethodCount)
@@ -3070,6 +3257,7 @@ def _translate_oop_methods(trans: HT.Translator | t.CPtr,
if oop_entry is not None:
oop_entry.MethodsEmitted = 1
stdio.printf("[VTDBG-STEP] class=%s oop_methods done\n", class_name)
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)
method_name: str = fd.name
stdio.printf("[VTDBG-STEP] class=%s translate_method enter: %s\n",
class_name, method_name)
# 构建方法全名: ClassName.method_name
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 作为查找名,支持后缀匹配)
max_funcs: int = 256
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
# 添加 self 参数(Ptr(struct_ty))
@@ -3192,6 +3383,9 @@ def _translate_method(trans: HT.Translator | t.CPtr,
viperlib.snprintf(pname, 32, "%%%s", arg.arg)
llvmlite.add_param(pool, func, param_ty, pname)
# 参数添加完成,补全全局函数表的 TypeStr(供 vtable 在 func 被 reset 后使用)
HandlesExprCall.update_global_func_typestr(pool, full_name, func)
# 创建 entry 块
entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry")
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:
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.HandlesVar as HandlesVar
import lib.core.Handles.HandlesExpr as HandlesExpr
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
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs
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)
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__
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
viperlib.snprintf(full_name_buf, 128, "%s.__before_init__", class_name)
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)
stdio.printf("[BI-DBG] step5 mangled=%s\n", mangled_name)
stdio.fflush(None)
# 创建函数
func: llvmlite.Function | t.CPtr = llvmlite.create_function(
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:
return 0
# 注册到函数表
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
# 添加 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_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:
return 0
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:
return 0
llvmlite.position_at_end(func_builder, entry_blk)
# 注册 self 为 SSA 值
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
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:
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)
# 用 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)
stdio.printf("[BI-DBG] step16 find_struct_by_type done, bi_entry=%p\n", bi_entry)
stdio.fflush(None)
bi_has_vt: int = 0
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
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:
vt_method_count: int = 0
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 找错)
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):
fe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry(
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:
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(
func_builder, pool, mod, fe.DefaultVal, None, 0, trans)
if default_val is None:
stdio.printf("[VTDBG-FIELD] class=%s fi=%d translate default -> None\n",
class_name, fi)
continue
stdio.printf("[VTDBG-STEP] class=%s before_init: field[%d] default translated\n",
class_name, fi)
# GEP 到字段
field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
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)
# 3. ret void
stdio.printf("[VTDBG-STEP] class=%s before_init: done, ret void\n", class_name)
llvmlite.build_ret_void(func_builder)
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)
if lhs_ptr_level != rhs_ptr_level:
# 类型不匹配:数值vs指针 或 不同级指针
VLogger.error(
"比较类型不匹配: lhs 指针层级=%d, rhs 指针层级=%d (禁止数值与指针、不同级指针比较)" % (lhs_ptr_level, rhs_ptr_level),
"Compare")
# 用 fmt_buf 构造可读消息(Viper % 格式化在部分路径生成 null)
fmt_msg: t.CChar | t.CPtr = VLogger.fmt_buf()
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
else:
# 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:
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
# 优先用 stdlib 常量快照重建(mdf_gd.Defaults 的 pool 内 AST 可能已被 reset 回收)
mdf_val: llvmlite.Value | t.CPtr = None
if mdf_gd is not None:
mdf_val = _build_const_from_snapshot(
pool, mod, mdf_gd, mdf_di, trans, builder)
if mdf_val is 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))
mdf_node: ast.AST | t.CPtr = mdf_defaults_list.get(mdf_di)
if mdf_node is not None:
mdf_val = 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)
@@ -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:
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
# 优先用 stdlib 常量快照重建(mdf_gd.Defaults 的 pool 内 AST 可能已被 reset 回收)
mdf_val: llvmlite.Value | t.CPtr = None
if mdf_gd is not None:
mdf_val = _build_const_from_snapshot(
pool, mod, mdf_gd, mdf_di, trans, builder)
if mdf_val is 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))
mdf_node: ast.AST | t.CPtr = mdf_defaults_list.get(mdf_di)
if mdf_node is not None:
mdf_val = 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)
@@ -4947,18 +4959,24 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr,
while df_di < df_default_count:
df_param_idx: int = df_offset + df_di
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))
df_default_node: ast.AST | t.CPtr = df_defaults_list.get(df_di)
if df_default_node is not None:
df_arg_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
builder, pool, mod, df_default_node, None, 0, trans)
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
# 优先用 stdlib 常量快照重建(gd_entry.Defaults 的 pool 内 AST 可能已被 reset 回收)
df_arg_val: llvmlite.Value | t.CPtr = None
if gd_entry is not None:
df_arg_val = _build_const_from_snapshot(
pool, mod, gd_entry, df_di, trans, builder)
if df_arg_val is 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))
df_default_node: ast.AST | t.CPtr = df_defaults_list.get(df_di)
if df_default_node is not None:
df_arg_val = HandlesExpr.translate_value(
builder, pool, mod, df_default_node, None, 0, trans)
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
# 使用模块中的实际函数名(可能带 SHA1 前缀,如 "83210a72e829a086.atoi")
@@ -5569,6 +5587,10 @@ class FuncEntry:
Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr]),None=无默认值
DefaultCount: int # 默认值数量
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,
defaults: t.CVoid | t.CPtr = None,
default_count: int = 0,
param_count: int = 0) -> int:
param_count: int = 0,
pool: memhub.MemBuddy | t.CPtr = None) -> int:
"""添加函数到函数表,返回 0 成功
Args:
defaults: ast.Arguments.defaults 列表节点指针,None=无默认值
default_count: 默认值数量(len(defaults))
param_count: 形参数量(不含 self,len(args.args))
pool: 内存池(用于生成 TypeStr;None 时 TypeStr 为空,vtable 回退读 Func 对象)
"""
if name is None or func is None or funcs is None:
return 1
@@ -5631,7 +5655,7 @@ def add_func_to_table(funcs: FuncEntry | t.CPtr,
entry.DefaultCount = default_count
entry.ParamCount = param_count
# 同时注册到全局函数表(供跨模块 vtable 初始化查找)
_register_global_func(name, func)
_register_global_func(name, func, pool)
# 同时注册到全局默认参数表(供跨模块调用时填充默认值)
if default_count > 0:
_register_global_defaults(name, defaults, default_count, param_count)
@@ -5662,10 +5686,64 @@ def _init_global_func_table() -> int:
_global_func_count = 0
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 成功
直接操作全局表,不调用 add_func_to_table,避免递归。
pool 用于生成 TypeStr(None 时 TypeStr 为空)。
"""
global _global_func_count
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_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.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
# TypeStr 不在此生成:函数参数在 add_func_to_table 之后才添加,
# 需由调用方在参数添加完成后调用 update_global_func_typestr 补全。
_global_func_count += 1
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:
"""在全局函数表中按名称查找,返回 Function 指针或 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)
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:
"""默认参数表条目"""
Name: str
Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr])
Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr])(pool 内,可能被 reset)
DefaultCount: int
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_count: int = 0
@@ -5730,7 +5855,11 @@ def _register_global_defaults(name: str,
defaults: t.CVoid | t.CPtr,
default_count: int,
param_count: int) -> int:
"""注册函数默认参数到全局表,返回 0 成功"""
"""注册函数默认参数到全局表,返回 0 成功
注册时提取每个默认值 Constant 的常量快照到 stdlib(ConstKinds/ConstInts/ConstStrs),
跨模块调用时优先用快照重建常量 IR,避免读取被 reset 回收的 pool 内 AST。
"""
global _global_defaults_count
if name is None or defaults is None:
return 1
@@ -5744,26 +5873,96 @@ def _register_global_defaults(name: str,
entry_size: t.CSizeT = FuncDefaultsEntry.__sizeof__()
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.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.DefaultCount = default_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
return 0
def find_func_defaults(name: str) -> FuncDefaultsEntry | t.CPtr:
"""按函数名查找默认参数信息,返回 FuncDefaultsEntry 或 None"""
if name is None or _global_defaults is None:
return None
entry_size: t.CSizeT = FuncDefaultsEntry.__sizeof__()
i: int = 0
while i < _global_defaults_count:
entry_addr: t.CUInt64T = t.CUInt64T(_global_defaults) + i * entry_size
entry: FuncDefaultsEntry | t.CPtr = (FuncDefaultsEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
if entry.Name is not None:
if string.strcmp(entry.Name, name) == 0:
return entry
i += 1
def find_func_defaults(name: str) -> FuncDefaultsEntry | t.CPtr:
"""按函数名查找默认参数信息,返回 FuncDefaultsEntry 或 None"""
if name is None or _global_defaults is None:
return None
entry_size: t.CSizeT = FuncDefaultsEntry.__sizeof__()
i: int = 0
while i < _global_defaults_count:
entry_addr: t.CUInt64T = t.CUInt64T(_global_defaults) + i * entry_size
entry: FuncDefaultsEntry | t.CPtr = (FuncDefaultsEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
if entry.Name is not None:
if string.strcmp(entry.Name, name) == 0:
return entry
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
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
cur_count: int = trans._func_count
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
# 注册 CExport 函数到全局表
@@ -410,6 +411,9 @@ def forward_declare_functions(trans: HT.Translator | t.CPtr,
if ags.vararg is not None:
func.IsVarArg = 1
# 参数添加完成,补全全局函数表的 TypeStr(供 vtable 在 func 被 reset 后使用)
HandlesExprCall.update_global_func_typestr(trans.Pool, fd.name, func)
return 0
@@ -497,7 +501,7 @@ def translate_function_def(trans: HT.Translator | t.CPtr,
# 注册到函数表
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
# 添加参数(支持类型注解)
@@ -530,6 +534,9 @@ def translate_function_def(trans: HT.Translator | t.CPtr,
if func_attrs_e is not None:
llvmlite.function_set_attrs(func, func_attrs_e)
# 参数添加完成,补全全局函数表的 TypeStr
HandlesExprCall.update_global_func_typestr(pool, fd.name, func)
return 0
# args_node 用于后续 alloca 创建,提前赋值
@@ -576,7 +583,8 @@ def translate_function_def(trans: HT.Translator | t.CPtr,
# 注册到函数表
max_funcs: int = 256
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
# 添加参数(支持类型注解)
@@ -607,6 +615,9 @@ def translate_function_def(trans: HT.Translator | t.CPtr,
if ags.vararg is not None:
func.IsVarArg = 1
# 参数添加完成,补全全局函数表的 TypeStr
HandlesExprCall.update_global_func_typestr(trans.Pool, fd.name, func)
# 创建 entry 块
entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry")
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)
if child is None: continue
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 已预处理导入语句,
# 此处跳过避免重复处理(from_imports 条目重复)
+48 -14
View File
@@ -66,6 +66,16 @@ class StructEntry:
_struct_table: StructEntry | t.CPtr = None
_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 结构体可见性
@@ -193,10 +203,12 @@ def register_struct(pool: memhub.MemBuddy | t.CPtr,
return None
# 用类型指针去重(同一类型不重复注册,支持跨模块同名类)
# 用 t.CUInt64T 指针值比较(is 比较会触发类型安全检查解引用悬空 Ty)
st_dedup: t.CUInt64T = t.CUInt64T(struct_ty)
for i in range(_struct_count):
existing: StructEntry | t.CPtr = _get_struct_entry(i)
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
if _struct_count >= STRUCT_MAX:
@@ -210,16 +222,22 @@ def register_struct(pool: memhub.MemBuddy | t.CPtr,
if entry is None:
return None
# 分配字段数组
# 分配字段数组(1b 阶段用 stdlib,避免 reset 回收后 Fields 悬空)
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:
return None
string.memset(entry.Fields, 0, field_size * FIELD_MAX)
# 复制类名
# 复制类名(1b 阶段用 stdlib)
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:
string.strcpy(name_buf, name)
entry.Name = name_buf
@@ -230,7 +248,10 @@ def register_struct(pool: memhub.MemBuddy | t.CPtr,
# 注册时直接设置 SHA1(避免 set_struct_sha1 跨模块同名时找错 entry)
if sha1 is not None:
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:
string.strcpy(sha1_buf, sha1)
entry.ModuleSha1 = sha1_buf
@@ -308,9 +329,12 @@ def add_field(pool: memhub.MemBuddy | t.CPtr,
if fe is None:
return -1
# 复制字段名
# 复制字段名(1b 阶段用 stdlib,避免 reset 回收后 fe.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:
string.strcpy(name_buf, field_name)
fe.Name = name_buf
@@ -399,13 +423,20 @@ def find_struct_by_module(name: str, sha1: str) -> StructEntry | t.CPtr:
# 直接用指针身份定位 entry,规避跨模块同名类 find_struct 找错的问题。
# ============================================================
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:
return None
st_val: t.CUInt64T = t.CUInt64T(struct_ty)
for i in range(_struct_count):
entry: StructEntry | t.CPtr = _get_struct_entry(i)
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 None
@@ -436,11 +467,12 @@ def lookup_field(struct_ty: llvmlite.LLVMType | t.CPtr,
# - 名称匹配但字段未找到时 continue(继续检查其他同名 entry)
# ============================================================
# 第一遍: is 身份比较
# 第一遍: is 身份比较(用 t.CUInt64T 指针值比较,避免 is 编译路径解引用悬空 Ty)
st_lk: t.CUInt64T = t.CUInt64T(struct_ty)
for i in range(_struct_count):
entry: StructEntry | t.CPtr = _get_struct_entry(i)
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 匹配,查找字段
for fi in range(entry.FieldCount):
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:
return 0
ty_name: str = _extract_struct_name(struct_ty)
st_iu: t.CUInt64T = t.CUInt64T(struct_ty)
for i in range(_struct_count):
entry: StructEntry | t.CPtr = _get_struct_entry(i)
if entry is not None and entry.Ty is not None:
matched: int = 0
if entry.Ty is struct_ty:
if t.CUInt64T(entry.Ty) == st_iu:
matched = 1
elif ty_name is not None and entry.Name is not None:
if string.strcmp(entry.Name, ty_name) == 0:
@@ -778,10 +811,11 @@ def get_class_name_by_type(pool: memhub.MemBuddy | t.CPtr,
"""按类型指针查找类名,返回类名字符串或 None"""
if struct_ty is None or _struct_table is None:
return None
st_cn: t.CUInt64T = t.CUInt64T(struct_ty)
for i in range(_struct_count):
entry: StructEntry | t.CPtr = _get_struct_entry(i)
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
# 回退: 类型指针比较失败时,遍历所有注册的结构体按名称匹配
# 提取 struct_ty 的 Name 字段(可能是 "SHA1.ClassName" 格式)
+34
View File
@@ -232,10 +232,16 @@ class Translator:
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)
stdio.printf("[TRDBG] after _init_state, funcs=%p\n", self._funcs)
stdio.fflush(None)
# 创建 LLVM 模块
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:
VLogger.error("NewModule returned NULL", "TR")
return 1
@@ -246,15 +252,21 @@ class Translator:
if triple is None:
triple = "x86_64-pc-windows-msvc"
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)
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
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_func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
pool, mod, "printf", i32_ty)
stdio.printf("[TRDBG] after create_declare printf=%p\n", printf_func)
stdio.fflush(None)
if printf_func is None:
VLogger.error("CreateDeclare printf returned NULL", "TR")
return 1
@@ -273,6 +285,8 @@ class Translator:
pool, mod, "llvm.va_end", void_ty_decl)
if va_end_func is not None:
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_func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
@@ -280,12 +294,18 @@ class Translator:
if malloc_func is not None:
i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool)
llvmlite.add_param(pool, malloc_func, i64_ty, "size")
stdio.printf("[TRDBG] after malloc decl\n")
stdio.fflush(None)
# 检查用户是否定义了 main 函数
has_user_main: int = 0
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:
cn_count: t.CSizeT = ch.__len__()
stdio.printf("[TRDBG] children count=%d\n", cn_count)
stdio.fflush(None)
for ci in range(cn_count):
child: ast.AST | t.CPtr = ch.get(ci)
if child is not None and child.kind() == ast.ASTKind.FunctionDef:
@@ -294,6 +314,8 @@ class Translator:
if string.strcmp(fd.name, "main") == 0:
has_user_main = 1
break
stdio.printf("[TRDBG] main check done, has_user_main=%d\n", has_user_main)
stdio.fflush(None)
if self._declare_only != 0:
# Phase 1a-pre(2=import扫描) / Phase 1a(1=struct注册): 只处理模块级,不创建 main 函数和 builder
@@ -343,9 +365,13 @@ class Translator:
elif kd == ast.ASTKind.ImportFrom:
self.ImportsH.HandleImportFromModule(child)
self.ImportsH.HandleImportFromNames(child)
stdio.printf("[MLDBG] after import preprocess\n")
stdio.fflush(None)
# 扫描当前模块的 CTypedef 声明(NAME: t.CTypedef = Type),
# 注册到动态 CTypedef 表,供 resolve_annotation_type 查询
HandlesType.ScanCTypedefDeclarations(pool, tree)
stdio.printf("[MLDBG] after ScanCTypedefDeclarations\n")
stdio.fflush(None)
# 跨模块 .vpi 注入:加载依赖模块的 .vpi 文件,
# 将函数 declare 声明注入到当前模块,解决跨模块函数调用找不到函数的问题
# 严格保证 declare_only == 0 时才注入(避免 Phase A-pre-inc 死锁)
@@ -354,6 +380,8 @@ class Translator:
StubMerger.LoadDepVpiIntoModule(
pool, mod, self._imported_modules, self._from_imports,
HandlesExprCall._g_temp_dir, self)
stdio.printf("[MLDBG] after LoadDepVpiIntoModule\n")
stdio.fflush(None)
# 预注册模块级变量(AnnAssign/Assign)到 SymTab
# 解决时序问题:class Logger 的 __init__ 引用 _mbuddy 时,
# _mbuddy 的 AnnAssign 在 AST 中位于 class Logger 之后,
@@ -369,9 +397,15 @@ class Translator:
kd_mv: int = child.kind()
if kd_mv == ast.ASTKind.AnnAssign or kd_mv == ast.ASTKind.Assign:
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)
stdio.printf("[MLDBG] after forward_declare_functions\n")
stdio.fflush(None)
added: int = HandlesMain.translate_children(self, tree)
stdio.printf("[MLDBG] after translate_children\n")
stdio.fflush(None)
# ============================================================
# 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)
f.close()
if bytes_read <= 0:
stdlib.free(buf)
return None
# 原地去除 \r(CRLF → LF),与 Projectrans.py 文本模式读取一致
@@ -190,17 +191,21 @@ def compute_file_sha1(pool: memhub.MemBuddy | t.CPtr,
# 计算 SHA1
ctx: hashlib.sha1 | t.CPtr = hashlib.sha1()
if ctx is None:
stdlib.free(buf)
return None
ctx.update(buf)
digest: bytes = stdlib.malloc(hashlib.SHA1_DIGEST_LEN)
if digest is None:
stdlib.free(buf)
return None
ctx.final(digest)
# 转为十六进制字符串(取前 8 字节 = 16 个十六进制字符)
hex_buf: str = stdlib.malloc(17)
if hex_buf is None:
stdlib.free(buf)
stdlib.free(digest)
return None
for i in range(8):
hi: int = (digest[i] >> 4) & 0xF
@@ -214,6 +219,8 @@ def compute_file_sha1(pool: memhub.MemBuddy | t.CPtr,
else:
hex_buf[i * 2 + 1] = 'a' + (lo - 10)
hex_buf[16] = '\0'
stdlib.free(buf)
stdlib.free(digest)
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._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 共用)
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_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):
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))
@@ -577,6 +582,9 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
p1a_skipped += 1
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
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)
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 集合
#
@@ -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)
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):
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))
@@ -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_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
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_ctypedefs()
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)
if ret_r != 0:
p1a_fl += 1
@@ -956,6 +975,18 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
# ============================================================
# 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
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)
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)
stdio.printf("[STDBG] stepB after free(stub_path)\n")
stdio.fflush(None)
# 读取文件内容
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
else:
src_buf[SRC_BUF_SIZE - 1] = 0
stdio.printf("[STDBG] stepC after file read, bytes_read=%d\n", bytes_read)
stdio.fflush(None)
# 解析 AST
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
continue
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)
stdio.printf("[STDBG] stepE after tokenize\n")
stdio.fflush(None)
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:
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
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)
if pyi_buf is not None:
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:
pyi_path: str = StubMerger._sliced_path(temp_dir, dir_len, sha1, "vpi")
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_ctypedefs()
HandlesStruct.reset_visible_structs(mb, 0)
stdio.printf("[STDBG] stepH before tr.translate\n")
stdio.fflush(None)
ret: int = tr.translate(tree)
stdio.printf("[STDBG] stepI after tr.translate, ret=%d\n", ret)
stdio.fflush(None)
if ret != 0:
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb is not None:
@@ -1133,6 +1185,8 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
continue
tr.dump_ir(stub_buf, PHASE1_IR_SIZE, llvmlite.OUTPUT_STUB)
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
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
tr.dump_ir(text_buf, PHASE1_IR_SIZE, llvmlite.OUTPUT_TEXT)
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
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
# 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()
if fb is not None:
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
# === 栈金丝雀检查(全局变量,不影响栈布局)===
global _g_canary
_g_canary = 305419896
fb: t.CChar | t.CPtr = VLogger.fmt_buf()