fix(viperc): 浮点常量按目标类型/声明宽度直接出 f32,不再先出 double
- 浮点字面量在 f32 目标(float(1.5) / x: float = 1.5 / f32 形参)下直接物化 f32 常量, 负号折叠(-c)同口径;去掉旧的「f64 常量 + fptrunc」 - CDefine 浮点条目记录宽度种类(1=f64 / 2=f32):define PI: float = ... 的使用处 直接出 f32 常量,与 f32 字面量混算不再被提升成 double(现场 33 处 cvtss2sd) - 本模块注册 / pyi·vpi 跨模块重解析 / xmod 缓存三处都按注解裁决宽度,保持跨模块一致
This commit is contained in:
1 parent
3a687db0bb
commit
508428bbc9
12 files changed
+201
-28
No files matched your search
@@ -2092,7 +2092,10 @@ def _vpi_register_typedef_closure(pool: memhub.MemBuddy*, import_mods: str, temp
|
||||
if cdef_t.id is None: continue
|
||||
if aa_r.value.kind() == ast.ASTKind.Constant:
|
||||
cn_v: ast.Constant* = ast.Constant*(aa_r.value)
|
||||
if cn_v.const_kind == ast.CONST_FLOAT: GenApi.register_cdefine_double(pool, cdef_t.id, cn_v.float_val)
|
||||
if cn_v.const_kind == ast.CONST_FLOAT:
|
||||
# 浮点宽度同样由声明注解裁决(与定义方同一套),
|
||||
# 否则 `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))
|
||||
elif cn_v.const_kind == ast.CONST_INT:
|
||||
cdef_val: int64 = GenApi.extract_cdefine_int_value(aa_r.value)
|
||||
# 位宽与定义方同一套裁决(注解 → 右侧强转 → 值的最小可存宽度),
|
||||
@@ -2421,7 +2424,8 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, v
|
||||
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).
|
||||
GenApi.register_cdefine_double(pool, cdef_tgt.id, cdef_float_val)
|
||||
# 注解声明 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)
|
||||
# 位宽与定义方同一套裁决(注解 → 右侧强转 → 值的最小可存宽度)
|
||||
|
||||
@@ -407,6 +407,60 @@ novirtual class AssignGenMixin:
|
||||
"""Return the bit width of a CDefine declaration's explicit type T."""
|
||||
return self._annot_int_bits(pool, self._define_explicit_annot(annot))
|
||||
|
||||
# cdefine_decl_float_bits - define 声明的**浮点**宽度裁决(定义方与跨模块使用方共用同一套)
|
||||
def cdefine_decl_float_bits(self, pool: memhub.MemBuddy*, annot: ast.AST*) -> int:
|
||||
"""1 = 注解显式声明了 32 位 float(`define PI: float = ...`),0 = double / 未声明 / 非浮点。
|
||||
|
||||
与 cdefine_decl_bits(整型位宽)并列:浮点常量的宽度只由注解决定(右侧字面量在
|
||||
.vpi 里只剩 `= 3.14159...`,已丢失 `float(...)` 包裹),故这里只看注解。
|
||||
"""
|
||||
return self._annot_float_kind(pool, self._define_explicit_annot(annot))
|
||||
|
||||
def _annot_float_kind(self, pool: memhub.MemBuddy*, annot: ast.AST*) -> int:
|
||||
"""注解节点 → 1(f32)/ 0(其余);成分与 _annot_int_bits 对齐。"""
|
||||
if annot is None: return 0
|
||||
nm: str = None
|
||||
k: int = annot.kind()
|
||||
if k == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute* = ast.Attribute*(annot)
|
||||
nm = at.attr
|
||||
elif k == ast.ASTKind.Name:
|
||||
n2: ast.Name* = ast.Name*(annot)
|
||||
nm = n2.id
|
||||
if nm is None: return 0
|
||||
return self._float_kind_of_type_name(pool, nm, 0)
|
||||
|
||||
def _float_kind_of_type_name(self, pool: memhub.MemBuddy*, nm: str, depth: int) -> int:
|
||||
"""类型名 → 1 表示它是 32 位 float(f32),0 表示 double 或非浮点/未知。depth 防 typedef 环。
|
||||
|
||||
覆盖:内建名 float、`t.CFloat` / `t.CFloat32T`(map_t_type)、用户/include typedef(递归展开)。
|
||||
"""
|
||||
if nm is None or depth > 10: return 0
|
||||
# 去掉模块/类限定前缀:`t.CFloat` → `CFloat`;`stdint.float32` → `float32`
|
||||
dot: str = string.strrchr(nm, 46)
|
||||
if dot is not None and dot[1] != '\0':
|
||||
return self._float_kind_of_type_name(pool, dot + 1, depth + 1)
|
||||
if string.strcmp(nm, "float") == 0: return 1
|
||||
if string.strcmp(nm, "float32") == 0: return 1
|
||||
ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.map_t_type(pool, nm)
|
||||
if ty is not None:
|
||||
match ty:
|
||||
case mlirlite.LLVMType.Float(bits):
|
||||
if bits == 32: return 1
|
||||
return 0
|
||||
case _:
|
||||
return 0
|
||||
# 用户/include typedef(如 `MYF: t.CTypedef = float`):展开后再递归判定
|
||||
underlying: str = self.Gen.TypeGenCType.lookup_ctypedef(nm)
|
||||
if underlying is None:
|
||||
underlying = self.Gen.TypeGenResolve._lookup_builtins_typedef(pool, nm)
|
||||
if underlying is not None:
|
||||
expanded: str = self.Gen.TypeGenResolve._expand_typedef_ref(pool, underlying)
|
||||
if expanded is not None: underlying = expanded
|
||||
if underlying is None: return 0
|
||||
if string.strcmp(underlying, nm) == 0: return 0
|
||||
return self._float_kind_of_type_name(pool, underlying, depth + 1)
|
||||
|
||||
def _cdefine_int_literal_text(self, name: str) -> str:
|
||||
"""Return the raw value text of a CDefine line, or None if not found."""
|
||||
if name is None: return None
|
||||
@@ -581,6 +635,25 @@ novirtual class AssignGenMixin:
|
||||
def _register_cdefine_from_value(self, pool: memhub.MemBuddy*, name: str, val_node: ast.AST*, annot: ast.AST* = None) -> None:
|
||||
"""Register a CDefine constant (double for floats, else integer)."""
|
||||
if pool is None or name is None: return
|
||||
# 浮点宽度种类(f32 与否)必须**在拆掉右侧包裹前**判定:
|
||||
# ① 注解有显式类型(`define PI: float = ...` / `PI: float | t.CDefine = ...`)→ 注解说了算
|
||||
# (`define X: double = float(1.5)` 按 double 走);
|
||||
# ② 注解没有显式类型(`PI: t.CDefine = float(3.14)`)→ 看右侧强转包裹 float(...) / double(...)。
|
||||
f32_kind: int = 0
|
||||
if self._define_explicit_annot(annot) is not None:
|
||||
f32_kind = self.cdefine_decl_float_bits(pool, annot)
|
||||
elif val_node is not None and val_node.kind() == ast.ASTKind.Call:
|
||||
cl_w: ast.Call* = ast.Call*(val_node)
|
||||
if cl_w.func is not None:
|
||||
fk_w: int = cl_w.func.kind()
|
||||
wname_w: str = None
|
||||
if fk_w == ast.ASTKind.Name:
|
||||
fn_w: ast.Name* = ast.Name*(cl_w.func)
|
||||
wname_w = fn_w.id
|
||||
elif fk_w == ast.ASTKind.Attribute:
|
||||
fa_w: ast.Attribute* = ast.Attribute*(cl_w.func)
|
||||
wname_w = fa_w.attr
|
||||
if wname_w is not None and string.strcmp(wname_w, "float") == 0: f32_kind = 1
|
||||
# Call-wrapped constant (e.g. float(3.14)): use its first argument as the value
|
||||
if val_node is not None and val_node.kind() == ast.ASTKind.Call:
|
||||
cl_cd: ast.Call* = ast.Call*(val_node)
|
||||
@@ -610,7 +683,7 @@ novirtual class AssignGenMixin:
|
||||
# Source recovery failed: fail fast to avoid registering a corrupted float
|
||||
self.Gen.TypeGenErr.fatal_error(val_node, "CDefine float value source-file recovery failed", "InternalCompilerError")
|
||||
return
|
||||
self.Gen.TypeGenCDef.register_cdefine_double(pool, name, use_val)
|
||||
self.Gen.TypeGenCDef.register_cdefine_double(pool, name, use_val, f32_kind)
|
||||
return
|
||||
if val_node is None:
|
||||
# CDefine declaration without a value node: fail fast
|
||||
|
||||
@@ -445,7 +445,10 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
|
||||
if cdef_str_v is not None: return self.Gen.ExprGenConst.create_global_string(builder, pool, mod, cdef_str_v, trans)
|
||||
# cross-module float CDefine (e.g. vipermath.U_M_PI) → float constant
|
||||
dchk_ma: double = self.Gen.TypeGenCDef.lookup_cdefine_double(at.attr)
|
||||
if self.Gen.TypeGenCDef.is_cdefine_double() != 0: return mlirlite.ConstFloat(pool, mlirlite.Double(pool), dchk_ma)
|
||||
# f32 声明的常量直接出 f32 常量(否则 f32 字面量会被提升成 double)
|
||||
if self.Gen.TypeGenCDef.is_cdefine_double() != 0:
|
||||
if self.Gen.TypeGenCDef.is_cdefine_float32() != 0: return mlirlite.ConstFloat(pool, mlirlite.Float(pool), dchk_ma)
|
||||
return mlirlite.ConstFloat(pool, mlirlite.Double(pool), dchk_ma)
|
||||
return self.Gen.ExprGenCdef._const_int_for_cdefine(pool, at.attr, cdef_ma_val)
|
||||
# check whether nm_ma.id.at.attr is an imported submodule (e.g. win32.win32file);
|
||||
# for a submodule do not create a global, let the nested attribute path handle it
|
||||
@@ -561,9 +564,11 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
|
||||
viperlib.snprintf(tmp_fi, tmp_fi_len, "%s:%s", at.attr, qual_buf)
|
||||
cdef_val_nested = self.Gen.ExprGenCdef._lookup_cross_module_cdefine(pool, at.attr, tmp_fi)
|
||||
if self.Gen.TypeGenCDef.is_cdefine_found() != 0:
|
||||
# cross-module float CDefine → float constant
|
||||
# cross-module float CDefine → float constant (f32 声明直接出 f32)
|
||||
dchk_nst: double = self.Gen.TypeGenCDef.lookup_cdefine_double(at.attr)
|
||||
if self.Gen.TypeGenCDef.is_cdefine_double() != 0: return mlirlite.ConstFloat(pool, mlirlite.Double(pool), dchk_nst)
|
||||
if self.Gen.TypeGenCDef.is_cdefine_double() != 0:
|
||||
if self.Gen.TypeGenCDef.is_cdefine_float32() != 0: return mlirlite.ConstFloat(pool, mlirlite.Float(pool), dchk_nst)
|
||||
return mlirlite.ConstFloat(pool, mlirlite.Double(pool), dchk_nst)
|
||||
return self.Gen.ExprGenCdef._const_int_for_cdefine(pool, at.attr, cdef_val_nested)
|
||||
# CDefine not found: fail-fast and stop compiling (no more undefined global
|
||||
# references, which would make llc report "use of undefined value").
|
||||
|
||||
@@ -95,6 +95,24 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase):
|
||||
return None
|
||||
else: pf_chk.close()
|
||||
return buf
|
||||
# _pyi_annot_float_kind - 从 .vpi/.pyi 行的注解段(`NAME:` 到 `=` 之间)判定浮点宽度种类:
|
||||
# 独立单词 float → 1(f32);double / 未声明 / 非浮点 → 0。词边界判定避免命中 `double`/`CFloat32`。
|
||||
def _pyi_annot_float_kind(self, buf: bytes, start: sizet, end: sizet) -> int:
|
||||
"""Return 1 when the annotation text [start,end) declares a 32-bit `float`, else 0."""
|
||||
i: sizet = start
|
||||
while i + 5 <= end:
|
||||
if (buf[i] == 'f' and buf[i + 1] == 'l' and buf[i + 2] == 'o' and buf[i + 3] == 'a' and buf[i + 4] == 't'):
|
||||
ok_before: int = 1
|
||||
ok_after: int = 1
|
||||
if i > start:
|
||||
pb: char = buf[i - 1]
|
||||
if (pb >= 'A' and pb <= 'Z') or (pb >= 'a' and pb <= 'z') or (pb >= '0' and pb <= '9') or pb == '_': ok_before = 0
|
||||
if i + 5 < end:
|
||||
pa: char = buf[i + 5]
|
||||
if (pa >= 'A' and pa <= 'Z') or (pa >= 'a' and pa <= 'z') or (pa >= '0' and pa <= '9') or pa == '_': ok_after = 0
|
||||
if ok_before != 0 and ok_after != 0: return 1
|
||||
i += 1
|
||||
return 0
|
||||
# _lookup_cross_module_cdefine - cross-module CDefine lookup: resolve the source module
|
||||
# from from_imports, parse its pyi "NAME: t.CDefine = value", then cache in the current module.
|
||||
def _lookup_cross_module_cdefine(self, pool: memhub.MemBuddy*, name: str, from_imports: str, imported_modules: str = None, depth: int = 0, node: ast.AST* = None) -> int64:
|
||||
@@ -147,7 +165,9 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase):
|
||||
if self.Gen.TypeGenCDef.is_cdefine_str() != 0: self.Gen.TypeGenCDef.register_cdefine_string(pool, name, xval)
|
||||
elif self.Gen.TypeGenCDef.is_cdefine_double() != 0:
|
||||
xd_v: double = string.atof(xval)
|
||||
self.Gen.TypeGenCDef.register_cdefine_double(pool, name, xd_v)
|
||||
# 缓存里带宽度种类(f32 声明 → 1),否则使用方会把 f32 常量当 double 物化
|
||||
xd_f32: int = self.Gen.TypeGenCDef.is_cdefine_float32()
|
||||
self.Gen.TypeGenCDef.register_cdefine_double(pool, name, xd_v, xd_f32)
|
||||
else:
|
||||
xv_i: int64 = string.atoll(xval)
|
||||
self.Gen.TypeGenCDef.register_cdefine_constant(pool, name, xv_i)
|
||||
@@ -286,6 +306,9 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase):
|
||||
result_val: int64 = 0
|
||||
result_found: int = 0
|
||||
res_is_double: int = 0
|
||||
# 浮点宽度种类(1 = 注解声明为 32 位 float):跨模块缓存与本地注册都要带上,
|
||||
# 否则使用方把 f32 常量当 double 物化(`define PI: float = ...` 现场)。
|
||||
res_is_f32: int = 0
|
||||
res_is_str: int = 0
|
||||
while pos < total_len:
|
||||
# find line start
|
||||
@@ -321,6 +344,9 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase):
|
||||
eq_pos: sizet = line_start + name_len + 1
|
||||
while eq_pos < line_start + line_len and pyi_buf[eq_pos] != '=': eq_pos += 1
|
||||
if eq_pos >= line_start + line_len: continue
|
||||
# 注解段 = [名字冒号后, '='),用于判定声明的浮点宽度(如 `PI: float | t.CDefine`)
|
||||
annot_start: sizet = line_start + name_len + 1
|
||||
annot_end: sizet = eq_pos
|
||||
eq_pos += 1 # skip '='
|
||||
|
||||
# skip spaces
|
||||
@@ -578,7 +604,9 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase):
|
||||
if is_float_val != 0:
|
||||
# float CDefine (e.g. U_M_PI = 3.14159...): cache as double for double
|
||||
# constant generation; int part serves the int path (is_cdefine_double flag).
|
||||
self.Gen.TypeGenCDef.register_cdefine_double(pool, name, ldbl)
|
||||
# 注解声明为 float 时带上 f32 种类,使用方才能直接出 f32 常量。
|
||||
res_is_f32 = self._pyi_annot_float_kind(pyi_buf, annot_start, annot_end)
|
||||
self.Gen.TypeGenCDef.register_cdefine_double(pool, name, ldbl, res_is_f32)
|
||||
result_val = lval
|
||||
result_found = 1
|
||||
res_is_double = 1
|
||||
@@ -800,7 +828,8 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase):
|
||||
cbuf_d: str = pool.alloc(64)
|
||||
if cbuf_d is not None:
|
||||
stdio.snprintf(cbuf_d, 64, "%.17g", dval_cc)
|
||||
self.Gen.TypeGenCDef.register_xmod_cdefine(ckey2, cbuf_d, 1, 0)
|
||||
# 浮点种类随缓存一起带上(1=f64 / 2=f32),供后续使用方直接物化宽度
|
||||
self.Gen.TypeGenCDef.register_xmod_cdefine(ckey2, cbuf_d, self.Gen.TypeGenCDef.xmod_float_kind(), 0)
|
||||
self.Gen.TypeGenCDef.set_cdefine_found(1)
|
||||
else: self.Gen.TypeGenCDef.set_cdefine_found(0)
|
||||
|
||||
|
||||
@@ -105,7 +105,12 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase):
|
||||
if iv > 2147483647 or iv < -2147483648: return mlirlite.const_int64(pool, iv)
|
||||
return mlirlite.const_int32(pool, iv)
|
||||
elif cn.const_kind == ast.CONST_FLOAT:
|
||||
# Float constants default to double (64-bit); coerce_to_type fptruncs on assignment
|
||||
# 目标类型是 32 位浮点(float(1.5) / x: float = 1.5 / f32 形参)→ 直接出 f32 常量。
|
||||
# 旧实现无视 target_ty 一律先出 double 常量、再由 coerce_to_type fptrunc,
|
||||
# 现场:float(2.0) / float(1.0) 生成 f64 常量 + fptrunc,与双精度常量混算时又多出 fpext。
|
||||
# 其余情况(无目标类型 / double / 非浮点)保持 double 常量,由 coerce_to_type 负责转换。
|
||||
if target_ty is not None and self.get_llvm_float_bits(target_ty) == 32:
|
||||
return mlirlite.ConstFloat(pool, target_ty, cn.float_val)
|
||||
double_ty: mlirlite.LLVMType* = mlirlite.Double(pool)
|
||||
return mlirlite.ConstFloat(pool, double_ty, cn.float_val)
|
||||
elif cn.const_kind == ast.CONST_CHAR:
|
||||
|
||||
@@ -51,7 +51,7 @@ novirtual class ExprGenMixin(ExprGenBase.ExprGenBase):
|
||||
# M2.4 `new stack|heap|memgr(x) [slife|hlife] T(args)`:只换"取存储",其余复用构造序列
|
||||
elif k == ast.ASTKind.New: return self.Gen.CallGenCtor._translate_new_expr(pool, builder, mod, ast.New*(node), trans)
|
||||
elif k == ast.ASTKind.Compare: return self.Gen.ExprGenOps.translate_compare(builder, pool, mod, node, trans)
|
||||
elif k == ast.ASTKind.UnaryOp: return self.Gen.ExprGenOps.translate_unaryop(builder, pool, mod, node, trans)
|
||||
elif k == ast.ASTKind.UnaryOp: return self.Gen.ExprGenOps.translate_unaryop(builder, pool, mod, node, trans, target_ty)
|
||||
elif k == ast.ASTKind.BoolOp: return self.Gen.ExprGenOps.translate_boolop(builder, pool, mod, node, funcs_ptr, func_count, trans)
|
||||
elif k == ast.ASTKind.Subscript: return self.Gen.ExprGenName.translate_subscript(builder, pool, mod, node, trans)
|
||||
elif k == ast.ASTKind.Attribute: return self.Gen.ExprGenAttr.translate_attribute(builder, pool, mod, node, trans)
|
||||
|
||||
@@ -55,7 +55,11 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase):
|
||||
cdef_sv: str = self.Gen.TypeGenCDef.lookup_cdefine_string(nm_id)
|
||||
if cdef_sv is not None: return self.Gen.ExprGenConst.create_global_string(builder, pool, mod, cdef_sv, trans)
|
||||
self.Gen.TypeGenErr.fatal_error(node, f"CDefine string value missing: {nm_id}", "InternalCompilerError")
|
||||
if self.Gen.TypeGenCDef.is_cdefine_double() != 0: return mlirlite.ConstFloat(pool, mlirlite.Double(pool), cdef_val_d)
|
||||
# 浮点常量:声明为 32 位 float(`define PI: float = ...`)时直接出 f32 常量,
|
||||
# 否则出 f64 —— 出 f64 会把后续 f32 字面量整体提升成 double(fpext/cvtss2sd)。
|
||||
if self.Gen.TypeGenCDef.is_cdefine_double() != 0:
|
||||
if self.Gen.TypeGenCDef.is_cdefine_float32() != 0: return mlirlite.ConstFloat(pool, mlirlite.Float(pool), cdef_val_d)
|
||||
return mlirlite.ConstFloat(pool, mlirlite.Double(pool), cdef_val_d)
|
||||
# Integer CDefine: re-look-up the full 64-bit value (a double round-trip loses
|
||||
# precision and would generate a wrong constant).
|
||||
cdef_val_c: int64 = self.Gen.TypeGenCDef.lookup_cdefine_constant(nm_id)
|
||||
@@ -81,7 +85,10 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase):
|
||||
# Cross-module float CDefine is cached as double; return a float constant
|
||||
# rather than a truncated integer.
|
||||
dchk_nm: double = self.Gen.TypeGenCDef.lookup_cdefine_double(nm_id)
|
||||
if self.Gen.TypeGenCDef.is_cdefine_double() != 0: return mlirlite.ConstFloat(pool, mlirlite.Double(pool), dchk_nm)
|
||||
# 同本模块路径:f32 声明的常量直接出 f32 常量(跨模块缓存已带宽度种类)。
|
||||
if self.Gen.TypeGenCDef.is_cdefine_double() != 0:
|
||||
if self.Gen.TypeGenCDef.is_cdefine_float32() != 0: return mlirlite.ConstFloat(pool, mlirlite.Float(pool), dchk_nm)
|
||||
return mlirlite.ConstFloat(pool, mlirlite.Double(pool), dchk_nm)
|
||||
# Same use-site width rule (cross-module CDefine)
|
||||
uw_x: mlirlite.Value* = self.Gen.ExprGenCdef.cdefine_use_width_value(pool, node, nm_id, cdef_val, target_ty, use_ctx)
|
||||
if uw_x is not None: return uw_x
|
||||
|
||||
@@ -654,7 +654,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
|
||||
return mlirlite.build_icmp(builder, predicate, lhs, rhs)
|
||||
# translate_unaryop - UnaryOp(op, operand)
|
||||
# ============================================================
|
||||
def translate_unaryop(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, trans: HT.Translator* = None) -> mlirlite.Value*:
|
||||
def translate_unaryop(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, trans: HT.Translator* = None, target_ty: mlirlite.LLVMType* = None) -> mlirlite.Value*:
|
||||
"""Translate unary operations (-x, +x, not x, ~x)."""
|
||||
uo: ast.UnaryOp* = ast.UnaryOp*(node)
|
||||
if uo is None: return None
|
||||
@@ -688,7 +688,12 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
|
||||
operand_fbits: int = self.get_llvm_float_bits(operand.Ty)
|
||||
if operand_fbits > 0:
|
||||
# 编译期常量折叠:-c 直接产出常量并保持 IsConst
|
||||
if operand.IsConst == 1: return mlirlite.ConstFloat(pool, operand.Ty, -operand.FloatVal)
|
||||
if operand.IsConst == 1:
|
||||
# 目标类型是 32 位浮点(`float(-3.5)` / `x: float = -3.5`)→ 直接出 f32 常量,
|
||||
# 不再"f64 常量 + fptrunc"(与 ExprGenConst.translate_constant 的浮点字面量同口径)。
|
||||
if target_ty is not None and self.get_llvm_float_bits(target_ty) == 32:
|
||||
return mlirlite.ConstFloat(pool, target_ty, -operand.FloatVal)
|
||||
return mlirlite.ConstFloat(pool, operand.Ty, -operand.FloatVal)
|
||||
return mlirlite.build_fneg(builder, operand)
|
||||
# 编译期常量折叠:-c 直接产出常量(IsConst=1)。否则 `v: int8 = -50` 会被当成运行时 i32 值,
|
||||
# 触发“隐式窄化禁止”,尽管其数值完全落在 i8 内(隐式窄化的“编译期常量”豁免失效)。
|
||||
|
||||
@@ -192,9 +192,17 @@ def cdefine_decl_bits(pool: memhub.MemBuddy*, annot: ast.AST*, value_node: ast.A
|
||||
|
||||
|
||||
# ---------------- register_cdefine_double (delegates to TypeGenCDef.register_cdefine_double) ----------------
|
||||
def register_cdefine_double(pool: memhub.MemBuddy*, name: str, value: double):
|
||||
"""Delegate to gen.register_cdefine_double"""
|
||||
if _g_gen is not None: _g_gen.TypeGenCDef.register_cdefine_double(pool, name, value)
|
||||
def register_cdefine_double(pool: memhub.MemBuddy*, name: str, value: double, is_f32: int = 0):
|
||||
"""Delegate to gen.register_cdefine_double (is_f32: 1=float 声明,0=double)"""
|
||||
if _g_gen is not None: _g_gen.TypeGenCDef.register_cdefine_double(pool, name, value, is_f32)
|
||||
|
||||
|
||||
# ---------------- cdefine_decl_float_bits (delegates to AssignGenMixin.cdefine_decl_float_bits) ----------------
|
||||
def cdefine_decl_float_bits(pool: memhub.MemBuddy*, annot: ast.AST*) -> int:
|
||||
"""define 声明的**浮点**宽度裁决:注解显式写了 float → 1(f32),double/未写 → 0。
|
||||
跨模块(.vpi 重解析 define 的 AST)注册必须用它,否则使用方把 f32 常量当 double 物化。"""
|
||||
if _g_gen is not None: return _g_gen.AssignGen.cdefine_decl_float_bits(pool, annot)
|
||||
return 0
|
||||
|
||||
|
||||
# ---------------- is_cdefine_annotation (delegates to AssignGenMixin.is_cdefine_annotation) ----------------
|
||||
|
||||
@@ -45,6 +45,9 @@ novirtual class TypeGenBase:
|
||||
# --- Global CDefine compile-time constant table (was _g_cdefine_*) ---
|
||||
CDefineNames: list[str]*
|
||||
CDefineValues: list[str]*
|
||||
# 浮点常量的**宽度种类**:1=f64(double,默认),2=f32(float);0=非浮点(整型/字符串)。
|
||||
# 判定"是不是浮点常量"一律用 `!= 0`(既有调用处口径不变),只有浮点常量物化处区分 64/32:
|
||||
# `define PI: float = 3.14159...` 必须直接出 f32 常量,否则与 f32 字面量混算会多出 fpext。
|
||||
CDefineDoubleFlags: list[int]*
|
||||
CDefineStrFlags: list[int]* # 1=string value (e.g. ZLIB_VERSION: t.CDefine = "1.3.2")
|
||||
# 值表达式的**位宽**(bit);0=未知(按值推断)。来源:右侧显式强转(如 WORD(0x0080))优先,
|
||||
@@ -63,6 +66,7 @@ novirtual class TypeGenBase:
|
||||
# Not cleared by reset_to(mark2)/clear_cdefine_constants, so CONST_INT lookup happens once.
|
||||
XmodCdefNames: list[str]*
|
||||
XmodCdefValues: list[str]*
|
||||
# 同 CDefineDoubleFlags 的编码:1=f64,2=f32,0=非浮点。
|
||||
XmodCdefDoubleFlags: list[int]*
|
||||
XmodCdefStrFlags: list[int]*
|
||||
|
||||
|
||||
@@ -23,6 +23,12 @@ define CDEF_IDX_FNV_OFFSET = 2166136261
|
||||
define CDEF_IDX_FNV_PRIME = 16777619
|
||||
define CDEF_IDX_FNV_MASK = 4294967295
|
||||
|
||||
# CDefine 浮点常量的宽度种类(CDefineDoubleFlags / XmodCdefDoubleFlags 条目编码)。
|
||||
# 1=f64(double,默认),2=f32(float);0 表示非浮点。既有读取处一律按 `!= 0` 判定
|
||||
# "是浮点常量",故 f32 天然兼容;只有浮点常量的物化处需要区分 64/32。
|
||||
define CDEFINE_FLOAT_KIND_F64 = 1
|
||||
define CDEFINE_FLOAT_KIND_F32 = 2
|
||||
|
||||
|
||||
# TypeGenCDef - split from TypeGenMixin (stage D): CDefine compile-time constant table (register/lookup/is/set/clear)
|
||||
novirtual class TypeGenCDef(TypeGenBase.TypeGenBase):
|
||||
@@ -148,8 +154,12 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase):
|
||||
if self.CDefineDoubleFlags is not None: self.CDefineDoubleFlags.append(0)
|
||||
if self.CDefineStrFlags is not None: self.CDefineStrFlags.append(0)
|
||||
if self.CDefineBits is not None: self.CDefineBits.append(bits)
|
||||
def register_cdefine_double(self, pool: memhub.MemBuddy*, name: str, value: double) -> None:
|
||||
"""Register a float CDefine constant; store the value as %f text and flag it."""
|
||||
def register_cdefine_double(self, pool: memhub.MemBuddy*, name: str, value: double, is_f32: int = 0) -> None:
|
||||
"""Register a float CDefine constant; store the value as %f text and flag it.
|
||||
|
||||
is_f32: 1 表示该常量声明为 32 位 float(`define PI: float = ...` / `float(...)`),
|
||||
物化时直接出 f32 常量;0(默认)表示 double。
|
||||
"""
|
||||
if name is None: return
|
||||
if self.CDefineNames is None:
|
||||
tp: memhub.MemBuddy* = self._cdefine_table_pool(pool)
|
||||
@@ -185,7 +195,10 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase):
|
||||
stdio.snprintf(val_buf, 32, "%.17g", value)
|
||||
self.CDefineValues.append(val_buf)
|
||||
else: self.CDefineValues.append("0")
|
||||
if self.CDefineDoubleFlags is not None: self.CDefineDoubleFlags.append(1)
|
||||
# 浮点宽度种类:f32=2,f64=1(判定处一律 `!= 0`,故与旧数据兼容)。
|
||||
if self.CDefineDoubleFlags is not None:
|
||||
if is_f32 != 0: self.CDefineDoubleFlags.append(CDEFINE_FLOAT_KIND_F32)
|
||||
else: self.CDefineDoubleFlags.append(CDEFINE_FLOAT_KIND_F64)
|
||||
if self.CDefineStrFlags is not None: self.CDefineStrFlags.append(0)
|
||||
if self.CDefineBits is not None: self.CDefineBits.append(0)
|
||||
# fail-fast: a failed CDefine value buffer must abort compilation
|
||||
@@ -241,7 +254,11 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase):
|
||||
self.CDefineFound = 1
|
||||
# Cross-module CDefine lookup cache (PermPool-allocated, reused across files)
|
||||
def register_xmod_cdefine(self, name: str, value_str: str, is_double: int, is_str: int) -> None:
|
||||
"""Cache a cross-module CDefine lookup result in the perm_pool global cache."""
|
||||
"""Cache a cross-module CDefine lookup result in the perm_pool global cache.
|
||||
|
||||
is_double 沿用 CDefineDoubleFlags 的编码(1=f64,2=f32,0=非浮点),
|
||||
这样跨模块读取 float 声明的常量时也能保持 f32。
|
||||
"""
|
||||
if name is None or value_str is None: return
|
||||
# Dedupe: skip if cached (first lookup wins; CDefines are globally unique)
|
||||
if self.XmodCdefNames is not None:
|
||||
@@ -285,7 +302,8 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase):
|
||||
if val_str is not None:
|
||||
self.CDefineFound = 1
|
||||
if self.XmodCdefStrFlags is not None and self.XmodCdefStrFlags.get(i) == 1: self.CDefineIsStr = 1
|
||||
elif self.XmodCdefDoubleFlags is not None and self.XmodCdefDoubleFlags.get(i) == 1: self.CDefineIsDouble = 1
|
||||
elif self.XmodCdefDoubleFlags is not None and self.XmodCdefDoubleFlags.get(i) != 0:
|
||||
self.CDefineIsDouble = int(self.XmodCdefDoubleFlags.get(i))
|
||||
return val_str
|
||||
return None
|
||||
def lookup_cdefine_constant(self, name: str) -> int64:
|
||||
@@ -316,8 +334,9 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase):
|
||||
# callers should use lookup_cdefine_string instead.
|
||||
self.CDefineIsStr = 1
|
||||
return 0
|
||||
if self.CDefineDoubleFlags is not None and self.CDefineDoubleFlags.get(i) == 1:
|
||||
self.CDefineIsDouble = 1
|
||||
if self.CDefineDoubleFlags is not None and self.CDefineDoubleFlags.get(i) != 0:
|
||||
# 浮点常量(f64=1 / f32=2):把种类原样带给 is_cdefine_double()/is_cdefine_float32()
|
||||
self.CDefineIsDouble = int(self.CDefineDoubleFlags.get(i))
|
||||
return string.atoll(val_str)
|
||||
return string.atoll(val_str)
|
||||
return 0
|
||||
@@ -368,8 +387,9 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase):
|
||||
if self.CDefineStrFlags is not None and self.CDefineStrFlags.get(i) == 1:
|
||||
self.CDefineIsStr = 1
|
||||
return 0.0
|
||||
if self.CDefineDoubleFlags is not None and self.CDefineDoubleFlags.get(i) == 1:
|
||||
self.CDefineIsDouble = 1
|
||||
if self.CDefineDoubleFlags is not None and self.CDefineDoubleFlags.get(i) != 0:
|
||||
# 种类原样带回(1=f64 / 2=f32),物化处据此决定出 f64 还是 f32 常量。
|
||||
self.CDefineIsDouble = int(self.CDefineDoubleFlags.get(i))
|
||||
ret_d: double = string.atof(val_str)
|
||||
return ret_d
|
||||
ret_i2: double = double(string.atoll(val_str))
|
||||
@@ -409,6 +429,18 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase):
|
||||
def is_cdefine_double(self) -> int:
|
||||
"""Whether the last CDefine hit was a float constant."""
|
||||
return self.CDefineIsDouble
|
||||
def is_cdefine_float32(self) -> int:
|
||||
"""Whether the last CDefine hit was an f32 (`float`) constant; 0 = f64/非浮点。
|
||||
|
||||
物化浮点常量时必须先看本函数:`define PI: float = ...` 要直接出 f32 常量,
|
||||
否则与 f32 字面量混算会被提升成 double(现场:33 处 cvtss2sd)。
|
||||
"""
|
||||
if self.CDefineIsDouble == CDEFINE_FLOAT_KIND_F32: return 1
|
||||
return 0
|
||||
def xmod_float_kind(self) -> int:
|
||||
"""跨模块缓存写入用的浮点种类(1=f64 / 2=f32):把编码留在本模块,写入方不必跨模块引用 define。"""
|
||||
if self.CDefineIsDouble == CDEFINE_FLOAT_KIND_F32: return CDEFINE_FLOAT_KIND_F32
|
||||
return CDEFINE_FLOAT_KIND_F64
|
||||
def is_cdefine_found(self) -> int:
|
||||
"""Whether the last CDefine lookup found a value."""
|
||||
return self.CDefineFound
|
||||
|
||||
@@ -571,7 +571,8 @@ def ReplBaselineCapture() -> int:
|
||||
if val is None: continue
|
||||
kind: int = 0
|
||||
if cdef_str is not None and int(cdef_str.get(i)) == 1: kind = 2
|
||||
elif cdef_dbl is not None and int(cdef_dbl.get(i)) == 1: kind = 1
|
||||
# 浮点条目:1=f64 / 2=f32(见 TypeGenCDef 的 CDEFINE_FLOAT_KIND_*),非 0 即浮点
|
||||
elif cdef_dbl is not None and int(cdef_dbl.get(i)) != 0: kind = 1
|
||||
nc: str = _repl_str_dup(_perm_pool, nm)
|
||||
vc: str = _repl_str_dup(_perm_pool, val)
|
||||
if nc is None or vc is None: continue
|
||||
|
||||
Reference in new issue
Block a user