类方法拆 Mixin: - ForHandleBase(HandlesBase.Mixin):__init__ + 公共工具 (_extract_tuple_names/_seq_kind/_build_seq_loop) - ForHandleIter(ForHandleBase):8 个 _handle_* 迭代 helper - ForHandle(ForHandleBase, ForHandleIter):保留 Handle 主分派 + 常量/ _g_gen/NewForHandle 委托;self 调用按 1 级父类解析(Handle→Iter、 Iter→Base 均直接父类) StmtGenCifMixin 仍以 HandlesFor.ForHandle 实例化/引用,类名不变
395 lines
21 KiB
Plaintext
395 lines
21 KiB
Plaintext
import t, c
|
||
from stdint import *
|
||
import ast
|
||
import llvmlite
|
||
import memhub
|
||
import string
|
||
import stdio
|
||
import viperlib
|
||
import lib.core.Handles.HandlesBase as HandlesBase
|
||
import lib.core.Handles.HandlesTranslator as HT
|
||
import lib.core.Handles.HandlesVar as HandlesVar
|
||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||
import lib.core.Handles.HandlesBody as HandlesBody
|
||
import lib.core.Handles.HandlesType as HandlesType
|
||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||
import lib.core.Handles.ExprCallBase as ExprCallBase
|
||
|
||
|
||
# ============================================================
|
||
# ForHandleBase - HandlesFor 拆分(阶段 E):ForHandleBase
|
||
#
|
||
# 类方法拆 Mixin:self 调用按 1 级父类解析(TPV 限制)。
|
||
# @t.NoVTable:静态绑定。
|
||
# ============================================================
|
||
@t.NoVTable
|
||
class ForHandleBase(HandlesBase.Mixin):
|
||
"""ForHandleBase"""
|
||
|
||
def __init__(self, trans: HT.Translator | t.CPtr):
|
||
self.Trans = trans
|
||
# ============================================================
|
||
# 多变量迭代(enumerate / zip)
|
||
#
|
||
# 支持迭代源: range(start, stop, step) / 字符串(常量|变量) / list[T]
|
||
# enumerate(x) → for i, v in enumerate(x):i 为序号,v 为元素
|
||
# zip(a, b) → for x, y in zip(a, b):任一源耗尽即终止
|
||
# ============================================================
|
||
|
||
def _extract_tuple_names(self, tup: ast.Tuple | t.CPtr,
|
||
out1: str | t.CPtr, out2: str | t.CPtr) -> int:
|
||
"""从 Tuple target 提取前两个 Name 变量名,写入 out1/out2,成功返回 1"""
|
||
if tup is None or tup.elts is None or out1 is None or out2 is None:
|
||
return 0
|
||
elts: list[ast.AST | t.CPtr] | t.CPtr = tup.elts
|
||
n: t.CSizeT = len(elts)
|
||
if n < 2:
|
||
return 0
|
||
e0: ast.AST | t.CPtr = elts.get(0)
|
||
e1: ast.AST | t.CPtr = elts.get(1)
|
||
if e0 is None or e1 is None:
|
||
return 0
|
||
if e0.kind() != ast.ASTKind.Name or e1.kind() != ast.ASTKind.Name:
|
||
return 0
|
||
n0: ast.Name | t.CPtr = (ast.Name | t.CPtr)(e0)
|
||
n1: ast.Name | t.CPtr = (ast.Name | t.CPtr)(e1)
|
||
if n0.id is None or n1.id is None:
|
||
return 0
|
||
string.strcpy(out1, n0.id)
|
||
string.strcpy(out2, n1.id)
|
||
return 1
|
||
def _seq_kind(self, src: ast.AST | t.CPtr) -> int:
|
||
"""判断迭代源类型: SEQ_KIND_RANGE / STR / LIST,不支持返回 0"""
|
||
if src is None:
|
||
return 0
|
||
k: int = src.kind()
|
||
if k == ast.ASTKind.Call:
|
||
cl_s: ast.Call | t.CPtr = (ast.Call | t.CPtr)(src)
|
||
fn_s: str = HandlesExpr.get_func_name(cl_s.func)
|
||
if fn_s is not None and string.strcmp(fn_s, "range") == 0:
|
||
return SEQ_KIND_RANGE
|
||
return 0
|
||
if k == ast.ASTKind.Constant:
|
||
cn_s: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(src)
|
||
if cn_s is not None and cn_s.const_kind == ast.CONST_STR:
|
||
return SEQ_KIND_STR
|
||
return 0
|
||
if k == ast.ASTKind.Name:
|
||
nm_s: ast.Name | t.CPtr = (ast.Name | t.CPtr)(src)
|
||
if nm_s.id is not None and self.Trans is not None:
|
||
ve_s: HandlesVar.VarEntry | t.CPtr = HandlesVar.lookup_var_entry(
|
||
self.Trans.SymTab, nm_s.id)
|
||
if ve_s is not None and ve_s.AnnotClassName is not None:
|
||
if string.strstr(ve_s.AnnotClassName, "list") is not None:
|
||
return SEQ_KIND_LIST
|
||
return SEQ_KIND_STR
|
||
return 0
|
||
def _build_seq_loop(self, for_node: ast.For | t.CPtr,
|
||
t1: str, t2: str,
|
||
src1: ast.AST | t.CPtr,
|
||
src2: ast.AST | t.CPtr,
|
||
n_srcs: int) -> int:
|
||
"""生成序列迭代循环(enumerate: n_srcs=1 / zip: n_srcs=2)
|
||
|
||
循环变量 alloca 自动创建或复用;元素类型由源类型决定
|
||
(RANGE→i32, STR→i8, LIST→i8*)。索引内部统一 i64。
|
||
"""
|
||
trans: HT.Translator | t.CPtr = self.Trans
|
||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||
func: llvmlite.Function | t.CPtr = trans._cur_func
|
||
|
||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool)
|
||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||
|
||
# ---- 源 1 准备 ----
|
||
kind1: int = self._seq_kind(src1)
|
||
if kind1 == 0:
|
||
HandlesType.fatal_error(for_node, "序列迭代: 源 1 类型不支持")
|
||
r1_start: llvmlite.Value | t.CPtr = None
|
||
r1_stop: llvmlite.Value | t.CPtr = None
|
||
r1_step: llvmlite.Value | t.CPtr = None
|
||
s1_ptr: llvmlite.Value | t.CPtr = None
|
||
l1_count: llvmlite.Value | t.CPtr = None
|
||
l1_data: llvmlite.Value | t.CPtr = None
|
||
l1_esize: llvmlite.Value | t.CPtr = None
|
||
elem1_ty: llvmlite.LLVMType | t.CPtr = i8_ptr_ty
|
||
if kind1 == SEQ_KIND_RANGE:
|
||
elem1_ty = i32_ty
|
||
r1_start = llvmlite.const_int64(pool, 0)
|
||
r1_step = llvmlite.const_int64(pool, 1)
|
||
r1_stop = llvmlite.const_int64(pool, 0)
|
||
# 先赋中间变量再取 args(cast 链式属性访问会推断错字段偏移)
|
||
call_src1: ast.Call | t.CPtr = (ast.Call | t.CPtr)(src1)
|
||
cargs1: list[ast.AST | t.CPtr] | t.CPtr = call_src1.args
|
||
if cargs1 is not None:
|
||
n1: t.CSizeT = len(cargs1)
|
||
if n1 >= 1:
|
||
sv: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, cargs1.get(0),
|
||
trans._funcs, trans._func_count, trans)
|
||
if sv is None:
|
||
# fail-fast: range 参数翻译失败
|
||
HandlesType.fatal_error(cargs1.get(0), "range 参数翻译失败", "TypeError")
|
||
r1_stop = HandlesExpr.coerce_to_type(builder, sv, i64_ty, cargs1.get(0))
|
||
if n1 >= 2:
|
||
sv2: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, cargs1.get(1),
|
||
trans._funcs, trans._func_count, trans)
|
||
if sv2 is None:
|
||
# fail-fast: range 参数翻译失败
|
||
HandlesType.fatal_error(cargs1.get(1), "range 参数翻译失败", "TypeError")
|
||
r1_start = HandlesExpr.coerce_to_type(builder, sv2, i64_ty, cargs1.get(1))
|
||
if n1 >= 3:
|
||
sv3: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, cargs1.get(2),
|
||
trans._funcs, trans._func_count, trans)
|
||
if sv3 is None:
|
||
# fail-fast: range 参数翻译失败
|
||
HandlesType.fatal_error(cargs1.get(2), "range 参数翻译失败", "TypeError")
|
||
r1_step = HandlesExpr.coerce_to_type(builder, sv3, i64_ty, cargs1.get(2))
|
||
elif kind1 == SEQ_KIND_STR:
|
||
elem1_ty = i8_ty
|
||
s1_ptr = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, src1,
|
||
trans._funcs, trans._func_count, trans)
|
||
if s1_ptr is None:
|
||
HandlesType.fatal_error(for_node, "序列迭代: 字符串源翻译失败")
|
||
elif kind1 == SEQ_KIND_LIST:
|
||
elem1_ty = i8_ptr_ty
|
||
l1_obj: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, src1,
|
||
trans._funcs, trans._func_count, trans)
|
||
if l1_obj is None or l1_obj.Ty is None \
|
||
or HandlesExpr.is_ptr_type(l1_obj.Ty) == 0:
|
||
HandlesType.fatal_error(for_node, "序列迭代: list 源不是指针类型")
|
||
l1_count = llvmlite.build_load(builder, i64_ty,
|
||
llvmlite.build_gep(builder, i64_ty, l1_obj, llvmlite.const_int64(pool, 1)))
|
||
l1_data = llvmlite.build_load(builder, i8_ptr_ty,
|
||
llvmlite.build_gep(builder, i64_ty, l1_obj, llvmlite.const_int64(pool, 0)))
|
||
l1_esize = llvmlite.build_load(builder, i64_ty,
|
||
llvmlite.build_gep(builder, i64_ty, l1_obj, llvmlite.const_int64(pool, 4)))
|
||
|
||
# ---- 源 2 准备(zip)----
|
||
kind2: int = 0
|
||
elem2_ty: llvmlite.LLVMType | t.CPtr = elem1_ty
|
||
s2_ptr: llvmlite.Value | t.CPtr = None
|
||
l2_count: llvmlite.Value | t.CPtr = None
|
||
l2_data: llvmlite.Value | t.CPtr = None
|
||
l2_esize: llvmlite.Value | t.CPtr = None
|
||
r2_start: llvmlite.Value | t.CPtr = None
|
||
r2_stop: llvmlite.Value | t.CPtr = None
|
||
r2_step: llvmlite.Value | t.CPtr = None
|
||
if n_srcs >= 2:
|
||
kind2 = self._seq_kind(src2)
|
||
if kind2 == 0:
|
||
HandlesType.fatal_error(for_node, "序列迭代: 源 2 类型不支持")
|
||
if kind2 == SEQ_KIND_RANGE:
|
||
elem2_ty = i32_ty
|
||
r2_start = llvmlite.const_int64(pool, 0)
|
||
r2_step = llvmlite.const_int64(pool, 1)
|
||
r2_stop = llvmlite.const_int64(pool, 0)
|
||
# 先赋中间变量再取 args(cast 链式属性访问会推断错字段偏移)
|
||
call_src2: ast.Call | t.CPtr = (ast.Call | t.CPtr)(src2)
|
||
cargs2: list[ast.AST | t.CPtr] | t.CPtr = call_src2.args
|
||
if cargs2 is not None:
|
||
n2: t.CSizeT = len(cargs2)
|
||
if n2 >= 1:
|
||
svz: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, cargs2.get(0),
|
||
trans._funcs, trans._func_count, trans)
|
||
if svz is None:
|
||
# fail-fast: range 参数翻译失败
|
||
HandlesType.fatal_error(cargs2.get(0), "range 参数翻译失败", "TypeError")
|
||
r2_stop = HandlesExpr.coerce_to_type(builder, svz, i64_ty, cargs2.get(0))
|
||
if n2 >= 2:
|
||
svz2: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, cargs2.get(1),
|
||
trans._funcs, trans._func_count, trans)
|
||
if svz2 is None:
|
||
# fail-fast: range 参数翻译失败
|
||
HandlesType.fatal_error(cargs2.get(1), "range 参数翻译失败", "TypeError")
|
||
r2_start = HandlesExpr.coerce_to_type(builder, svz2, i64_ty, cargs2.get(1))
|
||
if n2 >= 3:
|
||
svz3: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, cargs2.get(2),
|
||
trans._funcs, trans._func_count, trans)
|
||
if svz3 is None:
|
||
# fail-fast: range 参数翻译失败
|
||
HandlesType.fatal_error(cargs2.get(2), "range 参数翻译失败", "TypeError")
|
||
r2_step = HandlesExpr.coerce_to_type(builder, svz3, i64_ty, cargs2.get(2))
|
||
elif kind2 == SEQ_KIND_STR:
|
||
elem2_ty = i8_ty
|
||
s2_ptr = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, src2,
|
||
trans._funcs, trans._func_count, trans)
|
||
if s2_ptr is None:
|
||
HandlesType.fatal_error(for_node, "序列迭代: 字符串源 2 翻译失败")
|
||
elif kind2 == SEQ_KIND_LIST:
|
||
elem2_ty = i8_ptr_ty
|
||
l2_obj: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, src2,
|
||
trans._funcs, trans._func_count, trans)
|
||
if l2_obj is None or l2_obj.Ty is None \
|
||
or HandlesExpr.is_ptr_type(l2_obj.Ty) == 0:
|
||
HandlesType.fatal_error(for_node, "序列迭代: list 源 2 不是指针类型")
|
||
l2_count = llvmlite.build_load(builder, i64_ty,
|
||
llvmlite.build_gep(builder, i64_ty, l2_obj, llvmlite.const_int64(pool, 1)))
|
||
l2_data = llvmlite.build_load(builder, i8_ptr_ty,
|
||
llvmlite.build_gep(builder, i64_ty, l2_obj, llvmlite.const_int64(pool, 0)))
|
||
l2_esize = llvmlite.build_load(builder, i64_ty,
|
||
llvmlite.build_gep(builder, i64_ty, l2_obj, llvmlite.const_int64(pool, 4)))
|
||
|
||
# ---- 循环变量 alloca ----
|
||
# t1: enumerate → 序号 (i32);zip → 源 1 元素
|
||
t1_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, t1)
|
||
new_vars: int = 0
|
||
if t1_alloca is None:
|
||
if n_srcs == 1:
|
||
t1_alloca = HandlesVar._alloca_at_entry(builder, i32_ty)
|
||
else:
|
||
t1_alloca = HandlesVar._alloca_at_entry(builder, elem1_ty)
|
||
if t1_alloca is not None:
|
||
if HandlesVar.define_var(trans.SymTab, t1, t1_alloca) == 0:
|
||
new_vars += 1
|
||
# t2: 源 2 元素(enumerate 时 = 源 1 元素)
|
||
t2_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, t2)
|
||
if t2_alloca is None:
|
||
t2_alloca = HandlesVar._alloca_at_entry(builder, elem2_ty)
|
||
if t2_alloca is not None:
|
||
if HandlesVar.define_var(trans.SymTab, t2, t2_alloca) == 0:
|
||
new_vars += 1
|
||
|
||
# 隐式 index 变量 (i64)
|
||
idx_alloca: llvmlite.Value | t.CPtr = HandlesVar._alloca_at_entry(builder, i64_ty)
|
||
llvmlite.build_store(builder, llvmlite.const_int64(pool, 0), idx_alloca)
|
||
|
||
# 基本块: cond / body / incr / end
|
||
cnt: int = trans._label_counter
|
||
trans._label_counter = cnt + 1
|
||
|
||
name_buf: str = pool.alloc(32)
|
||
viperlib.snprintf(name_buf, 32, "seq.cond.%d", cnt)
|
||
cond_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
viperlib.snprintf(name_buf, 32, "seq.body.%d", cnt)
|
||
body_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
viperlib.snprintf(name_buf, 32, "seq.incr.%d", cnt)
|
||
incr_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
viperlib.snprintf(name_buf, 32, "seq.end.%d", cnt)
|
||
end_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
llvmlite.build_br(builder, cond_bb)
|
||
|
||
# cond 块: 源 1 done 检查(zip 需源 2 也 done)
|
||
llvmlite.position_at_end(builder, cond_bb)
|
||
cur_idx: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i64_ty, idx_alloca)
|
||
done1: llvmlite.Value | t.CPtr = None
|
||
if kind1 == SEQ_KIND_RANGE:
|
||
done1 = llvmlite.build_icmp(builder, llvmlite.ICMP_SLT, cur_idx, r1_stop)
|
||
elif kind1 == SEQ_KIND_STR:
|
||
ch_ptr1: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i8_ty, s1_ptr, cur_idx)
|
||
ch1: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ty, ch_ptr1)
|
||
zero1: llvmlite.Value | t.CPtr = llvmlite.const_int(pool, 8, 0)
|
||
done1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, ch1, zero1)
|
||
elif kind1 == SEQ_KIND_LIST:
|
||
done1 = llvmlite.build_icmp(builder, llvmlite.ICMP_SLT, cur_idx, l1_count)
|
||
cont: llvmlite.Value | t.CPtr = done1
|
||
if n_srcs >= 2:
|
||
done2: llvmlite.Value | t.CPtr = None
|
||
if kind2 == SEQ_KIND_RANGE:
|
||
done2 = llvmlite.build_icmp(builder, llvmlite.ICMP_SLT, cur_idx, r2_stop)
|
||
elif kind2 == SEQ_KIND_STR:
|
||
ch_ptr2: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i8_ty, s2_ptr, cur_idx)
|
||
ch2: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ty, ch_ptr2)
|
||
zero2: llvmlite.Value | t.CPtr = llvmlite.const_int(pool, 8, 0)
|
||
done2 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, ch2, zero2)
|
||
elif kind2 == SEQ_KIND_LIST:
|
||
done2 = llvmlite.build_icmp(builder, llvmlite.ICMP_SLT, cur_idx, l2_count)
|
||
cont = llvmlite.build_and(builder, done1, done2)
|
||
llvmlite.build_cond_br(builder, cont, body_bb, end_bb)
|
||
|
||
# body 块: 获取元素 → store → 循环体
|
||
llvmlite.position_at_end(builder, body_bb)
|
||
# 源 1 元素
|
||
v1: llvmlite.Value | t.CPtr = None
|
||
if kind1 == SEQ_KIND_RANGE:
|
||
step1: llvmlite.Value | t.CPtr = llvmlite.build_mul(builder, cur_idx, r1_step)
|
||
v1 = llvmlite.build_add(builder, r1_start, step1)
|
||
elif kind1 == SEQ_KIND_STR:
|
||
ch_ptr1b: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i8_ty, s1_ptr, cur_idx)
|
||
v1 = llvmlite.build_load(builder, i8_ty, ch_ptr1b)
|
||
elif kind1 == SEQ_KIND_LIST:
|
||
off1: llvmlite.Value | t.CPtr = llvmlite.build_mul(builder, cur_idx, l1_esize)
|
||
addr1: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i8_ty, l1_data, off1)
|
||
v1 = llvmlite.build_load(builder, i8_ptr_ty, addr1)
|
||
# store t1 / t2
|
||
if t1_alloca is not None and t1_alloca.Ty is not None:
|
||
t1_ty: llvmlite.LLVMType | t.CPtr = t1_alloca.Ty.Pointee
|
||
if n_srcs == 1:
|
||
# enumerate: t1 = 序号(trunc i64 → i32)
|
||
idx32: llvmlite.Value | t.CPtr = llvmlite.build_trunc(builder, cur_idx, i32_ty)
|
||
llvmlite.build_store(builder, idx32, t1_alloca)
|
||
if t2_alloca is not None and t2_alloca.Ty is not None and v1 is not None:
|
||
t2_ty: llvmlite.LLVMType | t.CPtr = t2_alloca.Ty.Pointee
|
||
v1c: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type(builder, v1, t2_ty, src1)
|
||
llvmlite.build_store(builder, v1c, t2_alloca)
|
||
else:
|
||
if v1 is not None:
|
||
v1c: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type(builder, v1, t1_ty, src1)
|
||
llvmlite.build_store(builder, v1c, t1_alloca)
|
||
# 源 2 元素 → t2
|
||
v2: llvmlite.Value | t.CPtr = None
|
||
if kind2 == SEQ_KIND_RANGE:
|
||
step2: llvmlite.Value | t.CPtr = llvmlite.build_mul(builder, cur_idx, r2_step)
|
||
v2 = llvmlite.build_add(builder, r2_start, step2)
|
||
elif kind2 == SEQ_KIND_STR:
|
||
ch_ptr2b: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i8_ty, s2_ptr, cur_idx)
|
||
v2 = llvmlite.build_load(builder, i8_ty, ch_ptr2b)
|
||
elif kind2 == SEQ_KIND_LIST:
|
||
off2: llvmlite.Value | t.CPtr = llvmlite.build_mul(builder, cur_idx, l2_esize)
|
||
addr2: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i8_ty, l2_data, off2)
|
||
v2 = llvmlite.build_load(builder, i8_ptr_ty, addr2)
|
||
if t2_alloca is not None and t2_alloca.Ty is not None and v2 is not None:
|
||
t2_ty2: llvmlite.LLVMType | t.CPtr = t2_alloca.Ty.Pointee
|
||
v2c: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type(builder, v2, t2_ty2, src2)
|
||
llvmlite.build_store(builder, v2c, t2_alloca)
|
||
|
||
# 保存旧循环上下文,设置 break/continue 目标
|
||
old_break: llvmlite.BasicBlock | t.CPtr = trans._break_bb
|
||
old_continue: llvmlite.BasicBlock | t.CPtr = trans._continue_bb
|
||
trans._break_bb = end_bb
|
||
trans._continue_bb = incr_bb
|
||
|
||
body: list[ast.AST | t.CPtr] | t.CPtr = for_node.children
|
||
if body is not None:
|
||
body_count: t.CSizeT = len(body)
|
||
for bi in range(body_count):
|
||
stmt: ast.AST | t.CPtr = body.get(bi)
|
||
if stmt is not None:
|
||
HandlesBody.translate_stmt(trans, stmt)
|
||
|
||
trans._break_bb = old_break
|
||
trans._continue_bb = old_continue
|
||
|
||
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
|
||
llvmlite.build_br(builder, incr_bb)
|
||
|
||
# incr 块: index++
|
||
llvmlite.position_at_end(builder, incr_bb)
|
||
one_val: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, 1)
|
||
next_idx: llvmlite.Value | t.CPtr = llvmlite.build_add(builder, cur_idx, one_val)
|
||
llvmlite.build_store(builder, next_idx, idx_alloca)
|
||
llvmlite.build_br(builder, cond_bb)
|
||
|
||
# 定位到 end 块
|
||
llvmlite.position_at_end(builder, end_bb)
|
||
# 追加90:for 循环正常结束路径 br 到 end_bb → merge 恒可达(需正常收尾)
|
||
trans._ctrl_merge_reachable = 1
|
||
return new_vars
|