fix(gen): 模块前言的声明池逐级判空,避免 PermPool 未就绪时空指针崩溃

现象:TransPyV.exe 编译任何工程都 AddressSanitizer access-violation on address 0x0(pc=0)。根因:_emit_module_prelude 跑在每个模块翻译的开头,此时 CompilerFactory.factory 或其 PermPool 可能尚未就绪,直接 factory.PermPool.alloc(...) 解引用空指针(PermPool 是 factory 的首字段,偏移 0,与 ASan 报的地址 0x0 吻合)。改为 factory / PermPool 逐级判空,不可用时回退模块池。
This commit is contained in:
TermiNexus committed 2026-10-09 09:45:36 +08:00
1 parent b71ed43f10
commit 8b63ae4ca2
1 file changed
+9 -7
+9 -7
View File
@@ -414,13 +414,15 @@ novirtual class Translator:
i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool)
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty)
# 模块前言里 C 库声明的**名字**必须落在 PermPool:create_declare 会 _str_dup(pool, name)
# 把名字拷进传入的池,而本模块池(trans.Pool)在大模块上会被复用/回绕,覆盖早期分配 →
# 名字悬空(现场:@malloc 被渲染成乱码 @"PL\xEF\xBF\xBDp…",mlir-opt 报
# "'llvm.call' op 'malloc' does not reference a symbol in the current scope";
# 类型是 mlirlite 内部 interned 的,所以只有名字坏、参数类型正常)。
# PermPool 是"persistent data; never reset",正好符合声明名的生命周期。
decl_pool: memhub.MemBuddy* = CompilerFactory.factory.PermPool
# 模块前言里 C 库声明的**名字**应当落在长生命周期池(PermPool):create_declare 会
# _str_dup(pool, name) 把名字拷进传入的池,而本模块池(trans.Pool)在大模块上会被
# 复用/回绕,覆盖早期分配 → 名字悬空(现场:@malloc 渲染成乱码)。
# **但本函数跑得非常早**(每个模块翻译的开头),此时 CompilerFactory.factory 或它的
# PermPool 可能尚未就绪:直接 `factory.PermPool.alloc(...)` 会解引用空指针
# (现场:TransPyV.exe 编译任何工程都 access-violation on address 0x0 —— PermPool 是
# factory 的首字段,偏移 0)。故逐级判空并回退到模块池。
decl_pool: memhub.MemBuddy* = None
if CompilerFactory.factory is not None: decl_pool = CompilerFactory.factory.PermPool
if decl_pool is None: decl_pool = pool
# Declare printf