fix(cdefine): stub 读取对负浮点字面量/浮点强转包裹剥壳后再注册 - 修 X: double = -100.0 走整型提取 fatal

This commit is contained in:
TermiNexus committed 2026-10-15 23:46:25 +08:00
1 parent 5460d78ff1
commit d06e665ebd
1 file changed
+46 -9
+46 -9
View File
@@ -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