feat(gen): range 边界与循环变量统一提升到至少 i32(取消 u8/u16 循环变量档),u64 边界保持 i64

This commit is contained in:
TermiNexus committed 2026-10-12 20:57:12 +08:00
1 parent 00bf7ebf38
commit ea2af739dd
1 file changed
+22 -4
+22 -4
View File
@@ -1115,8 +1115,28 @@ novirtual class StmtGenCifMixin:
skc_r: ast.Constant* = ast.Constant*(step_arg_node)
if skc_r.int_val < 0: step_neg_const = 1
# 3.5 loop-var storage width follows range arg type (u64→i64 / u16→i16 / u8→i8 / else i32);
# a fixed i32 alloca truncates uint64 bounds. Applies only to undeclared loop vars.
# 3.4 range 边界统一提升到**至少 i32**(仿 C 整数提升):i8/i16 边界不再以窄位宽参与比较
# 与自增。拓宽方向由 coerce_to_type → should_zext_widen 决定:非负 define 常量是**无符号
# 位模式**(Debugger/define-constants.md §7.2),必须 zext(define N = 50000 → 16 位 0xC350
# → 50000,而非 sext 成 -15536)。u64 边界保持 i64(不动,避免截断)。
if stop_val is not None and stop_val.Ty is not None:
sb_p4: int = self.Gen.ExprGenBase.get_llvm_type_bits(stop_val.Ty)
if sb_p4 != 0 and sb_p4 < 32:
nd_s4: ast.AST* = args.get(0)
if arg_count >= 2: nd_s4 = args.get(1)
stop_val = self.Gen.ExprGenBase.coerce_to_type(builder, stop_val, i32_ty, nd_s4, trans)
if start_val is not None and start_val.Ty is not None:
sa_p4: int = self.Gen.ExprGenBase.get_llvm_type_bits(start_val.Ty)
if sa_p4 != 0 and sa_p4 < 32:
start_val = self.Gen.ExprGenBase.coerce_to_type(builder, start_val, i32_ty, args.get(0), trans)
if step_val is not None and step_val.Ty is not None:
sp_p4: int = self.Gen.ExprGenBase.get_llvm_type_bits(step_val.Ty)
if sp_p4 != 0 and sp_p4 < 32:
step_val = self.Gen.ExprGenBase.coerce_to_type(builder, step_val, i32_ty, args.get(2), trans)
# 3.5 loop-var storage width: 边界已提升到 ≥i32,所以只有 i64 边界需要 i64 循环变量,
# 其余一律 i32(不再有 u16→i16 / u8→i8 档:窄位宽循环变量会把边界截断)。
# Applies only to undeclared loop vars.
loop_store_ty: mlirlite.LLVMType* = i32_ty
range_arg_bits: int = 0
if arg_count == 1:
@@ -1128,8 +1148,6 @@ novirtual class StmtGenCifMixin:
if stop_val is not None and stop_val.Ty is not None: stop_bits_rt = self.Gen.ExprGenBase.get_llvm_type_bits(stop_val.Ty)
range_arg_bits = start_bits_rt if start_bits_rt > stop_bits_rt else stop_bits_rt
if range_arg_bits == 64: loop_store_ty = mlirlite.Int64(pool)
elif range_arg_bits == 16: loop_store_ty = mlirlite.Int16(pool)
elif range_arg_bits == 8: loop_store_ty = mlirlite.Int8(pool)
# 3.6 loop unsignedness: an unsigned loop-var annotation or any unsigned range bound uses
# icmp ult/ugt instead of slt/sgt (via ExprGenOps._node_type_unsigned).