feat(tpv): 模块级对象全局按字段默认值生成 storage 初始化器

- 新增 _default_val_const_text:字段默认值 AST -> 常量文本(仅整型/字符/负号字面量可折叠,其余零值兜底)

- 新增 _build_stg_struct_init_text:按 StructEntry 字段默认值生成完整 struct 常量初始化器(LLVM 要求列全字段);无非零默认值返回 None

- storage 分支新增 elif:无 vtable 对象全局走默认值初始化器(vtable 路径不变)

- 效果:fat32.default_fs 的 .stg 由 zeroinitializer 变为含 sector_size=512/root_cluster=2/free_clusters=0xFFFFFFFF/backup_sector=6/winsect=-1 的完整常量;drive_lock 等零值等价场景保持 zeroinitializer
This commit is contained in:
TermiNexus committed 2026-09-11 14:52:29 +08:00
1 parent e20a6f3d11
commit f5ee178407
1 file changed
+107
+107
View File
@@ -504,6 +504,102 @@ class TranslatorGenMixin:
viperlib.snprintf(buf, 160, "%s zeroinitializer", ty_str)
return buf
# ============================================================
# _default_val_const_text - 字段默认值 → LLVM 常量元素文本
#
# 仅处理可常量折叠的整型默认值(CONST_INT/CONST_CHAR 及负号字面量);
# 其余(浮点/字符串/None/名字/表达式)返回 None,由调用方按零值兜底。
# ============================================================
def _default_val_const_text(self, pool: memhub.MemBuddy | t.CPtr,
fty: llvmlite.LLVMType | t.CPtr,
ty_str: str,
dval: ast.AST | t.CPtr) -> str:
"""字段默认值 → "ty 值" 文本;不可折叠返回 None"""
if dval is None or fty is None or ty_str is None:
return None
is_int: int = 0
dv_int: t.CInt64T = 0
if dval.kind() == ast.ASTKind.Constant:
dc: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(dval)
if dc is not None:
if dc.const_kind == ast.CONST_INT or dc.const_kind == ast.CONST_CHAR:
dv_int = dc.int_val
is_int = 1
elif dval.kind() == ast.ASTKind.UnaryOp:
# 负数/按位取反字面量(如 -1 / 0xFFFFFFFFFFFFFFFF)
dv_int = self.Gen.AssignGen.extract_cdefine_int_value(dval)
is_int = 1
if is_int == 0:
return None
# 仅整型字段可写整数常量(浮点/指针/聚合交给零值兜底)
match fty:
case llvmlite.LLVMType.Int(_):
pass
case _:
return None
buf: str = pool.alloc(48)
if buf is None:
return None
viperlib.snprintf(buf, 48, "%s %lld", ty_str, dv_int)
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(避免无谓文本)。
# start_idx:vtable 对象跳过字段 0(首元素由调用方单独写 vtable 指针)。
# ============================================================
def _build_stg_struct_init_text(self, pool: memhub.MemBuddy | t.CPtr,
se: GenTypes.StructEntry | t.CPtr,
start_idx: int) -> str:
"""按字段默认值生成完整 struct 初始化器;无非零默认值返回 None"""
if se is None or se.Fields is None:
return None
fc: int = se.FieldCount
if fc <= start_idx:
return None
buf_size: t.CSizeT = 256 + t.CSizeT(fc) * 160
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)
first: int = 1
has_nonzero: int = 0
i: int = start_idx
while i < fc:
fe: GenTypes.FieldEntry | t.CPtr = self.Gen.StructGen._get_field_entry(se, i)
i += 1
if fe is None or fe.Ty is None:
continue
ty_str: str = pool.alloc(128)
if ty_str is None:
continue
llvmlite.TypePrint(ty_str, 128, fe.Ty, pool)
elem: str = self._default_val_const_text(pool, fe.Ty, ty_str, fe.DefaultVal)
is_zero: int = 0
if elem is None:
elem = self._stg_field_zero_text(pool, fe.Ty, ty_str)
is_zero = 1
if elem is None:
continue
if first == 0:
written = viperlib.snprintf(buf + pos, buf_size - pos, ", ")
pos += t.CSizeT(written)
written = viperlib.snprintf(buf + pos, buf_size - pos, "%s", elem)
pos += t.CSizeT(written)
first = 0
if is_zero == 0:
has_nonzero = 1
if has_nonzero == 0:
return None
viperlib.snprintf(buf + pos, buf_size - pos, " }")
return buf
# ============================================================
# handle_module_level_var - 模块级变量声明 → 创建 LLVM 全局变量
#
@@ -901,6 +997,17 @@ class TranslatorGenMixin:
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:
# 无 vtable 的对象全局(@t.Object / 普通类):按字段默认值生成常量
# 初始化器(如 fat32.volinfo:sector_size=512、root_cluster=2、
# free_clusters=0xFFFFFFFF、backup_sector=6、winsect/fat_winsect=-1…)。
# 此前一律 zeroinitializer → 字段默认全部丢失(模块级 X: T = T() 的
# 构造调用不发射,见第十三节)。无任何非零默认值时返回 None →
# 保持 zeroinitializer(drive_lock 等零值等价场景零开销)。
stg_default_text: str = self._build_stg_struct_init_text(
pool, resolved_stg_entry, 0)
if stg_default_text is not None:
stg_init_text = stg_default_text
stg_name_len: t.CSizeT = t.CSizeT(string.strlen(mangled_name)) + 8
stg_name_buf: str = pool.alloc(stg_name_len)
if stg_name_buf is not None: