fix(exprattr): 包子模块属性访问支持全局注册表回退+裸名回退+数组退化
import intr 只注册包名 intr,intr.idt.idt[32] 的嵌套路径 is_module_imported
('intr.idt')=0 → 落入结构体字段访问报 '属性访问失败: .idt'(main.vp L98 根因)。
修复:1) 嵌套路径模块已知性增加 Sha1Store 全局注册表回退(包 __init__.vp
from . import X 注册的 pkg.X);2) 未显式 import 的已知子模块先经
LoadDepVpiIntoModule 注入其 .vpi 声明(含类完整结构体定义 + CExport 裸名
全局声明);3) 全局查找补 CExport 裸名回退;4) 模块级数组全局按 C 语义
返回基址指针(对齐读路径 L629-634),供下标/字段 GEP 继续。
This commit is contained in:
1 parent
50a4772a7d
commit
23ef8c94fa
1 file changed
+49
-4
@@ -16,6 +16,7 @@ import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.Stub.StubMerger as StubMerger
|
||||
import lib.Stub.StubMerger.StubMergerStore as StubMergerStore
|
||||
import lib.Stub.StubMerger.StubMergerBuild as StubMergerBuild
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.Projectrans.Config as Config
|
||||
import lib.Projectrans.Utils as Utils
|
||||
@@ -263,6 +264,13 @@ class ExprGenAttr(ExprGenBase.ExprGenBase):
|
||||
gv_q: str = self.Gen.FuncGenBase._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)
|
||||
# CExport 全局(定义端裸名 @_sched_ptr):mangled 名查不到时回退裸名精确
|
||||
# 查找。此前只查 mangled 名 → 找不到 → 新建 mangled external global 声明
|
||||
# (@"ef5b0ba0dc895058._sched_ptr")→ 与定义端裸名不匹配 → ld.lld
|
||||
# undefined symbol: ef5b0ba0dc895058._sched_ptr(idt.vp L134
|
||||
# sched._sched_ptr 根因)。
|
||||
if gv is None:
|
||||
gv = self.find_global_in_module(mod, at.attr)
|
||||
if gv is not None and gv.Ty is not None:
|
||||
# 用 gv.Name(完整名,带 SHA1 前缀时与定义端一致)构造引用,
|
||||
# 避免裸名 @_mbuddy 在多模块各自带前缀定义下 undefined symbol
|
||||
@@ -642,18 +650,41 @@ class ExprGenAttr(ExprGenBase.ExprGenBase):
|
||||
qual_buf: str = pool.alloc(qual_len)
|
||||
if qual_buf is not None:
|
||||
viperlib.snprintf(qual_buf, qual_len, "%s.%s", inner_nm.id, inner_at.attr)
|
||||
if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, qual_buf) == 1:
|
||||
# 模块已知性:显式 import(w32.win32file)或全局模块注册表登记
|
||||
#(包 __init__.vp 内 from . import X 注册的 pkg.X,如 intr.idt)
|
||||
mod_known_n: int = self.Gen.ImportsGen.is_module_imported(
|
||||
trans._imported_modules, qual_buf)
|
||||
if mod_known_n == 0 and self._lookup_module_sha1(qual_buf) is not None:
|
||||
# 未显式 import 的已知子模块:先注入其 .vpi 声明到当前模块,
|
||||
# 否则 find_global_in_module 找不到该模块的 CExport 全局(@idt)
|
||||
#(main.vp intr.idt.idt[32] 根因)
|
||||
StubMergerBuild.LoadDepVpiIntoModule(
|
||||
pool, mod, qual_buf, trans._from_imports,
|
||||
self.Gen.TypeGenBase.get_temp_dir(), trans)
|
||||
mod_known_n = 1
|
||||
if mod_known_n != 0:
|
||||
# 查找全局变量 at.attr(带限定模块 SHA1 前缀精确匹配,
|
||||
# 避免多模块同名全局后缀匹配串扰;sha1 未知退化裸名)
|
||||
gv_nested_q: str = self.Gen.FuncGenBase._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)
|
||||
# CExport 全局(定义端裸名 @idt)mangled 名查不到时回退
|
||||
# 裸名精确查找(对齐读路径 _resolve_module_attribute_global)
|
||||
if gv_nested is None:
|
||||
gv_nested = self.find_global_in_module(mod, at.attr)
|
||||
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, 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:
|
||||
# 模块级全局数组(如 idt.idt: CArray[T, N])按 C 语义
|
||||
# 返回基址指针(对齐读路径 L629-634),下标/取址继续 GEP
|
||||
match load_ty_nested:
|
||||
case llvmlite.LLVMType.Array(_, _):
|
||||
return gv_ref_nested
|
||||
case _:
|
||||
pass
|
||||
return llvmlite.build_load(builder, load_ty_nested, gv_ref_nested)
|
||||
# 未找到全局: 尝试 CDefine 常量查找
|
||||
# 对于 w32.win32base.INVALID_HANDLE_VALUE 等嵌套模块属性访问,
|
||||
@@ -801,7 +832,7 @@ class ExprGenAttr(ExprGenBase.ExprGenBase):
|
||||
if base_class is not None:
|
||||
cur_sha1: str = trans.ModuleSha1
|
||||
field_info = self.Gen.StructGen.lookup_field_by_class(
|
||||
base_class, at.attr, cur_sha1)
|
||||
base_class, at.attr, cur_sha1, at, trans._from_imports)
|
||||
# REnum 变体字段别名回退:base_class 是 REnum 类时,变体
|
||||
# 字段名(如 LLVMType.Pointee → _p2 槽位)不是普通字段,
|
||||
# lookup_field_by_class 查不到(LLVMType"字段 Pointee 未找到"
|
||||
@@ -868,6 +899,15 @@ class ExprGenAttr(ExprGenBase.ExprGenBase):
|
||||
annot_struct: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct(
|
||||
field_info.AnnotClassName)
|
||||
if annot_struct is not None and annot_struct.Ty is not None:
|
||||
# 确保目标结构体类型在当前模块有声明(可能未定义/未 opaque):
|
||||
# 联合字段 AnnotClassName 可能解析到本模块未 import 的类
|
||||
# (如 __types 的 ParamNode.Next 误解析到 __function.Param),
|
||||
# bitcast 引用未定义类型 → opt ASan 报 "use of undefined type"。
|
||||
# _scan_type_for_cross_module_refs 只扫 Ptr(Struct) 模式,
|
||||
# 因此传 Ptr(Ty) 让结构体名本身被 opaque 声明。
|
||||
# opaque 声明足以支撑指针 bitcast(不访问字段),行为不变。
|
||||
llvmlite.module_ensure_opaque_for_type(
|
||||
mod, pool, llvmlite.Ptr(pool, annot_struct.Ty))
|
||||
annot_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, annot_struct.Ty)
|
||||
return llvmlite.build_bitcast(builder, loaded_val, annot_ptr_ty)
|
||||
return loaded_val
|
||||
@@ -965,8 +1005,11 @@ class ExprGenAttr(ExprGenBase.ExprGenBase):
|
||||
cur_sha1: str = None
|
||||
if trans is not None:
|
||||
cur_sha1 = trans.ModuleSha1
|
||||
lfi_pc: str = None
|
||||
if trans is not None:
|
||||
lfi_pc = trans._from_imports
|
||||
fe: GenTypes.FieldEntry | t.CPtr = self.Gen.StructGen.lookup_field_by_class(
|
||||
parent_class, at.attr, cur_sha1)
|
||||
parent_class, at.attr, cur_sha1, at, lfi_pc)
|
||||
if fe is None:
|
||||
return None
|
||||
return self.Gen.StructGen.get_field_annot_class_name(fe)
|
||||
@@ -1098,10 +1141,12 @@ class ExprGenAttr(ExprGenBase.ExprGenBase):
|
||||
base_class = self._resolve_attr_field_class(pool, trans, at.value)
|
||||
if base_class is not None:
|
||||
cur_sha1: str = None
|
||||
lfi_gp: str = None
|
||||
if trans is not None:
|
||||
cur_sha1 = trans.ModuleSha1
|
||||
lfi_gp = trans._from_imports
|
||||
field_info = self.Gen.StructGen.lookup_field_by_class(
|
||||
base_class, at.attr, cur_sha1)
|
||||
base_class, at.attr, cur_sha1, at, lfi_gp)
|
||||
# REnum 变体字段别名回退(同 translate_attribute L5046-5062):
|
||||
# get_attribute_ptr 赋值路径的按需过滤同样需要——struct_ty 简化
|
||||
# i8 时主路径 REnum 别名查找被跳过(LLVMType.Pointee 报错根因)
|
||||
|
||||
Reference in new issue
Block a user