diff --git a/App/lib/Stub/StubGen/Converter.vp b/App/lib/Stub/StubGen/Converter.vp index 43a4031..ce73e75 100644 --- a/App/lib/Stub/StubGen/Converter.vp +++ b/App/lib/Stub/StubGen/Converter.vp @@ -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 diff --git a/App/lib/Stub/StubGen/VpiReader.vp b/App/lib/Stub/StubGen/VpiReader.vp index 85a2d84..a2b8670 100644 --- a/App/lib/Stub/StubGen/VpiReader.vp +++ b/App/lib/Stub/StubGen/VpiReader.vp @@ -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: diff --git a/App/lib/core/Gen/AssignGenMixin.vp b/App/lib/core/Gen/AssignGenMixin.vp index 302e2d8..79665b4 100644 --- a/App/lib/core/Gen/AssignGenMixin.vp +++ b/App/lib/core/Gen/AssignGenMixin.vp @@ -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 diff --git a/App/lib/core/Gen/GenApi.vp b/App/lib/core/Gen/GenApi.vp index 4d9f57c..016666c 100644 --- a/App/lib/core/Gen/GenApi.vp +++ b/App/lib/core/Gen/GenApi.vp @@ -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