snapshot before regression test
This commit is contained in:
141
TransPyV/App/lib/core/Handles/HandlesIf.py
Normal file
141
TransPyV/App/lib/core/Handles/HandlesIf.py
Normal file
@@ -0,0 +1,141 @@
|
||||
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.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesBody as HandlesBody
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesIf - if/elif/else 语句处理(Mixin 继承模式)
|
||||
#
|
||||
# 翻译 if 语句为 LLVM IR 控制流:
|
||||
# br i1 %cond, label %then, label %else
|
||||
# then:
|
||||
# ... body ...
|
||||
# br label %end
|
||||
# else:
|
||||
# ... orelse ...
|
||||
# br label %end
|
||||
# end:
|
||||
# ============================================================
|
||||
|
||||
|
||||
@t.NoVTable
|
||||
class IfHandle(HandlesBase.Mixin):
|
||||
"""if/elif/else 语句处理器:继承 Mixin 获得 Trans 回指针"""
|
||||
|
||||
def __init__(self, trans: HT.Translator | t.CPtr):
|
||||
self.Trans = trans
|
||||
|
||||
# ============================================================
|
||||
# Handle - 处理 if 语句,返回新增变量数
|
||||
# ============================================================
|
||||
def Handle(self, node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 if/elif/else 语句"""
|
||||
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
|
||||
|
||||
if_node: ast.If | t.CPtr = (ast.If | t.CPtr)(node)
|
||||
|
||||
# 1. 求值条件表达式
|
||||
cond_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, trans.Module, if_node.test,
|
||||
trans._funcs, trans._func_count, trans)
|
||||
|
||||
# 2. 转换为 i1 条件
|
||||
# Compare/Not 表达式已返回 i1,直接使用;其他类型与 0 比较
|
||||
if cond_val is None:
|
||||
cond_val = llvmlite.const_int32(pool, 0)
|
||||
cond_bits: int = HandlesExpr.get_llvm_type_bits(cond_val.Ty)
|
||||
if cond_bits == 1:
|
||||
cond_i1: llvmlite.Value | t.CPtr = cond_val
|
||||
else:
|
||||
zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
|
||||
cond_i1 = llvmlite.build_icmp(
|
||||
builder, llvmlite.ICMP_NE, cond_val, zero)
|
||||
|
||||
# 3. 创建基本块(使用 trans._label_counter 生成唯一标签名,不与 SSA 名共享)
|
||||
cnt: int = trans._label_counter
|
||||
trans._label_counter = cnt + 1
|
||||
|
||||
name_buf: t.CChar | t.CPtr = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "if.then.%d", cnt)
|
||||
then_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "if.end.%d", cnt)
|
||||
merge_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
|
||||
# 检查是否有 else 分支
|
||||
has_else: int = 0
|
||||
orelse_list: list[ast.AST | t.CPtr] | t.CPtr = if_node.orelse
|
||||
if orelse_list is not None:
|
||||
if orelse_list.__len__() > 0:
|
||||
has_else = 1
|
||||
|
||||
else_bb: llvmlite.BasicBlock | t.CPtr = None
|
||||
if has_else == 1:
|
||||
viperlib.snprintf(name_buf, 32, "if.else.%d", cnt)
|
||||
else_bb = llvmlite.create_block(pool, func, name_buf)
|
||||
|
||||
# 4. 发射条件分支
|
||||
if has_else == 1:
|
||||
llvmlite.build_cond_br(builder, cond_i1, then_bb, else_bb)
|
||||
else:
|
||||
llvmlite.build_cond_br(builder, cond_i1, then_bb, merge_bb)
|
||||
|
||||
# 5. 翻译 then body
|
||||
llvmlite.position_at_end(builder, then_bb)
|
||||
body: list[ast.AST | t.CPtr] | t.CPtr = if_node.children
|
||||
if body is not None:
|
||||
body_count: t.CSizeT = body.__len__()
|
||||
for bi in range(body_count):
|
||||
stmt: ast.AST | t.CPtr = body.get(bi)
|
||||
if stmt is not None:
|
||||
HandlesBody.translate_stmt(trans, stmt)
|
||||
|
||||
# then 块未终止则跳到 merge
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
|
||||
llvmlite.build_br(builder, merge_bb)
|
||||
|
||||
# 6. 翻译 else body(若有)
|
||||
if has_else == 1:
|
||||
llvmlite.position_at_end(builder, else_bb)
|
||||
else_count: t.CSizeT = orelse_list.__len__()
|
||||
for ei in range(else_count):
|
||||
stmt: ast.AST | t.CPtr = orelse_list.get(ei)
|
||||
if stmt is not None:
|
||||
HandlesBody.translate_stmt(trans, stmt)
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
|
||||
llvmlite.build_br(builder, merge_bb)
|
||||
|
||||
# 7. 定位到 merge 块继续后续代码
|
||||
llvmlite.position_at_end(builder, merge_bb)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewIfHandle - 工厂函数
|
||||
# ============================================================
|
||||
def NewIfHandle(pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> IfHandle | t.CPtr:
|
||||
h: IfHandle | t.CPtr = pool.alloc(IfHandle.__sizeof__())
|
||||
if h is None:
|
||||
return None
|
||||
string.memset(h, 0, IfHandle.__sizeof__())
|
||||
h.Trans = trans
|
||||
return h
|
||||
Reference in New Issue
Block a user