feat(tpv): Spec 注解侧填符号性(SpecWithSign + 变量/字段接入)

- TypeSpec 新增 SpecWithSign:整数 TS_INT↔TS_UINT 切换 + 驻留(SpecToText 键区分符号)
- set_var_annot_class_name 接入:注解类名提取符号性,补 Spec 无符号性
- add_field 接入:字段注解类名提取符号性,补 Spec 无符号性
This commit is contained in:
TermiNexus committed 2026-09-11 21:48:23 +08:00
1 parent 0a108e6289
commit 7fedf8daad
3 files changed
+65

No files matched your search

+6
View File
@@ -407,6 +407,12 @@ class StructGenMixin:
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)
# [S4 注解侧填 Spec] 补字段 Spec 整数符号性(annot_class_name 携带
# 真实无符号性;LLVM 反推恒 TS_INT)
if fe.Spec is not None and annot_class_name is not None:
sign_f: int = self.Gen.TypeGenCType.spec_sign_of_annot(annot_class_name)
if sign_f != TSpec.TS_SIGN_UNKNOWN:
fe.Spec = TSpec.SpecWithSign(arena_f, fe.Spec, sign_f)
struct_entry.FieldCount = idx + 1
return idx
+50
View File
@@ -817,6 +817,56 @@ def SpecPointedTo(sp: TypeSpec | t.CPtr) -> TypeSpec | t.CPtr:
return sp.Elem
# ============================================================
# SpecWithSign - 复制 Spec 并按注解覆盖整数符号性(TS_INT ↔ TS_UINT)
#
# 背景(S4 注解侧填 Spec):SpecFromLLVMType 从 LLVM 类型反推时,整数恒
# TS_INT(LLVM iN 不分符号)。但 SpecToText 对 TS_INT 编 "i%d"、TS_UINT 编
# "u%d",符号性由 **Kind** 区分 —— 若只改 IsSigned 不改 Kind,两个符号性不同
# 的整数会得到相同驻留键 "i%d" 而撞键(同键不同义,返回错误实例)。
# 注解侧知道真实符号性(uint32 等无符号名),须把 TS_INT 切为 TS_UINT。
#
# 浅拷贝结构(Elem/Ret/Params 指针共享已驻留子实例);仅当符号性实际变化才
# 复制并驻留,否则返回原实例。驻留去重 ⇒ 同「结构+符号」共享一份。
# ============================================================
def SpecWithSign(arena: TypeSpecArena | t.CPtr,
sp: TypeSpec | t.CPtr,
is_signed: int) -> TypeSpec | t.CPtr:
"""复制 sp 并覆盖整数符号性,驻留后返回;无变化返回原实例,失败返回 None"""
if sp is None:
return None
new_kind: int = sp.Kind
new_signed: int = sp.IsSigned
if is_signed == TS_SIGN_UNSIGNED and sp.Kind == TS_INT:
new_kind = TS_UINT
new_signed = TS_SIGN_UNSIGNED
elif is_signed == TS_SIGN_SIGNED and sp.Kind == TS_UINT:
new_kind = TS_INT
new_signed = TS_SIGN_SIGNED
if new_kind == sp.Kind:
return sp
cp: TypeSpec | t.CPtr = _spec_alloc()
if cp is None:
return None
cp.Kind = new_kind
cp.Bits = sp.Bits
cp.IsSigned = new_signed
cp.PtrLevel = sp.PtrLevel
cp.Elem = sp.Elem
cp.ArrayCount = sp.ArrayCount
cp.BaseName = sp.BaseName
cp.Ret = sp.Ret
cp.Params = sp.Params
cp.ParamCount = sp.ParamCount
cp.IsVarArg = sp.IsVarArg
cp.Storage = sp.Storage
cp.ElemBits = sp.ElemBits
cp.IsElemPtr = sp.IsElemPtr
cp.DerefBase = sp.DerefBase
cp.Ty = sp.Ty
return InternSpec(arena, cp)
def SpecIsUnsigned(sp: TypeSpec | t.CPtr) -> int:
"""是否无符号整数(单一真源;未知返回 0)"""
if sp is None:
+9
View File
@@ -129,6 +129,15 @@ class VarGenMixin:
if entry is None:
return 1
entry.AnnotClassName = class_name
# [S4 注解侧填 Spec] 补 Spec 整数符号性:SpecFromLLVMType 反推恒 TS_INT
# (LLVM iN 不分符号),注解类名携带真实无符号性(uint32/CUInt32T 等)。
# 切 TS_INT→TS_UINT 供后续消费者切读(逐步替代 AnnotClassName 的符号性判断)。
if entry.Spec is not None and class_name is not None:
sign: int = self.Gen.TypeGenCType.spec_sign_of_annot(class_name)
if sign != TSpec.TS_SIGN_UNKNOWN:
arena_sn: TSpec.TypeSpecArena | t.CPtr = self.Gen.TypeGenBase.ensure_spec_arena()
if arena_sn is not None:
entry.Spec = TSpec.SpecWithSign(arena_sn, entry.Spec, sign)
return 0
# ============================================================