From 2b2c242d14743f546fd8b6594fc89bf97bd30761 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 29 Aug 2026 12:03:12 +0800 Subject: [PATCH] =?UTF-8?q?fix(tpv):=20extern=20declare=20=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E7=B1=BB=E5=9E=8B=E5=90=AB=E7=9C=9F=E5=AE=9E=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E6=97=B6=E4=B8=8D=E5=86=8D=E8=AF=AF=E5=BD=92=20Void?= =?UTF-8?q?=20+=20=E7=99=BD=E5=90=8D=E5=8D=95=E5=85=9C=E5=BA=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vpi 注入 extern declare 时 has_state→Void 无条件触发:注解 HANDLE | t.State(FindFirstFileA/GetStdHandle)被归为 void → declare 返回 void,运行期 FindFirstFileA 句柄丢失 → 文件存在性判断失效(文件实际存在但报不存在)。修复:仅纯标记注解归 Void;含真实类型但解析 miss 时回退外部函数返回类型白名单(FindFirstFileA/GetStdHandle→i8*),GenApi 新增 infer_external_func_ret_ty 委托。 --- App/lib/Stub/StubGen/VpiReader.vp | 22 +++++++++++++++++++++- App/lib/core/Gen/GenApi.vp | 18 ++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/App/lib/Stub/StubGen/VpiReader.vp b/App/lib/Stub/StubGen/VpiReader.vp index 4980289..a002458 100644 --- a/App/lib/Stub/StubGen/VpiReader.vp +++ b/App/lib/Stub/StubGen/VpiReader.vp @@ -1863,8 +1863,28 @@ def _inject_function_declare(pool: memhub.MemBuddy | t.CPtr, pool, fd.returns, imported_modules, from_imports, trans) # 如果返回类型是纯 t.State(无实际类型),用 Void if ret_ty is None and fd.returns is not None: - if has_state != 0: + # t.State/t.CExtern 是存储类装饰器标记,非真实返回类型。 + # 注解 "HANDLE | t.State"(FindFirstFileA)含真实类型 → 不能归 Void + # (此前无条件 has_state→Void,extern declare 返回 void,运行期 + # FindFirstFileA 句柄丢失 → 文件存在性判断失效根因)。 + # 仅纯标记注解(t.State/t.CExtern/t.CExport 单独出现)才返回 Void。 + is_pure_marker_rt: int = 0 + rk2_rt: int = fd.returns.kind() + if rk2_rt == ast.ASTKind.Name or rk2_rt == ast.ASTKind.Constant: + is_pure_marker_rt = 1 + elif rk2_rt == ast.ASTKind.Attribute: + pm_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(fd.returns) + if pm_at.attr is not None and (string.strcmp(pm_at.attr, "State") == 0 + or string.strcmp(pm_at.attr, "CExtern") == 0 + or string.strcmp(pm_at.attr, "CExport") == 0): + is_pure_marker_rt = 1 + if is_pure_marker_rt != 0: ret_ty = llvmlite.Void(pool) + elif has_state != 0 or has_extern != 0 or has_export != 0: + # 含真实类型但解析失败:回退外部函数返回类型白名单 + # (FindFirstFileA/GetStdHandle → i8* HANDLE 等),避免默认 i32 + # 截断指针(vpi 缓存/AST 解析 miss 时的稳健兜底)。 + ret_ty = GenApi.infer_external_func_ret_ty(pool, fd.name) # 默认返回 i32 if ret_ty is None: ret_ty = i32_ty diff --git a/App/lib/core/Gen/GenApi.vp b/App/lib/core/Gen/GenApi.vp index a4e8219..f9a5f72 100644 --- a/App/lib/core/Gen/GenApi.vp +++ b/App/lib/core/Gen/GenApi.vp @@ -126,6 +126,24 @@ def resolve_typedef_or_map(pool: memhub.MemBuddy | t.CPtr, return None +# ---------------- infer_external_func_ret_ty(委托 CallGenLib._infer_external_func_ret_ty) ---------------- +def infer_external_func_ret_ty(pool: memhub.MemBuddy | t.CPtr, + func_name: str) -> llvmlite.LLVMType | t.CPtr: + """委托到 gen.CallGenLib._infer_external_func_ret_ty(外部函数返回类型白名单) + + vpi 注入 extern declare 时返回类型解析 miss 的兜底:FindFirstFileA/ + GetStdHandle 等 Win32 HANDLE 返回函数 → i8*,避免默认 i32/void 导致 + 声明签名错误(运行期 FindFirstFileA 句柄丢失 → 文件存在性判断失效根因)。 + fatal_if_unknown=0:白名单未命中返回默认 i32(不 fail-fast,注入上下文 + 无法收敛判断交给调用侧)。 + """ + 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.CallGenLib._infer_external_func_ret_ty(pool, func_name, None, 0) + return None + + # ---------------- get_current_file(委托 TypeGenResolve.get_current_file) ---------------- def get_current_file() -> str: """委托到 gen.get_current_file(原 Handles 壳)"""