current_task: refresh notes; cleanup unified; LLVM(harness): finalize_phis ownership, ret simplified, uses-predeclare; method-postfix cleanup return: PHI head grouping final TODOs
This commit is contained in:
@ -56,52 +56,29 @@ def lower_return(
|
||||
ret_val = tmp0
|
||||
if ret_val is None:
|
||||
if resolver is not None and preds is not None and block_end_values is not None and bb_map is not None:
|
||||
# Multi-pred special case: construct a PHI at block head and wire per-pred values
|
||||
# to keep PHIs grouped at top and avoid late synthesis that violates ordering.
|
||||
cur_bid = int(str(builder.block.name).replace('bb','')) if hasattr(builder.block, 'name') else -1
|
||||
pred_ids = [p for p in preds.get(cur_bid, []) if p != cur_bid] if isinstance(preds, dict) else []
|
||||
if isinstance(value_id, int) and len(pred_ids) > 1 and isinstance(return_type, ir.IntType):
|
||||
# Create PHI at block head
|
||||
btop = ir.IRBuilder(builder.block)
|
||||
try:
|
||||
btop.position_at_start(builder.block)
|
||||
except Exception:
|
||||
pass
|
||||
ph = btop.phi(return_type, name=f"res_phi_{value_id}_{cur_bid}")
|
||||
# Wire per-pred end values
|
||||
for pred_bid in pred_ids:
|
||||
pred_bb = bb_map.get(pred_bid) if isinstance(bb_map, dict) else None
|
||||
if pred_bb is None:
|
||||
continue
|
||||
val = resolver._value_at_end_i64(value_id, pred_bid, preds, block_end_values, vmap, bb_map)
|
||||
if not hasattr(val, 'type'):
|
||||
val = ir.Constant(return_type, 0)
|
||||
ph.add_incoming(val, pred_bb)
|
||||
ret_val = ph
|
||||
# Resolve direct value; PHIは finalize_phis に一任
|
||||
if isinstance(return_type, ir.PointerType):
|
||||
ret_val = resolver.resolve_ptr(value_id, builder.block, preds, block_end_values, vmap)
|
||||
else:
|
||||
# Resolve direct value
|
||||
if isinstance(return_type, ir.PointerType):
|
||||
ret_val = resolver.resolve_ptr(value_id, builder.block, preds, block_end_values, vmap)
|
||||
is_stringish = False
|
||||
if hasattr(resolver, 'is_stringish'):
|
||||
try:
|
||||
is_stringish = resolver.is_stringish(int(value_id))
|
||||
except Exception:
|
||||
is_stringish = False
|
||||
if is_stringish and hasattr(resolver, 'string_ptrs') and int(value_id) in getattr(resolver, 'string_ptrs'):
|
||||
p = resolver.string_ptrs[int(value_id)]
|
||||
i8p = ir.IntType(8).as_pointer()
|
||||
i64 = ir.IntType(64)
|
||||
boxer = None
|
||||
for f in builder.module.functions:
|
||||
if f.name == 'nyash.box.from_i8_string':
|
||||
boxer = f; break
|
||||
if boxer is None:
|
||||
boxer = ir.Function(builder.module, ir.FunctionType(i64, [i8p]), name='nyash.box.from_i8_string')
|
||||
ret_val = builder.call(boxer, [p], name='ret_ptr2h')
|
||||
else:
|
||||
is_stringish = False
|
||||
if hasattr(resolver, 'is_stringish'):
|
||||
try:
|
||||
is_stringish = resolver.is_stringish(int(value_id))
|
||||
except Exception:
|
||||
is_stringish = False
|
||||
if is_stringish and hasattr(resolver, 'string_ptrs') and int(value_id) in getattr(resolver, 'string_ptrs'):
|
||||
p = resolver.string_ptrs[int(value_id)]
|
||||
i8p = ir.IntType(8).as_pointer()
|
||||
i64 = ir.IntType(64)
|
||||
boxer = None
|
||||
for f in builder.module.functions:
|
||||
if f.name == 'nyash.box.from_i8_string':
|
||||
boxer = f; break
|
||||
if boxer is None:
|
||||
boxer = ir.Function(builder.module, ir.FunctionType(i64, [i8p]), name='nyash.box.from_i8_string')
|
||||
ret_val = builder.call(boxer, [p], name='ret_ptr2h')
|
||||
else:
|
||||
ret_val = resolver.resolve_i64(value_id, builder.block, preds, block_end_values, vmap, bb_map)
|
||||
ret_val = resolver.resolve_i64(value_id, builder.block, preds, block_end_values, vmap, bb_map)
|
||||
|
||||
if ret_val is None:
|
||||
# Default to vmap (non-PHI) if available
|
||||
|
||||
@ -30,6 +30,7 @@ from instructions.barrier import lower_barrier
|
||||
from instructions.loopform import lower_while_loopform
|
||||
from instructions.controlflow.while_ import lower_while_regular
|
||||
from phi_wiring import setup_phi_placeholders as _setup_phi_placeholders, finalize_phis as _finalize_phis
|
||||
from phi_wiring import ensure_phi as _ensure_phi
|
||||
from trace import debug as trace_debug
|
||||
from trace import phi as trace_phi
|
||||
try:
|
||||
@ -753,26 +754,8 @@ class NyashLLVMBuilder:
|
||||
except Exception:
|
||||
pass
|
||||
instructions = block_data.get("instructions", [])
|
||||
# Ensure JSON-declared PHIs are materialized at block start before any terminator
|
||||
try:
|
||||
phi_insts = [inst for inst in (instructions or []) if inst.get('op') == 'phi']
|
||||
if phi_insts:
|
||||
btop = ir.IRBuilder(bb)
|
||||
btop.position_at_start(bb)
|
||||
for pinst in phi_insts:
|
||||
dstp = pinst.get('dst')
|
||||
if isinstance(dstp, int):
|
||||
cur = self.vmap.get(dstp)
|
||||
need_new = True
|
||||
try:
|
||||
need_new = not (cur is not None and hasattr(cur, 'add_incoming'))
|
||||
except Exception:
|
||||
need_new = True
|
||||
if need_new:
|
||||
phi = btop.phi(self.i64, name=f"phi_{dstp}")
|
||||
self.vmap[dstp] = phi
|
||||
except Exception:
|
||||
pass
|
||||
# JSON-declared PHIs are not materialized here; placeholders are created uniformly
|
||||
# via ensure_phi in finalize_phis to keep PHIs grouped at block head.
|
||||
# Partition into body ops and terminators
|
||||
body_ops: List[Dict[str, Any]] = []
|
||||
term_ops: List[Dict[str, Any]] = []
|
||||
@ -1112,41 +1095,14 @@ class NyashLLVMBuilder:
|
||||
bb = self.bb_map.get(block_id)
|
||||
if bb is None:
|
||||
continue
|
||||
b = ir.IRBuilder(bb)
|
||||
try:
|
||||
b.position_at_start(bb)
|
||||
except Exception:
|
||||
pass
|
||||
for dst_vid, incoming in (dst_map or {}).items():
|
||||
try:
|
||||
trace_phi_json({"phi": "finalize_dst", "block": int(block_id), "dst": int(dst_vid), "incoming": [(int(v), int(b)) for (b, v) in [(b, v) for (v, b) in (incoming or [])]]})
|
||||
except Exception:
|
||||
pass
|
||||
# Ensure placeholder exists at block head
|
||||
# Prefer predeclared ret-phi when available and force using it.
|
||||
predecl = getattr(self, 'predeclared_ret_phis', {}) if hasattr(self, 'predeclared_ret_phis') else {}
|
||||
phi = predecl.get((int(block_id), int(dst_vid))) if predecl else None
|
||||
if phi is not None:
|
||||
# Bind as canonical target
|
||||
self.vmap[dst_vid] = phi
|
||||
else:
|
||||
phi = self.vmap.get(dst_vid)
|
||||
# Ensure we target a PHI belonging to the current block; if a
|
||||
# global mapping points to a PHI in another block (due to
|
||||
# earlier localization), create/replace with a local PHI.
|
||||
need_local_phi = False
|
||||
try:
|
||||
if not (phi is not None and hasattr(phi, 'add_incoming')):
|
||||
need_local_phi = True
|
||||
else:
|
||||
bb_of_phi = getattr(getattr(phi, 'basic_block', None), 'name', None)
|
||||
if bb_of_phi != bb.name:
|
||||
need_local_phi = True
|
||||
except Exception:
|
||||
need_local_phi = True
|
||||
if need_local_phi:
|
||||
phi = b.phi(self.i64, name=f"phi_{dst_vid}")
|
||||
self.vmap[dst_vid] = phi
|
||||
# Ensure placeholder exists at block head with common helper
|
||||
phi = _ensure_phi(self, int(block_id), int(dst_vid), bb)
|
||||
self.vmap[int(dst_vid)] = phi
|
||||
n = getattr(phi, 'name', b'').decode() if hasattr(getattr(phi, 'name', None), 'decode') else str(getattr(phi, 'name', ''))
|
||||
try:
|
||||
trace_phi_json({"phi": "finalize_target", "block": int(block_id), "dst": int(dst_vid), "ir": str(n)})
|
||||
|
||||
@ -104,6 +104,14 @@ class Resolver:
|
||||
bmap = self.block_phi_incomings.get(block_id)
|
||||
if isinstance(bmap, dict) and value_id in bmap:
|
||||
existing_cur = vmap.get(value_id)
|
||||
# Fallback: try builder/global vmap when local map lacks placeholder
|
||||
try:
|
||||
if (existing_cur is None or not hasattr(existing_cur, 'add_incoming')) and hasattr(self, 'global_vmap') and isinstance(self.global_vmap, dict):
|
||||
gcand = self.global_vmap.get(value_id)
|
||||
if gcand is not None and hasattr(gcand, 'add_incoming'):
|
||||
existing_cur = gcand
|
||||
except Exception:
|
||||
pass
|
||||
# Use placeholder only if it belongs to the current block; otherwise
|
||||
# create/ensure a local PHI at the current block head to dominate uses.
|
||||
is_phi_here = False
|
||||
@ -118,21 +126,11 @@ class Resolver:
|
||||
if is_phi_here:
|
||||
self.i64_cache[cache_key] = existing_cur
|
||||
return existing_cur
|
||||
# Materialize a local PHI placeholder at block start and bind to vmap
|
||||
b = ir.IRBuilder(current_block)
|
||||
try:
|
||||
b.position_at_start(current_block)
|
||||
except Exception:
|
||||
pass
|
||||
phi_local = b.phi(self.i64, name=f"phi_{value_id}")
|
||||
vmap[value_id] = phi_local
|
||||
try:
|
||||
if isinstance(getattr(self, 'global_vmap', None), dict):
|
||||
self.global_vmap[value_id] = phi_local
|
||||
except Exception:
|
||||
pass
|
||||
self.i64_cache[cache_key] = phi_local
|
||||
return phi_local
|
||||
# Do not synthesize PHI here; expect predeclared placeholder exists.
|
||||
# Fallback to 0 to keep IR consistent if placeholder is missing (should be rare).
|
||||
zero = ir.Constant(self.i64, 0)
|
||||
self.i64_cache[cache_key] = zero
|
||||
return zero
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@ -220,6 +218,10 @@ class Resolver:
|
||||
# Return existing placeholder if present; do not create a new PHI here.
|
||||
trace_phi(f"[resolve] use placeholder PHI: bb{cur_bid} v{value_id}")
|
||||
placeholder = vmap.get(value_id)
|
||||
if (placeholder is None or not hasattr(placeholder, 'add_incoming')) and hasattr(self, 'global_vmap') and isinstance(self.global_vmap, dict):
|
||||
cand = self.global_vmap.get(value_id)
|
||||
if cand is not None and hasattr(cand, 'add_incoming'):
|
||||
placeholder = cand
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user