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

Phase 131-8: ExternCall が PHI 値を正しく受け取るように修正

問題:
- ExternCall が resolve_ptr() を使用
- PHI 値は local vmap にない → null を返す
- 結果: console.log が常に 0 を出力

修正:
- src/llvm_py/instructions/externcall.py:
  - resolve_ptr() → resolve_i64_strict() に統一
  - 他の命令(binop, compare, copy)と同じ resolver を使用

テスト結果:
- Before: 0,0,0
- After: 0,01,011 (PHI 値が正しく渡る!)
- Case A:  退行なし (exit code 42)

新規発見(スコープ外):
- MIR 型推論バグ: %3 が String 型として扱われる
- 出力が 0,1,2 ではなく 0,01,011(文字列連結)
- → Rust frontend の問題(Phase 131-9 候補)

箱化モジュール化:
-  resolve_i64_strict() に統一
-  Value resolution vs Type conversion の責務分離
-  構造的解決

🤖 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 08:02:23 +09:00
parent 22753f8cc3
commit cf4d98ed08

View File

@ -7,6 +7,7 @@ import llvmlite.ir as ir
from typing import Dict, List, Optional, Any
from instructions.safepoint import insert_automatic_safepoint
from instructions.extern_normalize import normalize_extern_name
from utils.values import resolve_i64_strict
def lower_externcall(
builder: ir.IRBuilder,
@ -103,20 +104,19 @@ def lower_externcall(
call_args: List[ir.Value] = []
for i, arg_id in enumerate(args):
orig_arg_id = arg_id
# Prefer resolver/ctx
# ALWAYS resolve as i64 first (handles PHI values correctly)
# Type coercion to pointer happens below if needed
aval = None
if resolver is not None and preds is not None and block_end_values is not None and bb_map is not None:
try:
if len(func.args) > i and isinstance(func.args[i].type, ir.PointerType):
aval = resolver.resolve_ptr(arg_id, builder.block, preds, block_end_values, vmap)
else:
aval = resolver.resolve_i64(arg_id, builder.block, preds, block_end_values, vmap, bb_map)
# Use strict resolver (handles PHI values correctly, same as binop/compare/copy)
aval = resolve_i64_strict(resolver, arg_id, builder.block, preds, block_end_values, vmap, bb_map)
except Exception:
aval = None
if aval is None:
aval = vmap.get(arg_id)
if aval is None:
# Default guess
# Fallback (should rarely hit with resolve_i64_strict)
aval = ir.Constant(i64, 0)
# If function prototype is known, coerce to expected type