From 50d53d3ce66c368dfdf13658d790433f7f383be2 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 5 Sep 2026 12:48:03 +0800 Subject: [PATCH] =?UTF-8?q?fix(link):=20=E8=A1=A5=20CallGenLib.=5Fpromote?= =?UTF-8?q?=5Fclib=5Fcall=5Fargs=20=E5=AE=9A=E4=B9=89=EF=BC=9BBuildPipelin?= =?UTF-8?q?e=20PYI=5FBUF=5FSIZE=20=E6=94=B9=20t.CDefine=20=E5=AE=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CallGenMixin.translate_call 调用 self.Gen.CallGenLib._promote_clib_call_args(B3 裸名 C 库函数第三参 i64 提升),但 CallGenLib 缺该方法 → ld.lld undefined symbol。按 TPVAppBK 旧语法移植完整方法。 PYI_BUF_SIZE 是跨模块共享裸全局(@PYI_BUF_SIZE),Phase1/__init__ 与 BuildPipeline 两模块各定义强符号 → duplicate symbol。BuildPipeline 侧改用 t.CDefine 宏(同 SRC_BUF_SIZE),不再产生全局。 --- App/lib/Phase/BuildPipeline.vp | 4 +- App/lib/core/Gen/Call/CallGenLib.vp | 74 +++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/App/lib/Phase/BuildPipeline.vp b/App/lib/Phase/BuildPipeline.vp index 11786e8..a2d1d6e 100644 --- a/App/lib/Phase/BuildPipeline.vp +++ b/App/lib/Phase/BuildPipeline.vp @@ -50,7 +50,9 @@ _phase2_bat_init: int = 0 SRC_BUF_SIZE: t.CDefine = 1048576 # 2^20 = 1MB # .vpi 存根缓冲区大小(256KB,与 Phase1 一致) -PYI_BUF_SIZE: t.CSizeT = 262144 +# 用 t.CDefine 宏而非模块级全局:模块级全局是跨模块共享裸符号(@PYI_BUF_SIZE), +# Phase1/__init__.vp 已定义同名全局 → 两模块各定义强符号 → ld.lld duplicate symbol。 +PYI_BUF_SIZE: t.CDefine = 262144 # ============================================================ # TranslateFileGetTrans - 翻译单个文件,返回 Translator 对象 diff --git a/App/lib/core/Gen/Call/CallGenLib.vp b/App/lib/core/Gen/Call/CallGenLib.vp index 089da70..4168489 100644 --- a/App/lib/core/Gen/Call/CallGenLib.vp +++ b/App/lib/core/Gen/Call/CallGenLib.vp @@ -109,6 +109,80 @@ class CallGenLib(CallGenBase.CallGenBase): llvmlite.add_param(pool, fn, i8_ptr_ty, "src") llvmlite.add_param(pool, fn, i64_ty, "n") return fn + + def _promote_clib_call_args(self, pool: memhub.MemBuddy | t.CPtr, + builder: llvmlite.IRBuilder | t.CPtr, + mod: llvmlite.LLVMModule | t.CPtr, + call_name: str, + head: llvmlite.Value | t.CPtr, + count: int) -> llvmlite.Value | t.CPtr: + """裸名 C 库函数实参按标准签名提升(B3)。 + + 跨模块裸名调用(string.memset → @memset)时 _ensure_method_declare 用 + 实参类型建 declare:第三参字面量 32=i32 把定义 t.CSizeT(i64) 固化窄 + → declare/call @memset(i8*,i32,i32) vs 定义 @memset(i8*,i32,i64), + ABI 宽度不一致(VKernel process.vp B3)。调用点先把第三参窄整数 + 实参提升到 i64,declare 与 call 均按 i64 生成 → 与定义一致。 + 未命中白名单原样返回 head。 + """ + if pool is None or builder is None or call_name is None or head is None: + return head + # 仅裸名(无 '.' 分隔 → 无 sha1 前缀);带前缀走 vpi 定义侧解析 + if string.strchr(call_name, 46) is not None: + return head + # 白名单:第三参 size_t(i64) 的函数(与 _ensure_c_lib_declare 一致) + is_3rd_i64: int = 0 + if string.strcmp(call_name, "memset") == 0: is_3rd_i64 = 1 + elif string.strcmp(call_name, "memcpy") == 0: is_3rd_i64 = 1 + elif string.strcmp(call_name, "memmove") == 0: is_3rd_i64 = 1 + elif string.strcmp(call_name, "memcmp") == 0: is_3rd_i64 = 1 + elif string.strcmp(call_name, "strncmp") == 0: is_3rd_i64 = 1 + elif string.strcmp(call_name, "strncpy") == 0: is_3rd_i64 = 1 + elif string.strcmp(call_name, "strncat") == 0: is_3rd_i64 = 1 + if is_3rd_i64 == 0 or count < 3: + return head + # 定位第三参(index 2) + cur: llvmlite.Value | t.CPtr = head + idx: int = 0 + while cur is not None and idx < 2: + cur = cur.Next + idx += 1 + if cur is None or cur.Ty is None: + return head + i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool) + promoted: llvmlite.Value | t.CPtr = None + match cur.Ty: + case llvmlite.LLVMType.Int(bits): + if bits >= 64: + return head + if cur.IsConst != 0: + # 常量:直接 i64 常量(位模式保留,无符号长度语义) + promoted = llvmlite.const_int(pool, 64, cur.IntVal) + else: + # SSA 值:zext 到 i64(size_t 无符号长度) + promoted = llvmlite.build_zext(builder, cur, i64_ty) + case _: + return head + if promoted is None: + return head + # 重建实参链表:index 2 替换为提升后的值 + new_head: llvmlite.Value | t.CPtr = None + new_tail: llvmlite.Value | t.CPtr = None + cur2: llvmlite.Value | t.CPtr = head + i2: int = 0 + while cur2 is not None: + node_v: llvmlite.Value | t.CPtr = cur2 + if i2 == 2: + node_v = promoted + if new_head is None: + new_head = node_v + else: + new_tail.Next = node_v + new_tail = node_v + cur2 = cur2.Next + i2 += 1 + return new_head + def _infer_external_func_ret_ty(self, pool: memhub.MemBuddy | t.CPtr, func_name: str, node: ast.AST | t.CPtr,