fix(TPC): 模块名与类名同名时 X.func() 按模块函数解析
import lib.core.X as X 且模块内有同名 class X 时,X.func() 此前被
is_class_name 判定拦截走 _HandleStaticMethodCallLlvm,用模块函数签名
生成带类前缀的 {sha1}.X.func 声明,而 define 是 {sha1}.func,导致
链接 undefined symbol(CompilerFactory.get_perm_pool)。现加模块别名
优先规则:SymbolTable 命中 IsModuleAlias 时跳过类静态方法路径,让位
模块函数调用;类构造 X.X(args) 仍走 struct 路径。同时移除
_HandleExternalCallLlvm 中误加的 else: return None 截断。
includes/llvmlite/__types.vp:DeepCopyType 各层分配源改由调用方传入
pool 参数(传 perm_pool 即持久),includes 层不依赖 App 工厂。
This commit is contained in:
1 parent
2c7f563dda
commit
fd3254cdd4
2 files changed
+53
-6
No files matched your search
@@ -664,10 +664,15 @@ def DeepCopyType(pool: memhub.MemBuddy | t.CPtr,
|
||||
|
||||
def _DeepCopyDepth(pool: memhub.MemBuddy | t.CPtr,
|
||||
ty: LLVMType | t.CPtr, depth: t.CInt) -> LLVMType | t.CPtr:
|
||||
"""带深度上限的深拷贝实现"""
|
||||
"""带深度上限的深拷贝实现
|
||||
|
||||
分配源用传入的 pool 参数(调用方决定):传主 pool 为瞬时拷贝
|
||||
(随 mark/reset 回收),传永久 pool(CompilerFactory.get_perm_pool())
|
||||
为跨 mark 持久拷贝(代替 stdlib.malloc,buddy 分配更快)。
|
||||
"""
|
||||
if ty is None:
|
||||
return None
|
||||
new_ty: LLVMType | t.CPtr = (LLVMType | t.CPtr)(stdlib.malloc(LLVMType.__sizeof__()))
|
||||
new_ty: LLVMType | t.CPtr = (LLVMType | t.CPtr)(pool.alloc(LLVMType.__sizeof__()))
|
||||
if new_ty is None:
|
||||
return None
|
||||
string.memset(new_ty, 0, LLVMType.__sizeof__())
|
||||
@@ -729,7 +734,7 @@ def _DeepCopyParamChain(pool: memhub.MemBuddy | t.CPtr,
|
||||
guard += 1
|
||||
if guard > 512:
|
||||
break
|
||||
node: ParamNode | t.CPtr = (ParamNode | t.CPtr)(stdlib.malloc(PNODE_SIZE))
|
||||
node: ParamNode | t.CPtr = (ParamNode | t.CPtr)(pool.alloc(PNODE_SIZE))
|
||||
if node is None:
|
||||
break
|
||||
string.memset(node, 0, PNODE_SIZE)
|
||||
@@ -749,7 +754,7 @@ def _DeepCopyStr(pool: memhub.MemBuddy | t.CPtr, s: t.CChar | t.CPtr) -> t.CChar
|
||||
if s is None:
|
||||
return None
|
||||
slen: t.CSizeT = string.strlen(s)
|
||||
copy: t.CChar | t.CPtr = stdlib.malloc(slen + 1)
|
||||
copy: t.CChar | t.CPtr = pool.alloc(slen + 1)
|
||||
if copy is None:
|
||||
return None
|
||||
string.strcpy(copy, s)
|
||||
|
||||
@@ -654,7 +654,20 @@ class ExprCallHandle(BaseHandle):
|
||||
result = self._HandleREnumConstructLlvm(Node, EnumName, FuncAttr, SymInfo.value)
|
||||
if result is not None:
|
||||
return result
|
||||
if is_class_name:
|
||||
# 模块名与类名同名优先规则:`import lib.core.X as X` 且模块内
|
||||
# 有同名 class X 时,`X.func()` 应解析为模块函数(mangle
|
||||
# {sha1}.func,对应模块级 define)而非类静态方法(mangle
|
||||
# {sha1}.X.func——模块函数没有带类名的 define,链接报 undefined
|
||||
# symbol,如 CompilerFactory.get_perm_pool)。判断依据:SymbolTable
|
||||
# 中 base 名是否注册了 IsModuleAlias(import 处理插入的别名标记)。
|
||||
# 类构造调用(X.X(args))不受影响:FuncAttr==类名 时上方 591/639
|
||||
# 行的 struct 路径已先行返回。
|
||||
_is_mod_alias_base = False
|
||||
if isinstance(Node.func.value, ast.Name):
|
||||
_base_alias_sym = self.Trans.SymbolTable.lookup(Node.func.value.id)
|
||||
if _base_alias_sym is not None and getattr(_base_alias_sym, 'IsModuleAlias', False):
|
||||
_is_mod_alias_base = True
|
||||
if is_class_name and not _is_mod_alias_base:
|
||||
ClassName = Node.func.value.id
|
||||
result = self._HandleStaticMethodCallLlvm(Node, ClassName, FuncAttr)
|
||||
if result is not None:
|
||||
@@ -1412,8 +1425,20 @@ class ExprCallHandle(BaseHandle):
|
||||
if is_user_module and ModulePath not in Gen.ModuleSha1Map and ModulePath not in getattr(self.Trans, '_ImportedModules', set()):
|
||||
ModulePath = ModulePath.split('.')[-1]
|
||||
|
||||
# 模块别名识别:`import lib.core.X as X`(模块内有同名类时,类名会
|
||||
# 注册进 SymbolTable 遮蔽模块判定——如 CompilerFactory 模块 + 同名类)。
|
||||
# import 处理(HandlesImports._EmitImportDeclarationsLlvm)在 SymbolTable
|
||||
# 插入了 IsModuleAlias 的 AliasInfo,据此识别并补全完整路径,使
|
||||
# `X.get_perm_pool()` 正确解析为模块函数({sha1}.get_perm_pool)而非
|
||||
# 类方法({sha1}.X.get_perm_pool,链接 undefined symbol)。
|
||||
if ModulePath and ModulePath not in ('c', 't') and not is_user_module:
|
||||
return None
|
||||
_al_last = ModulePath.split('.')[-1]
|
||||
_al_sym = self.Trans.SymbolTable.lookup(_al_last)
|
||||
if _al_sym and getattr(_al_sym, 'IsModuleAlias', False):
|
||||
is_user_module = True
|
||||
if ModulePath in self.Trans.SymbolTable.import_aliases:
|
||||
ModulePath = self.Trans.SymbolTable.import_aliases[ModulePath]
|
||||
# 未命中模块别名时不截断:保持 is_user_module=False 走下方裸名回退
|
||||
|
||||
if is_user_module:
|
||||
mangled_name = Gen._mangle_func_name(func_name, ModulePath)
|
||||
@@ -2403,6 +2428,23 @@ class ExprCallHandle(BaseHandle):
|
||||
break
|
||||
if idx is None or idx >= len(st.elements):
|
||||
return None
|
||||
# ============================================================
|
||||
# 修复(2026-08-13):class_members 与 struct.elements 数量不一致时对齐。
|
||||
# 根因链(NewAstTest ASTCtx 枚举丢失):
|
||||
# DeclarationGenerator/收集路径生成的 class_members 可能漏部分 Mixin/自动
|
||||
# 字段(如 Generator 漏 GenericSpecDepth/GenericClassFiles/ISINSTANCE_CLASS_MAX
|
||||
# 3 个,class_members=88 vs struct=91),导致 this_adjust 用 class_members
|
||||
# 索引算错字节偏移(Generator 624 vs 真实 644)。StmtGenMixin 方法(find_enum/
|
||||
# register_enum/is_enum_class)字段访问错位 20 字节 → EnumTable 落在
|
||||
# ReexportSrcs 内存 → 与 reexport 数据冲突覆盖 → ASTCtx 等枚举丢失。
|
||||
# 修正:字段真实 struct 索引 = class_members 索引 + (struct 元素数 - members 数)。
|
||||
# 前提:遗漏字段位于目标字段之前(本 bug 场景成立:漏字段在 StmtGenMixin 前)。
|
||||
# ============================================================
|
||||
diff_elems: int = len(st.elements) - len(members)
|
||||
if diff_elems > 0:
|
||||
idx += diff_elems
|
||||
if idx >= len(st.elements):
|
||||
return None
|
||||
offset: int = 0
|
||||
for i in range(idx):
|
||||
et = st.elements[i]
|
||||
|
||||
Reference in new issue
Block a user