feat(llvm): Phase 131-11-H/12 - ループキャリアPHI型修正 & vmap snapshot SSOT
## Phase 131-11-H: ループキャリアPHI型修正 - PHI生成時に初期値(entry block)の型のみ使用 - backedge の値を型推論に使わない(循環依存回避) - NYASH_CARRIER_PHI_DEBUG=1 でトレース ## Phase 131-12-P0: def_blocks 登録 & STRICT エラー化 - safe_vmap_write() で PHI 上書き保護 - resolver miss を STRICT でエラー化(フォールバック 0 禁止) - def_blocks 自動登録 ## Phase 131-12-P1: vmap_cur スナップショット実装 - DeferredTerminator 構造体(block, term_ops, vmap_snapshot) - Pass A で vmap_cur をスナップショット - Pass C でスナップショット復元(try-finally) - STRICT モード assert ## 結果 - ✅ MIR PHI型: Integer(正しい) - ✅ VM: Result: 3 - ✅ vmap snapshot 機構: 動作確認 - ⚠️ LLVM: Result: 0(別のバグ、次Phase で調査) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -88,7 +88,20 @@ class Resolver:
|
||||
Creates PHI at block start if needed, caches the result.
|
||||
"""
|
||||
cache_key = (current_block.name, value_id)
|
||||
|
||||
|
||||
import os
|
||||
if os.environ.get('NYASH_LLVM_PHI_DEBUG') == '1':
|
||||
try:
|
||||
bid = int(str(current_block.name).replace('bb',''))
|
||||
in_def_blocks = value_id in self.def_blocks
|
||||
if in_def_blocks:
|
||||
def_in_blocks = list(self.def_blocks.get(value_id, set()))
|
||||
else:
|
||||
def_in_blocks = []
|
||||
trace_phi(f"[resolve_i64/entry] bb{bid} v{value_id} in_def_blocks={in_def_blocks} def_in={def_in_blocks}")
|
||||
except Exception as e:
|
||||
trace_phi(f"[resolve_i64/entry] ERROR: {e}")
|
||||
|
||||
# Check cache
|
||||
if cache_key in self.i64_cache:
|
||||
return self.i64_cache[cache_key]
|
||||
@ -158,10 +171,18 @@ class Resolver:
|
||||
defined_here = False
|
||||
if defined_here:
|
||||
existing = vmap.get(value_id)
|
||||
import os
|
||||
if os.environ.get('NYASH_LLVM_PHI_DEBUG') == '1':
|
||||
existing_type = type(existing).__name__ if existing is not None else "None"
|
||||
trace_phi(f"[resolve/def_here] bb{bid} v{value_id} existing={existing_type} in vmap={value_id in vmap}")
|
||||
if existing is not None and hasattr(existing, 'type') and isinstance(existing.type, ir.IntType) and existing.type.width == 64:
|
||||
trace_values(f"[resolve] local reuse: bb{bid} v{value_id}")
|
||||
self.i64_cache[cache_key] = existing
|
||||
return existing
|
||||
elif existing is not None:
|
||||
if os.environ.get('NYASH_LLVM_PHI_DEBUG') == '1':
|
||||
existing_llvm_type = str(existing.type) if hasattr(existing, 'type') else "no_type"
|
||||
trace_phi(f"[resolve/def_here] bb{bid} v{value_id} existing has wrong type: {existing_llvm_type}")
|
||||
else:
|
||||
# Do NOT blindly reuse vmap across blocks: it may reference values defined
|
||||
# in non-dominating predecessors (e.g., other branches). Only reuse when
|
||||
@ -235,6 +256,24 @@ class Resolver:
|
||||
result = placeholder if (placeholder is not None and hasattr(placeholder, 'add_incoming')) else ir.Constant(self.i64, 0)
|
||||
else:
|
||||
# No declared PHI and multi-pred: do not synthesize; fallback to zero
|
||||
import os
|
||||
if os.environ.get('NYASH_LLVM_STRICT') == '1':
|
||||
# P0-2: STRICT mode - fail fast on undeclared PHI in multi-pred context
|
||||
def_blocks_info = "not_in_def_blocks"
|
||||
try:
|
||||
if value_id in self.def_blocks:
|
||||
def_blocks_info = f"def_blocks={sorted(list(self.def_blocks[value_id]))}"
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
raise RuntimeError(
|
||||
f"[LLVM_PY/STRICT] Undeclared PHI in multi-pred block:\n"
|
||||
f" ValueId: {value_id}\n"
|
||||
f" Block: bb{cur_bid}\n"
|
||||
f" Predecessors: {pred_ids}\n"
|
||||
f" {def_blocks_info}\n"
|
||||
f" Hint: Value needs PHI but not declared in block_phi_incomings"
|
||||
)
|
||||
result = ir.Constant(self.i64, 0)
|
||||
|
||||
# Cache and return
|
||||
@ -342,6 +381,31 @@ class Resolver:
|
||||
|
||||
preds_s = ','.join(str(x) for x in pred_ids)
|
||||
trace_phi(f"[resolve] end_i64 miss: bb{block_id} v{value_id} preds=[{preds_s}] → 0")
|
||||
|
||||
# P0-2: STRICT mode - fail fast on resolution miss
|
||||
import os
|
||||
if os.environ.get('NYASH_LLVM_STRICT') == '1':
|
||||
# Collect diagnostic information
|
||||
def_blocks_info = "not_in_def_blocks"
|
||||
try:
|
||||
if value_id in self.def_blocks:
|
||||
def_blocks_info = f"def_blocks={sorted(list(self.def_blocks[value_id]))}"
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Build search path for diagnostics
|
||||
search_path = [block_id] + pred_ids
|
||||
|
||||
raise RuntimeError(
|
||||
f"[LLVM_PY/STRICT] PHI resolution miss:\n"
|
||||
f" ValueId: {value_id}\n"
|
||||
f" Target block: {block_id}\n"
|
||||
f" Predecessors: [{preds_s}]\n"
|
||||
f" Search path: {search_path}\n"
|
||||
f" {def_blocks_info}\n"
|
||||
f" Hint: PHI dst may not be registered in def_blocks, or dominance issue"
|
||||
)
|
||||
|
||||
z = ir.Constant(self.i64, 0)
|
||||
self._end_i64_cache[key] = z
|
||||
return z
|
||||
|
||||
Reference in New Issue
Block a user