From e0bcf4bcef546351ceefb0bf44f1dcd192fce86d Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Thu, 1 Oct 2026 21:37:40 +0800 Subject: [PATCH] =?UTF-8?q?feat(TPV):=20=E8=A3=B8=E5=90=8D=20void=20?= =?UTF-8?q?=E4=BD=9C=E4=B8=BA=20t.CVoid=20=E7=9A=84=E5=88=AB=E5=90=8D?= =?UTF-8?q?=EF=BC=88void*=20=3D=20i8*=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户 2026-10-01 需求:`void` 即 t.CVoid 的别名,只允许两种用法——`a: void*` 与 `typedef 不透明结构体 = void`(后者 `X*` 亦为 i8*)。 - TypeGenResolve 内置名表:新增 "void"(与 "CVoid" 同义 → llvmlite.Void) - TypeGenResolve._is_cvoid_marker:裸名 "void" 与 "CVoid" 同判 - TypeGenResolve BinOp 联合合并:裸名 "void" 直接置 other_is_cvoid(无需 import t); 解析结果本身是 Void 时亦按 void* = i8* 归并,覆盖 `typedef X = void` 的 `X*` (否则会拼出非法的 Ptr(void)) - VpiReader:注解文本里的裸 "void" 段与 "CVoid" 同判(has_cvoid → i8*); has_cptr 分支对解析结果为 Void 的 first_ty 同样归并为 i8*(跨模块侧同口径) TPC 侧无需改动:HandlesBase 的内置名表已有 'void': (t.CVoid, 0), `void*` 经既有 CVoid+CPtr 合并即 i8*。 --- App/lib/Stub/StubGen/VpiReader.vp | 14 ++++++++++++- App/lib/core/Gen/Type/TypeGenResolve.vp | 28 +++++++++++++++++++------ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/App/lib/Stub/StubGen/VpiReader.vp b/App/lib/Stub/StubGen/VpiReader.vp index 6397fbc..b23f081 100644 --- a/App/lib/Stub/StubGen/VpiReader.vp +++ b/App/lib/Stub/StubGen/VpiReader.vp @@ -1584,7 +1584,11 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, cptr_sub_ty = seg_ty_cs elif string.strcmp(seg_buf, "t.CPtr") == 0 or string.strcmp(seg_buf, "CPtr") == 0: has_cptr = 1 - elif string.strcmp(seg_buf, "t.CVoid") == 0 or string.strcmp(seg_buf, "CVoid") == 0: + elif string.strcmp(seg_buf, "t.CVoid") == 0 or string.strcmp(seg_buf, "CVoid") == 0 \ + or string.strcmp(seg_buf, "void") == 0: + # 裸名 void 是 t.CVoid 的别名(用户 2026-10-01):必须与 CVoid 同处理, + # 否则会走 else 分支取到 first_td=1 → Ptr(Void) 这种非法类型 + # (void* 应为 i8*,由下方 has_cptr 分支统一给出)。 has_cvoid = 1 else: seg_ty: llvmlite.LLVMType* = _resolve_single_vpi_type_str(pool, seg_buf) @@ -1618,6 +1622,14 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, if has_cvoid != 0: return i8_ptr_ty if first_ty is not None: + # 解析结果本身即 void(如 `typedef 不透明结构体 = void` 的名字经 typedef 兜底 + # 解析出 void)⇒ 与 t.CPtr 合并即 void* = i8*,与 has_cvoid 分支同结论 + # (否则会拼出非法的 Ptr(void))。 + match first_ty: + case llvmlite.LLVMType.Void(): + return i8_ptr_ty + case _: + pass # 复刻定义侧规则(N12/N13):限定名 / 白名单裸标量 / 已注册结构体 / 可解析的非指针裸 typedef 别名 → 保留 pointee; # 其余(解析失败、裸枚举名、指针别名)→ 联合坍缩为 i8*,与定义侧 resolve_annotation_type 对称(两侧同型即收敛)。 # 指针别名(first_td 不置位,如 VOIDPTR = CVoid|CPtr → i8*):`| t.CPtr` diff --git a/App/lib/core/Gen/Type/TypeGenResolve.vp b/App/lib/core/Gen/Type/TypeGenResolve.vp index 36f1aee..5cac4cd 100644 --- a/App/lib/core/Gen/Type/TypeGenResolve.vp +++ b/App/lib/core/Gen/Type/TypeGenResolve.vp @@ -1938,7 +1938,9 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 小写别名 callable:注解位置等价于 t.Callable(`func: callable = 函数名`)。 elif string.strcmp(type_name, "callable") == 0: return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(type_name, "CVoid") == 0: + # 裸名 void 是 t.CVoid 的别名(用户 2026-10-01 定):单独出现即 LLVM void; + # `void*`(= `void | t.CPtr`)由下方 BinOp 分支归并为 i8*。 + elif string.strcmp(type_name, "CVoid") == 0 or string.strcmp(type_name, "void") == 0: return llvmlite.Void(pool) # CDefine: 编译期常量定义标记(X: t.CDefine = 64),底层为 32 位有符号整数 # (对齐 TPC t.CDefine Size=32 IsSigned=True;超大值由 DefineValue 路径升 i64)。 @@ -2079,8 +2081,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): return 1 if node is not None and node.kind() == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) - if nm.id is not None and string.strcmp(nm.id, "CVoid") == 0: - return 1 + # 裸名 CVoid(from t import CVoid)与内置别名 void(无需 import)同义 + if nm.id is not None: + if string.strcmp(nm.id, "CVoid") == 0 or string.strcmp(nm.id, "void") == 0: + return 1 return 0 def annotation_to_str(self, annot: ast.AST*) -> str: """将类型注解 AST 转换为可读字符串,返回 None=无法提取 @@ -3101,12 +3105,24 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): other_is_cvoid = 1 elif other_node.kind() == ast.ASTKind.Name: onm2: ast.Name* = ast.Name*(other_node) - if onm2.id is not None and string.strcmp(onm2.id, "CVoid") == 0: - if self.Gen.ImportsGen.is_module_imported(imported_modules, "t") != 0: + if onm2.id is not None: + if string.strcmp(onm2.id, "CVoid") == 0: + if self.Gen.ImportsGen.is_module_imported(imported_modules, "t") != 0: + other_is_cvoid = 1 + elif string.strcmp(onm2.id, "void") == 0: + # 内置别名 void:t.CVoid 同义,无需 import t other_is_cvoid = 1 if other_is_cvoid != 0: return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - other_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, other_node, imported_modules, from_imports, trans, depth + 1) + other_ty: llvmlite.LLVMType* = self.resolve_annotation_type(pool, other_node, imported_modules, from_imports, trans, depth + 1) + # 解析结果本身即 void(如 `typedef 不透明结构体 = void` 的那个名字, + # 或经 typedef 兜底解析出的 void)⇒ 与 CPtr 合并即 void* = i8*, + # 与上方 other_is_cvoid 分支同一结论(否则会拼出非法的 Ptr(void))。 + match other_ty: + case llvmlite.LLVMType.Void(): + return llvmlite.Ptr(pool, llvmlite.Int8(pool)) + case _: + pass # 仅裸名(Name)场景验证解析结果必须是已注册 struct: # 损坏节点可能解析出基础类型垃圾(如 Int8 → Ptr(i8))。 # Attribute 场景(Module.Class / t.XXX)resolve 结果直接可用