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