From d3690f91432e3d1d0c0459ca246c93b5a3e9d9b6 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Fri, 11 Sep 2026 17:39:21 +0800 Subject: [PATCH] =?UTF-8?q?fix(tpv):=20=E4=BE=9D=E8=B5=96=E6=B3=A8?= =?UTF-8?q?=E5=85=A5=E6=9C=9F=E9=BB=98=E8=AE=A4=E5=8F=82=E6=95=B0=E6=8C=89?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E6=A8=A1=E5=9D=97=20SHA1=20=E7=99=BB?= =?UTF-8?q?=E8=AE=B0=EF=BC=8C=E6=B6=88=E9=99=A4=E8=B7=A8=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E5=90=8C=E5=90=8D=E5=87=BD=E6=95=B0=E4=B8=B2=E5=91=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit N17:VpiReader 注入函数/方法 declare 时显式传入 src_sha1(被依赖模块自身 sha1),add_func_to_table 透传至 _register_global_defaults;调用点默认值查找 改用 find_func_entry_in_table_owned 按 "{owner_sha1}." 前缀限定。修复 usb.uhci.init 误命中 mm.init 的 5 形参/2 默认值而凭空补 2 个 i32 0 的 ABI 错位(IR 实证:call @...init(i16 %4, i32 0, i32 0) → (i16 %4))。 同轮并入的其他编译器侧改动: - N11 Converter.vp:无 -> 但带 @c.CReturn 时合成 tuple 返回注解,与 define 对齐 - N12 VpiReader.vp:union 指针(T | t.CPtr)stub 解析与定义侧收敛到 i8* - N14 ExprGenFstr.vp:f-string 32 位整型不再写 l 修饰符 - N2 撤回 ExprGenOps.vp:删除在 _node_type_unsigned 热点查/填 vpi 缓存的 _call_ret_annot_unsigned(有副作用,触发 fat32_diskio.vp match 路径崩溃) --- App/lib/Stub/StubGen/Converter.vp | 45 +++++++++++++++++++ App/lib/Stub/StubGen/VpiReader.vp | 33 ++++++++++++-- App/lib/core/Gen/Call/CallGenLeafKit.vp | 26 +++++++---- App/lib/core/Gen/Call/CallGenMixin.vp | 39 +++++++++-------- App/lib/core/Gen/Expr/ExprGenFstr.vp | 6 ++- App/lib/core/Gen/Expr/ExprGenOps.vp | 58 ------------------------- App/lib/core/Gen/GenApi.vp | 9 ++-- 7 files changed, 124 insertions(+), 92 deletions(-) diff --git a/App/lib/Stub/StubGen/Converter.vp b/App/lib/Stub/StubGen/Converter.vp index c95b62c..d3d4a85 100644 --- a/App/lib/Stub/StubGen/Converter.vp +++ b/App/lib/Stub/StubGen/Converter.vp @@ -424,6 +424,37 @@ def _PyiDefaultStr(buf: bytes, buf_size: t.CSizeT, pos: t.CSizeT, return pos +# ============================================================ +# _PyiCreturnArgs - 从装饰器列表提取 @c.CReturn(...) 的实参列表 +# +# N11:`@c.CReturn(a, b, c)` 在定义侧被 FuncGenBase._resolve_creturn_ret_ty +# 展开为聚合返回类型 `{a, b, c}`,但 vpi 里该函数只有装饰器行、没有 `->` 注解 +# → stub declare 退化成 i32(mm.GetMemoryStats 定义 `{i64,i64,i64}` vs +# `declare i32`)。生成 vpi 时据此合成 `-> tuple[a, b, c]` +# (_resolve_vpi_ret_annot_str 的既有 tuple 分支同样打包成 Struct), +# 使 stub declare 与 define 的返回类型一致。 +# 返回 None = 装饰器列表里没有 CReturn。 +# ============================================================ +def _PyiCreturnArgs(decorators: list[ast.AST | t.CPtr] | t.CPtr) -> list[ast.AST | t.CPtr] | t.CPtr: + """在装饰器列表里找 @c.CReturn(...),返回其实参列表;未找到返回 None""" + if decorators is None: + return None + dn: t.CSizeT = len(decorators) + di: t.CSizeT = 0 + while di < dn: + dnode: ast.AST | t.CPtr = decorators.get(di) + di += 1 + if dnode is None or dnode.kind() != ast.ASTKind.Call: + continue + dcall: ast.Call | t.CPtr = (ast.Call | t.CPtr)(dnode) + if dcall.func is None or dcall.func.kind() != ast.ASTKind.Attribute: + continue + dat: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(dcall.func) + if dat.attr is not None and string.strcmp(dat.attr, "CReturn") == 0: + return dcall.args + return None + + # ============================================================ # _PyiFunction - 生成函数签名 # @@ -518,6 +549,20 @@ def _PyiFunction(buf: bytes, buf_size: t.CSizeT, pos: t.CSizeT, if fn.returns is not None: pos = _PyiEmit(buf, buf_size, pos, " -> ") pos = _PyiTypeStr(buf, buf_size, pos, fn.returns) + else: + # 无 `->` 注解但带 @c.CReturn(...):合成 " -> tuple[a, b, c]"(N11) + cre_args: list[ast.AST | t.CPtr] | t.CPtr = _PyiCreturnArgs(fn.decorator_list) + if cre_args is not None: + cre_n: t.CSizeT = len(cre_args) + if cre_n > 0: + pos = _PyiEmit(buf, buf_size, pos, " -> tuple[") + cre_i: t.CSizeT = 0 + while cre_i < cre_n: + if cre_i > 0: + pos = _PyiEmit(buf, buf_size, pos, ", ") + pos = _PyiTypeStr(buf, buf_size, pos, cre_args.get(cre_i)) + cre_i += 1 + pos = _PyiEmit(buf, buf_size, pos, "]") pos = _PyiEmit(buf, buf_size, pos, ": pass\n") return pos diff --git a/App/lib/Stub/StubGen/VpiReader.vp b/App/lib/Stub/StubGen/VpiReader.vp index 4bc1b3d..57a7571 100644 --- a/App/lib/Stub/StubGen/VpiReader.vp +++ b/App/lib/Stub/StubGen/VpiReader.vp @@ -1021,6 +1021,11 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy | t.CPtr, has_cptr: int = 0 has_cvoid: int = 0 first_ty: llvmlite.LLVMType | t.CPtr = None + # 产生 first_ty 那一段文本的属性(供末尾 has_cptr 分支复刻定义侧规则,N12): + # first_qual=1 段是限定名(含 '.',如 t.CUInt64T / mod.Class) + # first_wl =1 段是白名单裸标量名(int/char/str/bytes/bool/float/double) + first_qual: int = 0 + first_wl: int = 0 buf_len: t.CSizeT = string.strlen(ret_annot) pos: t.CSizeT = 0 @@ -1050,6 +1055,20 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy | t.CPtr, seg_ty: llvmlite.LLVMType | t.CPtr = _resolve_single_vpi_type_str(pool, seg_buf) if seg_ty is not None and first_ty is None: first_ty = seg_ty + # 记录该段属性(N12):定义侧 TypeGenResolve.resolve_annotation_type + # 对**裸名** pointee 仅在它解析为已注册结构体、泛型参数名或白名单 + # 裸标量时才保留 pointee,否则联合坍缩为 i8*;stub 侧此前无条件 + # Ptr(first_ty) → `uint64 | t.CPtr` 两侧不一致(定义 i8* vs declare i64*)。 + if string.strchr(seg_buf, 46) is not None: + first_qual = 1 + if string.strcmp(seg_buf, "int") == 0 or \ + string.strcmp(seg_buf, "char") == 0 or \ + string.strcmp(seg_buf, "str") == 0 or \ + string.strcmp(seg_buf, "bytes") == 0 or \ + string.strcmp(seg_buf, "bool") == 0 or \ + string.strcmp(seg_buf, "float") == 0 or \ + string.strcmp(seg_buf, "double") == 0: + first_wl = 1 stdlib.free(seg_buf) pos += 1 # 跳过 '|' @@ -1057,7 +1076,15 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy | t.CPtr, if has_cvoid != 0: return i8_ptr_ty if first_ty is not None: - return llvmlite.Ptr(pool, first_ty) + # 复刻定义侧规则(N12):限定名 / 白名单裸标量 / 已注册结构体 → 保留 + # pointee;其余**裸名**(如 uint64/uint32 等 typedef 别名、裸枚举名) + # → 联合坍缩为 i8*,与 resolve_annotation_type 一致,避免 + # `save_buf: uint64 | t.CPtr` 定义侧 i8* 而 stub 侧 i64* 跨模块不收敛。 + if first_qual != 0 or first_wl != 0: + return llvmlite.Ptr(pool, first_ty) + if first_ty.kind() == llvmlite.LLVMType.Struct: + return llvmlite.Ptr(pool, first_ty) + return i8_ptr_ty return i8_ptr_ty if has_cvoid != 0: # t.CVoid | t.State:State 是装饰器标记(编译侧忽略),t.CVoid → void。 @@ -2320,7 +2347,7 @@ def _inject_function_declare(pool: memhub.MemBuddy | t.CPtr, if funcs_ptr is not None: cur_count: int = trans._func_count if GenApi.add_func_to_table(funcs_ptr, cur_count, fd.name, func, max_funcs, - fd_defaults, fd_default_count, param_count) == 0: + fd_defaults, fd_default_count, param_count, None, src_sha1) == 0: trans._func_count = cur_count + 1 # 补全全局函数表 TypeStr(参数已全部添加,对齐 FuncGenDef L211 行为): # vpi 注入路径若不补全,跨模块 vtable/调用解析 find_func_entry_global() @@ -2512,7 +2539,7 @@ def _inject_method_declare(pool: memhub.MemBuddy | t.CPtr, if param_count_no_self > 0: param_count_no_self -= 1 if GenApi.add_func_to_table(funcs_ptr, cur_count, lookup_name, func, max_funcs, - md_defaults, md_default_count, param_count_no_self) == 0: + md_defaults, md_default_count, param_count_no_self, None, src_sha1) == 0: trans._func_count = cur_count + 1 # 补全全局函数表 TypeStr(参数已全部添加,对齐 ClassGenVTable L832 行为): # vpi 注入的方法声明若不补全 TypeStr,跨模块继承 vtable 生成时 diff --git a/App/lib/core/Gen/Call/CallGenLeafKit.vp b/App/lib/core/Gen/Call/CallGenLeafKit.vp index 362c5a4..2d3ae90 100644 --- a/App/lib/core/Gen/Call/CallGenLeafKit.vp +++ b/App/lib/core/Gen/Call/CallGenLeafKit.vp @@ -994,7 +994,8 @@ class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): defaults: t.CVoid | t.CPtr = None, default_count: int = 0, param_count: int = 0, - pool: memhub.MemBuddy | t.CPtr = None) -> int: + pool: memhub.MemBuddy | t.CPtr = None, + def_sha1: str = None) -> int: """添加函数到函数表,返回 0 成功 Args: @@ -1019,7 +1020,7 @@ class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): self._register_global_func(name, func, pool) # 同时注册到全局默认参数表(供跨模块调用时填充默认值) if default_count > 0: - self._register_global_defaults(name, defaults, default_count, param_count) + self._register_global_defaults(name, defaults, default_count, param_count, def_sha1) return 0 @@ -1172,21 +1173,30 @@ class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): def _register_global_defaults(self, name: str, defaults: t.CVoid | t.CPtr, default_count: int, - param_count: int) -> int: + param_count: int, + def_sha1: str = None) -> int: """注册函数默认参数到全局表,返回 0 成功 注册时提取每个默认值 Constant 的常量快照到 stdlib(ConstKinds/ConstInts/ConstStrs), 跨模块调用时优先用快照重建常量 IR,避免读取被 reset 回收的 pool 内 AST。 + + def_sha1:**定义该函数的模块 SHA1**。依赖注入路径(VpiReader)必须显式传入, + 否则会退回 CurrentModuleSha1 —— 注入期它是**导入方**,会把被依赖模块函数的 + 默认值挂到导入方名下(如 mm.init 的 2 个默认值挂到 usb)→ usb 的 + `uhci.init(io_base)` 经 find_func_defaults("init", usb_sha) 命中该错账条目 + 而被补 2 个 i32 0(N17 真因;模块函数表的"按定义模块限定查找"救不了这条 + 全局表路径,因为该处 found_func 仍为 None、交叉校验被整体跳过)。 """ if name is None or defaults is None: return 1 if self._init_global_defaults_table() == 0: return 1 - # 当前模块 SHA1 作为限定键:同一函数名在不同模块各存一条, - # 查询时按「名 + 定义模块」精确匹配,消除跨模块同名串味 - # (usb.uhci.init 1 参误命中 mm.init 5 参/2 默认值根因)。 - cur_sha: str = None - if self.Gen is not None and self.Gen.TypeGenBase is not None: + # 限定键 = **定义该函数的模块 SHA1**:同一函数名在不同模块各存一条,查询时 + # 按「名 + 定义模块」精确匹配,消除跨模块同名串味。def_sha1 由依赖注入 + # 路径显式传入被依赖模块自身 sha1;非注入路径(本模块真实定义)取 + # CurrentModuleSha1(此时它就是定义模块)。 + cur_sha: str = def_sha1 + if cur_sha is None and self.Gen is not None and self.Gen.TypeGenBase is not None: cur_sha = self.Gen.TypeGenBase.CurrentModuleSha1 # 同模块同名已存在则跳过 if self.find_func_defaults(name, cur_sha) is not None: diff --git a/App/lib/core/Gen/Call/CallGenMixin.vp b/App/lib/core/Gen/Call/CallGenMixin.vp index 754a0f5..fbc8209 100644 --- a/App/lib/core/Gen/Call/CallGenMixin.vp +++ b/App/lib/core/Gen/Call/CallGenMixin.vp @@ -1088,13 +1088,14 @@ class CallGenMixin(CallGenBase.CallGenBase): # 默认参数填充:当实参数量 < 形参数量时,用默认值填充缺失参数 # defaults 数组右对齐到 args:defaults[0] 对应 args[offset],offset = param_count - default_count if can > 0 or (can == 0 and cargs is not None): - df_defaults: t.CVoid | t.CPtr = None - df_default_count: int = 0 - df_param_count: int = 0 + df_defaults: t.CVoid | t.CPtr = None + df_default_count: int = 0 + df_param_count: int = 0 # 计算被调模块 SHA1 作限定键(消除跨模块同名函数串味): # module.func(...) → 该 module 的 SHA1;裸名调用 → 当前模块 SHA1。 - # 全局默认参数表按「名 + 定义模块 SHA1」精确匹配,避免 usb.uhci.init(1 参) - # 误命中 mm.init(5 参/2 默认值) 而补出多余实参。 + # 模块表与全局默认参数表都按「名 + 定义模块 SHA1」精确匹配,避免 + # usb.uhci.init(1 参) 误命中 mm.init(5 参/2 默认值) 而补出多余实参。 + # 必须先算(模块表查找也要用它限定定义模块 → 见下)。 dfx_callee_sha: str = None if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: dfx_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) @@ -1104,10 +1105,15 @@ class CallGenMixin(CallGenBase.CallGenBase): dfx_callee_sha = self._lookup_module_sha1(dfx_mn.id) if dfx_callee_sha is None and self.Gen.TypeGenBase is not None: dfx_callee_sha = self.Gen.TypeGenBase.CurrentModuleSha1 - # 先从当前模块函数表查找 FuncEntry —— 必须按**定义模块 SHA1 限定**: - # 表内含 LoadDepVpiIntoModule 以裸名注入的依赖 stub(如 mm.init, - # 槽位在前),裸名首命中会让 usb 的 `uhci.init(io_base)`(1 形参) - # 拿到 mm.init 的 5 形参/2 默认值 → 调用点被补 2 个 i32 0(N17)。 + # 从当前模块函数表查找 FuncEntry —— 必须按**定义模块 SHA1 限定**: + # 表内含 LoadDepVpiIntoModule 以裸名注入的依赖 stub(槽位在前), + # 裸名首命中会让 usb 的 `uhci.init(io_base)`(1 形参)拿到 mm.init 的 + # 5 形参/2 默认值 → 调用点被补 2 个 i32 0(N17)。 + # 注:仅做「精确到定义模块」这一项改动;下方交叉校验守卫(dfx_cnt) + # 保持原样(`dfx_cnt > 0 and ...`)——收紧它会让 dfx_cnt==0 的场景 + # 落入 `elif found_func is not None` 零值兜底分支,改动面更大, + # 且本项改动已足以修掉 N17(受限查找命中本模块/同定义模块条目, + # Defaults 为 None 或本模块池内 AST)。 if trans is not None and trans._funcs is not None: df_entry: GenTypes.FuncEntry | t.CPtr = self.Gen.CallGenLeafKit.find_func_entry_in_table_owned( trans._funcs, trans._func_count, func_name, dfx_callee_sha) @@ -1125,14 +1131,11 @@ class CallGenMixin(CallGenBase.CallGenBase): df_defaults = gd_entry.Defaults df_default_count = gd_entry.DefaultCount df_param_count = gd_entry.ParamCount - # 交叉校验:默认参数表(模块表裸名 / 全局表按导入方 sha1 登记)仍可能 - # 跨模块同名串味(如 usb.uhci.init 只有 1 形参,却拿到 mm.init 的 - # 5 形参/2 默认值记录 → 被补 2 个 i32 0 → call 3 实参 vs declare 1 形参 - # → ABI 错位,N17)。若被调声明(found_func)的实际形参数与表记录 - # ParamCount 不符,则丢弃该表,交由下方 `elif found_func is not None` - # 分支按真实形参数零值兜底。 - # 注意:必须覆盖 dfx_cnt == 0(found_func 被后缀匹配成同模块无参同名 - # 函数时原有 `dfx_cnt > 0` 守卫失效 → usb.uhci.init(1 参) 仍被补参)。 + # 交叉校验:全局默认参数表按「裸函数名」登记/查询,跨模块同名函数会串味 + # (如 usb.uhci.init 只有 1 形参,却命中 mm.init 的 5 形参/2 默认值记录 + # → 被补 2 个 i32 0 → call 3 实参 vs declare 1 形参 → ABI 错位)。 + # 若被调声明(found_func)的实际形参数与表记录 ParamCount 不符,则丢弃该表, + # 交由下方 `elif found_func is not None` 分支按真实形参数零值兜底。 if found_func is not None and df_default_count > 0: dfx_cnt: int = 0 dfx_p: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(found_func) @@ -1142,7 +1145,7 @@ class CallGenMixin(CallGenBase.CallGenBase): and string.strcmp(dfx_nm, "%__eh_code_out__") != 0): dfx_cnt += 1 dfx_p = llvmlite.param_get_next(dfx_p) - if dfx_cnt != df_param_count: + if dfx_cnt > 0 and dfx_cnt != df_param_count: df_defaults = None df_default_count = 0 df_param_count = 0 diff --git a/App/lib/core/Gen/Expr/ExprGenFstr.vp b/App/lib/core/Gen/Expr/ExprGenFstr.vp index 93148a9..1accede 100644 --- a/App/lib/core/Gen/Expr/ExprGenFstr.vp +++ b/App/lib/core/Gen/Expr/ExprGenFstr.vp @@ -338,10 +338,12 @@ class ExprGenFstr(ExprGenBase.ExprGenBase): return None len_mod[0] = '\0' ibits: int = self.Gen.ExprGenBase.get_llvm_type_bits(val.Ty) + # 32 位**不写**长度修饰符(N14):`{x:08X}` 的实参是 i32,此前推导出 + # `l` → 格式串 `%08lX`(long)与实参宽度不符(LP64 下 printf 按 64 位 + # 读参 → 变参错位)。与同文件无 spec 路径 `_fstr_infer_c_fmt`(32 位用 + # `%u/%d`)以及 TPC 侧 HandlesExprFormat.py 保持一致。 if ibits == 64: string.strcpy(len_mod, "ll") - elif ibits == 32: - string.strcpy(len_mod, "l") elif ibits == 16: string.strcpy(len_mod, "h") elif ibits == 8: diff --git a/App/lib/core/Gen/Expr/ExprGenOps.vp b/App/lib/core/Gen/Expr/ExprGenOps.vp index bbb4c1e..968f149 100644 --- a/App/lib/core/Gen/Expr/ExprGenOps.vp +++ b/App/lib/core/Gen/Expr/ExprGenOps.vp @@ -235,12 +235,6 @@ class ExprGenOps(ExprGenBase.ExprGenBase): and at.attr is not None: if self._type_name_unsigned(at.attr) != 0: return 1 - # 用户函数/方法调用:查被调方 vpi 返回类型注解(N2)。 - # `read(LAPIC_ID) >> 24`(apic.read 返回 uint32)此前落到 return 0 - # → translate_binop 生成 ashr(应 lshr)。查询失败一律返回 0(本函数 - # 契约:只读、失败返回 0、绝不 fatal)。 - if self._call_ret_annot_unsigned(cl, trans) != 0: - return 1 return 0 if k == ast.ASTKind.Name: nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) @@ -322,58 +316,6 @@ class ExprGenOps(ExprGenBase.ExprGenBase): fi_u += 1 return 0 return 0 - def _call_ret_annot_unsigned(self, cl: ast.Call | t.CPtr, - trans: HT.Translator | t.CPtr) -> int: - """用户函数/方法调用的返回类型是否为无符号整型(查被调方 vpi 返回注解) - - 1=无符号,0=否/未知。N2 根因:apic.`read(offset: uint32) -> uint32` 的 - 调用结果参与 `>> 24` 时,Call 分支只认 `t.CXXXT(...)` 强转 → 返回 0 → - translate_binop 选 ashr(应 lshr)。 - - 严格遵循 _node_type_unsigned 的契约「只读、失败返回 0」: - - 不做任何 fatal_error / 断言; - - vpi 未生成、TempDir 为空、模块名不可解、注解缺失等一律返回 0 - (退回既有有符号语义,不引入新语义)。 - 返回注解缓存为幂等(已加载即跳过),故热路径仅一次哈希查表。 - """ - if cl is None or cl.func is None or trans is None: - return 0 - callee_sha: str = None - callee_meth: str = None - fk: int = cl.func.kind() - if fk == ast.ASTKind.Name: - # 裸名调用(同模块函数或 from-import):按当前模块 sha1 限定 - nm_f: ast.Name | t.CPtr = (ast.Name | t.CPtr)(cl.func) - if nm_f.id is None: - return 0 - callee_meth = nm_f.id - callee_sha = trans.ModuleSha1 - elif fk == ast.ASTKind.Attribute: - # module.func(...) / 模块限定调用:按模块名反查定义模块 sha1 - at_r: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) - if at_r.attr is None or at_r.value is None: - return 0 - if at_r.value.kind() != ast.ASTKind.Name: - return 0 - mod_r: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at_r.value) - if mod_r.id is None or string.strcmp(mod_r.id, "t") == 0: - return 0 - callee_meth = at_r.attr - callee_sha = self.Gen.CallGenBase._lookup_module_sha1(mod_r.id) - else: - return 0 - if callee_sha is None or callee_meth is None: - return 0 - # 函数内懒 import:与 CallGenLib._coerce_args_to_def_params 同源,规避循环依赖 - import lib.Stub.StubGen.VpiReader as VpiReader - td_r: str = self.Gen.CallGenBase.TempDir - if td_r is not None and self.Gen.CallGenBase.TempDirLen > 0: - VpiReader._ensure_vpi_ret_annot_loaded(callee_sha, td_r) - ret_annot_r: str = VpiReader._lookup_vpi_ret_annot(callee_sha, None, callee_meth) - if ret_annot_r is None: - return 0 - return self._annot_str_unsigned(ret_annot_r) - def _type_name_unsigned(self, type_name: str) -> int: """类型名是否为无符号整数类型(精确匹配,避免子串误伤如 nUIntCount)""" if type_name is None: diff --git a/App/lib/core/Gen/GenApi.vp b/App/lib/core/Gen/GenApi.vp index c5c4245..d5d7cd2 100644 --- a/App/lib/core/Gen/GenApi.vp +++ b/App/lib/core/Gen/GenApi.vp @@ -594,12 +594,15 @@ def find_func_in_module(mod: llvmlite.LLVMModule | t.CPtr, name: str) -> llvmlit # ---------------- add_func_to_table(委托 CallGenLeafKit.add_func_to_table) ---------------- -def add_func_to_table(funcs: GenTypes.FuncEntry | t.CPtr, func_count: int, name: str, func: llvmlite.Function | t.CPtr, max_count: int, defaults: t.CVoid | t.CPtr = None, default_count: int = 0, param_count: int = 0, pool: memhub.MemBuddy | t.CPtr = None) -> int: - """委托到 gen.add_func_to_table(原 Handles 壳)""" +def add_func_to_table(funcs: GenTypes.FuncEntry | t.CPtr, func_count: int, name: str, func: llvmlite.Function | t.CPtr, max_count: int, defaults: t.CVoid | t.CPtr = None, default_count: int = 0, param_count: int = 0, pool: memhub.MemBuddy | t.CPtr = None, def_sha1: str = None) -> int: + """委托到 gen.add_func_to_table(原 Handles 壳) + + def_sha1:定义该函数的模块 SHA1(依赖注入路径必须传,避免默认值被挂到导入方名下) + """ import lib.core.Gen.Generator as Generator g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) if g is not None: - return g.CallGenLeafKit.add_func_to_table(funcs, func_count, name, func, max_count, defaults, default_count, param_count, pool) + return g.CallGenLeafKit.add_func_to_table(funcs, func_count, name, func, max_count, defaults, default_count, param_count, pool, def_sha1) return 0