feat(codegen): 值引用自动取址收口到 _adjust_args,补齐 vtable/方法/构造等路径

查表键统一为真实发射出的函数名: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,覆盖同模块先调用后定义的场景。
This commit is contained in:
TermiNexus committed 2026-10-07 19:59:36 +08:00
1 parent b49b5c3ba6
commit 9656bb161a
6 files changed
+82 -32

No files matched your search

+3 -3
View File
@@ -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}")
+1 -1
View File
@@ -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}")
+13 -12
View File
@@ -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}")
+15
View File
@@ -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。
+35 -16
View File
@@ -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
+15
View File
@@ -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: