Files
hakorune/src/llvm_py/instructions/controlflow/branch.py
nyash-codex 22753f8cc3 fix(llvm): Phase 131-7 - Multi-pass vmap sync 修正(Branch bug 解消)
Phase 131-7: Multi-pass block lowering の vmap sync バグ修正

問題:
- Pass A (body instructions) が vmap_cur に値を保存
- Pass C (deferred terminators) が builder.vmap を参照
- → Pass A の値が Pass C に届かない
- → Branch condition が 0 に fallback → 無限ループ

修正:
- src/llvm_py/builders/block_lower.py (lines 237-248):
  - PHI-only フィルタを削除
  - 全ての値を global vmap に sync

変更ファイル:
- src/llvm_py/builders/block_lower.py: vmap sync 修正
- src/llvm_py/instructions/controlflow/branch.py: trace logging 追加
- src/llvm_py/instructions/unop.py: trace logging 追加
- src/llvm_py/llvm_builder.py: debug helpers 追加
- src/llvm_py/phi_wiring/wiring.py: trace logging 追加
- src/runner/modes/common_util/exec.rs: Python stdout 転送

結果:
-  Branch bug 修正: ループが正しく終了
-  出力: 無限ループ → 3回で停止
-  新 bug 発見: ExternCall が null を受け取る(PHI 値の代わりに)

Next: Phase 131-8 (ExternCall argument handling 修正)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 07:38:21 +09:00

73 lines
2.3 KiB
Python

"""
Branch instruction lowering
Conditional branch based on condition value
"""
import llvmlite.ir as ir
from typing import Dict
from utils.values import resolve_i64_strict
def lower_branch(
builder: ir.IRBuilder,
cond_vid: int,
then_bid: int,
else_bid: int,
vmap: Dict[int, ir.Value],
bb_map: Dict[int, ir.Block],
resolver=None,
preds=None,
block_end_values=None
) -> 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
"""
# Get condition value with preference to same-block SSA
# 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
cond = resolve_i64_strict(resolver, cond_vid, builder.block, preds, block_end_values, vmap, bb_map)
try:
import os, sys
if os.environ.get('NYASH_CLI_VERBOSE') == '1':
print(f"[branch] resolved cond={cond}", file=sys.stderr)
except Exception:
pass
if cond is None:
# Default to false if missing
cond = ir.Constant(ir.IntType(1), 0)
# Convert to i1 if needed
if hasattr(cond, 'type'):
# 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:
# i64 to i1: compare != 0
zero = ir.Constant(ir.IntType(64), 0)
cond = builder.icmp_unsigned('!=', cond, zero, name="cond_i1")
elif isinstance(cond.type, ir.PointerType):
# 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:
builder.cbranch(cond, then_bb, else_bb)