diff --git a/App/lib/core/Gen/StructGenMixin.vp b/App/lib/core/Gen/StructGenMixin.vp index 17d8fe1..ced7906 100644 --- a/App/lib/core/Gen/StructGenMixin.vp +++ b/App/lib/core/Gen/StructGenMixin.vp @@ -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 diff --git a/App/lib/core/Gen/Type/TypeSpec.vp b/App/lib/core/Gen/Type/TypeSpec.vp index c05ca20..59d1364 100644 --- a/App/lib/core/Gen/Type/TypeSpec.vp +++ b/App/lib/core/Gen/Type/TypeSpec.vp @@ -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: diff --git a/App/lib/core/Gen/VarGenMixin.vp b/App/lib/core/Gen/VarGenMixin.vp index 7d4cf07..20ae4bd 100644 --- a/App/lib/core/Gen/VarGenMixin.vp +++ b/App/lib/core/Gen/VarGenMixin.vp @@ -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 # ============================================================