fix(gen): 模块级全局变量命名带 SHA1 前缀,消除 ld.lld duplicate symbol
多个模块声明同名模块级全局(如 _mbuddy)时全部生成裸名强定义(zeroinit)
→ 链接时 ld.lld duplicate symbol: _mbuddy(大量 warning)。函数名早已
mangled,全局变量漏做。
修复(对齐函数名 _mangle_name,SymTab key 保持裸名查找逻辑零改动):
1. 定义端 TranslatorGenMixin:全局名 = {模块sha1}.{变量名}
2. 模块属性访问 ExprGenAttr:按目标模块 SHA1 前缀精确查找/创建(含嵌套
模块 w32.xxx 与 t 类型对象裸名 linkonce_odr 特例),引用用完整名
3. from-import 全局 ExprGenName:带源模块 SHA1 前缀查找,引用用完整名
4. _find_pool_var 兜底:linkonce_odr + zeroinitializer 定义(每模块独立,
不再依赖裸名链接合并共享;运行时未初始化则真实崩溃暴露,不掩盖)
This commit is contained in:
1 parent
cf6c917e83
commit
5f7a87341a
4 files changed
+66
-24
No files matched your search
@@ -21,7 +21,9 @@ import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.StubMergerStore as StubMergerStore
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.Projectrans.Config as Config
|
||||
import lib.Projectrans.Utils as Utils
|
||||
@@ -238,10 +240,16 @@ class ExprGenAttr(ExprGenBase.ExprGenBase):
|
||||
# 检查是否是已导入模块
|
||||
if HandlesImports.is_module_imported(trans._imported_modules, mod_path_w) == 0:
|
||||
return None
|
||||
# 在当前模块查找全局变量 (stub 可能已注入)
|
||||
gv: llvmlite.GlobalVariable | t.CPtr = self.find_global_in_module(mod, at.attr)
|
||||
# 在当前模块查找全局变量:优先按"目标模块 SHA1 前缀 + 属性名"精确匹配,
|
||||
# 避免多模块同名全局(@<A>._mbuddy / @<B>._mbuddy 同时注入)时裸名后缀
|
||||
# 匹配返回错误模块的全局(串扰)。目标 sha1 未知时退化裸名(后缀匹配兜底)
|
||||
gv_q: str = HandlesFunctions._mangle_name_with_sha1(
|
||||
self._lookup_module_sha1(mod_path_w), at.attr)
|
||||
gv: llvmlite.GlobalVariable | t.CPtr = self.find_global_in_module(mod, gv_q)
|
||||
if gv is not None and gv.Ty is not None:
|
||||
return self.make_global_ref(pool, at.attr, gv.Ty)
|
||||
# 用 gv.Name(完整名,带 SHA1 前缀时与定义端一致)构造引用,
|
||||
# 避免裸名 @_mbuddy 在多模块各自带前缀定义下 undefined symbol
|
||||
return self.make_global_ref(pool, gv.Name, gv.Ty)
|
||||
# 未找到: 创建 external global 声明并添加到模块
|
||||
# 否则只生成 @_argc 引用而无声明,LLVM 报 "use of undefined value '@_argc'"
|
||||
use_ty: llvmlite.LLVMType | t.CPtr = ty_hint
|
||||
@@ -256,7 +264,14 @@ class ExprGenAttr(ExprGenBase.ExprGenBase):
|
||||
is_t_type_obj: int = 0
|
||||
if string.strcmp(mod_path_w, "t") == 0:
|
||||
is_t_type_obj = self._is_t_type_object_name(at.attr)
|
||||
ext_gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, at.attr, use_ty)
|
||||
# 兜底声明名:t 类型对象(t.py 不编译、无 sha1)保持裸名 linkonce_odr;
|
||||
# 其他模块属性带目标模块 SHA1 前缀(对齐定义端 mangling,跨模块同名
|
||||
# 全局独立命名,消除 duplicate symbol / 串扰)
|
||||
gv_name_ba: str = at.attr
|
||||
if is_t_type_obj == 0:
|
||||
gv_name_ba = HandlesFunctions._mangle_name_with_sha1(
|
||||
self._lookup_module_sha1(mod_path_w), at.attr)
|
||||
ext_gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, gv_name_ba, use_ty)
|
||||
if ext_gv is not None:
|
||||
if is_t_type_obj != 0:
|
||||
# t.CPtr 等类型对象: 创建带 null 初值的定义(linkonce_odr)
|
||||
@@ -277,7 +292,11 @@ class ExprGenAttr(ExprGenBase.ExprGenBase):
|
||||
ext_gv.Linkage = "external"
|
||||
ext_gv.Initializer = None
|
||||
llvmlite.module_add_global(mod, ext_gv)
|
||||
return self.make_global_ref(pool, at.attr, use_ty)
|
||||
return self.make_global_ref(pool, gv_name_ba, use_ty)
|
||||
def _lookup_module_sha1(self, mod_name: str) -> str:
|
||||
"""查找模块名对应的 SHA1(委托 StubMergerStore,支持包名回退;
|
||||
None=未找到,调用方退化为裸名)"""
|
||||
return StubMergerStore.LookupSha1ByModName(mod_name)
|
||||
# ============================================================
|
||||
# 翻译属性访问 Attribute(value, attr, ctx) — obj.field
|
||||
#
|
||||
@@ -607,11 +626,14 @@ class ExprGenAttr(ExprGenBase.ExprGenBase):
|
||||
if qual_buf is not None:
|
||||
viperlib.snprintf(qual_buf, qual_len, "%s.%s", inner_nm.id, inner_at.attr)
|
||||
if HandlesImports.is_module_imported(trans._imported_modules, qual_buf) == 1:
|
||||
# 查找全局变量 at.attr (stub 已注入的情况)
|
||||
gv_nested: llvmlite.GlobalVariable | t.CPtr = self.find_global_in_module(mod, at.attr)
|
||||
# 查找全局变量 at.attr(带限定模块 SHA1 前缀精确匹配,
|
||||
# 避免多模块同名全局后缀匹配串扰;sha1 未知退化裸名)
|
||||
gv_nested_q: str = HandlesFunctions._mangle_name_with_sha1(
|
||||
self._lookup_module_sha1(qual_buf), at.attr)
|
||||
gv_nested: llvmlite.GlobalVariable | t.CPtr = self.find_global_in_module(mod, gv_nested_q)
|
||||
if gv_nested is not None and gv_nested.Ty is not None:
|
||||
gv_ref_nested: llvmlite.Value | t.CPtr = self.make_global_ref(
|
||||
pool, at.attr, gv_nested.Ty)
|
||||
pool, gv_nested.Name, gv_nested.Ty)
|
||||
if gv_ref_nested is not None and gv_ref_nested.Ty is not None:
|
||||
load_ty_nested: llvmlite.LLVMType | t.CPtr = gv_ref_nested.Ty.Pointee
|
||||
if load_ty_nested is not None:
|
||||
|
||||
@@ -21,6 +21,7 @@ import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.Projectrans.Config as Config
|
||||
@@ -207,8 +208,12 @@ class ExprGenConst(ExprGenBase.ExprGenBase):
|
||||
alloca = HandlesVar.lookup_var(trans.SymTab, "mb")
|
||||
if alloca is not None:
|
||||
return alloca
|
||||
# 兜底: 创建外部全局 @_mbuddy 引用(i8** 类型)
|
||||
# 仅用于函数内动态 list 字面量,@_mbuddy 由入口模块定义并初始化
|
||||
# 兜底: 创建当前模块 mangled 的 @_mbuddy 定义(linkonce_odr + zeroinitializer)
|
||||
# 对齐模块级全局带 SHA1 前缀命名:裸名 @_mbuddy 依赖链接合并共享
|
||||
# (--allow-multiple-definition),带前缀后每模块独立。linkonce_odr 允许
|
||||
# 链接器合并同模板重复特化定义,zeroinitializer 保证编译链接通过。
|
||||
# 运行时若该模块未在入口 main 赋值 _mbuddy(null pool 上动态建 list),
|
||||
# 由真实崩溃暴露(fail-fast 哲学,不掩盖上游未初始化)。
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
if pool is None or trans.Module is None or trans.SymTab is None:
|
||||
return None
|
||||
@@ -219,16 +224,19 @@ class ExprGenConst(ExprGenBase.ExprGenBase):
|
||||
# 创建 i8* 类型(t.CVoid | t.CPtr = i8*)
|
||||
i8_ty_fb: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
i8_ptr_ty_fb: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_fb)
|
||||
# 创建外部全局 @_mbuddy(external linkage,无初始值)
|
||||
gv_ext: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, "_mbuddy", i8_ptr_ty_fb)
|
||||
# 当前模块 mangled 名(@<模块sha1>._mbuddy)
|
||||
mb_name_fb: str = HandlesFunctions._mangle_name(trans, "_mbuddy")
|
||||
# 创建 linkonce_odr 定义(可被链接器合并,自给自足保证链接通过)
|
||||
gv_ext: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, mb_name_fb, i8_ptr_ty_fb)
|
||||
if gv_ext is not None:
|
||||
gv_ext.Linkage = "external"
|
||||
gv_ext.Linkage = "linkonce_odr"
|
||||
gv_ext.Initializer = "zeroinitializer"
|
||||
llvmlite.module_add_global(trans.Module, gv_ext)
|
||||
# 创建 Value 引用(@_mbuddy, 类型为 i8**)
|
||||
# 创建 Value 引用(@<模块sha1>._mbuddy, 类型为 i8**)
|
||||
i8_ptr_ptr_ty_fb: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty_fb)
|
||||
ref_name_fb: str = pool.alloc(16)
|
||||
ref_name_fb: str = pool.alloc(96)
|
||||
if ref_name_fb is not None:
|
||||
string.strcpy(ref_name_fb, "@_mbuddy")
|
||||
viperlib.snprintf(ref_name_fb, 96, "@%s", mb_name_fb)
|
||||
gv_ref_fb: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, i8_ptr_ptr_ty_fb, ref_name_fb)
|
||||
# 注册到模块作用域,避免重复创建
|
||||
HandlesVar.define_module_var(trans.SymTab, "_mbuddy", gv_ref_fb)
|
||||
|
||||
@@ -22,6 +22,8 @@ import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.StubMergerStore as StubMergerStore
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.Projectrans.Config as Config
|
||||
import lib.Projectrans.Utils as Utils
|
||||
@@ -107,11 +109,14 @@ class ExprGenName(ExprGenBase.ExprGenBase):
|
||||
fi_mod_raw: str = HandlesImports.lookup_from_import(
|
||||
trans._from_imports, nm_id, 0)
|
||||
if fi_mod_raw is not None:
|
||||
# 带源模块 SHA1 前缀精确查找,避免多模块同名全局后缀匹配串扰
|
||||
fi_gv_q: str = HandlesFunctions._mangle_name_with_sha1(
|
||||
StubMergerStore.LookupSha1ByModName(fi_mod_raw), nm_id)
|
||||
fi_gv: llvmlite.GlobalVariable | t.CPtr = HandlesExpr.find_global_in_module(
|
||||
trans.Module, nm_id)
|
||||
trans.Module, fi_gv_q)
|
||||
if fi_gv is not None and fi_gv.Ty is not None:
|
||||
fi_ref: llvmlite.Value | t.CPtr = HandlesExpr.make_global_ref(
|
||||
pool, nm_id, fi_gv.Ty)
|
||||
pool, fi_gv.Name, fi_gv.Ty)
|
||||
if fi_ref is not None and fi_ref.Ty is not None:
|
||||
fi_pty: llvmlite.LLVMType | t.CPtr = fi_ref.Ty.Pointee
|
||||
if fi_pty is not None:
|
||||
@@ -292,11 +297,14 @@ class ExprGenName(ExprGenBase.ExprGenBase):
|
||||
# stub 已注入全局(精确类型)→ 直接引用;未注入 → fail-fast
|
||||
# (不再创建 external i8* 声明,否则 llc 报 "use of undefined value",
|
||||
# 静默回退掩盖 stub 未注入的上游根因)
|
||||
# 带源模块 SHA1 前缀精确查找(避免多模块同名全局后缀匹配串扰)
|
||||
gv_fi_q: str = HandlesFunctions._mangle_name_with_sha1(
|
||||
StubMergerStore.LookupSha1ByModName(fi_mod), fi_gname)
|
||||
gv_fi: llvmlite.GlobalVariable | t.CPtr = HandlesExpr.find_global_in_module(
|
||||
trans.Module, fi_gname)
|
||||
trans.Module, gv_fi_q)
|
||||
ref_fi: llvmlite.Value | t.CPtr = None
|
||||
if gv_fi is not None and gv_fi.Ty is not None:
|
||||
ref_fi = HandlesExpr.make_global_ref(pool, fi_gname, gv_fi.Ty)
|
||||
ref_fi = HandlesExpr.make_global_ref(pool, gv_fi.Name, gv_fi.Ty)
|
||||
else:
|
||||
HandlesType.fatal_error(
|
||||
node,
|
||||
|
||||
@@ -497,7 +497,11 @@ class TranslatorGenMixin:
|
||||
# "use of undefined type named 'sha1.ClassName'" 错误
|
||||
# (如 _mbuddy: memhub.MemManager | t.CPtr → Ptr(Struct("aeb3...MemManager")))
|
||||
llvmlite.module_ensure_opaque_for_type(mod, pool, var_ty)
|
||||
gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, var_name, var_ty)
|
||||
# 模块级全局命名带 SHA1 前缀(对齐函数名 mangling):多个模块声明同名
|
||||
# 全局(如 _mbuddy)时各自独立命名,消除 ld.lld duplicate symbol。
|
||||
# SymTab 注册 key 保持裸名(查找逻辑零改动),LLVM 符号名用 mangled 名。
|
||||
mangled_name: str = HandlesFunctions._mangle_name(trans, var_name)
|
||||
gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, mangled_name, var_ty)
|
||||
if gv is None:
|
||||
return 0
|
||||
llvmlite.module_add_global(mod, gv)
|
||||
@@ -551,11 +555,11 @@ class TranslatorGenMixin:
|
||||
# 整数/聚合类型也兼容 zeroinitializer,避免 "integer constant must have integer type"
|
||||
gv.Initializer = "zeroinitializer"
|
||||
|
||||
# 创建 Value 引用(@var_name, 类型为 var_ty*)
|
||||
# 创建 Value 引用(@mangled_name, 类型为 var_ty*)
|
||||
var_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, var_ty)
|
||||
ref_name: str = pool.alloc(64)
|
||||
ref_name: str = pool.alloc(96)
|
||||
if ref_name is not None:
|
||||
viperlib.snprintf(ref_name, 64, "@%s", var_name)
|
||||
viperlib.snprintf(ref_name, 96, "@%s", mangled_name)
|
||||
gv_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, var_ptr_ty, ref_name)
|
||||
|
||||
# 注册到模块作用域
|
||||
|
||||
Reference in new issue
Block a user