2025-09-25 10:23:14 +09:00
|
|
|
|
/*!
|
|
|
|
|
|
* phi_core::common – shared types and invariants (scaffold)
|
|
|
|
|
|
*
|
|
|
|
|
|
* Phase 1 keeps this minimal; future phases may move debug asserts and
|
|
|
|
|
|
* predicate set checks here for both if/loop PHI normalization.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/// Placeholder for future shared PHI input type alias.
|
|
|
|
|
|
/// Using the same tuple form as MIR Phi instruction inputs.
|
|
|
|
|
|
pub type PhiInput = (crate::mir::BasicBlockId, crate::mir::ValueId);
|
|
|
|
|
|
|
|
|
|
|
|
pub fn debug_verify_phi_inputs(
|
|
|
|
|
|
function: &crate::mir::MirFunction,
|
|
|
|
|
|
merge_bb: crate::mir::BasicBlockId,
|
|
|
|
|
|
inputs: &[(crate::mir::BasicBlockId, crate::mir::ValueId)],
|
|
|
|
|
|
) {
|
|
|
|
|
|
use std::collections::HashSet;
|
2025-11-02 10:58:09 +09:00
|
|
|
|
// Always compute when env toggle is set; otherwise no-op in release use.
|
2025-11-21 06:25:17 +09:00
|
|
|
|
let verify_on = std::env::var("HAKO_PHI_VERIFY")
|
|
|
|
|
|
.ok()
|
|
|
|
|
|
.map(|v| v.to_ascii_lowercase())
|
|
|
|
|
|
.map(|v| v == "1" || v == "true" || v == "on")
|
|
|
|
|
|
.unwrap_or(false)
|
|
|
|
|
|
|| std::env::var("NYASH_PHI_VERIFY")
|
|
|
|
|
|
.ok()
|
|
|
|
|
|
.map(|v| v.to_ascii_lowercase())
|
|
|
|
|
|
.map(|v| v == "1" || v == "true" || v == "on")
|
|
|
|
|
|
.unwrap_or(false);
|
|
|
|
|
|
if !verify_on {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-11-02 10:58:09 +09:00
|
|
|
|
|
|
|
|
|
|
// Rebuild CFG to avoid stale predecessor sets
|
2025-11-01 15:23:28 +09:00
|
|
|
|
let mut func = function.clone();
|
|
|
|
|
|
func.update_cfg();
|
2025-11-02 10:58:09 +09:00
|
|
|
|
|
|
|
|
|
|
// Duplicate check
|
2025-09-25 10:23:14 +09:00
|
|
|
|
let mut seen = HashSet::new();
|
|
|
|
|
|
for (pred, _v) in inputs.iter() {
|
2025-11-02 10:58:09 +09:00
|
|
|
|
if *pred == merge_bb {
|
|
|
|
|
|
eprintln!("[phi/check][bad-self] merge={:?} pred={:?}", merge_bb, pred);
|
|
|
|
|
|
}
|
|
|
|
|
|
if !seen.insert(*pred) {
|
|
|
|
|
|
eprintln!("[phi/check][dup] merge={:?} pred={:?}", merge_bb, pred);
|
|
|
|
|
|
}
|
2025-09-25 10:23:14 +09:00
|
|
|
|
}
|
2025-11-02 10:58:09 +09:00
|
|
|
|
|
|
|
|
|
|
// Missing predecessor inputs check
|
2025-11-01 15:23:28 +09:00
|
|
|
|
if let Some(block) = func.blocks.get(&merge_bb) {
|
2025-11-02 10:58:09 +09:00
|
|
|
|
for pred in &block.predecessors {
|
|
|
|
|
|
let has = inputs.iter().any(|(bb, _)| bb == pred);
|
|
|
|
|
|
if !has {
|
|
|
|
|
|
eprintln!("[phi/check][missing] merge={:?} pred={:?}", merge_bb, pred);
|
2025-11-01 15:23:28 +09:00
|
|
|
|
}
|
2025-09-25 10:23:14 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|