From d06e665ebda891910c796f2752bf2c6b1303b766 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Thu, 15 Oct 2026 23:46:25 +0800 Subject: [PATCH] =?UTF-8?q?fix(cdefine):=20stub=20=E8=AF=BB=E5=8F=96?= =?UTF-8?q?=E5=AF=B9=E8=B4=9F=E6=B5=AE=E7=82=B9=E5=AD=97=E9=9D=A2=E9=87=8F?= =?UTF-8?q?/=E6=B5=AE=E7=82=B9=E5=BC=BA=E8=BD=AC=E5=8C=85=E8=A3=B9?= =?UTF-8?q?=E5=89=A5=E5=A3=B3=E5=90=8E=E5=86=8D=E6=B3=A8=E5=86=8C=20-=20?= =?UTF-8?q?=E4=BF=AE=20X:=20double=20=3D=20-100.0=20=E8=B5=B0=E6=95=B4?= =?UTF-8?q?=E5=9E=8B=E6=8F=90=E5=8F=96=20fatal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/lib/Stub/StubGen/VpiReader.vp | 55 ++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/App/lib/Stub/StubGen/VpiReader.vp b/App/lib/Stub/StubGen/VpiReader.vp index 6dcb107..c30b2a3 100644 --- a/App/lib/Stub/StubGen/VpiReader.vp +++ b/App/lib/Stub/StubGen/VpiReader.vp @@ -2090,17 +2090,36 @@ def _vpi_register_typedef_closure(pool: memhub.MemBuddy*, import_mods: str, temp if aa_r.target.kind() != ast.ASTKind.Name: continue cdef_t: ast.Name* = ast.Name*(aa_r.target) if cdef_t.id is None: continue - if aa_r.value.kind() == ast.ASTKind.Constant: - cn_v: ast.Constant* = ast.Constant*(aa_r.value) + # 与定义端同口径:剥掉 `float(...)`/`double(...)` 包裹与负浮点字面量 + # `UnaryOp(USub, Constant(float))`;否则 `X: double = -100.0` 既不注册 + # 浮点(静默丢失),又可能被误当整型去走常驻提取。 + vnode_r: ast.AST* = aa_r.value + neg_r: int = 0 + if vnode_r.kind() == ast.ASTKind.Call: + cl_r: ast.Call* = ast.Call*(vnode_r) + if cl_r.args is not None and len(cl_r.args) > 0: + fa_r: ast.AST* = cl_r.args.get(0) + if fa_r is not None and fa_r.kind() == ast.ASTKind.Constant: vnode_r = fa_r + if vnode_r.kind() == ast.ASTKind.UnaryOp: + uu_r: ast.UnaryOp* = ast.UnaryOp*(vnode_r) + if uu_r.op == ast.OpKind.USub and uu_r.operand is not None and uu_r.operand.kind() == ast.ASTKind.Constant: + ic_r: ast.Constant* = ast.Constant*(uu_r.operand) + if ic_r.const_kind == ast.CONST_FLOAT: + vnode_r = uu_r.operand + neg_r = 1 + if vnode_r.kind() == ast.ASTKind.Constant: + cn_v: ast.Constant* = ast.Constant*(vnode_r) if cn_v.const_kind == ast.CONST_FLOAT: + fv_r: double = cn_v.float_val + if neg_r != 0: fv_r = -fv_r # 浮点宽度同样由声明注解裁决(与定义方同一套), # 否则 `define PI: float = ...` 的使用方会把 f32 当 double - GenApi.register_cdefine_double(pool, cdef_t.id, cn_v.float_val, GenApi.cdefine_decl_float_bits(pool, aa_r.annotation)) + GenApi.register_cdefine_double(pool, cdef_t.id, fv_r, GenApi.cdefine_decl_float_bits(pool, aa_r.annotation)) elif cn_v.const_kind == ast.CONST_INT: - cdef_val: int64 = GenApi.extract_cdefine_int_value(aa_r.value) + cdef_val: int64 = GenApi.extract_cdefine_int_value(vnode_r) # 位宽与定义方同一套裁决(注解 → 右侧强转 → 值的最小可存宽度), # 否则使用方拿 bits=0 只能兜底,跨模块位宽会与定义方不一致 - GenApi.register_cdefine_constant(pool, cdef_t.id, cdef_val, GenApi.cdefine_decl_bits(pool, aa_r.annotation, aa_r.value)) + GenApi.register_cdefine_constant(pool, cdef_t.id, cdef_val, GenApi.cdefine_decl_bits(pool, aa_r.annotation, vnode_r)) # recurse into child imports (cycle guarded by the visited marks) if sub_imports[0] != '\0': _vpi_register_typedef_closure(pool, sub_imports, temp_dir, depth + 1) stdlib.free(sub_imports) @@ -2412,24 +2431,42 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, v if cdef_tgt.id is not None: # Skip string CDefines (version numbers etc.): extract_cdefine_int_value # fails fast on string constants, and count refs only need integer CDefines. + # 与定义端 `_register_cdefine_from_value` 同口径:先剥掉 `float(...)`/`double(...)` + # 强转包裹与负浮点字面量的 `UnaryOp(USub, Constant(float))`,否则 + # `X: double = -100.0` 会被判成"非 float"而落到整型提取 ⇒ fatal。 + vnode: ast.AST* = aa.value + cdef_neg_f: int = 0 + if vnode.kind() == ast.ASTKind.Call: + cl_w2: ast.Call* = ast.Call*(vnode) + if cl_w2.args is not None and len(cl_w2.args) > 0: + fa2: ast.AST* = cl_w2.args.get(0) + if fa2 is not None and fa2.kind() == ast.ASTKind.Constant: vnode = fa2 + if vnode.kind() == ast.ASTKind.UnaryOp: + uu2: ast.UnaryOp* = ast.UnaryOp*(vnode) + if uu2.op == ast.OpKind.USub and uu2.operand is not None and uu2.operand.kind() == ast.ASTKind.Constant: + ic2: ast.Constant* = ast.Constant*(uu2.operand) + if ic2.const_kind == ast.CONST_FLOAT: + vnode = uu2.operand + cdef_neg_f = 1 cdef_is_str: int = 0 cdef_is_float: int = 0 cdef_float_val: double = 0.0 - if aa.value.kind() == ast.ASTKind.Constant: - cn_v: ast.Constant* = ast.Constant*(aa.value) + if vnode.kind() == ast.ASTKind.Constant: + cn_v: ast.Constant* = ast.Constant*(vnode) if cn_v.const_kind == ast.CONST_STR: cdef_is_str = 1 elif cn_v.const_kind == ast.CONST_FLOAT: cdef_is_float = 1 cdef_float_val = cn_v.float_val + if cdef_neg_f != 0: cdef_float_val = -cdef_float_val if cdef_is_str == 0 and cdef_is_float != 0: # Float CDefine (e.g. FRAGMENTATION_THRESHOLD: t.CDefine = 0.7): register via # register_cdefine_double (integer extraction would fail fast). # 注解声明 float 时带上 f32 种类(与定义方同一套裁决)。 GenApi.register_cdefine_double(pool, cdef_tgt.id, cdef_float_val, GenApi.cdefine_decl_float_bits(pool, aa.annotation)) elif cdef_is_str == 0: - cdef_val: int64 = GenApi.extract_cdefine_int_value(aa.value) + cdef_val: int64 = GenApi.extract_cdefine_int_value(vnode) # 位宽与定义方同一套裁决(注解 → 右侧强转 → 值的最小可存宽度) - GenApi.register_cdefine_constant(pool, cdef_tgt.id, cdef_val, GenApi.cdefine_decl_bits(pool, aa.annotation, aa.value)) + GenApi.register_cdefine_constant(pool, cdef_tgt.id, cdef_val, GenApi.cdefine_decl_bits(pool, aa.annotation, vnode)) else: _inject_global_variable_declare(pool, mod, aa, trans, stub_imported_modules, stub_from_imports, i32_ty, i8_ptr_ty, src_sha1) continue