fix(tpv): vpi 返回注解纯 marker(t.State 等)解析为 void,修 void 调用被当 i32

调用侧 `_resolve_vpi_ret_annot_str` 只把 `t.CVoid` 映射为 void,纯 `t.State`
(存储类装饰器标记)会解析失败返回 None → 调用侧回退外部函数白名单默认 i32。

现场(MLIRLiteTest):`includes/stdlib.vp` 的 `extern def exit(status: int)`
在 stdlib 的 vpi 中是 `def exit(status: int) -> t.State: pass`,于是生成
  %6 = llvm.call @exit(%c3) : (i32) -> i32
而模块声明是 `llvm.func @exit(%status: i32)`(void),mlir-opt 报
  'llvm.call' op calling function with void result must not produce values

修复:在 `_resolve_vpi_ret_annot_str` 增加"纯 marker 注解 → void"分支,与
declare 注入路径 `_inject_module_declare` 的 is_pure_marker_rt 判据同口径。
仅**纯** marker(`t.State` / `t.CExtern` / `t.CExport`,可带 t./c. 前缀)
才归 void;`HANDLE | t.State` 等含真实类型的注解仍由段循环返回真实类型。
This commit is contained in:
TermiNexus committed 2026-10-03 21:51:13 +08:00
1 parent 94b174c8a0
commit b7e4861e6c
1 file changed
+26
+26
View File
@@ -1542,6 +1542,32 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*,
return None
return mlirlite.Struct(pool, tup_head_t, tup_count_t, None)
# 纯 marker 注解(`t.State` / `t.CExtern` / `t.CExport` 单独出现,可带 t./c.
# 前缀)→ void:这些是存储类装饰器标记,不是真实返回类型,与 declare 注入
# 路径(_inject_module_declare 的 is_pure_marker_rt)**同口径**。
# 缺此分支时 `extern def exit(status: int)` 的 vpi 注解 `t.State` 在本函数
# 解析为 None → 调用侧回退外部函数白名单默认 i32 → 生成
# `%N = call i32 @exit(...)` 而模块声明 `llvm.func @exit(...)`(void),
# mlir-opt 报 "calling function with void result must not produce values"。
# 注意仅**纯** marker 才归 void;`HANDLE | t.State`(FindFirstFileA)含真实
# 类型,其段循环会以 first_ty 返回真实类型,不得在此误判。
marker_len: sizet = string.strlen(ret_annot)
mk_s: sizet = 0
while mk_s < marker_len and ret_annot[mk_s] == ' ':
mk_s += 1
mk_e: sizet = marker_len
while mk_e > mk_s and ret_annot[mk_e - 1] == ' ':
mk_e -= 1
mk_off_m: sizet = 0
if mk_e - mk_s >= 2 and (ret_annot[mk_s] == 't' or ret_annot[mk_s] == 'c') \
and ret_annot[mk_s + 1] == '.':
mk_off_m = 2
mk_nlen: sizet = mk_e - mk_s - mk_off_m
if (mk_nlen == 5 and string.strncmp(ret_annot + mk_s + mk_off_m, "State", 5) == 0) \
or (mk_nlen == 7 and string.strncmp(ret_annot + mk_s + mk_off_m, "CExtern", 7) == 0) \
or (mk_nlen == 7 and string.strncmp(ret_annot + mk_s + mk_off_m, "CExport", 7) == 0):
return mlirlite.Void(pool)
has_cptr: int = 0
has_cvoid: int = 0
first_ty: mlirlite.LLVMType* = None