Files
hakorune/docs/development/current/main/phase131-6-next-steps.md
nyash-codex 18bf35e6d4 fix(llvm): Phase 131-10 - Smart console.log routing(Segfault修正)
## 問題
- Integer値をi8*ポインタに変換 → Segfault(Exit 139)

## 解決策
- String literal → nyash.console.log(i8*)
- Integer/Handle → nyash.console.log_handle(i64)

## 結果
- Case B (loop_min_while): LLVM outputs `0,1,2` 
- VM/LLVM完全パリティ達成

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

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

4.6 KiB
Raw Blame History

Phase 131-6: Next Steps - PHI Bug Fix

Update (Phase 131-10)

Phase 131-6 時点では PHI wiring を主因として疑っていたが、実際には multi-pass lowering の値伝播・ExternCall の引数解決/ABI ルーティング・PHI 型推論など複数の要因が重なっていた。

最終的に Case B は解決済みLLVM AOT で 0,1,2 を出して終了)。到達点と修正の全体像は次を SSOT とする:

  • docs/development/current/main/phase131-3-llvm-lowering-inventory.md

Summary

Problem: LLVM backend generates infinite loop for loop_min_while.hako Root Cause: PHI node incoming values not properly wired in finalize_phis() Impact: P0 - Breaks basic loop functionality

Approach: Fix the PHI wiring logic in finalize_phis() to properly connect incoming values.

Location: /home/tomoaki/git/hakorune-selfhost/src/llvm_py/llvm_builder.py:601-735

Suspected Issue:

# Lines 679-681: Self-carry logic
if vs == int(dst_vid) and init_src_vid is not None:
    vs = int(init_src_vid)   # ← May incorrectly replace %12 with %2

Fix Hypothesis: The self-carry logic is meant to handle PHI nodes that reference themselves, but it may be incorrectly triggering for normal loop-carried dependencies. We need to:

  1. Add trace logging to see what values are being resolved
  2. Check if vs == int(dst_vid) is incorrectly matching %12 (the updated value) as a self-reference
  3. Verify that _value_at_end_i64() is correctly retrieving the value of %12 from bb7

Debug Commands:

# Enable verbose logging (if available)
export NYASH_CLI_VERBOSE=1
export NYASH_LLVM_DEBUG=1

# Generate LLVM IR to inspect
tools/build_llvm.sh apps/tests/loop_min_while.hako -o /tmp/loop_test

# Check generated LLVM IR
llvm-dis /tmp/loop_test.o  # If object contains IR
# Or add --emit-llvm-ir flag if available

Steps:

  1. Add debug prints in finalize_phis() to log:

    • Which incoming values are being wired: (block_id, dst_vid, [(pred_id, value_id)])
    • What nearest_pred_on_path() returns for each incoming edge
    • What _value_at_end_i64() returns for each value
  2. Compare debug output between working (VM) and broken (LLVM) paths

  3. Fix the logic that's causing %12 to be ignored or replaced

  4. Verify fix doesn't break Case A or B2

Disable loop optimization or use VM backend for loops. This doesn't solve the root cause.

Acceptance Tests

Must Pass

  1. Simple Add (already passing):
./target/release/hakorune /tmp/simple_add.hako  # Should print 1
  1. Loop Min While (currently failing):
tools/build_llvm.sh apps/tests/loop_min_while.hako -o /tmp/loop_test
timeout 2 /tmp/loop_test  # Should print 0\n1\n2 and exit
  1. Phase 87 LLVM Min (regression check):
tools/build_llvm.sh apps/tests/phase87_llvm_exe_min.hako -o /tmp/phase87_test
/tmp/phase87_test
echo $?  # Should be 42

Should Not Regress

  • Case A: phase87_llvm_exe_min.hako
  • Case B2: Simple print without loop
  • VM backend: All existing VM tests

Implementation Checklist

  • Add debug logging to finalize_phis()
  • Identify which incoming value is being incorrectly wired
  • Fix the wiring logic
  • Test Case B (loop_min_while) - must output 0\n1\n2
  • Test Case A regression - must exit with 42
  • Test Case B2 regression - must print 42
  • Document the fix in this file and phase131-3-llvm-lowering-inventory.md
  • Consider adding MIR→LLVM IR validation pass

Timeline

  • Phase 131-6 Diagnosis: 2025-12-14 Complete
  • Phase 131-7 Fix: TBD
  • Phase 131-8 Verification: TBD

Notes for Future Self

Why MIR is correct but LLVM is wrong:

  • MIR SSA form verified
  • VM execution verified
  • LLVM emission succeeds
  • LLVM linking succeeds
  • LLVM runtime fails → Bug is in IR generation, not MIR

Key Insight: The bug is NOT in the MIR builder or JoinIR merger. The bug is specifically in how the Python LLVM builder (llvm_builder.py) translates MIR PHI nodes into LLVM IR PHI nodes. This is a translation bug, not a semantic bug.

Architecture Note: This confirms the value of the 2-pillar strategy (VM + LLVM). The VM serves as a reference implementation to verify MIR correctness before blaming the frontend.