From 9656bb161a0af27c37422828334cc140d5594a0a Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 7 Oct 2026 19:59:36 +0800 Subject: [PATCH] =?UTF-8?q?feat(codegen):=20=E5=80=BC=E5=BC=95=E7=94=A8?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=8F=96=E5=9D=80=E6=94=B6=E5=8F=A3=E5=88=B0?= =?UTF-8?q?=20=5Fadjust=5Fargs=EF=BC=8C=E8=A1=A5=E9=BD=90=20vtable/?= =?UTF-8?q?=E6=96=B9=E6=B3=95/=E6=9E=84=E9=80=A0=E7=AD=89=E8=B7=AF?= =?UTF-8?q?=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 查表键统一为真实发射出的函数名:FuncGen._adjust_args 开头以 func.name 调用 _apply_auto_addr,于是 direct/vtable 虚分派/构造/静态/__call__/下标赋值/c.Addr 构造/闭包/泛型/方法兜底全部自动取址,不再依赖每个调用点手写;同时删除 16 处冗余显式取址(t.CAutoPtr 的 always 模式不幂等,重复应用会多包一层指针)。登记侧:HandlesImports 把模式登记提前到 FuncName-in-Gen.functions 早退之前并按 func.name 主键写表,_TryLoadStructFromStub 改为无条件调用;HandlesFunctions 在函数对象就绪后按真实名登记,并在 _EmitFunctionForwardDeclLlvm 把逻辑名下的模式播种到 MangledName,覆盖同模块先调用后定义的场景。 --- lib/core/Handles/HandlesAnnAssign.py | 6 ++-- lib/core/Handles/HandlesAssign.py | 2 +- lib/core/Handles/HandlesExprCall.py | 25 +++++++------- lib/core/Handles/HandlesFunctions.py | 15 ++++++++ lib/core/Handles/HandlesImports.py | 51 +++++++++++++++++++--------- lib/core/LLVMCG/FuncGen.py | 15 ++++++++ 6 files changed, 82 insertions(+), 32 deletions(-) diff --git a/lib/core/Handles/HandlesAnnAssign.py b/lib/core/Handles/HandlesAnnAssign.py index bb682e3..c3cb6f2 100644 --- a/lib/core/Handles/HandlesAnnAssign.py +++ b/lib/core/Handles/HandlesAnnAssign.py @@ -406,7 +406,7 @@ class AnnAssignHandle(BaseHandle): if new_func: new_args: list[ir.Value] = [alloca_ptr, pool_val] self.Trans.ExprCallHandle._fill_default_args(new_args, new_func, new_method_name) - new_args = Gen._apply_auto_addr(new_method_name, new_args) + # 自动取址已收口到 Gen._adjust_args(唯一汇聚点,按 func.name 查表)。 adjusted_new: list[ir.Value] = Gen._adjust_args(new_args, new_func) heap_ptr = Gen.builder.call(new_func, adjusted_new, name=f"new_{VarName}") # 转换返回指针类型 @@ -431,7 +431,7 @@ class AnnAssignHandle(BaseHandle): elem_size_val: ir.Constant = ir.Constant(ir.IntType(64), 0) init_args: list[ir.Value] = [heap_ptr, pool_val, elem_size_val] self.Trans.ExprCallHandle._fill_default_args(init_args, init_func, init_name) - init_args = Gen._apply_auto_addr(init_name, init_args) + # 自动取址已收口到 Gen._adjust_args(唯一汇聚点,按 func.name 查表)。 adjusted_init: list[ir.Value] = Gen._adjust_args(init_args, init_func) Gen.builder.call(init_func, adjusted_init, name=f"init_{VarName}") @@ -445,7 +445,7 @@ class AnnAssignHandle(BaseHandle): if elem_val: append_args: list[ir.Value] = [heap_ptr, elem_val] self.Trans.ExprCallHandle._fill_default_args(append_args, append_func, append_name) - append_args = Gen._apply_auto_addr(append_name, append_args) + # 自动取址已收口到 Gen._adjust_args(唯一汇聚点,按 func.name 查表)。 adjusted_append: list[ir.Value] = Gen._adjust_args(append_args, append_func) Gen.builder.call(append_func, adjusted_append, name=f"append_{VarName}_{i}") diff --git a/lib/core/Handles/HandlesAssign.py b/lib/core/Handles/HandlesAssign.py index 680e392..a3b2124 100644 --- a/lib/core/Handles/HandlesAssign.py +++ b/lib/core/Handles/HandlesAssign.py @@ -1460,7 +1460,7 @@ class AssignHandle(BaseHandle): obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") setitem_args: list[ir.Value] = [obj_val, idx_val, Value] setitem_func_name: str = f'{ClassName}.__setitem__' - setitem_args = Gen._apply_auto_addr(setitem_func_name, setitem_args) + # 自动取址已收口到 Gen._adjust_args(唯一汇聚点,按 func.name 查表)。 setitem_func: ir.Function = Gen._get_function(setitem_func_name) setitem_args = Gen._adjust_args(setitem_args, setitem_func) Gen.builder.call(setitem_func, setitem_args, name=f"call_{setitem_func_name}") diff --git a/lib/core/Handles/HandlesExprCall.py b/lib/core/Handles/HandlesExprCall.py index 32a352c..f3c790b 100644 --- a/lib/core/Handles/HandlesExprCall.py +++ b/lib/core/Handles/HandlesExprCall.py @@ -1382,7 +1382,8 @@ class ExprCallHandle(BaseHandle): self._check_eh_return(result, FullMethodName, Gen, called_func=func) return result self._append_eh_msg_out_arg(CallArgs, func, Gen) - CallArgs = Gen._apply_auto_addr(MangledName, CallArgs) + # 自动取址已收口到 Gen._adjust_args(唯一汇聚点,按 func.name 查表), + # 此处的显式取址已删除,避免 'always' 模式被重复应用(不幂等)。 adjusted = Gen._adjust_args(CallArgs, func) result = Gen.builder.call(func, adjusted, name=f"call_{MangledName}") self._check_eh_return(result, MangledName, Gen, called_func=func) @@ -2780,7 +2781,7 @@ class ExprCallHandle(BaseHandle): adjusted.append(arg) result = Gen.builder.call(func, adjusted, name=f"call_{FuncName}") else: - CallArgs = Gen._apply_auto_addr(FuncName, CallArgs) + # 自动取址已收口到 Gen._adjust_args(唯一汇聚点,按 func.name 查表)。 adjusted = Gen._adjust_args(CallArgs, func) # 兜底:确保所有指针类型参数与函数签名匹配(如 struct* -> i8*) for i, (arg, param) in enumerate(zip(adjusted, func.args)): @@ -3481,7 +3482,7 @@ class ExprCallHandle(BaseHandle): adjusted.append(arg) result = Gen.builder.call(func, adjusted, name=f"call_{MethodName}") else: - CallArgs = Gen._apply_auto_addr(MethodName, CallArgs) + # 自动取址已收口到 Gen._adjust_args(唯一汇聚点,按 func.name 查表)。 adjusted = Gen._adjust_args(CallArgs, func) result = Gen.builder.call(func, adjusted, name=f"call_{MethodName}") return result @@ -3542,7 +3543,7 @@ class ExprCallHandle(BaseHandle): adjusted.append(arg) result = Gen.builder.call(func, adjusted, name=f"call_{MethodName}") else: - CallArgs = Gen._apply_auto_addr(MethodName, CallArgs) + # 自动取址已收口到 Gen._adjust_args(唯一汇聚点,按 func.name 查表)。 adjusted = Gen._adjust_args(CallArgs, func) result = Gen.builder.call(func, adjusted, name=f"call_{MethodName}") return result @@ -3570,7 +3571,7 @@ class ExprCallHandle(BaseHandle): mangled_name, _ai + 1, arg, Node)) self._fill_default_args(CallArgs, func, mangled_name) self._append_eh_msg_out_arg(CallArgs, func, Gen) - CallArgs = Gen._apply_auto_addr(mangled_name, CallArgs) + # 自动取址已收口到 Gen._adjust_args(唯一汇聚点,按 func.name 查表)。 adjusted = Gen._adjust_args(CallArgs, func) result = Gen.builder.call(func, adjusted, name=f"call_{MethodName}") self._check_eh_return(result, mangled_name, Gen, called_func=func) @@ -3944,7 +3945,7 @@ class ExprCallHandle(BaseHandle): call_args = [self_arg] + CallArgs self._fill_default_args(call_args, func, FullMethodName) self._append_eh_msg_out_arg(call_args, func, Gen) - call_args = Gen._apply_auto_addr(FullMethodName, call_args) + # 自动取址已收口到 Gen._adjust_args(唯一汇聚点,按 func.name 查表)。 adjusted = Gen._adjust_args(call_args, func) result = Gen.builder.call(func, adjusted, name=f"call_{FullMethodName}") self._check_eh_return(result, FullMethodName, Gen, called_func=func) @@ -5201,7 +5202,7 @@ class ExprCallHandle(BaseHandle): NewMethodArgs.append(ArgVal) self._fill_default_args(NewMethodArgs, NewMethodFunc, NewMethodFuncName) self._ApplyKeywordArgs(Node, NewMethodArgs, NewMethodFunc, NewMethodFuncName, self_offset=1) - NewMethodArgs = Gen._apply_auto_addr(NewMethodFuncName, NewMethodArgs) + # 自动取址已收口到 Gen._adjust_args(唯一汇聚点,按 func.name 查表)。 adjusted_new = Gen._adjust_args(NewMethodArgs, NewMethodFunc) heap_ptr = Gen.builder.call(NewMethodFunc, adjusted_new, name=f"new_{ClassName}") if heap_ptr: @@ -5233,7 +5234,7 @@ class ExprCallHandle(BaseHandle): self._fill_default_args(InitArgs, InitFunc, InitFuncName) self._ApplyKeywordArgs(Node, InitArgs, InitFunc, InitFuncName, self_offset=1) self._append_eh_msg_out_arg(InitArgs, InitFunc, Gen) - InitArgs = Gen._apply_auto_addr(InitFuncName, InitArgs) + # 自动取址已收口到 Gen._adjust_args(唯一汇聚点,按 func.name 查表)。 adjusted_init = Gen._adjust_args(InitArgs, InitFunc) Gen.builder.call(InitFunc, adjusted_init, name=f"init_{ClassName}") return result @@ -5266,7 +5267,7 @@ class ExprCallHandle(BaseHandle): NewMethodArgs.append(ArgVal) self._fill_default_args(NewMethodArgs, NewMethodFunc, NewMethodFuncName) self._ApplyKeywordArgs(Node, NewMethodArgs, NewMethodFunc, NewMethodFuncName, self_offset=1) - NewMethodArgs = Gen._apply_auto_addr(NewMethodFuncName, NewMethodArgs) + # 自动取址已收口到 Gen._adjust_args(唯一汇聚点,按 func.name 查表)。 adjusted_new = Gen._adjust_args(NewMethodArgs, NewMethodFunc) heap_ptr = Gen.builder.call(NewMethodFunc, adjusted_new, name=f"new_{ClassName}") if heap_ptr: @@ -5306,7 +5307,7 @@ class ExprCallHandle(BaseHandle): self._fill_default_args(InitArgs, InitFunc, InitFuncName) self._ApplyKeywordArgs(Node, InitArgs, InitFunc, InitFuncName, self_offset=1) self._append_eh_msg_out_arg(InitArgs, InitFunc, Gen) - InitArgs = Gen._apply_auto_addr(InitFuncName, InitArgs) + # 自动取址已收口到 Gen._adjust_args(唯一汇聚点,按 func.name 查表)。 adjusted_init = Gen._adjust_args(InitArgs, InitFunc) Gen.builder.call(InitFunc, adjusted_init, name=f"init_{ClassName}") elif Node.args or Node.keywords: @@ -5538,7 +5539,7 @@ class ExprCallHandle(BaseHandle): CallArgs.append(arg_val) if not CallArgs: CallArgs = [ir.Constant(ir.IntType(32), 0) for _ in func.args] - CallArgs = Gen._apply_auto_addr(spec_name, CallArgs) + # 自动取址已收口到 Gen._adjust_args(唯一汇聚点,按 func.name 查表)。 adjusted = Gen._adjust_args(CallArgs, func) return Gen.builder.call(func, adjusted, name=f"call_{spec_name}") @@ -5583,7 +5584,7 @@ class ExprCallHandle(BaseHandle): return None if not CallArgs: CallArgs = [ir.Constant(ir.IntType(32), 0) for _ in func.args] - CallArgs = Gen._apply_auto_addr(spec_name, CallArgs) + # 自动取址已收口到 Gen._adjust_args(唯一汇聚点,按 func.name 查表)。 adjusted = Gen._adjust_args(CallArgs, func) return Gen.builder.call(func, adjusted, name=f"call_{spec_name}") diff --git a/lib/core/Handles/HandlesFunctions.py b/lib/core/Handles/HandlesFunctions.py index a5caef7..7d070a1 100644 --- a/lib/core/Handles/HandlesFunctions.py +++ b/lib/core/Handles/HandlesFunctions.py @@ -1260,6 +1260,13 @@ class FunctionHandle(BaseHandle): if not IsUserMarkedExport and FuncName in Gen._export_funcs: Gen._export_funcs.discard(FuncName) MangledName: str = Gen._mangle_func_name(FuncName) + # 自动取址模式:查表侧统一按**真实发射名**(func.name,即 MangledName)查 + # (FuncGen._adjust_args)。签名阶段(_GetFunctionSignatureLlvm)只能按逻辑名 + # (FuncName)登记,故在此把该逻辑名下的模式复制到真实名下——否则同模块 + # "先调用、后定义"的 &T / &temp T 会在前向声明路径上静默丢失取址。 + _aam_fwd: list[str | None] | None = Gen._auto_addr_params.get(FuncName) + if _aam_fwd: + Gen._auto_addr_params[MangledName] = _aam_fwd need_new: bool = MangledName not in Gen.functions if not need_new: existing: Any = Gen.functions[MangledName] @@ -1739,6 +1746,9 @@ class FunctionHandle(BaseHandle): total_params_emit: int = len(ParamTypes) while len(auto_addr_modes_emit) < total_params_emit: auto_addr_modes_emit.append(None) + # 逻辑名(FuncName = 裸名 / "类名.方法")登记:真身定义路径下它是真实发射名的 + # 别名,保留以便按逻辑名查表;真实发射名(func.name)的登记在下方 func 就绪后 + # 进行(查表侧 FuncGen._adjust_args 统一按 func.name 查)。 Gen._auto_addr_params[FuncName] = auto_addr_modes_emit self.Trans.FunctionDefCache[FuncName] = Node IsInlineFunc = False @@ -1800,6 +1810,11 @@ class FunctionHandle(BaseHandle): func = Gen._CreateOrReuseFuncDecl(MangledName, FuncType) if MangledName == FuncName or FuncName not in Gen._export_extern_funcs: Gen.functions[FuncName] = func + # 自动取址模式(ref/temp/always)的**主键**必须是真实发射出的函数名 func.name, + # 与查表侧 FuncGen._adjust_args 的 func.name 逐字一致;FuncName(上方已登记)作别名。 + _auto_addr_real_name: str | None = getattr(func, 'name', None) + if _auto_addr_real_name: + Gen._auto_addr_params[_auto_addr_real_name] = auto_addr_modes_emit func.attributes.add('noredzone') # 泛型特化类方法(如 GSList[NameEntry].__before_init__):多个模块各自 # 特化会生成同名定义(external linkage)→ ld.lld duplicate symbol warning。 diff --git a/lib/core/Handles/HandlesImports.py b/lib/core/Handles/HandlesImports.py index 2a9dd41..3536b70 100644 --- a/lib/core/Handles/HandlesImports.py +++ b/lib/core/Handles/HandlesImports.py @@ -1692,6 +1692,21 @@ class ImportHandle(BaseHandle): _src_sha1 = Gen.ModuleSha1Map[_init_name] if _src_sha1: Gen._export_extern_funcs[FuncName] = _src_sha1 + # 自动取址模式(ref/temp/always)的登记**必须先于下面的 `FuncName in Gen.functions` + # 早退**:该函数已存在(stub / 调用点先建)时本函数会在此直接返回,若把登记放在 + # 后面 func 创建处(约 :1885)就永远不会执行 ⇒ 跨模块函数的取址模式静默失效。 + # 查表键与查表侧 FuncGen._adjust_args 的 func.name 逐字一致,故这里按"真实名候选" + # 双写:新算出的 mangled 名,以及已存在函数对象的实际名字(若已存在)。 + _auto_modes: list[str | None] = [ + FindAutoAddrMode(a.annotation) for a in Node.args.args] + if any(m is not None for m in _auto_modes): + _early_mangled: str = Gen._mangle_func_name(FuncName, module_name=source_module_name) + Gen._auto_addr_params[_early_mangled] = _auto_modes + Gen._auto_addr_params[FuncName] = _auto_modes + _early_existing = Gen.functions.get(FuncName) + _early_real: str | None = getattr(_early_existing, 'name', None) + if _early_real: + Gen._auto_addr_params[_early_real] = _auto_modes if FuncName in Gen.functions: return if Node.decorator_list: @@ -1870,11 +1885,12 @@ class ImportHandle(BaseHandle): func = Gen._get_or_declare_function(MangledName, FuncType) Gen.functions[MangledName] = func Gen.functions[FuncName] = func - # 跨模块自动取址模式登记(ref/temp/always):调用点 Gen._apply_auto_addr 按函数名 - # 查表,命中才做取址适配。ParamTypes 与 Node.args.args 逐位对齐(含方法 self)。 - _auto_modes: list[str | None] = [ - FindAutoAddrMode(a.annotation) for a in Node.args.args] + # 跨模块自动取址模式登记(ref/temp/always):以**真实发射名** func.name 为主键, + # 与查表侧 FuncGen._adjust_args 的 func.name 逐字一致;MangledName / FuncName + # 保留为别名键。ParamTypes 与 Node.args.args 逐位对齐(含方法 self)。 + # (_auto_modes 已在函数开头"早退之前"处计算,此处复用。) if any(m is not None for m in _auto_modes): + Gen._auto_addr_params[func.name] = _auto_modes Gen._auto_addr_params[MangledName] = _auto_modes Gen._auto_addr_params[FuncName] = _auto_modes func_meta = FuncMeta.NONE @@ -2526,18 +2542,21 @@ class ImportHandle(BaseHandle): DeclFuncName = FuncFullName + '$set' elif is_item_prop_deleter: DeclFuncName = FuncFullName + '$del' - if DeclFuncName not in Gen.functions: - FuncDeclNode = ast.FunctionDef( - name=DeclFuncName, - args=item.args, - body=item.body, - decorator_list=item.decorator_list, - returns=item.returns - ) - try: - self._EmitExternalFuncDeclLlvm(FuncDeclNode, Gen, is_class_method=not is_item_static and not is_item_classmethod, source_module_name=module_name) - except Exception as e: - raise + # 无条件调用:即使 DeclFuncName 已在 Gen.functions 中,也必须让 + # _EmitExternalFuncDeclLlvm 走到其**早退之前**的自动取址登记逻辑 + # (该函数在早退前完成登记后即返回,对已存在符号无其它副作用); + # 否则下面的守卫会让整个调用被跳过,stub 方法的取址模式永不生效。 + FuncDeclNode = ast.FunctionDef( + name=DeclFuncName, + args=item.args, + body=item.body, + decorator_list=item.decorator_list, + returns=item.returns + ) + try: + self._EmitExternalFuncDeclLlvm(FuncDeclNode, Gen, is_class_method=not is_item_static and not is_item_classmethod, source_module_name=module_name) + except Exception as e: + raise func_meta = FuncMeta.NONE if is_item_static: func_meta |= FuncMeta.STATIC_METHOD diff --git a/lib/core/LLVMCG/FuncGen.py b/lib/core/LLVMCG/FuncGen.py index 6e01e10..e3a5f99 100644 --- a/lib/core/LLVMCG/FuncGen.py +++ b/lib/core/LLVMCG/FuncGen.py @@ -105,6 +105,9 @@ class FuncGenMixin: 非指针左值的地址取自实参 load 指令的指针操作数(`load(p)` ⇒ p 即左值地址), 因为调用点实参已按 rvalue 求值(标量变量的 load 结果)。 + + 唯一入口:本方法**只在** `_adjust_args` 开头被调用(调用链唯一汇聚点), + 故同一次调用绝不会取址两次——'always' 不幂等,多调一次即多包一层指针。 """ modes: list[str | None] | None = self._auto_addr_params.get(func_name) if not modes: @@ -138,6 +141,18 @@ class FuncGenMixin: return new_args def _adjust_args(self, args: list[ir.Value], func: ir.Function) -> list[ir.Value]: + # 自动取址(&T=ref / &temp T=temp / t.CAutoPtr=always)的**唯一汇聚点**: + # 任何类型强转之前先做一次取址适配,于是 direct / vtable 虚分派 / 构造 / + # 静态方法 / __call__ / 下标赋值 / c.Addr 构造 / 闭包 / 泛型 / 方法兜底等 + # **所有**调用路径都自动获得取址能力,无需在每个调用点手写。 + # 为什么只能在这里做:'always'(t.CAutoPtr)不幂等——它无条件 + # alloca+store+传地址,重复应用会把指针再包一层;原先散落在各调用点的 + # 显式 Gen._apply_auto_addr(...) 与本汇聚点重复 ⇒ 已全部删除,由本处唯一负责。 + # 查表键统一为**真实发射出的函数名** func.name(登记侧逐字写入同名键)。 + if func is not None: + _auto_addr_name: str | None = getattr(func, 'name', None) + if _auto_addr_name: + args = self._apply_auto_addr(_auto_addr_name, args) adjusted: list[ir.Value] = [] for i, (arg, param) in enumerate(zip(args, func.args)): if arg.type != param.type: