diff --git a/App/lib/core/Gen/Call/CallGenCtor.vp b/App/lib/core/Gen/Call/CallGenCtor.vp index 96e13d1..2d72794 100644 --- a/App/lib/core/Gen/Call/CallGenCtor.vp +++ b/App/lib/core/Gen/Call/CallGenCtor.vp @@ -686,6 +686,13 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): return llvmlite.build_zext(builder, val, target_ty) return llvmlite.build_sext(builder, val, target_ty) else: + # 目标 i1(bool / t.CBool):显式强转 `t.CBool(x)` 与隐式落存储 + # **同一判据** —— 真值归一化 `x != 0 → 1/0`(coerce_to_type 的同名 + # 分支、CallGenDispatch 的 bool(x)、条件归一化三处一致),不是 + # trunc(取最低位,会让 x=2 得 false 而 `if 2:` 为真)。 + if target_bits == 1: + zero_tc: llvmlite.Value* = llvmlite.const_int(pool, val_bits, 0) + return llvmlite.build_icmp(builder, llvmlite.ICMP_NE, val, zero_tc) return llvmlite.build_trunc(builder, val, target_ty) # 整数 → 浮点: sitofp diff --git a/App/lib/core/Gen/Expr/ExprGenBase.vp b/App/lib/core/Gen/Expr/ExprGenBase.vp index cf0a29b..c0b944b 100644 --- a/App/lib/core/Gen/Expr/ExprGenBase.vp +++ b/App/lib/core/Gen/Expr/ExprGenBase.vp @@ -865,6 +865,17 @@ novirtual class ExprGenBase: if val_bits != 0 and target_bits != 0: if val_bits == target_bits: return val + # 目标 i1(bool / t.CBool):**真值归一化** `x != 0 → 1/0`(C 6.3.1.2 的 + # _Bool 转换语义),不是 trunc(取最低位)。判据与 `bool(x)` + # (CallGenDispatch.vp:255-281)、条件归一化(AsyncGenMixin.vp:1611 + # _normalize_cond)、and/or 操作数三处**同一**:同一个运行时值 2 在 + # `if 2:` 里为真,赋给 bool 变量/字段/形参必须同样为真。此处此前走 trunc + # ⇒ 值 2 取最低位得 0 → false,与条件上下文结论相反(静默语义分裂); + # 值 3 得 true 而同值域下 `!= 0` 亦为 true,故只在偶数非零时暴露。 + # 归一化不丢位 ⇒ 下方「窄化截断溢出」常量诊断对 i1 目标不适用(先返回)。 + if target_bits == 1: + zero_i1: llvmlite.Value* = llvmlite.const_int(builder.Pool, val_bits, 0) + return llvmlite.build_icmp(builder, llvmlite.ICMP_NE, val, zero_i1) if val_bits < target_bits: # 统一 zext/sext(问题2修正):i1/i8 默认 zext;AST 节点解析为 # 无符号类型(t.CUIntXXT 强转/无符号类型名)走 zext;否则 sext。