feat(tpv): S3 条目双写接线,三个唯一创建点填 TypeSpec
- GenTypes: VarEntry / FieldEntry / FuncEntry 各加 Spec 字段(FuncEntry 合并为单个整签名 Spec,替代设计 D4 的 RetSpec+ParamSpecs,理由见注释) - VarGenMixin: add_var 新增 _spec_of_var_alloca,用 alloca.Ty 的 pointee 构造 Spec(is_ptr_type 判定) - StructGenMixin: add_field 统一在两条写入分支之后填 Spec(PermPool 驻留故无需 DeepCopyType) - CallGenLeafKit: _register_global_func / add_func_to_table 初始化为 None;update_global_func_typestr 新增 _build_func_spec 填整签名 Spec(用 function_get_param_head 两遍遍历,变参取 func.IsVarArg,避免 SpecFromLLVMType 的 Func 分支丢变参) - 注: 当前尚无读取方;驻留表溢出会导致该条目 Spec=None(已记录,S4 改 fatal)
This commit is contained in:
1 parent
f0deff931d
commit
ff7caa57e8
4 files changed
+103
-2
No files matched your search
@@ -10,7 +10,8 @@ import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Gen.GenApi as GenApi
|
||||
import lib.core.Gen.Translator as HT
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.core.Gen.Type.TypeSpec as TSpec
|
||||
|
||||
from . import CallGenCBuiltin
|
||||
|
||||
@@ -1016,6 +1017,8 @@ class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
|
||||
entry.Defaults = defaults
|
||||
entry.DefaultCount = default_count
|
||||
entry.ParamCount = param_count
|
||||
# [S3 条目双写] Spec 在形参 add_param 完成后由 update_global_func_typestr 填
|
||||
entry.Spec = None
|
||||
# 同时注册到全局函数表(供跨模块 vtable 初始化查找)
|
||||
self._register_global_func(name, func, pool)
|
||||
# 同时注册到全局默认参数表(供跨模块调用时填充默认值)
|
||||
@@ -1121,6 +1124,8 @@ class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
|
||||
string.strcpy(name_copy, name)
|
||||
entry.Name = name_copy
|
||||
entry.Func = func
|
||||
# [S3 条目双写] Spec 待 update_global_func_typestr 填(形参未 add 完)
|
||||
entry.Spec = None
|
||||
# TypeStr 不在此生成:函数参数在 add_func_to_table 之后才添加,
|
||||
# 需由调用方在参数添加完成后调用 update_global_func_typestr 补全。
|
||||
self.GlobalFuncCount += 1
|
||||
@@ -1142,9 +1147,63 @@ class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
|
||||
if entry is None:
|
||||
return 1
|
||||
entry.TypeStr = self._build_func_type_str(pool, func)
|
||||
# [S3 条目双写] 整签名 Spec(与 TypeStr 同源同表;此处形参已全部 add_param)
|
||||
entry.Spec = self._build_func_spec(func)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _build_func_spec - 由函数对象构造整签名 TypeSpec(S3 条目双写)
|
||||
#
|
||||
# Kind=TS_FUNC:Ret + 形参 Spec 数组 + ParamCount + IsVarArg。必须在形参
|
||||
# 全部 add_param 完成后调用(同 _build_func_type_str 的时机)。
|
||||
# 参数沿 `llvmlite.function_get_param_head` 的 Param 链表**两遍遍历**(先计数
|
||||
# 再填充)——llvmlite 无按下标取参,且无法预知长度以一次分配。
|
||||
# 注意与 `TSpec.SpecFromLLVMType` 的 Func 分支的区别:后者只能看到
|
||||
# `LLVMType.Func`(**不含变参信息**,恒置 IsVarArg=0),故此处直接用
|
||||
# `NewTypeFunc(..., func.IsVarArg)` 构造。
|
||||
# 失败(池分配失败等)返回 None;调用方保留 None,不静默造伪 spec。
|
||||
# ============================================================
|
||||
def _build_func_spec(self, func: llvmlite.Function | t.CPtr) -> TSpec.TypeSpec | t.CPtr:
|
||||
"""由函数对象构造整签名 TypeSpec,失败返回 None"""
|
||||
if func is None:
|
||||
return None
|
||||
arena: TSpec.TypeSpecArena | t.CPtr = self.Gen.TypeGenBase.ensure_spec_arena()
|
||||
if arena is None:
|
||||
return None
|
||||
ret_s: TSpec.TypeSpec | t.CPtr = TSpec.SpecFromLLVMType(
|
||||
arena, llvmlite.function_get_ret_ty(func))
|
||||
if ret_s is None:
|
||||
return None
|
||||
# 第一遍:计数
|
||||
cnt: int = 0
|
||||
cur: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(func)
|
||||
while cur is not None and cnt < 256:
|
||||
cnt += 1
|
||||
cur = llvmlite.param_get_next(cur)
|
||||
# 第二遍:逐个构造并写入连续参数数组
|
||||
params_arr: sizet | t.CPtr = None
|
||||
if cnt > 0:
|
||||
params_arr = CompilerFactory.factory.PermPool.alloc(8 * cnt)
|
||||
if params_arr is None:
|
||||
return None
|
||||
cur = llvmlite.function_get_param_head(func)
|
||||
i: int = 0
|
||||
while cur is not None and i < cnt:
|
||||
ps: TSpec.TypeSpec | t.CPtr = TSpec.SpecFromLLVMType(
|
||||
arena, llvmlite.param_get_ty(cur))
|
||||
if ps is None:
|
||||
return None
|
||||
slot: sizet | t.CPtr = (sizet | t.CPtr)(
|
||||
t.CVoid(uint64(params_arr) + uint64(i * 8), t.CPtr))
|
||||
if slot is None:
|
||||
return None
|
||||
slot[0] = sizet(ps)
|
||||
cur = llvmlite.param_get_next(cur)
|
||||
i += 1
|
||||
return TSpec.NewTypeFunc(arena, ret_s, params_arr, cnt, func.IsVarArg)
|
||||
|
||||
|
||||
def find_func_global(self, name: str) -> llvmlite.Function | t.CPtr:
|
||||
"""在全局函数表中按名称查找,返回 Function 指针或 None"""
|
||||
if name is None or self.GlobalFuncs is None:
|
||||
|
||||
@@ -69,6 +69,9 @@ class VarEntry:
|
||||
Used: int
|
||||
AnnotClassName: str # 原始类型注解的类名(str 别名在结构体字段中触发编译器 bug,改用显式联合类型)
|
||||
IsPtrElement: int # 标志: 1=注解为 bytes|t.CPtr 或 str|t.CPtr, 下标按 8 字节步长
|
||||
# TypeSpec(S3 条目双写;Debugger/_Type.md D4):由 add_var 用 SpecFromLLVMType
|
||||
# 从 alloca.Ty 的 pointee 填充,PermPool 驻留 ⇒ 跨文件安全。当前尚无读取方。
|
||||
Spec: TSpec.TypeSpec | t.CPtr
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -103,6 +106,9 @@ class FieldEntry:
|
||||
Ty: llvmlite.LLVMType | t.CPtr # 字段的 LLVM 类型
|
||||
DefaultVal: ast.AST | t.CPtr # 默认值 AST 节点(None=无默认值)
|
||||
AnnotClassName: str # 原始类型注解的类名(str 别名在结构体字段中触发编译器 bug,改用显式联合类型)
|
||||
# TypeSpec(S3 条目双写):由 add_field 用 SpecFromLLVMType 从 field_ty 填充,
|
||||
# PermPool 驻留 ⇒ 跨 1b reset 安全(无需 DeepCopyType)。当前尚无读取方。
|
||||
Spec: TSpec.TypeSpec | t.CPtr
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -179,7 +185,13 @@ class FuncEntry:
|
||||
# TypeStr: 函数类型文本(stdlib 深拷贝,跨文件安全)
|
||||
# 1b 每文件 reset_to(mark1) 回收 pool 内 Function 对象后,
|
||||
# vtable 生成 find_func_global 读类型改用此文本,避免悬空。
|
||||
TypeStr: str
|
||||
TypeStr: str
|
||||
# TypeSpec(S3 条目双写):Kind=TS_FUNC 的**整签名**(Ret/Params/ParamCount/
|
||||
# IsVarArg 都在其内),由 update_global_func_typestr 在形参 add_param 完成后
|
||||
# 用 NewTypeFunc 构造(含 func.IsVarArg)。PermPool 驻留 ⇒ 跨 1b reset 安全。
|
||||
# 说明:设计 D4 原写 RetSpec+ParamSpecs 两字段,此处合并为单个 Spec —— 单字段
|
||||
# 即可完整表达签名,且与 VarEntry/FieldEntry 的 Spec 命名一致,避免参数数组重复。
|
||||
Spec: TSpec.TypeSpec | t.CPtr
|
||||
|
||||
|
||||
# ============================================================
|
||||
|
||||
@@ -13,6 +13,7 @@ import lib.core.VLogger as VLogger
|
||||
import lib.Stub.StubMerger.StubMergerStore as StubMergerStore
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import lib.core.Gen.Type.TypeSpec as TSpec
|
||||
|
||||
# ============================================================
|
||||
# StructGenMixin - 结构体注册/字段查找 Mixin(对象化 P2-2,wiki/14-oo-refactor.md)
|
||||
@@ -401,6 +402,12 @@ class StructGenMixin:
|
||||
fe.AnnotClassName = annot_class_name
|
||||
fe.DefaultVal = default_val
|
||||
|
||||
# [S3 条目双写] 字段类型 Spec。与上方 Ty/AnnotClassName 的区别:TypeSpec
|
||||
# 实例一律 PermPool 驻留 ⇒ 天然跨 1b reset 存活,**无需** DeepCopyType。
|
||||
arena_f: TSpec.TypeSpecArena | t.CPtr = self.Gen.TypeGenBase.ensure_spec_arena()
|
||||
if arena_f is not None:
|
||||
fe.Spec = TSpec.SpecFromLLVMType(arena_f, field_ty)
|
||||
|
||||
struct_entry.FieldCount = idx + 1
|
||||
return idx
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import lib.core.Gen.Type.TypeSpec as TSpec
|
||||
import t, c
|
||||
from stdint import *
|
||||
import llvmlite
|
||||
@@ -166,8 +167,30 @@ class VarGenMixin:
|
||||
entry.Name = name
|
||||
entry.Alloca = alloca
|
||||
entry.Used = 1
|
||||
# [S3 条目双写] 值类型 Spec(alloca.Ty 是 Ptr(值类型) ⇒ 取其 pointee)
|
||||
entry.Spec = self._spec_of_var_alloca(alloca)
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# _spec_of_var_alloca - 由 alloca 的值类型构造 TypeSpec(S3 条目双写)
|
||||
#
|
||||
# alloca.Ty 为 Ptr(var_ty)(见 _alloca_at_entry / 全局变量 SSAValue 路径),
|
||||
# 故取 pointee 才是变量的**值类型**。失败或类型不适用(Label/Metadata 等
|
||||
# SpecFromLLVMType 不支持者)返回 None —— 后者是设计内的「不适用」,非兜底。
|
||||
# 分配一律 PermPool 驻留 ⇒ 跨文件/跨 1b reset 安全。
|
||||
# ============================================================
|
||||
def _spec_of_var_alloca(self, alloca: llvmlite.Value | t.CPtr) -> TSpec.TypeSpec | t.CPtr:
|
||||
"""由 alloca 的值类型构造 TypeSpec,不适用/失败返回 None"""
|
||||
if alloca is None or alloca.Ty is None:
|
||||
return None
|
||||
ty: llvmlite.LLVMType | t.CPtr = alloca.Ty
|
||||
if self.Gen.ExprGenBase.is_ptr_type(ty) != 0:
|
||||
ty = ty.Pointee
|
||||
arena: TSpec.TypeSpecArena | t.CPtr = self.Gen.TypeGenBase.ensure_spec_arena()
|
||||
if arena is None:
|
||||
return None
|
||||
return TSpec.SpecFromLLVMType(arena, ty)
|
||||
|
||||
# ============================================================
|
||||
# _alloca_at_entry - 在函数入口块生成 alloca(确保支配性)
|
||||
#
|
||||
|
||||
Reference in new issue
Block a user