feat(tpv): vtable 对象全局 storage 也按字段默认值折叠

补 f5ee178 未覆盖的 vtable 分支:抽出 _build_stg_struct_body_text,_build_stg_struct_init_text 改为其包装;vtable 分支以 start_idx=1 复用默认值折叠,字段默认值全零时回退原零值循环(元素个数语义不变)。
This commit is contained in:
TermiNexus committed 2026-09-11 15:29:43 +08:00
1 parent f5ee178407
commit 751fbccb29
1 file changed
+58 -26
+58 -26
View File
@@ -544,19 +544,19 @@ class TranslatorGenMixin:
return buf
# ============================================================
# _build_stg_struct_init_text - storage struct 完整常量初始化器(含字段默认值)
# _build_stg_struct_body_text - storage struct 字段元素文本(不含大括号)
#
# 用于模块级对象全局 `X: T = T()`:此前 storage 一律 zeroinitializer,
# `__before_init__`/字段默认(如 fat32.volinfo 的 sector_size=512、
# root_cluster=2、free_clusters=0xFFFFFFFF、backup_sector=6)全部丢失。
# 现按字段默认值生成完整 struct 常量(LLVM 要求列全每个字段)。
# 无任何非零默认值时返回 None,由调用方保持 zeroinitializer(避免无谓文本)。
# start_idx:vtable 对象跳过字段 0(首元素由调用方单独写 vtable 指针)。
# 生成 "elem0, elem1, ..." 形式(含字段默认值折叠,缺失处按类型零值兜底),
# 供两处复用:
# - _build_stg_struct_init_text:外包 "{ ... }" 作为完整初始化器;
# - vtable 对象 storage:首元素为 vtable 指针,其后追加本函数结果
# (此时 start_idx=1 跳过字段 0)。
# 无任何非零默认值时返回 None,调用方据此保持原零值路径(避免无谓文本)。
# ============================================================
def _build_stg_struct_init_text(self, pool: memhub.MemBuddy | t.CPtr,
def _build_stg_struct_body_text(self, pool: memhub.MemBuddy | t.CPtr,
se: GenTypes.StructEntry | t.CPtr,
start_idx: int) -> str:
"""按字段默认值生成完整 struct 初始化器;无非零默认值返回 None"""
"""按字段默认值生成 "e0, e1, ..." 元素文本;无非零默认值返回 None"""
if se is None or se.Fields is None:
return None
fc: int = se.FieldCount
@@ -566,8 +566,7 @@ class TranslatorGenMixin:
buf: str = pool.alloc(buf_size)
if buf is None:
return None
written: t.CInt = viperlib.snprintf(buf, buf_size, "{ ")
pos: t.CSizeT = t.CSizeT(written)
pos: t.CSizeT = 0
first: int = 1
has_nonzero: int = 0
i: int = start_idx
@@ -587,6 +586,7 @@ class TranslatorGenMixin:
is_zero = 1
if elem is None:
continue
written: t.CInt = 0
if first == 0:
written = viperlib.snprintf(buf + pos, buf_size - pos, ", ")
pos += t.CSizeT(written)
@@ -597,7 +597,29 @@ class TranslatorGenMixin:
has_nonzero = 1
if has_nonzero == 0:
return None
viperlib.snprintf(buf + pos, buf_size - pos, " }")
return buf
# ============================================================
# _build_stg_struct_init_text - storage struct 完整常量初始化器(含字段默认值)
#
# 用于模块级对象全局 `X: T = T()`:此前 storage 一律 zeroinitializer,
# `__before_init__`/字段默认(如 fat32.volinfo 的 sector_size=512、
# root_cluster=2、free_clusters=0xFFFFFFFF、backup_sector=6)全部丢失。
# 现按字段默认值生成完整 struct 常量(LLVM 要求列全每个字段)。
# 无任何非零默认值时返回 None,由调用方保持 zeroinitializer(避免无谓文本)。
# ============================================================
def _build_stg_struct_init_text(self, pool: memhub.MemBuddy | t.CPtr,
se: GenTypes.StructEntry | t.CPtr,
start_idx: int) -> str:
"""按字段默认值生成完整 struct 初始化器;无非零默认值返回 None"""
body: str = self._build_stg_struct_body_text(pool, se, start_idx)
if body is None:
return None
body_len: t.CSizeT = t.CSizeT(string.strlen(body))
buf: str = pool.alloc(body_len + 8)
if buf is None:
return None
viperlib.snprintf(buf, body_len + 8, "{ %s }", body)
return buf
# ============================================================
@@ -980,21 +1002,31 @@ class TranslatorGenMixin:
else:
written_v = viperlib.snprintf(init_full + pos_v, init_full_len - pos_v, "i8* @%s", vt_mangled)
pos_v += t.CSizeT(written_v)
fc_v: int = resolved_stg_entry.FieldCount
for fi_v in range(1, fc_v):
fe_v: GenTypes.FieldEntry | t.CPtr = self.Gen.StructGen._get_field_entry(
resolved_stg_entry, fi_v)
if fe_v is None or fe_v.Ty is None:
continue
ty_buf_v: str = pool.alloc(128)
if ty_buf_v is None:
continue
llvmlite.TypePrint(ty_buf_v, 128, fe_v.Ty, pool)
zero_v: str = self._stg_field_zero_text(pool, fe_v.Ty, ty_buf_v)
if zero_v is None:
continue
written_v = viperlib.snprintf(init_full + pos_v, init_full_len - pos_v, ", %s", zero_v)
# 字段 1..N 优先按字段默认值折叠(vtable 对象全局
# 如 `_mbuddy: MemBuddy` 的字段默认不再丢失);
# 全部默认值恰为零时回退逐字段零值,避免无谓文本。
# 两者均列全字段(LLVM 要求初始化器元素数匹配)。
rest_v: str = self._build_stg_struct_body_text(
pool, resolved_stg_entry, 1)
if rest_v is not None:
written_v = viperlib.snprintf(init_full + pos_v, init_full_len - pos_v, ", %s", rest_v)
pos_v += t.CSizeT(written_v)
else:
fc_v: int = resolved_stg_entry.FieldCount
for fi_v in range(1, fc_v):
fe_v: GenTypes.FieldEntry | t.CPtr = self.Gen.StructGen._get_field_entry(
resolved_stg_entry, fi_v)
if fe_v is None or fe_v.Ty is None:
continue
ty_buf_v: str = pool.alloc(128)
if ty_buf_v is None:
continue
llvmlite.TypePrint(ty_buf_v, 128, fe_v.Ty, pool)
zero_v: str = self._stg_field_zero_text(pool, fe_v.Ty, ty_buf_v)
if zero_v is None:
continue
written_v = viperlib.snprintf(init_full + pos_v, init_full_len - pos_v, ", %s", zero_v)
pos_v += t.CSizeT(written_v)
viperlib.snprintf(init_full + pos_v, init_full_len - pos_v, " }")
stg_init_text = init_full
elif resolved_stg_entry is not None: