基本稳定可以编译 Test
This commit is contained in:
1 parent
a3b9bdc409
commit
8ad500c4da
12 files changed
+738
-119
No files matched your search
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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(一级指针)
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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 条目重复)
|
||||||
|
|||||||
@@ -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" 格式)
|
||||||
|
|||||||
@@ -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 输出
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in new issue
Block a user