llvm(py): introduce BuildCtx + trace hub; refactor if-merge prepass + PHI wiring into module; unify logs; ctx-enable compare/ret/call/boxcall/externcall/typeop/newbox/safepoint; curated smoke option for if-merge; README updates; keep behavior stable
This commit is contained in:
80
src/llvm_py/instructions/controlflow/while_.py
Normal file
80
src/llvm_py/instructions/controlflow/while_.py
Normal file
@ -0,0 +1,80 @@
|
||||
"""
|
||||
Lowering helpers for while-control flow (regular structured)
|
||||
"""
|
||||
|
||||
from typing import List, Dict, Any
|
||||
import llvmlite.ir as ir
|
||||
|
||||
def lower_while_regular(
|
||||
builder: ir.IRBuilder,
|
||||
func: ir.Function,
|
||||
cond_vid: int,
|
||||
body_insts: List[Dict[str, Any]],
|
||||
loop_id: int,
|
||||
vmap: Dict[int, ir.Value],
|
||||
bb_map: Dict[int, ir.Block],
|
||||
resolver,
|
||||
preds,
|
||||
block_end_values,
|
||||
):
|
||||
"""Create a minimal while in IR: cond -> body -> cond, with exit.
|
||||
The body instructions are lowered using the caller's dispatcher.
|
||||
"""
|
||||
i1 = ir.IntType(1)
|
||||
i64 = ir.IntType(64)
|
||||
|
||||
# Create basic blocks: cond -> body -> cond, and exit
|
||||
cond_bb = func.append_basic_block(name=f"while{loop_id}_cond")
|
||||
body_bb = func.append_basic_block(name=f"while{loop_id}_body")
|
||||
exit_bb = func.append_basic_block(name=f"while{loop_id}_exit")
|
||||
|
||||
# Jump from current to cond
|
||||
builder.branch(cond_bb)
|
||||
|
||||
# Cond block
|
||||
cbuild = ir.IRBuilder(cond_bb)
|
||||
try:
|
||||
# Resolve against the condition block to localize dominance
|
||||
cond_val = resolver.resolve_i64(cond_vid, cond_bb, preds, block_end_values, vmap, bb_map)
|
||||
except Exception:
|
||||
cond_val = vmap.get(cond_vid)
|
||||
if cond_val is None:
|
||||
cond_val = ir.Constant(i1, 0)
|
||||
# Normalize to i1
|
||||
if hasattr(cond_val, 'type'):
|
||||
if isinstance(cond_val.type, ir.IntType) and cond_val.type.width == 64:
|
||||
zero64 = ir.Constant(i64, 0)
|
||||
cond_val = cbuild.icmp_unsigned('!=', cond_val, zero64, name="while_cond_i1")
|
||||
elif isinstance(cond_val.type, ir.PointerType):
|
||||
nullp = ir.Constant(cond_val.type, None)
|
||||
cond_val = cbuild.icmp_unsigned('!=', cond_val, nullp, name="while_cond_p1")
|
||||
elif isinstance(cond_val.type, ir.IntType) and cond_val.type.width == 1:
|
||||
# already i1
|
||||
pass
|
||||
else:
|
||||
# Fallback: treat as false
|
||||
cond_val = ir.Constant(i1, 0)
|
||||
else:
|
||||
cond_val = ir.Constant(i1, 0)
|
||||
|
||||
cbuild.cbranch(cond_val, body_bb, exit_bb)
|
||||
|
||||
# Body block
|
||||
bbuild = ir.IRBuilder(body_bb)
|
||||
# The caller must provide a dispatcher to lower body_insts; do a simple inline here.
|
||||
# We expect the caller to have a method lower_instruction(builder, inst, func).
|
||||
lower_instruction = getattr(resolver, '_owner_lower_instruction', None)
|
||||
if lower_instruction is None:
|
||||
raise RuntimeError('resolver._owner_lower_instruction not set (needs NyashLLVMBuilder.lower_instruction)')
|
||||
for sub in body_insts:
|
||||
if bbuild.block.terminator is not None:
|
||||
cont = func.append_basic_block(name=f"cont_bb_{bbuild.block.name}")
|
||||
bbuild.position_at_end(cont)
|
||||
lower_instruction(bbuild, sub, func)
|
||||
# Ensure terminator: if not terminated, branch back to cond
|
||||
if bbuild.block.terminator is None:
|
||||
bbuild.branch(cond_bb)
|
||||
|
||||
# Continue at exit
|
||||
builder.position_at_end(exit_bb)
|
||||
|
||||
Reference in New Issue
Block a user