diff --git a/App/lib/core/Gen/TranslatorGenMixin.vp b/App/lib/core/Gen/TranslatorGenMixin.vp index a48c780..14dfb4b 100644 --- a/App/lib/core/Gen/TranslatorGenMixin.vp +++ b/App/lib/core/Gen/TranslatorGenMixin.vp @@ -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: