fix(stub): .vpi 读取侧复刻字段标记判定(volatile/pointee-volatile/const/字节序),跨模块不再丢字段标记

This commit is contained in:
TermiNexus committed 2026-10-13 12:30:23 +08:00
1 parent 37c4b0da3b
commit 32599a08c1
2 files changed
+53 -1

No files matched your search

+39 -1
View File
@@ -2645,9 +2645,25 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModul
# 2. collect field types (AnnAssign children, mirroring ClassGenDef.translate_class_def)
field_names_buf: sizet* = pool.alloc(8 * GenTypes.FIELD_MAX)
field_types_buf: sizet* = pool.alloc(8 * GenTypes.FIELD_MAX)
# Per-field marker buffers, index-aligned with field_names_buf / add_field order. The .vpi text
# keeps each field's raw annotation (Converter._PyiTypeStr renders BinOp/Attribute verbatim, so
# `X | t.BigEndian` / `t.CVolatile | int` survive), so the same markers ClassGenDef extracts on
# the definition side must be re-extracted here; otherwise a struct referenced across a module
# boundary loses its volatile/const/byte-order semantics and the same field compiles differently
# per module (the bug this fixes).
field_volatile_buf: sizet* = pool.alloc(8 * GenTypes.FIELD_MAX)
field_pointee_volatile_buf: sizet* = pool.alloc(8 * GenTypes.FIELD_MAX)
field_const_buf: sizet* = pool.alloc(8 * GenTypes.FIELD_MAX)
field_byteorder_buf: sizet* = pool.alloc(8 * GenTypes.FIELD_MAX)
if field_names_buf is None or field_types_buf is None: return 0
if field_volatile_buf is None or field_pointee_volatile_buf is None: return 0
if field_const_buf is None or field_byteorder_buf is None: return 0
string.memset(field_names_buf, 0, 8 * GenTypes.FIELD_MAX)
string.memset(field_types_buf, 0, 8 * GenTypes.FIELD_MAX)
string.memset(field_volatile_buf, 0, 8 * GenTypes.FIELD_MAX)
string.memset(field_pointee_volatile_buf, 0, 8 * GenTypes.FIELD_MAX)
string.memset(field_const_buf, 0, 8 * GenTypes.FIELD_MAX)
string.memset(field_byteorder_buf, 0, 8 * GenTypes.FIELD_MAX)
field_count: int = 0
cls_children_c: list[ast.AST*]* = class_cd.children
if cls_children_c is not None:
@@ -2668,6 +2684,18 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModul
if field_count < GenTypes.FIELD_MAX:
field_names_buf[field_count] = sizet(m_tgt_c.id)
field_types_buf[field_count] = sizet(field_ty_c)
# Re-extract the field-level markers from the raw annotation, exactly as
# ClassGenDef.translate_class_def does on the definition side (same predicates, same
# precedence), so a cross-module reference gets identical field semantics.
annot_fc: ast.AST* = m_aa_c.annotation
if annot_fc is not None:
if GenApi.has_decorator_marker(annot_fc, "CVolatile", 0) != 0: field_volatile_buf[field_count] = 1
if GenApi.has_pointee_volatile_marker(annot_fc) != 0: field_pointee_volatile_buf[field_count] = 1
if GenApi.is_const_object_marker(annot_fc, field_ty_c) != 0: field_const_buf[field_count] = 1
# Byte order: 1 = t.BigEndian / 2 = t.LittleEndian (0 stays native);
# annotation `|` means "and", so `X | t.BigEndian` is a BigEndian X.
if GenApi.has_decorator_marker(annot_fc, "BigEndian", 0) != 0: field_byteorder_buf[field_count] = 1
elif GenApi.has_decorator_marker(annot_fc, "LittleEndian", 0) != 0: field_byteorder_buf[field_count] = 2
field_count += 1
# 3. The vpi stub has no class fields -> field_count is 0; registering an empty class would make
# the source module hit an empty struct and raise InternalCompilerError, so do not register.
@@ -2734,7 +2762,17 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModul
for afi_c in range(int(field_count)):
af_name_c: str = str(field_names_buf[afi_c])
af_ty_c: mlirlite.LLVMType* = (mlirlite.LLVMType*)(field_types_buf[afi_c])
GenApi.add_field(pool, entry_c, af_name_c, af_ty_c)
af_idx_c: int = GenApi.add_field(pool, entry_c, af_name_c, af_ty_c)
# Restore the per-field markers AFTER add_field, because StructGenMixin.add_field always
# resets them to 0 (it cannot see the annotation). Buffers are index-aligned with add_field
# order, so afi_c indexes them directly (mirrors ClassGenDef's post-add_field set).
if af_idx_c >= 0 and GenApi._g_gen is not None:
af_fe_c: GenTypes.FieldEntry* = GenApi._g_gen.StructGen._get_field_entry(entry_c, af_idx_c)
if af_fe_c is not None:
if field_volatile_buf[afi_c] != 0: af_fe_c.IsVolatile = 1
if field_pointee_volatile_buf[afi_c] != 0: af_fe_c.PointeeVolatile = 1
if field_const_buf[afi_c] != 0: af_fe_c.IsConst = 1
if field_byteorder_buf[afi_c] != 0: af_fe_c.ByteOrder = int(field_byteorder_buf[afi_c])
GenApi.add_visible_struct(pool, real_name)
return 1