fix(llvm): Phase 131-6 調査 - TAG-RUN 3バグ発見(1修正/1部分/1未修正)

Phase 131-6: Infinite Loop Bug 調査完了

発見したバグ(3件):
1. Bug #1: Copy-to-PHI 命令(SSA 違反) 修正完了
   - instruction_rewriter.rs: PHI destination への Copy をスキップ
2. Bug #2: Type Inference 混同(String vs Integer)⚠️ 部分修正
   - binop.py: force_string ロジック削除
3. Bug #3: SSA Dominance Violation  未修正
   - MIR builder が定義前に値を使用(根本問題)

変更ファイル:
- src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs:
  - Lines 428-443: header PHI への Copy スキップ追加
- src/llvm_py/instructions/binop.py:
  - Lines 128-159: force_string 削除、Phase 131-6 コメント追加
- docs/development/current/main/phase131-3-llvm-lowering-inventory.md:
  - 3バグの詳細追記

テスト結果:
- Case A/B2:  退行なし
- Case B:  infinite loop 継続(Bug #3 が原因)
- Simple Add:  0 を出力(期待: 1)

Next: Phase 131-6 続き - MIR SSA dominance 根治

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-14 06:52:50 +09:00
parent 9e76173c99
commit 1510dcb7d8
3 changed files with 74 additions and 18 deletions

View File

@ -125,13 +125,19 @@ def lower_binop(
# pointer present?
is_ptr_side = (hasattr(lhs_raw, 'type') and isinstance(lhs_raw.type, ir.PointerType)) or \
(hasattr(rhs_raw, 'type') and isinstance(rhs_raw.type, ir.PointerType))
# Explicit dst_type hint from MIR JSON?
force_string = False
try:
if isinstance(dst_type, dict) and dst_type.get('kind') == 'handle' and dst_type.get('box_type') == 'StringBox':
force_string = True
except Exception:
pass
# Phase 131-6 FIX: Do NOT use dst_type hint from MIR JSON!
# The dst_type is a forward-looking type hint that may be incorrect
# (e.g., "i + 1" gets StringBox hint because i is later used as string in print(i))
# We should only do string concat if operands are actually strings.
#
# OLD CODE (REMOVED):
# force_string = False
# try:
# if isinstance(dst_type, dict) and dst_type.get('kind') == 'handle' and dst_type.get('box_type') == 'StringBox':
# force_string = True
# except Exception:
# pass
# tagged string handles?(どちらかが string-ish のとき)
any_tagged = False
try:
@ -143,7 +149,14 @@ def lower_binop(
any_tagged = (lhs in resolver.string_literals) or (rhs in resolver.string_literals)
except Exception:
pass
is_str = force_string or is_ptr_side or any_tagged
# Phase 131-6: Removed force_string from this check
is_str = is_ptr_side or any_tagged
# Phase 131-6 DEBUG
if os.environ.get('NYASH_BINOP_DEBUG') == '1':
print(f"[binop +] lhs={lhs} rhs={rhs} dst={dst}")
print(f" is_ptr_side={is_ptr_side} any_tagged={any_tagged} is_str={is_str}")
print(f" dst_type={dst_type}")
if is_str:
# Helper: convert raw or resolved value to string handle
def to_handle(raw, val, tag: str, vid: int):