fix(gen): zip/enumerate 的 range 源工作位宽随参数(仿 for-range),修 range(3) 被 i64 索引误判窄化

This commit is contained in:
TermiNexus committed 2026-10-12 20:24:50 +08:00
1 parent 54b239747e
commit e3743b185f
1 file changed
+82 -34
+82 -34
View File
@@ -1325,6 +1325,22 @@ novirtual class StmtGenCifMixin:
return GenTypes.SEQ_KIND_STR
return 0
# _range_work_bits - range 工作位宽:取各已求值参数位宽的最大值,下限 i32(32)。
# 与 `for i in range(...)` 的 loop_store_ty 同口径,避免内部 i64 索引写回 i32 循环变量时误报窄化。
def _range_work_bits(self, a: mlirlite.Value*, b: mlirlite.Value*, c: mlirlite.Value*) -> int:
"""Working integer width for a range() source: max of the provided argument widths, at least 32."""
bits: int = 32
if a is not None and a.Ty is not None:
ab: int = self.Gen.ExprGenBase.get_llvm_type_bits(a.Ty)
if ab > bits: bits = ab
if b is not None and b.Ty is not None:
bb: int = self.Gen.ExprGenBase.get_llvm_type_bits(b.Ty)
if bb > bits: bits = bb
if c is not None and c.Ty is not None:
cb: int = self.Gen.ExprGenBase.get_llvm_type_bits(c.Ty)
if cb > bits: bits = cb
return bits
def _build_seq_loop(self, trans: HT.Translator*, for_node: ast.For*, t1: str, t2: str, src1: ast.AST*, src2: ast.AST*, n_srcs: int) -> int:
"""Build a sequence iteration loop for enumerate (n_srcs=1) or zip (n_srcs=2)."""
pool: memhub.MemBuddy* = trans.Pool
@@ -1347,34 +1363,45 @@ novirtual class StmtGenCifMixin:
l1_data: mlirlite.Value* = None
l1_esize: mlirlite.Value* = None
elem1_ty: mlirlite.LLVMType* = i8_ptr_ty
# range 的工作位宽/类型(随参数位宽,仿 `for i in range(...)`);非 range 源不使用。
r1_wty: mlirlite.LLVMType* = None
r1_bits: int = 0
if kind1 == GenTypes.SEQ_KIND_RANGE:
elem1_ty = i32_ty
r1_start = mlirlite.const_int64(pool, 0)
r1_step = mlirlite.const_int64(pool, 1)
r1_stop = mlirlite.const_int64(pool, 0)
# assign to a temp before taking args (chained cast attrs misinfer field offsets)
# 先求值参数,再由参数位宽决定工作类型:i32 字面量就按 i32 算,
# 避免内部 i64 索引写回 i32 循环变量时触发隐式窄化误报。
call_src1: ast.Call* = ast.Call*(src1)
cargs1: list[ast.AST*]* = call_src1.args
a1: mlirlite.Value* = None
b1: mlirlite.Value* = None
c1: mlirlite.Value* = None
n1: sizet = 0
if cargs1 is not None:
n1: sizet = len(cargs1)
n1 = len(cargs1)
if n1 >= 1:
sv: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs1.get(0), trans._funcs, trans._func_count, trans)
if sv is None:
a1 = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs1.get(0), trans._funcs, trans._func_count, trans)
if a1 is None:
# fail-fast: range argument failed to translate
self.Gen.TypeGenErr.fatal_error(cargs1.get(0), "failed to translate the range argument", "TypeError")
r1_stop = self.Gen.ExprGenBase.coerce_to_type(builder, sv, i64_ty, cargs1.get(0))
if n1 >= 2:
sv2: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs1.get(1), trans._funcs, trans._func_count, trans)
if sv2 is None:
b1 = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs1.get(1), trans._funcs, trans._func_count, trans)
if b1 is None:
# fail-fast: range argument failed to translate
self.Gen.TypeGenErr.fatal_error(cargs1.get(1), "failed to translate the range argument", "TypeError")
r1_start = self.Gen.ExprGenBase.coerce_to_type(builder, sv2, i64_ty, cargs1.get(1))
if n1 >= 3:
sv3: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs1.get(2), trans._funcs, trans._func_count, trans)
if sv3 is None:
c1 = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs1.get(2), trans._funcs, trans._func_count, trans)
if c1 is None:
# fail-fast: range argument failed to translate
self.Gen.TypeGenErr.fatal_error(cargs1.get(2), "failed to translate the range argument", "TypeError")
r1_step = self.Gen.ExprGenBase.coerce_to_type(builder, sv3, i64_ty, cargs1.get(2))
r1_bits = self._range_work_bits(a1, b1, c1)
r1_wty = self.Gen.ExprGenBase._int_type_of_bits(pool, r1_bits)
if r1_wty is None: r1_wty = i32_ty
elem1_ty = r1_wty
r1_start = mlirlite.const_int(pool, r1_bits, 0)
r1_step = mlirlite.const_int(pool, r1_bits, 1)
r1_stop = mlirlite.const_int(pool, r1_bits, 0)
if a1 is not None: r1_stop = self.Gen.ExprGenBase.coerce_to_type(builder, a1, r1_wty, cargs1.get(0))
if b1 is not None: r1_start = self.Gen.ExprGenBase.coerce_to_type(builder, b1, r1_wty, cargs1.get(1))
if c1 is not None: r1_step = self.Gen.ExprGenBase.coerce_to_type(builder, c1, r1_wty, cargs1.get(2))
elif kind1 == GenTypes.SEQ_KIND_STR:
elem1_ty = i8_ty
s1_ptr = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, src1, trans._funcs, trans._func_count, trans)
@@ -1397,37 +1424,47 @@ novirtual class StmtGenCifMixin:
r2_start: mlirlite.Value* = None
r2_stop: mlirlite.Value* = None
r2_step: mlirlite.Value* = None
# range 的工作位宽/类型(source 2 对称处理)。
r2_wty: mlirlite.LLVMType* = None
r2_bits: int = 0
if n_srcs >= 2:
kind2 = self._seq_kind(trans, src2)
if kind2 == 0: self.Gen.TypeGenErr.fatal_error(for_node, "sequence iteration: source 2 type is not supported")
if kind2 == GenTypes.SEQ_KIND_RANGE:
elem2_ty = i32_ty
r2_start = mlirlite.const_int64(pool, 0)
r2_step = mlirlite.const_int64(pool, 1)
r2_stop = mlirlite.const_int64(pool, 0)
# assign to a temp before taking args (chained cast attrs misinfer field offsets)
# 与 source 1 同口径:工作类型随参数位宽,避免 i64 索引写回窄位宽循环变量误报。
call_src2: ast.Call* = ast.Call*(src2)
cargs2: list[ast.AST*]* = call_src2.args
a2: mlirlite.Value* = None
b2: mlirlite.Value* = None
c2: mlirlite.Value* = None
n2: sizet = 0
if cargs2 is not None:
n2: sizet = len(cargs2)
n2 = len(cargs2)
if n2 >= 1:
svz: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs2.get(0), trans._funcs, trans._func_count, trans)
if svz is None:
a2 = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs2.get(0), trans._funcs, trans._func_count, trans)
if a2 is None:
# fail-fast: range argument failed to translate
self.Gen.TypeGenErr.fatal_error(cargs2.get(0), "failed to translate the range argument", "TypeError")
r2_stop = self.Gen.ExprGenBase.coerce_to_type(builder, svz, i64_ty, cargs2.get(0))
if n2 >= 2:
svz2: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs2.get(1), trans._funcs, trans._func_count, trans)
if svz2 is None:
b2 = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs2.get(1), trans._funcs, trans._func_count, trans)
if b2 is None:
# fail-fast: range argument failed to translate
self.Gen.TypeGenErr.fatal_error(cargs2.get(1), "failed to translate the range argument", "TypeError")
r2_start = self.Gen.ExprGenBase.coerce_to_type(builder, svz2, i64_ty, cargs2.get(1))
if n2 >= 3:
svz3: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs2.get(2), trans._funcs, trans._func_count, trans)
if svz3 is None:
c2 = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs2.get(2), trans._funcs, trans._func_count, trans)
if c2 is None:
# fail-fast: range argument failed to translate
self.Gen.TypeGenErr.fatal_error(cargs2.get(2), "failed to translate the range argument", "TypeError")
r2_step = self.Gen.ExprGenBase.coerce_to_type(builder, svz3, i64_ty, cargs2.get(2))
r2_bits = self._range_work_bits(a2, b2, c2)
r2_wty = self.Gen.ExprGenBase._int_type_of_bits(pool, r2_bits)
if r2_wty is None: r2_wty = i32_ty
elem2_ty = r2_wty
r2_start = mlirlite.const_int(pool, r2_bits, 0)
r2_step = mlirlite.const_int(pool, r2_bits, 1)
r2_stop = mlirlite.const_int(pool, r2_bits, 0)
if a2 is not None: r2_stop = self.Gen.ExprGenBase.coerce_to_type(builder, a2, r2_wty, cargs2.get(0))
if b2 is not None: r2_start = self.Gen.ExprGenBase.coerce_to_type(builder, b2, r2_wty, cargs2.get(1))
if c2 is not None: r2_step = self.Gen.ExprGenBase.coerce_to_type(builder, c2, r2_wty, cargs2.get(2))
elif kind2 == GenTypes.SEQ_KIND_STR:
elem2_ty = i8_ty
s2_ptr = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, src2, trans._funcs, trans._func_count, trans)
@@ -1487,7 +1524,11 @@ novirtual class StmtGenCifMixin:
mlirlite.position_at_end(builder, cond_bb)
cur_idx: mlirlite.Value* = mlirlite.build_load(builder, i64_ty, idx_alloca)
done1: mlirlite.Value* = None
if kind1 == GenTypes.SEQ_KIND_RANGE: done1 = mlirlite.build_icmp(builder, mlirlite.ICMP_SLT, cur_idx, r1_stop)
if kind1 == GenTypes.SEQ_KIND_RANGE:
# range 的索引按工作位宽截断后再比较(索引是编译器内部量,不涉及用户窄化)
idx1_cmp: mlirlite.Value* = cur_idx
if r1_bits != 64: idx1_cmp = mlirlite.build_trunc(builder, cur_idx, r1_wty)
done1 = mlirlite.build_icmp(builder, mlirlite.ICMP_SLT, idx1_cmp, r1_stop)
elif kind1 == GenTypes.SEQ_KIND_STR:
ch_ptr1: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, s1_ptr, cur_idx)
ch1: mlirlite.Value* = mlirlite.build_load(builder, i8_ty, ch_ptr1)
@@ -1497,7 +1538,10 @@ novirtual class StmtGenCifMixin:
cont: mlirlite.Value* = done1
if n_srcs >= 2:
done2: mlirlite.Value* = None
if kind2 == GenTypes.SEQ_KIND_RANGE: done2 = mlirlite.build_icmp(builder, mlirlite.ICMP_SLT, cur_idx, r2_stop)
if kind2 == GenTypes.SEQ_KIND_RANGE:
idx2_cmp: mlirlite.Value* = cur_idx
if r2_bits != 64: idx2_cmp = mlirlite.build_trunc(builder, cur_idx, r2_wty)
done2 = mlirlite.build_icmp(builder, mlirlite.ICMP_SLT, idx2_cmp, r2_stop)
elif kind2 == GenTypes.SEQ_KIND_STR:
ch_ptr2: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, s2_ptr, cur_idx)
ch2: mlirlite.Value* = mlirlite.build_load(builder, i8_ty, ch_ptr2)
@@ -1512,7 +1556,9 @@ novirtual class StmtGenCifMixin:
# source-1 element
v1: mlirlite.Value* = None
if kind1 == GenTypes.SEQ_KIND_RANGE:
step1: mlirlite.Value* = mlirlite.build_mul(builder, cur_idx, r1_step)
idx1_b: mlirlite.Value* = cur_idx
if r1_bits != 64: idx1_b = mlirlite.build_trunc(builder, cur_idx, r1_wty)
step1: mlirlite.Value* = mlirlite.build_mul(builder, idx1_b, r1_step)
v1 = mlirlite.build_add(builder, r1_start, step1)
elif kind1 == GenTypes.SEQ_KIND_STR:
ch_ptr1b: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, s1_ptr, cur_idx)
@@ -1539,7 +1585,9 @@ novirtual class StmtGenCifMixin:
# source-2 element → t2
v2: mlirlite.Value* = None
if kind2 == GenTypes.SEQ_KIND_RANGE:
step2: mlirlite.Value* = mlirlite.build_mul(builder, cur_idx, r2_step)
idx2_b: mlirlite.Value* = cur_idx
if r2_bits != 64: idx2_b = mlirlite.build_trunc(builder, cur_idx, r2_wty)
step2: mlirlite.Value* = mlirlite.build_mul(builder, idx2_b, r2_step)
v2 = mlirlite.build_add(builder, r2_start, step2)
elif kind2 == GenTypes.SEQ_KIND_STR:
ch_ptr2b: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, s2_ptr, cur_idx)