类方法拆 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 实例化/引用,类名不变
821 lines
38 KiB
Plaintext
821 lines
38 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
|
||
|
||
|
||
import lib.core.Handles.ForHandleBase as ForHandleBase
|
||
# ============================================================
|
||
# ForHandleIter - HandlesFor 拆分(阶段 E):ForHandleIter
|
||
#
|
||
# 类方法拆 Mixin:self 调用按 1 级父类解析(TPV 限制)。
|
||
# @t.NoVTable:静态绑定。
|
||
# ============================================================
|
||
@t.NoVTable
|
||
class ForHandleIter(ForHandleBase.ForHandleBase):
|
||
"""ForHandleIter"""
|
||
|
||
# ============================================================
|
||
# _handle_ptr_iter - 指针迭代: for x in ptr:
|
||
# 遍历指针,依赖隐式 index,直到解引用为空(null 终止符)
|
||
#
|
||
# 生成 IR 结构:
|
||
# %idx = alloca i32
|
||
# store i32 0, i32* %idx
|
||
# br label %cond
|
||
# cond:
|
||
# %i = load i32, i32* %idx
|
||
# %ep = getelementptr elem_ty, ptr_ty %ptr, i32 %i
|
||
# %ev = load elem_ty, elem_ty* %ep
|
||
# %null = icmp eq elem_ty %ev, 0
|
||
# br i1 %null, label %end, label %body
|
||
# body:
|
||
# store elem_ty %ev, elem_ty* %var
|
||
# ... 循环体 ...
|
||
# br label %incr
|
||
# incr:
|
||
# %next = add i32 %i, 1
|
||
# store i32 %next, i32* %idx
|
||
# br label %cond
|
||
# end:
|
||
# ============================================================
|
||
def _handle_ptr_iter(self, for_node: ast.For | t.CPtr,
|
||
var_name: str) -> int:
|
||
"""指针迭代: for x in ptr: 直到解引用为空"""
|
||
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
|
||
|
||
# 翻译迭代器表达式,获取指针值
|
||
ptr_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, for_node.iter,
|
||
trans._funcs, trans._func_count, trans)
|
||
if ptr_val is None:
|
||
HandlesType.fatal_error(for_node, "指针迭代: 无法翻译迭代器表达式")
|
||
|
||
# 检查迭代器类型
|
||
if HandlesExpr.is_ptr_type(ptr_val.Ty) == 0:
|
||
# 数组迭代:for k in arr(定长数组按长度迭代,元素可为任意类型)
|
||
if HandlesExpr.is_array_type(ptr_val.Ty) != 0:
|
||
return self._handle_array_iter(for_node, var_name, ptr_val)
|
||
HandlesType.fatal_error(for_node, "指针迭代: 迭代器不是指针类型")
|
||
|
||
# 获取元素类型
|
||
elem_ty: llvmlite.LLVMType | t.CPtr = ptr_val.Ty.Pointee
|
||
if elem_ty is None:
|
||
HandlesType.fatal_error(for_node, "指针迭代: 无法获取元素类型")
|
||
|
||
# 元素类型是数组(Ptr([N x T]),如 t.CArray 变量退化指针):
|
||
# load 出数组值后走数组迭代(按长度,非 null 终止)
|
||
if HandlesExpr.is_array_type(elem_ty) != 0:
|
||
arr_v2: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, elem_ty, ptr_val)
|
||
if arr_v2 is not None:
|
||
return self._handle_array_iter(for_node, var_name, arr_v2)
|
||
|
||
# 元素类型必须是整数(用于 icmp eq 0 检查 null 终止符)
|
||
elem_bits: int = HandlesExpr.get_llvm_type_bits(elem_ty)
|
||
if elem_bits == 0:
|
||
HandlesType.fatal_error(for_node, "指针迭代: 元素类型不是整数,无法检查 null 终止符")
|
||
|
||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
|
||
# 创建循环变量 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, elem_ty)
|
||
if HandlesVar.define_var(
|
||
trans.SymTab, var_name, var_alloca) == 0:
|
||
new_vars = 1
|
||
|
||
# 创建隐式 index 变量,初始为 0
|
||
idx_alloca: llvmlite.Value | t.CPtr = HandlesVar._alloca_at_entry(builder, i32_ty)
|
||
llvmlite.build_store(builder, llvmlite.const_int32(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, "ptr.cond.%d", cnt)
|
||
cond_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
viperlib.snprintf(name_buf, 32, "ptr.body.%d", cnt)
|
||
body_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
viperlib.snprintf(name_buf, 32, "ptr.incr.%d", cnt)
|
||
incr_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
viperlib.snprintf(name_buf, 32, "ptr.end.%d", cnt)
|
||
end_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
# 跳转到 cond
|
||
llvmlite.build_br(builder, cond_bb)
|
||
|
||
# cond 块: load index, GEP, load elem, icmp eq 0
|
||
llvmlite.position_at_end(builder, cond_bb)
|
||
cur_idx: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i32_ty, idx_alloca)
|
||
elem_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep(
|
||
builder, elem_ty, ptr_val, cur_idx)
|
||
cur_elem: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, elem_ty, elem_ptr)
|
||
null_val: llvmlite.Value | t.CPtr = llvmlite.const_int(pool, elem_bits, 0)
|
||
is_null: llvmlite.Value | t.CPtr = llvmlite.build_icmp(
|
||
builder, llvmlite.ICMP_EQ, cur_elem, null_val)
|
||
llvmlite.build_cond_br(builder, is_null, end_bb, body_bb)
|
||
|
||
# body 块: store elem to var, 翻译循环体
|
||
llvmlite.position_at_end(builder, body_bb)
|
||
llvmlite.build_store(builder, cur_elem, var_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++, br cond
|
||
llvmlite.position_at_end(builder, incr_bb)
|
||
one_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(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
|
||
# ============================================================
|
||
# _handle_array_iter - 数组迭代: for x in arr:
|
||
# 定长数组按长度迭代(元素可为任意类型,不做 null 终止符检查)
|
||
#
|
||
# 数组值是数组类型而非指针(如局部 t.CArray 修复后),
|
||
# 先拷到临时 alloca 获得地址,再按 [0, N) 迭代。
|
||
#
|
||
# 生成 IR 结构:
|
||
# %tmp = alloca [N x elem_ty]
|
||
# store [N x elem_ty] %arr_val, [N x elem_ty]* %tmp
|
||
# %idx = alloca i32 ; store 0
|
||
# br %cond
|
||
# cond:
|
||
# %i = load i32, i32* %idx
|
||
# %c = icmp slt i32 %i, N
|
||
# br i1 %c, %body, %end
|
||
# body:
|
||
# %ep = getelementptr [N x elem_ty], [N x elem_ty]* %tmp, i32 0, i32 %i
|
||
# %ev = load elem_ty, elem_ty* %ep
|
||
# store elem_ty %ev, elem_ty* %var
|
||
# ... 循环体 ...
|
||
# br %incr
|
||
# incr:
|
||
# %n = add i32 %i, 1 ; store %n ; br %cond
|
||
# end:
|
||
# ============================================================
|
||
def _handle_array_iter(self, for_node: ast.For | t.CPtr,
|
||
var_name: str,
|
||
array_val: llvmlite.Value | t.CPtr) -> int:
|
||
"""数组迭代: for x in arr: 按数组长度迭代"""
|
||
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
|
||
|
||
# 解析数组类型 [N x elem_ty]
|
||
arr_ty: llvmlite.LLVMType | t.CPtr = array_val.Ty
|
||
elem_ty: llvmlite.LLVMType | t.CPtr = None
|
||
elem_count: int = 0
|
||
match arr_ty:
|
||
case llvmlite.LLVMType.Array(et, n):
|
||
elem_ty = et
|
||
elem_count = n
|
||
if elem_ty is None or elem_count <= 0:
|
||
HandlesType.fatal_error(for_node, "数组迭代: 无法解析数组类型")
|
||
|
||
# 数组值 → 临时 alloca(数组值不是指针,需拷贝后 GEP 迭代)
|
||
arr_tmp: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, arr_ty)
|
||
if arr_tmp is None:
|
||
HandlesType.fatal_error(for_node, "数组迭代: 临时存储分配失败")
|
||
llvmlite.build_store(builder, array_val, arr_tmp)
|
||
|
||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
|
||
# 循环变量 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, elem_ty)
|
||
if HandlesVar.define_var(
|
||
trans.SymTab, var_name, var_alloca) == 0:
|
||
new_vars = 1
|
||
|
||
# 隐式 index 变量,初始为 0
|
||
idx_alloca: llvmlite.Value | t.CPtr = HandlesVar._alloca_at_entry(builder, i32_ty)
|
||
llvmlite.build_store(builder, llvmlite.const_int32(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, "arr.cond.%d", cnt)
|
||
cond_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
viperlib.snprintf(name_buf, 32, "arr.body.%d", cnt)
|
||
body_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
viperlib.snprintf(name_buf, 32, "arr.incr.%d", cnt)
|
||
incr_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
viperlib.snprintf(name_buf, 32, "arr.end.%d", cnt)
|
||
end_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
llvmlite.build_br(builder, cond_bb)
|
||
|
||
# cond 块: load index, icmp slt idx, elem_count
|
||
llvmlite.position_at_end(builder, cond_bb)
|
||
cur_idx: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i32_ty, idx_alloca)
|
||
count_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, elem_count)
|
||
in_bounds: llvmlite.Value | t.CPtr = llvmlite.build_icmp(
|
||
builder, llvmlite.ICMP_SLT, cur_idx, count_val)
|
||
llvmlite.build_cond_br(builder, in_bounds, body_bb, end_bb)
|
||
|
||
# body 块: GEP(0, idx) → load elem → store to var → 循环体
|
||
llvmlite.position_at_end(builder, body_bb)
|
||
elem_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_array(
|
||
builder, arr_ty, elem_ty, arr_tmp, cur_idx)
|
||
cur_elem: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, elem_ty, elem_ptr)
|
||
llvmlite.build_store(builder, cur_elem, var_alloca)
|
||
|
||
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_int32(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
|
||
# ============================================================
|
||
# _handle_list_literal_iter - 列表字面量迭代: for x in [a, b, c]:
|
||
# 把列表字面量转成定长数组值,再复用数组迭代(按长度迭代)。
|
||
#
|
||
# 元素类型取第一个元素的值类型,其余元素 coerce 到该类型。
|
||
# ============================================================
|
||
def _handle_list_literal_iter(self, for_node: ast.For | t.CPtr,
|
||
var_name: str,
|
||
list_node: ast.AST | t.CPtr) -> int:
|
||
"""列表字面量迭代: for x in [a, b, c]: 按元素顺序迭代"""
|
||
trans: HT.Translator | t.CPtr = self.Trans
|
||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||
|
||
lst: ast.List | t.CPtr = (ast.List | t.CPtr)(list_node)
|
||
if lst is None or lst.elts is None:
|
||
HandlesType.fatal_error(for_node, "列表字面量迭代: 空列表")
|
||
elts: list[ast.AST | t.CPtr] | t.CPtr = lst.elts
|
||
elts_count: t.CSizeT = len(elts)
|
||
if elts_count <= 0:
|
||
HandlesType.fatal_error(for_node, "列表字面量迭代: 空列表")
|
||
|
||
# 翻译第一个元素,确定元素类型
|
||
first_el: ast.AST | t.CPtr = elts.get(0)
|
||
first_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, first_el,
|
||
trans._funcs, trans._func_count, trans)
|
||
if first_val is None or first_val.Ty is None:
|
||
HandlesType.fatal_error(first_el, "列表字面量迭代: 无法确定元素类型")
|
||
elem_ty: llvmlite.LLVMType | t.CPtr = first_val.Ty
|
||
|
||
# 构建 [N x elem_ty] 数组值:临时 alloca 逐元素写入后 load
|
||
arr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Array(pool, elem_ty, elts_count)
|
||
tmp_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, arr_ty)
|
||
if tmp_alloca is None:
|
||
HandlesType.fatal_error(for_node, "列表字面量迭代: 临时数组分配失败")
|
||
first_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_array(
|
||
builder, arr_ty, elem_ty, tmp_alloca, llvmlite.const_int32(pool, 0))
|
||
if first_ptr is not None:
|
||
llvmlite.build_store(builder, first_val, first_ptr)
|
||
# 写其余元素(coerce 到 elem_ty)
|
||
i: t.CSizeT = 1
|
||
while i < elts_count:
|
||
el_node: ast.AST | t.CPtr = elts.get(i)
|
||
el_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, trans.Module, el_node,
|
||
trans._funcs, trans._func_count, trans)
|
||
if el_val is not None:
|
||
el_val = HandlesExpr.coerce_to_type(builder, el_val, elem_ty, el_node)
|
||
el_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_array(
|
||
builder, arr_ty, elem_ty, tmp_alloca,
|
||
llvmlite.const_int32(pool, i))
|
||
if el_ptr is not None:
|
||
llvmlite.build_store(builder, el_val, el_ptr)
|
||
i += 1
|
||
# load 回数组值,复用数组迭代
|
||
arr_val: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, arr_ty, tmp_alloca)
|
||
if arr_val is None:
|
||
HandlesType.fatal_error(for_node, "列表字面量迭代: 数组加载失败")
|
||
return self._handle_array_iter(for_node, var_name, arr_val)
|
||
# ============================================================
|
||
# _handle_list_iter - list[T] 容器迭代: for v in lst:
|
||
# 按 __count__ 动态长度迭代(元素任意类型,不做 null 终止符检查)
|
||
#
|
||
# list 结构布局 (6 字段 × 8 字节):
|
||
# __data__(0) __count__(8) __capacity__(16) __pool__(24)
|
||
# __elem_size__(32) __iter_index__(40)
|
||
#
|
||
# 生成 IR 结构:
|
||
# %count = load __count__
|
||
# %idx = alloca i64 ; store 0
|
||
# br %cond
|
||
# cond:
|
||
# %i = load i64, %idx
|
||
# %c = icmp slt i64 %i, %count
|
||
# br i1 %c, %body, %end
|
||
# body:
|
||
# %data = load __data__ (i8*)
|
||
# %es = load __elem_size__ (i64)
|
||
# %off = mul i64 %i, %es
|
||
# %addr = getelementptr i8, i8* %data, i64 %off
|
||
# %el = load i8*, i8** %addr
|
||
# store i8* %el, i8** %var
|
||
# ... 循环体 ...
|
||
# br %incr
|
||
# incr:
|
||
# %n = add i64 %i, 1 ; store ; br %cond
|
||
# end:
|
||
# ============================================================
|
||
def _handle_list_iter(self, for_node: ast.For | t.CPtr,
|
||
var_name: str,
|
||
list_val: llvmlite.Value | t.CPtr) -> int:
|
||
"""list[T] 容器迭代: for v in lst: 按 __count__ 动态长度迭代"""
|
||
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
|
||
|
||
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)
|
||
|
||
# 读取 __count__ (偏移 8, GEP index 1)
|
||
cnt_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep(
|
||
builder, i64_ty, list_val, llvmlite.const_int64(pool, 1))
|
||
if cnt_ptr is None:
|
||
HandlesType.fatal_error(for_node, "list 迭代: 无法定位 __count__")
|
||
count_val: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i64_ty, cnt_ptr)
|
||
|
||
# 循环变量 alloca(元素类型 i8*,与 list.get 内联一致)
|
||
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, i8_ptr_ty)
|
||
if HandlesVar.define_var(
|
||
trans.SymTab, var_name, var_alloca) == 0:
|
||
new_vars = 1
|
||
|
||
# 隐式 index 变量 (i64,与 __count__ 类型对齐)
|
||
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, "lst.cond.%d", cnt)
|
||
cond_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
viperlib.snprintf(name_buf, 32, "lst.body.%d", cnt)
|
||
body_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
viperlib.snprintf(name_buf, 32, "lst.incr.%d", cnt)
|
||
incr_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
viperlib.snprintf(name_buf, 32, "lst.end.%d", cnt)
|
||
end_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
llvmlite.build_br(builder, cond_bb)
|
||
|
||
# cond 块: load index, icmp slt idx, count
|
||
llvmlite.position_at_end(builder, cond_bb)
|
||
cur_idx: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i64_ty, idx_alloca)
|
||
in_bounds: llvmlite.Value | t.CPtr = llvmlite.build_icmp(
|
||
builder, llvmlite.ICMP_SLT, cur_idx, count_val)
|
||
llvmlite.build_cond_br(builder, in_bounds, body_bb, end_bb)
|
||
|
||
# body 块: __data__ + idx*__elem_size__ → load 元素 → store to var
|
||
llvmlite.position_at_end(builder, body_bb)
|
||
dpp: llvmlite.Value | t.CPtr = llvmlite.build_gep(
|
||
builder, i64_ty, list_val, llvmlite.const_int64(pool, 0))
|
||
data_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, dpp)
|
||
epp: llvmlite.Value | t.CPtr = llvmlite.build_gep(
|
||
builder, i64_ty, list_val, llvmlite.const_int64(pool, 4))
|
||
esize: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i64_ty, epp)
|
||
offset: llvmlite.Value | t.CPtr = llvmlite.build_mul(builder, cur_idx, esize)
|
||
elem_addr: llvmlite.Value | t.CPtr = llvmlite.build_gep(
|
||
builder, i8_ty, data_ptr, offset)
|
||
cur_elem: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, elem_addr)
|
||
llvmlite.build_store(builder, cur_elem, var_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
|
||
def _handle_dict_iter(self, for_node: ast.For | t.CPtr,
|
||
var_name: str,
|
||
dict_val: llvmlite.Value | t.CPtr) -> int:
|
||
"""dict 容器迭代: for key in d: 按 __count__/__keys__ 布局迭代
|
||
|
||
_dict.vp 布局(8 字节槽):__keys__@0, __values__@1, __count__@2,
|
||
__capacity__@3, __mbuddy__@4, __iter_index__@5。
|
||
__iter__ 协议(__iter__ 重置 iter_index + __next__ 取 key)内联为
|
||
循环:iter_idx < __count__ → key = __keys__[iter_idx]。
|
||
"""
|
||
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
|
||
|
||
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)
|
||
|
||
# 读取 __count__(槽 2,字节偏移 16)
|
||
cnt_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep(
|
||
builder, i64_ty, dict_val, llvmlite.const_int64(pool, 2))
|
||
if cnt_ptr is None:
|
||
HandlesType.fatal_error(for_node, "dict 迭代: 无法定位 __count__")
|
||
count_val: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i64_ty, cnt_ptr)
|
||
|
||
# 循环变量 alloca(元素类型 i8*,与 dict.__next__ 返回 str 一致)
|
||
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, i8_ptr_ty)
|
||
if HandlesVar.define_var(
|
||
trans.SymTab, var_name, var_alloca) == 0:
|
||
new_vars = 1
|
||
|
||
# 隐式 index 变量 (i64,与 __count__ 类型对齐)
|
||
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, "dict.cond.%d", cnt)
|
||
cond_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
viperlib.snprintf(name_buf, 32, "dict.body.%d", cnt)
|
||
body_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
viperlib.snprintf(name_buf, 32, "dict.incr.%d", cnt)
|
||
incr_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
viperlib.snprintf(name_buf, 32, "dict.end.%d", cnt)
|
||
end_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
|
||
llvmlite.build_br(builder, cond_bb)
|
||
|
||
# cond 块: load index, icmp slt idx, count
|
||
llvmlite.position_at_end(builder, cond_bb)
|
||
cur_idx: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i64_ty, idx_alloca)
|
||
in_bounds: llvmlite.Value | t.CPtr = llvmlite.build_icmp(
|
||
builder, llvmlite.ICMP_SLT, cur_idx, count_val)
|
||
llvmlite.build_cond_br(builder, in_bounds, body_bb, end_bb)
|
||
|
||
# body 块: __keys__ + idx*8 → load key (i8*) → store to var
|
||
llvmlite.position_at_end(builder, body_bb)
|
||
kpp: llvmlite.Value | t.CPtr = llvmlite.build_gep(
|
||
builder, i64_ty, dict_val, llvmlite.const_int64(pool, 0))
|
||
keys_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, kpp)
|
||
eight_val: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, 8)
|
||
key_offset: llvmlite.Value | t.CPtr = llvmlite.build_mul(builder, cur_idx, eight_val)
|
||
key_addr: llvmlite.Value | t.CPtr = llvmlite.build_gep(
|
||
builder, i8_ty, keys_ptr, key_offset)
|
||
cur_key: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, key_addr)
|
||
llvmlite.build_store(builder, cur_key, var_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
|
||
# ============================================================
|
||
# _handle_oop_iter - OOP 迭代协议: for x in obj:
|
||
# obj 的类有 __iter__/__next__ 方法时调用协议迭代
|
||
# (对齐 TPC HandlesFor.py _HandleForIterLlvm L599-663)
|
||
#
|
||
# 生成 IR 结构:
|
||
# %it = call {Class}.__iter__(obj)
|
||
# %flag = alloca i1 ; store 0
|
||
# br %cond
|
||
# cond:
|
||
# store 0, %flag
|
||
# %v = call {Class}.__next__(%it, %flag)
|
||
# %stop = load i1, %flag
|
||
# br i1 %stop==0, %body, %end
|
||
# body:
|
||
# store %v, %var
|
||
# ... 循环体 ...
|
||
# br %step
|
||
# step:
|
||
# br %cond
|
||
# end:
|
||
#
|
||
# __next__ 的隐藏参数 __stop_iter_flag__(i1*)由 ClassGenMixin
|
||
# _translate_method 注入,raise StopIteration 时置 1(translate_raise);
|
||
# VpiReader stub 声明同步该参数(_inject_method_declare)。
|
||
# ============================================================
|
||
def _handle_oop_iter(self, for_node: ast.For | t.CPtr,
|
||
var_name: str,
|
||
class_name: str,
|
||
obj_val: llvmlite.Value | t.CPtr) -> int:
|
||
"""OOP iter 协议: for x in obj: 调用 __iter__/__next__ 迭代"""
|
||
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
|
||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||
|
||
if builder is None or func is None or mod is None:
|
||
return 0
|
||
if obj_val is None or obj_val.Ty is None:
|
||
HandlesType.fatal_error(for_node, "OOP 迭代: 迭代源对象类型未知")
|
||
if HandlesExpr.is_ptr_type(obj_val.Ty) == 0:
|
||
HandlesType.fatal_error(for_node, "OOP 迭代: 迭代源对象不是指针类型")
|
||
|
||
# 1. 查找 {Class}.__iter__ 并调用,得到迭代器
|
||
iter_lookup: str = pool.alloc(128)
|
||
if iter_lookup is None:
|
||
return 0
|
||
viperlib.snprintf(iter_lookup, 128, "%s.__iter__", class_name)
|
||
iter_fn: llvmlite.Function | t.CPtr = ExprCallBase.find_func_in_module(
|
||
mod, iter_lookup)
|
||
if iter_fn is None:
|
||
HandlesType.fatal_error(
|
||
for_node, f"OOP 迭代: 类 '{class_name}' 没有 __iter__ 方法")
|
||
iter_ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(iter_fn)
|
||
iter_fn_name: str = llvmlite.function_get_name(iter_fn)
|
||
if iter_ret_ty is None or iter_fn_name is None:
|
||
return 0
|
||
# self 参数按 __iter__ 首参类型对齐(stub 声明 self 可能是 i8*)
|
||
iter_self: llvmlite.Value | t.CPtr = obj_val
|
||
iter_first: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(iter_fn)
|
||
if iter_first is not None:
|
||
iter_self_ty: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(iter_first)
|
||
if iter_self_ty is not None:
|
||
iter_self = llvmlite.build_bitcast(builder, obj_val, iter_self_ty)
|
||
if iter_self is None:
|
||
return 0
|
||
iter_self.Next = None
|
||
iter_result: llvmlite.Value | t.CPtr = llvmlite.build_call(
|
||
builder, iter_fn_name, iter_self, 1, iter_ret_ty, 0)
|
||
if iter_result is None:
|
||
return 0
|
||
|
||
# 2. 查找 {Class}.__next__(带隐藏 __stop_iter_flag__ i1* 参数)
|
||
next_lookup: str = pool.alloc(128)
|
||
if next_lookup is None:
|
||
return 0
|
||
viperlib.snprintf(next_lookup, 128, "%s.__next__", class_name)
|
||
next_fn: llvmlite.Function | t.CPtr = ExprCallBase.find_func_in_module(
|
||
mod, next_lookup)
|
||
if next_fn is None:
|
||
HandlesType.fatal_error(
|
||
for_node, f"OOP 迭代: 类 '{class_name}' 没有 __next__ 方法")
|
||
next_ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(next_fn)
|
||
next_fn_name: str = llvmlite.function_get_name(next_fn)
|
||
if next_ret_ty is None or next_fn_name is None:
|
||
return 0
|
||
|
||
# 3. 循环变量 alloca(元素类型 = __next__ 返回类型)
|
||
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, next_ret_ty)
|
||
if var_alloca is not None:
|
||
if HandlesVar.define_var(
|
||
trans.SymTab, var_name, var_alloca) == 0:
|
||
new_vars = 1
|
||
|
||
# 4. stop flag alloca(i1,初始 0)
|
||
i1_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int1(pool)
|
||
flag_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, i1_ty)
|
||
if flag_alloca is None:
|
||
return 0
|
||
flag_zero: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i1_ty, 0, "0")
|
||
if flag_zero is not None:
|
||
llvmlite.build_store(builder, flag_zero, flag_alloca)
|
||
|
||
# 5. 创建基本块: cond / body / step / end
|
||
cnt: int = trans._label_counter
|
||
trans._label_counter = cnt + 1
|
||
name_buf: str = pool.alloc(32)
|
||
viperlib.snprintf(name_buf, 32, "oop.cond.%d", cnt)
|
||
cond_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
viperlib.snprintf(name_buf, 32, "oop.body.%d", cnt)
|
||
body_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
viperlib.snprintf(name_buf, 32, "oop.step.%d", cnt)
|
||
step_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
viperlib.snprintf(name_buf, 32, "oop.end.%d", cnt)
|
||
end_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||
if cond_bb is None or body_bb is None or step_bb is None or end_bb is None:
|
||
return 0
|
||
|
||
llvmlite.build_br(builder, cond_bb)
|
||
|
||
# 6. cond 块: 重置 flag → 调 __next__(iter, flag) → 检查 flag 判结束
|
||
llvmlite.position_at_end(builder, cond_bb)
|
||
if flag_zero is not None:
|
||
llvmlite.build_store(builder, flag_zero, flag_alloca)
|
||
# __next__ 参数 1:迭代器(按首参类型 bitcast)
|
||
next_self: llvmlite.Value | t.CPtr = iter_result
|
||
next_first: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(next_fn)
|
||
if next_first is not None:
|
||
next_self_ty: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(next_first)
|
||
if next_self_ty is not None and iter_result.Ty is not None:
|
||
next_self = llvmlite.build_bitcast(builder, iter_result, next_self_ty)
|
||
if next_self is None:
|
||
return 0
|
||
# 参数链表: arg1(iter).Next = arg2(flag);flag 独立 null 结尾防自链接
|
||
next_self.Next = flag_alloca
|
||
flag_alloca.Next = None
|
||
next_val: llvmlite.Value | t.CPtr = llvmlite.build_call(
|
||
builder, next_fn_name, next_self, 2, next_ret_ty, 0)
|
||
if next_val is None:
|
||
return 0
|
||
stop_val: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i1_ty, flag_alloca)
|
||
if stop_val is None:
|
||
return 0
|
||
flag_zero2: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i1_ty, 0, "0")
|
||
continue_i1: llvmlite.Value | t.CPtr = None
|
||
if flag_zero2 is not None:
|
||
continue_i1 = llvmlite.build_icmp(
|
||
builder, llvmlite.ICMP_EQ, stop_val, flag_zero2)
|
||
if continue_i1 is None:
|
||
return 0
|
||
llvmlite.build_cond_br(builder, continue_i1, body_bb, end_bb)
|
||
|
||
# 7. body 块: store 元素 → 翻译循环体 → br step
|
||
llvmlite.position_at_end(builder, body_bb)
|
||
if var_alloca is not None:
|
||
llvmlite.build_store(builder, next_val, var_alloca)
|
||
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 = step_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, step_bb)
|
||
|
||
# 8. step 块 → cond;定位到 end 块
|
||
llvmlite.position_at_end(builder, step_bb)
|
||
llvmlite.build_br(builder, cond_bb)
|
||
llvmlite.position_at_end(builder, end_bb)
|
||
# 追加90:for 循环正常结束路径 br 到 end_bb → merge 恒可达(需正常收尾)
|
||
trans._ctrl_merge_reachable = 1
|
||
return new_vars
|
||
def _handle_enumerate_iter(self, for_node: ast.For | t.CPtr,
|
||
t1: str, t2: str,
|
||
call: ast.Call | t.CPtr) -> int:
|
||
"""enumerate 迭代: for i, v in enumerate(x)"""
|
||
if call is None or call.args is None:
|
||
return 0
|
||
cargs: list[ast.AST | t.CPtr] | t.CPtr = call.args
|
||
if len(cargs) < 1:
|
||
HandlesType.fatal_error(for_node, "enumerate 需要至少一个参数")
|
||
return self._build_seq_loop(for_node, t1, t2, cargs.get(0), None, 1)
|
||
def _handle_zip_iter(self, for_node: ast.For | t.CPtr,
|
||
t1: str, t2: str,
|
||
call: ast.Call | t.CPtr) -> int:
|
||
"""zip 迭代: for a, b in zip(x, y)"""
|
||
if call is None or call.args is None:
|
||
# fail-fast: zip 参数缺失
|
||
HandlesType.fatal_error(call, "zip 参数缺失", "SyntaxError")
|
||
cargs: list[ast.AST | t.CPtr] | t.CPtr = call.args
|
||
if len(cargs) < 2:
|
||
HandlesType.fatal_error(for_node, "zip 需要至少两个参数")
|
||
return self._build_seq_loop(for_node, t1, t2, cargs.get(0), cargs.get(1), 2)
|