fix(defines): resolve chained define references in vpi stubs

This commit is contained in:
TermiNexus committed 2026-10-27 12:49:00 +08:00
1 parent d13eb6b063
commit 8367b5f65b
4 files changed
+31 -17

No files matched your search

+13 -3
View File
@@ -1278,12 +1278,22 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf
# is_ctypedef_ann guard a Name RHS got a second suffix
# (`typedef pid_t = int32 = int32`, which no longer parses as an alias).
elif is_ctypedef_ann == 0 and aa.value is not None and aa.value.kind() == ast.ASTKind.Name:
# Name reference constant (e.g. ALIAS = OTHER_CONST):
# emit the referenced name for the consumer to resolve locally.
# Name reference constant (e.g. TICKS_PER_SECOND = TIMER_FREQUENCY):
# if the referenced define is already registered (declaration-order
# pre-pass), emit its numeric value so the vpi is self-contained.
# Only an unresolved reference keeps the symbolic name (the reader
# resolves it inside the same vpi module).
name_val: ast.Name* = ast.Name*(aa.value)
if name_val.id is not None:
ref_val: int64 = _lookup_cdefine_for_pyi(name_val.id)
pos = _PyiEmit(buf, buf_size, pos, " = ")
pos = _PyiEmit(buf, buf_size, pos, name_val.id)
if _pyi_cdefine_found() != 0:
num_buf_n: bytes = mb.alloc(32)
if num_buf_n is not None:
viperlib.snprintf(num_buf_n, 32, "%lld", ref_val)
pos = _PyiEmit(buf, buf_size, pos, num_buf_n)
else:
pos = _PyiEmit(buf, buf_size, pos, name_val.id)
pos = _PyiEmit(buf, buf_size, pos, "\n")
# Global assignment (no annotation) - infer type from the Constant value
+2 -2
View File
@@ -2311,7 +2311,7 @@ def _vpi_register_typedef_closure(pool: memhub.MemBuddy*, import_mods: str, temp
# 否则 `define PI: float = ...` 的使用方会把 f32 当 double
GenApi.register_cdefine_double(pool, cdef_t.id, fv_r, GenApi.cdefine_decl_float_bits(pool, aa_r.annotation), sha1_r)
elif cn_v.const_kind == ast.CONST_INT:
cdef_val: int64 = GenApi.extract_cdefine_int_value(vnode_r)
cdef_val: int64 = GenApi.extract_cdefine_int_value(vnode_r, sha1_r)
# 位宽与定义方同一套裁决(注解 → 右侧强转 → 值的最小可存宽度),
# 否则使用方拿 bits=0 只能兜底,跨模块位宽会与定义方不一致
GenApi.register_cdefine_constant(pool, cdef_t.id, cdef_val, GenApi.cdefine_decl_bits(pool, aa_r.annotation, vnode_r), sha1_r)
@@ -3315,7 +3315,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, v
# 注解声明 float 时带上 f32 种类(与定义方同一套裁决)。
GenApi.register_cdefine_double(pool, cdef_tgt.id, cdef_float_val, GenApi.cdefine_decl_float_bits(pool, aa.annotation), def_mod)
elif cdef_is_str == 0:
cdef_val: int64 = GenApi.extract_cdefine_int_value(vnode)
cdef_val: int64 = GenApi.extract_cdefine_int_value(vnode, def_mod)
# 位宽与定义方同一套裁决(注解 → 右侧强转 → 值的最小可存宽度)
GenApi.register_cdefine_constant(pool, cdef_tgt.id, cdef_val, GenApi.cdefine_decl_bits(pool, aa.annotation, vnode), def_mod)
else:
+13 -9
View File
@@ -43,12 +43,12 @@ novirtual class AssignGenMixin:
# ---- 统一编译期常量表达式求值(值 + 位宽) ----
# 所有 define/常量折叠入口都走这里,避免各写一套(此前 extract_cdefine_int_value /
# _eval_const_int_expr / _cif_eval_node 三套互相独立,导致位宽信息在 define 上丢失)。
def extract_cdefine_int_value(self, val_node: ast.AST*) -> int64:
def extract_cdefine_int_value(self, val_node: ast.AST*, module: str = None) -> int64:
"""仅取值(丢弃位宽)的薄封装;需要位宽请用 extract_cdefine_int_value_bits。"""
b_legacy: int = 0
return self.extract_cdefine_int_value_bits(val_node, None, &b_legacy)
return self.extract_cdefine_int_value_bits(val_node, None, &b_legacy, module)
def extract_cdefine_int_value_bits(self, val_node: ast.AST*, pool: memhub.MemBuddy*, bits_out: int*) -> int64:
def extract_cdefine_int_value_bits(self, val_node: ast.AST*, pool: memhub.MemBuddy*, bits_out: int*, module: str = None) -> int64:
"""编译期常量表达式求值:返回值,并把**位宽**写入 bits_out[0](0=未知)。
位宽规则(供 define 物化用):
@@ -79,8 +79,8 @@ novirtual class AssignGenMixin:
bop: ast.BinOp* = ast.BinOp*(val_node)
lb: int = 0
rb: int = 0
left_val: int64 = self.extract_cdefine_int_value_bits(bop.left, pool, &lb)
right_val: int64 = self.extract_cdefine_int_value_bits(bop.right, pool, &rb)
left_val: int64 = self.extract_cdefine_int_value_bits(bop.left, pool, &lb, module)
right_val: int64 = self.extract_cdefine_int_value_bits(bop.right, pool, &rb, module)
# 操作数位宽(各自的**声明宽度**,保持最小、不提升):两侧不等取较宽,一侧未知则沿用另一侧
wbase: int = 0
if lb != 0 and rb != 0: wbase = lb if lb > rb else rb
@@ -143,10 +143,14 @@ novirtual class AssignGenMixin:
# True/False literal -> 1/0 (bool treated as int in DefineT context)
if string.strcmp(nm.id, "True") == 0: return 1
if string.strcmp(nm.id, "False") == 0: return 0
looked_up: int64 = self.Gen.TypeGenCDef.lookup_cdefine_constant(nm.id)
looked_up: int64 = self.Gen.TypeGenCDef.lookup_cdefine_constant(nm.id, module)
hit_mod: str = module
if self.Gen.TypeGenCDef.is_cdefine_found() == 0 and module is not None:
looked_up = self.Gen.TypeGenCDef.lookup_cdefine_constant(nm.id)
hit_mod = None
if self.Gen.TypeGenCDef.is_cdefine_found() != 0:
# 沿用被引用 define 的位宽(宽度随宏传播,不再丢)
if bits_out is not None: bits_out[0] = self.Gen.TypeGenCDef.lookup_cdefine_bits(nm.id)
if bits_out is not None: bits_out[0] = self.Gen.TypeGenCDef.lookup_cdefine_bits(nm.id, hit_mod)
return looked_up
# Unregistered reference: fail fast
self.Gen.TypeGenErr.fatal_error(val_node, "DefineT value extraction failed: cannot parse a compile-time constant from the expression", "TypeError")
@@ -162,7 +166,7 @@ novirtual class AssignGenMixin:
if cl_args_list is not None and len(cl_args_list) > 0:
first_arg: ast.AST* = cl_args_list.get(0)
ib: int = 0
arg_val: int64 = self.extract_cdefine_int_value_bits(first_arg, pool, &ib)
arg_val: int64 = self.extract_cdefine_int_value_bits(first_arg, pool, &ib, module)
if t_bits != 0:
if bits_out is not None: bits_out[0] = t_bits
return self._normalize_cdefine_bits(arg_val, t_bits)
@@ -175,7 +179,7 @@ novirtual class AssignGenMixin:
if k == ast.ASTKind.UnaryOp:
uop: ast.UnaryOp* = ast.UnaryOp*(val_node)
ob: int = 0
operand_val: int64 = self.extract_cdefine_int_value_bits(uop.operand, pool, &ob)
operand_val: int64 = self.extract_cdefine_int_value_bits(uop.operand, pool, &ob, module)
if bits_out is not None: bits_out[0] = ob
if uop.op == ast.OpKind.USub: return -operand_val
if uop.op == ast.OpKind.UAdd: return operand_val
+3 -3
View File
@@ -218,9 +218,9 @@ def is_cdefine_annotation(annot: ast.AST*) -> int:
# ---------------- extract_cdefine_int_value (delegates to AssignGenMixin.extract_cdefine_int_value) ----------------
def extract_cdefine_int_value(val_node: ast.AST*) -> int64:
"""Delegate to gen.extract_cdefine_int_value"""
if _g_gen is not None: return _g_gen.AssignGen.extract_cdefine_int_value(val_node)
def extract_cdefine_int_value(val_node: ast.AST*, module: str = None) -> int64:
"""Delegate to gen.extract_cdefine_int_value (module: source SHA1 for cross-module names)"""
if _g_gen is not None: return _g_gen.AssignGen.extract_cdefine_int_value(val_node, module)
return 0