From 939f7f2497fe21e50322814450f02254713ba81d Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 8 Aug 2026 21:35:58 +0800 Subject: [PATCH] =?UTF-8?q?fix(llvmlite):=20ConstFloat=20=E6=B5=AE?= =?UTF-8?q?=E7=82=B9=E5=B8=B8=E9=87=8F=E6=96=87=E6=9C=AC=E6=94=B9=E5=8D=81?= =?UTF-8?q?=E5=85=AD=E8=BF=9B=E5=88=B6=E4=BD=8D=E6=A8=A1=E5=BC=8F(0x%016ll?= =?UTF-8?q?x/0x%08x),=20=E6=B6=88=E9=99=A4=20llc=20=E7=A7=91=E5=AD=A6?= =?UTF-8?q?=E8=AE=A1=E6=95=B0=E6=B3=95=E8=A7=A3=E6=9E=90=20=C2=B11=20ulp?= =?UTF-8?q?=20=E8=AF=AF=E5=B7=AE(11.0=20=E8=A7=A3=E6=9E=90=E4=B8=BA=2011.0?= =?UTF-8?q?00000000000002);=20vipermath=20modf=20=E7=94=A8=E5=9B=9E=20c.Se?= =?UTF-8?q?t(c.Deref())=20=E5=90=8C=E6=AD=A5=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- includes/llvmlite/__values.vp | 22 +++++++++++++++------- includes/vipermath.vp | 2 ++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/includes/llvmlite/__values.vp b/includes/llvmlite/__values.vp index a2767b0..96fe07f 100644 --- a/includes/llvmlite/__values.vp +++ b/includes/llvmlite/__values.vp @@ -96,16 +96,24 @@ def ConstFloat(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr, v.IsConst = 1 v.FloatVal = val v.IntVal = 0 - # 格式化名字: LLVM IR 浮点常量文本 - # 必须用 %.17e 保证 double 精度(17 位小数)且恒为科学计数法(带小数点), - # LLVM 语法要求浮点常量不能是裸整数(%.17g 对 1.0 输出 "1" 会报 - # "integer constant must have integer type")。原 %e 默认仅 6 位小数, - # 常量被截断(3.1415926535897931 -> "3.141593e+00",llc 解析后值错, - # 导致浮点 CDefine/字面量生成错误 LLVM 值,llc 报 ret i32 0)。 + # 格式化名字: LLVM IR 浮点常量文本用十六进制位模式(0x%016llx / 0x%08x) + # 原因: %.17e 科学计数法文本经 llc 解析对部分值产生 ±1 ulp 误差 + # (如 "1.10000000000000000e+01" 解析为 11.000000000000002 而非 11.0, + # 导致 add_scalar[0]==11 等浮点常量比较失败)。位模式无精度损失。 + # 原 %e 默认 6 位小数还会截断精度(3.1415926535897931 -> 3.141593e+00)。 # 用 CRT stdio.snprintf: viperlib 自实现 %g 有小数位反转 bug。 + f_bits: t.CInt = 64 + match ty: + case llvmlite.LLVMType.Float(ftb): + f_bits = ftb + fv_bits: t.CUInt64T = 0 + c.Load(c.Addr(fv_bits), c.Addr(val)) name_buf: t.CChar | t.CPtr = pool.alloc(32) if name_buf is not None: - stdio.snprintf(name_buf, 32, "%.17e", val) + if f_bits == 32: + stdio.snprintf(name_buf, 32, "0x%08x", t.CUInt32T(fv_bits)) + else: + stdio.snprintf(name_buf, 32, "0x%016llx", fv_bits) v.Name = name_buf return v diff --git a/includes/vipermath.vp b/includes/vipermath.vp index bf38b32..b121af1 100644 --- a/includes/vipermath.vp +++ b/includes/vipermath.vp @@ -377,6 +377,8 @@ def fmodf(x: float, y: float) -> float: def modf(x: t.CDouble, iptr: t.CDouble | t.CPtr) -> t.CDouble: int_part: t.CDouble = floor(x) + # c.Set(a, b) = a = b:a 为 c.Deref(iptr) 左值表达式 → *iptr = int_part + # TPV 的 c.Deref 立即 load 返回右值,故 c.Set 需识别 Deref 左值形态(translate_c_set 形态 1) c.Set(c.Deref(iptr), int_part) return x - int_part