From e3743b185f126f2f555bb4220f60be2f3d779284 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 12 Oct 2026 20:24:50 +0800 Subject: [PATCH] =?UTF-8?q?fix(gen):=20zip/enumerate=20=E7=9A=84=20range?= =?UTF-8?q?=20=E6=BA=90=E5=B7=A5=E4=BD=9C=E4=BD=8D=E5=AE=BD=E9=9A=8F?= =?UTF-8?q?=E5=8F=82=E6=95=B0=EF=BC=88=E4=BB=BF=20for-range=EF=BC=89?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=20range(3)=20=E8=A2=AB=20i64=20=E7=B4=A2?= =?UTF-8?q?=E5=BC=95=E8=AF=AF=E5=88=A4=E7=AA=84=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/lib/core/Gen/Stmt/StmtGenCifMixin.vp | 116 ++++++++++++++++------- 1 file changed, 82 insertions(+), 34 deletions(-) diff --git a/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp b/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp index 320e43b..7e76834 100644 --- a/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp +++ b/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp @@ -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)