2025-09-12 20:40:48 +09:00
|
|
|
"""
|
|
|
|
|
Branch instruction lowering
|
|
|
|
|
Conditional branch based on condition value
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import llvmlite.ir as ir
|
|
|
|
|
from typing import Dict
|
2025-09-17 16:11:01 +09:00
|
|
|
from utils.values import resolve_i64_strict
|
2025-09-12 20:40:48 +09:00
|
|
|
|
|
|
|
|
def lower_branch(
|
|
|
|
|
builder: ir.IRBuilder,
|
|
|
|
|
cond_vid: int,
|
|
|
|
|
then_bid: int,
|
|
|
|
|
else_bid: int,
|
|
|
|
|
vmap: Dict[int, ir.Value],
|
2025-09-13 15:37:58 +09:00
|
|
|
bb_map: Dict[int, ir.Block],
|
|
|
|
|
resolver=None,
|
|
|
|
|
preds=None,
|
|
|
|
|
block_end_values=None
|
2025-09-12 20:40:48 +09:00
|
|
|
) -> None:
|
|
|
|
|
"""
|
|
|
|
|
Lower MIR Branch instruction
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
builder: Current LLVM IR builder
|
|
|
|
|
cond_vid: Condition value ID
|
|
|
|
|
then_bid: Then block ID
|
|
|
|
|
else_bid: Else block ID
|
|
|
|
|
vmap: Value map
|
|
|
|
|
bb_map: Block map
|
|
|
|
|
"""
|
2025-09-17 16:11:01 +09:00
|
|
|
# Get condition value with preference to same-block SSA
|
2025-12-14 07:38:21 +09:00
|
|
|
# Phase 131-7 debug
|
|
|
|
|
try:
|
|
|
|
|
import os, sys
|
|
|
|
|
if os.environ.get('NYASH_CLI_VERBOSE') == '1':
|
|
|
|
|
print(f"[branch] cond_vid={cond_vid} in vmap={cond_vid in vmap} (vmap id={id(vmap)})", file=sys.stderr)
|
|
|
|
|
if cond_vid in vmap:
|
|
|
|
|
print(f"[branch] vmap[{cond_vid}] = {vmap[cond_vid]}", file=sys.stderr)
|
|
|
|
|
except Exception:
|
|
|
|
|
pass
|
2025-09-17 16:11:01 +09:00
|
|
|
cond = resolve_i64_strict(resolver, cond_vid, builder.block, preds, block_end_values, vmap, bb_map)
|
2025-12-14 07:38:21 +09:00
|
|
|
try:
|
|
|
|
|
import os, sys
|
|
|
|
|
if os.environ.get('NYASH_CLI_VERBOSE') == '1':
|
|
|
|
|
print(f"[branch] resolved cond={cond}", file=sys.stderr)
|
|
|
|
|
except Exception:
|
|
|
|
|
pass
|
2025-09-17 16:11:01 +09:00
|
|
|
if cond is None:
|
2025-09-12 20:40:48 +09:00
|
|
|
# Default to false if missing
|
|
|
|
|
cond = ir.Constant(ir.IntType(1), 0)
|
|
|
|
|
|
|
|
|
|
# Convert to i1 if needed
|
|
|
|
|
if hasattr(cond, 'type'):
|
2025-09-17 16:11:01 +09:00
|
|
|
# If we already have an i1 (canonical compare result), use it directly.
|
|
|
|
|
if isinstance(cond.type, ir.IntType) and cond.type.width == 1:
|
|
|
|
|
pass
|
|
|
|
|
elif isinstance(cond.type, ir.IntType) and cond.type.width == 64:
|
2025-09-12 20:40:48 +09:00
|
|
|
# i64 to i1: compare != 0
|
|
|
|
|
zero = ir.Constant(ir.IntType(64), 0)
|
|
|
|
|
cond = builder.icmp_unsigned('!=', cond, zero, name="cond_i1")
|
2025-09-17 16:11:01 +09:00
|
|
|
elif isinstance(cond.type, ir.PointerType):
|
2025-09-12 20:40:48 +09:00
|
|
|
# Pointer to i1: compare != null
|
|
|
|
|
null = ir.Constant(cond.type, None)
|
|
|
|
|
cond = builder.icmp_unsigned('!=', cond, null, name="cond_p1")
|
|
|
|
|
|
|
|
|
|
# Get target blocks
|
|
|
|
|
then_bb = bb_map.get(then_bid)
|
|
|
|
|
else_bb = bb_map.get(else_bid)
|
|
|
|
|
|
|
|
|
|
if then_bb and else_bb:
|
2025-09-13 15:37:58 +09:00
|
|
|
builder.cbranch(cond, then_bb, else_bb)
|