diff --git a/includes/llvmlite/__types.vp b/includes/llvmlite/__types.vp index dae4d99..a3be5a9 100644 --- a/includes/llvmlite/__types.vp +++ b/includes/llvmlite/__types.vp @@ -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) diff --git a/lib/core/Handles/HandlesExprCall.py b/lib/core/Handles/HandlesExprCall.py index 43740ed..9a041f4 100644 --- a/lib/core/Handles/HandlesExprCall.py +++ b/lib/core/Handles/HandlesExprCall.py @@ -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]