类方法拆 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 实例化/引用,类名不变
449 lines
22 KiB
Plaintext
449 lines
22 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.ForHandleBase as ForHandleBase
|
||
import lib.core.Handles.ForHandleIter as ForHandleIter
|
||
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
|
||
|
||
|
||
# ============================================================
|
||
# HandlesFor - for 循环语句处理(P6 对象化后的委托层)
|
||
#
|
||
# NewForHandle 工厂已迁移为 lib.core.Gen.StmtGenMixin 的方法
|
||
# (ForHandle 类保留:trans.ForH 的类型,由 HandlesTranslator.
|
||
# _init_state 经 NewForHandle 委托创建)。
|
||
#
|
||
# 支持 for i in range(start, stop, step) 模式:
|
||
# %i = alloca i32
|
||
# store i32 start, i32* %i
|
||
# br label %cond
|
||
# cond:
|
||
# %cur = load i32, i32* %i
|
||
# %cmp = icmp slt i32 %cur, stop
|
||
# br i1 %cmp, label %body, label %end
|
||
# body:
|
||
# ... body ...
|
||
# br label %incr
|
||
# incr:
|
||
# %cur2 = load i32, i32* %i
|
||
# %next = add i32 %cur2, step
|
||
# store i32 %next, i32* %i
|
||
# br label %cond
|
||
# end:
|
||
# ============================================================
|
||
|
||
|
||
# ============================================================
|
||
# 全局 gen 单例(模块级镜像,同 HandlesStruct 模式)
|
||
#
|
||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||
# 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||
# StmtGenMixin 方法,避免函数体 import 包模块与类/模块名歧义。
|
||
# ============================================================
|
||
_g_gen: t.CVoid | t.CPtr = None
|
||
|
||
|
||
# ============================================================
|
||
# 序列迭代源类型码(for x in ... / enumerate / zip 迭代源分类)
|
||
# RANGE: range(start, stop, step)
|
||
# STR: 字符串(常量或 str 变量)
|
||
# LIST: list[T] 容器(按 __count__ + __data__ 迭代)
|
||
# ============================================================
|
||
SEQ_KIND_RANGE: t.CDefine = 1
|
||
SEQ_KIND_STR: t.CDefine = 2
|
||
SEQ_KIND_LIST: t.CDefine = 3
|
||
|
||
|
||
def set_global_gen(gen: t.CVoid | t.CPtr) -> None:
|
||
"""注入全局 gen 单例(BuildPipeline/main 调用)"""
|
||
global _g_gen
|
||
_g_gen = gen
|
||
|
||
|
||
@t.NoVTable
|
||
class ForHandle(ForHandleBase.ForHandleBase, ForHandleIter.ForHandleIter):
|
||
"""for 循环语句处理器:继承 Mixin 获得 Trans 回指针"""
|
||
|
||
|
||
# ============================================================
|
||
# Handle - 处理 for 语句,返回新增变量数
|
||
# ============================================================
|
||
def Handle(self, node: ast.AST | t.CPtr) -> int:
|
||
"""翻译 for i in range(...) 循环语句"""
|
||
if node is None:
|
||
return 0
|
||
|
||
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
|
||
|
||
if builder is None or func is None:
|
||
return 0
|
||
|
||
for_node: ast.For | t.CPtr = (ast.For | t.CPtr)(node)
|
||
|
||
# 1. 获取循环变量(Name 单变量 / Tuple 多变量)
|
||
target: ast.AST | t.CPtr = for_node.target
|
||
if target is None:
|
||
return 0
|
||
tk: int = target.kind()
|
||
if tk != ast.ASTKind.Name and tk != ast.ASTKind.Tuple:
|
||
return 0
|
||
var_name: str = None
|
||
if tk == ast.ASTKind.Name:
|
||
target_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(target)
|
||
var_name = target_nm.id
|
||
if var_name is None:
|
||
return 0
|
||
|
||
# 2. 解析迭代器:支持 range() 和指针迭代
|
||
iter_node: ast.AST | t.CPtr = for_node.iter
|
||
if iter_node is None:
|
||
return 0
|
||
|
||
# 检查是否是 range() 调用
|
||
is_range_iter: int = 0
|
||
if iter_node.kind() == ast.ASTKind.Call:
|
||
call_pre: ast.Call | t.CPtr = (ast.Call | t.CPtr)(iter_node)
|
||
fn_pre: str = HandlesExpr.get_func_name(call_pre.func)
|
||
if fn_pre is not None:
|
||
if string.strcmp(fn_pre, "range") == 0:
|
||
is_range_iter = 1
|
||
elif string.strcmp(fn_pre, "enumerate") == 0 or string.strcmp(fn_pre, "zip") == 0:
|
||
pass # 多变量迭代,在下方非 range 分支处理
|
||
else:
|
||
err_msg: str = pool.alloc(256)
|
||
if err_msg is not None:
|
||
viperlib.snprintf(err_msg, 256, "仅支持 range()/enumerate()/zip() 或指针迭代,got call '%s'", fn_pre)
|
||
HandlesType.fatal_error(iter_node, err_msg)
|
||
HandlesType.fatal_error(iter_node, "仅支持 range()/enumerate()/zip() 或指针迭代")
|
||
|
||
# 非范围迭代:走指针/数组/列表字面量/容器/多变量迭代路径
|
||
if is_range_iter == 0:
|
||
# 列表字面量:按元素顺序迭代(for x in [1, 2, 3])
|
||
if iter_node.kind() == ast.ASTKind.List:
|
||
return self._handle_list_literal_iter(for_node, var_name, iter_node)
|
||
# enumerate(x):for i, v in enumerate(x)(多变量迭代)
|
||
if iter_node.kind() == ast.ASTKind.Call:
|
||
call_mi: ast.Call | t.CPtr = (ast.Call | t.CPtr)(iter_node)
|
||
fn_mi: str = HandlesExpr.get_func_name(call_mi.func)
|
||
if fn_mi is not None and string.strcmp(fn_mi, "enumerate") == 0:
|
||
if tk != ast.ASTKind.Tuple:
|
||
HandlesType.fatal_error(iter_node, "enumerate 迭代需要两个循环变量 (for i, v in enumerate(x))")
|
||
tup_ie: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(target)
|
||
t1_buf_ie: bytes = pool.alloc(128)
|
||
t2_buf_ie: bytes = pool.alloc(128)
|
||
if t1_buf_ie is None or t2_buf_ie is None:
|
||
return 0
|
||
t1_buf_ie[0] = '\0'
|
||
t2_buf_ie[0] = '\0'
|
||
if self._extract_tuple_names(tup_ie, t1_buf_ie, t2_buf_ie) == 0:
|
||
HandlesType.fatal_error(iter_node, "enumerate 迭代变量必须是简单名称")
|
||
return self._handle_enumerate_iter(for_node, t1_buf_ie, t2_buf_ie, call_mi)
|
||
if fn_mi is not None and string.strcmp(fn_mi, "zip") == 0:
|
||
if tk != ast.ASTKind.Tuple:
|
||
HandlesType.fatal_error(iter_node, "zip 迭代需要两个循环变量 (for a, b in zip(...))")
|
||
tup_iz: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(target)
|
||
t1_buf_iz: bytes = pool.alloc(128)
|
||
t2_buf_iz: bytes = pool.alloc(128)
|
||
if t1_buf_iz is None or t2_buf_iz is None:
|
||
return 0
|
||
t1_buf_iz[0] = '\0'
|
||
t2_buf_iz[0] = '\0'
|
||
if self._extract_tuple_names(tup_iz, t1_buf_iz, t2_buf_iz) == 0:
|
||
HandlesType.fatal_error(iter_node, "zip 迭代变量必须是简单名称")
|
||
return self._handle_zip_iter(for_node, t1_buf_iz, t2_buf_iz, call_mi)
|
||
# list[T] 容器变量:按 __count__ 动态长度迭代
|
||
if iter_node.kind() == ast.ASTKind.Name and trans is not None:
|
||
nm_lst: ast.Name | t.CPtr = (ast.Name | t.CPtr)(iter_node)
|
||
if nm_lst.id is not None:
|
||
ve_lst: HandlesVar.VarEntry | t.CPtr = HandlesVar.lookup_var_entry(
|
||
trans.SymTab, nm_lst.id)
|
||
if ve_lst is not None and ve_lst.AnnotClassName is not None:
|
||
# dict 容器变量:按 __count__/__keys__ 布局迭代(__iter__ 协议内联)
|
||
if string.strstr(ve_lst.AnnotClassName, "dict") is not None:
|
||
lst_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, iter_node,
|
||
trans._funcs, trans._func_count, trans)
|
||
if lst_val is not None and lst_val.Ty is not None \
|
||
and HandlesExpr.is_ptr_type(lst_val.Ty) != 0:
|
||
return self._handle_dict_iter(for_node, var_name, lst_val)
|
||
if string.strstr(ve_lst.AnnotClassName, "list") is not None:
|
||
lst_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, iter_node,
|
||
trans._funcs, trans._func_count, trans)
|
||
if lst_val is not None and lst_val.Ty is not None \
|
||
and HandlesExpr.is_ptr_type(lst_val.Ty) != 0:
|
||
return self._handle_list_iter(for_node, var_name, lst_val)
|
||
# OOP iter 协议:迭代源是类对象且类有 __iter__/__next__ 方法 →
|
||
# 走 __iter__/__next__ 调用迭代(对齐 TPC HandlesFor.py L142-166
|
||
# _HandleForIterLlvm)。dict/list 是内置泛型容器已在上方内联处理。
|
||
ov_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, iter_node,
|
||
trans._funcs, trans._func_count, trans)
|
||
if ov_val is not None and ov_val.Ty is not None \
|
||
and HandlesExpr.is_ptr_type(ov_val.Ty) != 0:
|
||
ov_st: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type_from_value(
|
||
ov_val)
|
||
if ov_st is not None:
|
||
ov_cn: str = HandlesStruct.get_class_name_by_type(pool, ov_st)
|
||
if ov_cn is not None:
|
||
oi_lookup: str = pool.alloc(128)
|
||
if oi_lookup is not None:
|
||
viperlib.snprintf(oi_lookup, 128, "%s.__iter__", ov_cn)
|
||
oi_fn: llvmlite.Function | t.CPtr = ExprCallBase.find_func_in_module(
|
||
trans.Module, oi_lookup)
|
||
if oi_fn is not None:
|
||
on_lookup: str = pool.alloc(128)
|
||
if on_lookup is not None:
|
||
viperlib.snprintf(on_lookup, 128, "%s.__next__", ov_cn)
|
||
on_fn: llvmlite.Function | t.CPtr = ExprCallBase.find_func_in_module(
|
||
trans.Module, on_lookup)
|
||
if on_fn is not None:
|
||
return self._handle_oop_iter(
|
||
for_node, var_name, ov_cn, ov_val)
|
||
# 其它不支持的字面量:fast-fail 显式报错,
|
||
# 避免 translate_value 触发 list[T] 特化崩溃或语义歧义。
|
||
ik: int = iter_node.kind()
|
||
if ik == ast.ASTKind.Constant:
|
||
cn_ik: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(iter_node)
|
||
if cn_ik.const_kind != ast.CONST_STR:
|
||
HandlesType.fatal_error(
|
||
iter_node,
|
||
"for 迭代不支持该常量(仅支持字符串、数组、列表字面量、range())")
|
||
elif ik == ast.ASTKind.Dict or ik == ast.ASTKind.Set or ik == ast.ASTKind.Tuple \
|
||
or ik == ast.ASTKind.SetComp or ik == ast.ASTKind.DictComp:
|
||
HandlesType.fatal_error(
|
||
iter_node,
|
||
"for 迭代不支持字典/集合/元组字面量,请使用 range()、t.CArray 数组或列表字面量")
|
||
return self._handle_ptr_iter(for_node, var_name)
|
||
|
||
call: ast.Call | t.CPtr = (ast.Call | t.CPtr)(iter_node)
|
||
|
||
# 3. 解析 range 参数: range(stop) / range(start, stop) / range(start, stop, step)
|
||
args: list[ast.AST | t.CPtr] | t.CPtr = call.args
|
||
if args is None:
|
||
return 0
|
||
arg_count: t.CSizeT = len(args)
|
||
|
||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
start_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
|
||
stop_val: llvmlite.Value | t.CPtr = None
|
||
step_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 1)
|
||
|
||
if arg_count == 0:
|
||
# fail-fast: range 无参数,立即终止
|
||
HandlesType.fatal_error(call, "range 需要至少一个参数", "SyntaxError")
|
||
elif arg_count == 1:
|
||
stop_val = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, args.get(0),
|
||
trans._funcs, trans._func_count, trans)
|
||
if stop_val is None:
|
||
# fail-fast: range 参数翻译失败
|
||
HandlesType.fatal_error(args.get(0), "range 参数翻译失败", "TypeError")
|
||
elif arg_count >= 2:
|
||
start_val = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, args.get(0),
|
||
trans._funcs, trans._func_count, trans)
|
||
if start_val is None:
|
||
# fail-fast: range 参数翻译失败
|
||
HandlesType.fatal_error(args.get(0), "range 参数翻译失败", "TypeError")
|
||
stop_val = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, args.get(1),
|
||
trans._funcs, trans._func_count, trans)
|
||
if stop_val is None:
|
||
# fail-fast: range 参数翻译失败
|
||
HandlesType.fatal_error(args.get(1), "range 参数翻译失败", "TypeError")
|
||
if arg_count >= 3:
|
||
step_val = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, args.get(2),
|
||
trans._funcs, trans._func_count, trans)
|
||
if step_val is None:
|
||
# fail-fast: range 参数翻译失败
|
||
HandlesType.fatal_error(args.get(2), "range 参数翻译失败", "TypeError")
|
||
# step 为负数字面量时循环条件反转(对齐 TPC HandlesFor.py L86-94):
|
||
# range(a, b, -1) → i > stop;range(a, b, +1) → i < stop。
|
||
# TPC 仅识别负数字面量(UnaryOp USub 常量 / 负常量);变量 step 保守按正。
|
||
# 修复 _find_provider 的 range(top-1, -1, -1) 循环体不执行(i < -1 恒假)。
|
||
step_neg_const: int = 0
|
||
if arg_count >= 3:
|
||
step_arg_node: ast.AST | t.CPtr = args.get(2)
|
||
if step_arg_node is not None:
|
||
skn: int = step_arg_node.kind()
|
||
if skn == ast.ASTKind.UnaryOp:
|
||
uop_r: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(step_arg_node)
|
||
if uop_r.op == ast.OpKind.USub and uop_r.operand is not None:
|
||
if uop_r.operand.kind() == ast.ASTKind.Constant:
|
||
uoc_r: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(uop_r.operand)
|
||
if uoc_r.int_val > 0:
|
||
step_neg_const = 1
|
||
elif skn == ast.ASTKind.Constant:
|
||
skc_r: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(step_arg_node)
|
||
if skc_r.int_val < 0:
|
||
step_neg_const = 1
|
||
|
||
# 4. 创建/查找循环变量 alloca
|
||
var_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(
|
||
trans.SymTab, var_name)
|
||
new_vars: int = 0
|
||
if var_alloca is None:
|
||
var_alloca = HandlesVar._alloca_at_entry(builder, i32_ty)
|
||
if HandlesVar.define_var(
|
||
trans.SymTab, var_name, var_alloca) == 0:
|
||
new_vars = 1
|
||
|
||
# 获取循环变量的实际元素类型(alloca 是指针类型,需解引用 Pointee)
|
||
# 当循环变量已声明为 i64(如 t.CSizeT),使用 i64 而非硬编码 i32
|
||
# 避免 load i32, i64* / store i32, i64* 类型不匹配
|
||
loop_var_ty: llvmlite.LLVMType | t.CPtr = i32_ty
|
||
if var_alloca is not None and var_alloca.Ty is not None:
|
||
match var_alloca.Ty:
|
||
case llvmlite.LLVMType.Ptr(pointee_ty):
|
||
if pointee_ty is not None:
|
||
loop_var_ty = pointee_ty
|
||
loop_var_bits: int = HandlesExpr.get_llvm_type_bits(loop_var_ty)
|
||
|
||
# 5. 存储初始值 (类型对齐: start_val 可能是 i32/i64,需对齐到 loop_var_ty)
|
||
init_val: llvmlite.Value | t.CPtr = start_val
|
||
if start_val is not None and start_val.Ty is not None:
|
||
start_bits: int = HandlesExpr.get_llvm_type_bits(start_val.Ty)
|
||
if start_bits != 0 and start_bits != loop_var_bits:
|
||
if start_bits < loop_var_bits:
|
||
init_val = llvmlite.build_sext(builder, start_val, loop_var_ty)
|
||
else:
|
||
init_val = llvmlite.build_trunc(builder, start_val, loop_var_ty)
|
||
llvmlite.build_store(builder, init_val, var_alloca)
|
||
|
||
# 6. 创建基本块: cond / body / incr / end(使用 trans._label_counter,不与 SSA 名共享)
|
||
cnt: int = trans._label_counter
|
||
trans._label_counter = cnt + 1
|
||
|
||
name_buf: str = pool.alloc(32)
|
||
viperlib.snprintf(name_buf, 32, "for.cond.%d", cnt)
|
||
cond_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
viperlib.snprintf(name_buf, 32, "for.body.%d", cnt)
|
||
body_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
viperlib.snprintf(name_buf, 32, "for.incr.%d", cnt)
|
||
incr_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
viperlib.snprintf(name_buf, 32, "for.end.%d", cnt)
|
||
end_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
# 7. 跳转到 cond 块
|
||
llvmlite.build_br(builder, cond_bb)
|
||
|
||
# 8. cond 块: load i, icmp slt i, stop, cond_br body/end
|
||
llvmlite.position_at_end(builder, cond_bb)
|
||
cur_i: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, loop_var_ty, var_alloca)
|
||
# 类型对齐: stop_val 可能是 i64 (如 range(strlen(s))),需将 cur_i 提升到 stop_val 类型
|
||
cmp_lhs: llvmlite.Value | t.CPtr = cur_i
|
||
cmp_rhs: llvmlite.Value | t.CPtr = stop_val
|
||
if stop_val is not None and stop_val.Ty is not None:
|
||
stop_bits: int = HandlesExpr.get_llvm_type_bits(stop_val.Ty)
|
||
cur_bits: int = HandlesExpr.get_llvm_type_bits(cur_i.Ty)
|
||
if stop_bits != 0 and cur_bits != 0 and stop_bits != cur_bits:
|
||
if cur_bits < stop_bits:
|
||
cmp_lhs = llvmlite.build_sext(builder, cur_i, stop_val.Ty)
|
||
else:
|
||
# 循环变量位宽 > stop 位宽(如 t.CSizeT 循环变量 + range(i32)):
|
||
# 应把 cur_i 截断到 stop_val 类型(低向高才 sext/zext,高向低用
|
||
# trunc)。原实现反了——把小的 stop_val trunc 到大的 loop_var_ty,
|
||
# 生成 `trunc i32 to i64` 扩宽非法 IR,llc 报
|
||
# "invalid cast opcode for cast from 'i32' to 'i64'"
|
||
# (VpiReader.vp range(arg_count) 追加86 根因)。
|
||
cmp_lhs = llvmlite.build_trunc(builder, cur_i, stop_val.Ty)
|
||
# step 为负时条件反转:i > stop(ICMP_SGT);正/缺省 step 保持 i < stop
|
||
range_cmp_op: int = llvmlite.ICMP_SLT
|
||
if step_neg_const != 0:
|
||
range_cmp_op = llvmlite.ICMP_SGT
|
||
cond_i1: llvmlite.Value | t.CPtr = llvmlite.build_icmp(
|
||
builder, range_cmp_op, cmp_lhs, cmp_rhs)
|
||
llvmlite.build_cond_br(builder, cond_i1, body_bb, end_bb)
|
||
|
||
# 9. body 块: 翻译循环体,跳到 incr
|
||
llvmlite.position_at_end(builder, body_bb)
|
||
|
||
# 保存旧循环上下文,设置 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)
|
||
|
||
# 10. incr 块: i = i + step, 跳回 cond
|
||
llvmlite.position_at_end(builder, incr_bb)
|
||
cur_i2: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, loop_var_ty, var_alloca)
|
||
# 类型对齐: step_val 可能是 i32/i64,需对齐到 loop_var_ty 与 cur_i2 类型一致
|
||
incr_step: llvmlite.Value | t.CPtr = step_val
|
||
if step_val is not None and step_val.Ty is not None:
|
||
step_bits: int = HandlesExpr.get_llvm_type_bits(step_val.Ty)
|
||
cur2_bits: int = HandlesExpr.get_llvm_type_bits(cur_i2.Ty)
|
||
if step_bits != 0 and cur2_bits != 0 and step_bits != cur2_bits:
|
||
if step_bits > cur2_bits:
|
||
incr_step = llvmlite.build_trunc(builder, step_val, loop_var_ty)
|
||
else:
|
||
incr_step = llvmlite.build_sext(builder, step_val, loop_var_ty)
|
||
next_i: llvmlite.Value | t.CPtr = llvmlite.build_add(builder, cur_i2, incr_step)
|
||
llvmlite.build_store(builder, next_i, var_alloca)
|
||
llvmlite.build_br(builder, cond_bb)
|
||
|
||
# 11. 定位到 end 块
|
||
llvmlite.position_at_end(builder, end_bb)
|
||
# 追加90:for 循环正常结束路径 br 到 end_bb → merge 恒可达(需正常收尾)
|
||
trans._ctrl_merge_reachable = 1
|
||
return new_vars
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
# ============================================================
|
||
# NewForHandle - 工厂函数(委托到 gen.NewForHandle)
|
||
# ============================================================
|
||
def NewForHandle(pool: memhub.MemBuddy | t.CPtr,
|
||
trans: HT.Translator | t.CPtr) -> ForHandle | t.CPtr:
|
||
"""创建 ForHandle 实例(委托到 gen.NewForHandle)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g.NewForHandle(pool, trans)
|
||
return None
|