fix(stub): .vpi 读取侧复刻字段标记判定(volatile/pointee-volatile/const/字节序),跨模块不再丢字段标记
This commit is contained in:
1 parent
37c4b0da3b
commit
32599a08c1
2 files changed
+53
-1
No files matched your search
@@ -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
|
||||
|
||||
|
||||
Reference in new issue
Block a user