From 9d02cc468467418b565c772dc115a920ce9cfdc4 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 12 Oct 2026 18:42:54 +0800 Subject: [PATCH] =?UTF-8?q?fix(gen):=20=E7=A7=BB=E4=BD=8D=E6=8C=89=20C=20?= =?UTF-8?q?=E8=AF=AD=E4=B9=89=E6=8A=8A=E5=B7=A6=E6=93=8D=E4=BD=9C=E6=95=B0?= =?UTF-8?q?=E6=8F=90=E5=8D=87=E5=88=B0=20int=EF=BC=8C=E4=B8=94=E7=A7=BB?= =?UTF-8?q?=E4=BD=8D=E6=95=B0=E4=B8=8D=E5=8F=82=E4=B8=8E=E5=B8=B8=E9=87=8F?= =?UTF-8?q?=E9=80=82=E9=85=8D=EF=BC=88=E4=BF=AE=20uchar<<8=20=E8=AF=AF?= =?UTF-8?q?=E6=8A=A5=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/lib/core/Gen/Expr/ExprGenOps.vp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/App/lib/core/Gen/Expr/ExprGenOps.vp b/App/lib/core/Gen/Expr/ExprGenOps.vp index a875a3e..7ad7513 100644 --- a/App/lib/core/Gen/Expr/ExprGenOps.vp +++ b/App/lib/core/Gen/Expr/ExprGenOps.vp @@ -1229,14 +1229,28 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): lhs_bits = 32 rhs_bits = 32 + # 移位:C 语义先按**左操作数**做整数提升到 int(与右操作数宽度无关)。 + # 否则 `uchar(x) << 8`(8 位左操作数 + 32 位计数字面量)在下面等宽化里若被“常量适配”改了方向, + # 会误报「移位数 8 >= 左操作数位宽 8」。 + if (op == ast.OpKind.LShift or op == ast.OpKind.RShift) and lhs_bits != 0 and lhs_bits < 32: + i32_ty_sh: mlirlite.LLVMType* = mlirlite.Int32(pool) + sh_probe: mlirlite.Value* = mlirlite.const_int32(pool, 0) + if self.should_zext_widen(pool, lhs, sh_probe, lhs_node, trans) != 0: lhs = mlirlite.build_zext(builder, lhs, i32_ty_sh) + else: lhs = self.coerce_to_type(builder, lhs, i32_ty_sh, node, trans) + lhs_bits = 32 + + # 移位运算的右操作数是「移位数」,其宽度不参与结果类型判定(C 语义:左操作数提升到 int 即可)。 + is_shift_op: int = 0 + if op == ast.OpKind.LShift or op == ast.OpKind.RShift: is_shift_op = 1 + if lhs_bits > rhs_bits: # 宽侧是「值能无损落进窄侧」的编译期常量时,把**常量**降到窄侧类型(C 语义:常量优先适配另一侧), # 否则 `crc(u32) ^ 0xFFFFFFFF(i64)` 会把 crc 抬成 64 位,结果再赋回 32 位时报隐式窄化。 - if self._const_fits_int_type(lhs, rhs.Ty) != 0: lhs = self.coerce_to_type(builder, lhs, rhs.Ty, node, trans) + if is_shift_op == 0 and self._const_fits_int_type(lhs, rhs.Ty) != 0: lhs = self.coerce_to_type(builder, lhs, rhs.Ty, node, trans) elif self.should_zext_widen(pool, rhs, lhs, rhs_node, trans) != 0: rhs = mlirlite.build_zext(builder, rhs, lhs.Ty) else: rhs = self.coerce_to_type(builder, rhs, lhs.Ty, node, trans) elif rhs_bits > lhs_bits: - if self._const_fits_int_type(rhs, lhs.Ty) != 0: rhs = self.coerce_to_type(builder, rhs, lhs.Ty, node, trans) + if is_shift_op == 0 and self._const_fits_int_type(rhs, lhs.Ty) != 0: rhs = self.coerce_to_type(builder, rhs, lhs.Ty, node, trans) elif self.should_zext_widen(pool, lhs, rhs, lhs_node, trans) != 0: lhs = mlirlite.build_zext(builder, lhs, rhs.Ty) else: lhs = self.coerce_to_type(builder, lhs, rhs.Ty, node, trans)