feat(llvm): Phase 131-13/14 - MIR JSON順序修正 & 2パスsnapshot解決
## Phase 131-13: MIR JSON 命令順序修正 - copy 遅延ロジック削除(~80行) - MIR の def→use 順序をそのまま出力(SSOT) - PHI 先頭集約のみ維持 ## Phase 131-14: jump-only block 2パス snapshot 解決 - Pass A: jump-only block はメタ記録のみ - Pass B: resolve_jump_only_snapshots() で CFG ベース解決 - path compression で連鎖を効率的に解決 - サイクル検出で Fail-Fast ## 結果 - ✅ STRICT モードでエラーなし - ✅ bb7 が bb5 の snapshot を正しく継承 - ✅ ループが正しく動作(1, 2 出力確認) - ⚠️ print/concat で segfault(別問題、次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:
@ -190,43 +190,11 @@ pub fn emit_mir_json_for_harness(
|
||||
for bid in ids {
|
||||
if let Some(bb) = f.blocks.get(&bid) {
|
||||
let mut insts = Vec::new();
|
||||
// Pre-scan: collect values defined anywhere in this block (to delay use-before-def copies)
|
||||
let mut block_defines: std::collections::HashSet<u32> =
|
||||
std::collections::HashSet::new();
|
||||
// Phase 131-13: Emit all instructions in MIR order (SSOT principle)
|
||||
// No reordering except PHI consolidation at block start (LLVM constraint)
|
||||
|
||||
// Step 1: Emit all PHI instructions first (LLVM requirement)
|
||||
for inst in &bb.instructions {
|
||||
match inst {
|
||||
I::UnaryOp { dst, .. }
|
||||
| I::Const { dst, .. }
|
||||
| I::BinOp { dst, .. }
|
||||
| I::Compare { dst, .. }
|
||||
| I::Call { dst: Some(dst), .. }
|
||||
| I::ExternCall { dst: Some(dst), .. }
|
||||
| I::BoxCall { dst: Some(dst), .. }
|
||||
| I::NewBox { dst, .. }
|
||||
| I::Phi { dst, .. } => {
|
||||
block_defines.insert(dst.as_u32());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
// Track which values have been emitted (to order copies after their sources)
|
||||
let mut emitted_defs: std::collections::HashSet<u32> =
|
||||
std::collections::HashSet::new();
|
||||
// PHI first(オプション)
|
||||
for inst in &bb.instructions {
|
||||
if let I::Copy { dst, src } = inst {
|
||||
// For copies whose source will be defined later in this block, delay emission
|
||||
let s = src.as_u32();
|
||||
if block_defines.contains(&s) && !emitted_defs.contains(&s) {
|
||||
// delayed; will be emitted after non-PHI pass
|
||||
} else {
|
||||
insts.push(
|
||||
json!({"op":"copy","dst": dst.as_u32(), "src": src.as_u32()}),
|
||||
);
|
||||
emitted_defs.insert(dst.as_u32());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if let I::Phi { dst, inputs, .. } = inst {
|
||||
let incoming: Vec<_> = inputs
|
||||
.iter()
|
||||
@ -250,20 +218,16 @@ pub fn emit_mir_json_for_harness(
|
||||
insts.push(phi_inst);
|
||||
}
|
||||
}
|
||||
// Non-PHI
|
||||
// Non-PHI
|
||||
let mut delayed_copies: Vec<(u32, u32)> = Vec::new();
|
||||
|
||||
// Step 2: Emit all non-PHI instructions in MIR order (no reordering!)
|
||||
for inst in &bb.instructions {
|
||||
match inst {
|
||||
I::Phi { .. } => {
|
||||
// Already emitted in step 1
|
||||
continue;
|
||||
}
|
||||
I::Copy { dst, src } => {
|
||||
let d = dst.as_u32();
|
||||
let s = src.as_u32();
|
||||
if block_defines.contains(&s) && !emitted_defs.contains(&s) {
|
||||
delayed_copies.push((d, s));
|
||||
} else {
|
||||
insts.push(json!({"op":"copy","dst": d, "src": s}));
|
||||
emitted_defs.insert(d);
|
||||
}
|
||||
insts.push(json!({"op":"copy","dst": dst.as_u32(), "src": src.as_u32()}));
|
||||
}
|
||||
I::UnaryOp { dst, op, operand } => {
|
||||
let kind = match op {
|
||||
@ -322,7 +286,6 @@ pub fn emit_mir_json_for_harness(
|
||||
"dst": dst.as_u32(),
|
||||
"target_type": ty_s,
|
||||
}));
|
||||
emitted_defs.insert(dst.as_u32());
|
||||
}
|
||||
I::BinOp { dst, op, lhs, rhs } => {
|
||||
let op_s = match op {
|
||||
@ -456,7 +419,6 @@ pub fn emit_mir_json_for_harness(
|
||||
}
|
||||
insts.push(obj);
|
||||
if let Some(d) = dst.map(|v| v.as_u32()) {
|
||||
emitted_defs.insert(d);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
@ -531,7 +493,6 @@ pub fn emit_mir_json_for_harness(
|
||||
}
|
||||
insts.push(obj);
|
||||
if let Some(d) = dst.map(|v| v.as_u32()) {
|
||||
emitted_defs.insert(d);
|
||||
}
|
||||
}
|
||||
I::NewBox {
|
||||
@ -541,7 +502,6 @@ pub fn emit_mir_json_for_harness(
|
||||
} => {
|
||||
let args_a: Vec<_> = args.iter().map(|v| json!(v.as_u32())).collect();
|
||||
insts.push(json!({"op":"newbox","type": box_type, "args": args_a, "dst": dst.as_u32()}));
|
||||
emitted_defs.insert(dst.as_u32());
|
||||
}
|
||||
I::Branch {
|
||||
condition,
|
||||
@ -559,10 +519,7 @@ pub fn emit_mir_json_for_harness(
|
||||
_ => { /* skip non-essential ops for initial harness */ }
|
||||
}
|
||||
}
|
||||
// Emit delayed copies now (sources should be available)
|
||||
for (d, s) in delayed_copies {
|
||||
insts.push(json!({"op":"copy","dst": d, "src": s}));
|
||||
}
|
||||
// Phase 131-13: Terminator emitted inline (no delayed copies)
|
||||
if let Some(term) = &bb.terminator {
|
||||
match term {
|
||||
I::Return { value } => insts.push(json!({"op":"ret","value": value.map(|v| v.as_u32())})),
|
||||
@ -650,27 +607,10 @@ pub fn emit_mir_json_for_harness_bin(
|
||||
for bid in ids {
|
||||
if let Some(bb) = f.blocks.get(&bid) {
|
||||
let mut insts = Vec::new();
|
||||
// Pre-scan to collect values defined in this block
|
||||
let mut block_defines: std::collections::HashSet<u32> =
|
||||
std::collections::HashSet::new();
|
||||
for inst in &bb.instructions {
|
||||
match inst {
|
||||
I::Copy { dst, .. }
|
||||
| I::Const { dst, .. }
|
||||
| I::BinOp { dst, .. }
|
||||
| I::Compare { dst, .. }
|
||||
| I::Call { dst: Some(dst), .. }
|
||||
| I::ExternCall { dst: Some(dst), .. }
|
||||
| I::BoxCall { dst: Some(dst), .. }
|
||||
| I::NewBox { dst, .. }
|
||||
| I::Phi { dst, .. } => {
|
||||
block_defines.insert(dst.as_u32());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
let mut emitted_defs: std::collections::HashSet<u32> =
|
||||
std::collections::HashSet::new();
|
||||
// Phase 131-13: Emit all instructions in MIR order (SSOT principle)
|
||||
// No reordering except PHI consolidation at block start (LLVM constraint)
|
||||
|
||||
// Step 1: Emit all PHI instructions first (LLVM requirement)
|
||||
for inst in &bb.instructions {
|
||||
if let I::Phi { dst, inputs, .. } = inst {
|
||||
let incoming: Vec<_> = inputs
|
||||
@ -693,21 +633,18 @@ pub fn emit_mir_json_for_harness_bin(
|
||||
}
|
||||
}
|
||||
insts.push(phi_inst);
|
||||
emitted_defs.insert(dst.as_u32());
|
||||
}
|
||||
}
|
||||
let mut delayed_copies: Vec<(u32, u32)> = Vec::new();
|
||||
|
||||
// Step 2: Emit all non-PHI instructions in MIR order (no reordering!)
|
||||
for inst in &bb.instructions {
|
||||
match inst {
|
||||
I::Phi { .. } => {
|
||||
// Already emitted in step 1
|
||||
continue;
|
||||
}
|
||||
I::Copy { dst, src } => {
|
||||
let d = dst.as_u32();
|
||||
let s = src.as_u32();
|
||||
if block_defines.contains(&s) && !emitted_defs.contains(&s) {
|
||||
delayed_copies.push((d, s));
|
||||
} else {
|
||||
insts.push(json!({"op":"copy","dst": d, "src": s}));
|
||||
emitted_defs.insert(d);
|
||||
}
|
||||
insts.push(json!({"op":"copy","dst": dst.as_u32(), "src": src.as_u32()}));
|
||||
}
|
||||
I::Const { dst, value } => {
|
||||
match value {
|
||||
@ -734,7 +671,6 @@ pub fn emit_mir_json_for_harness_bin(
|
||||
insts.push(json!({"op":"const","dst": dst.as_u32(), "value": {"type": "void", "value": 0}}));
|
||||
}
|
||||
}
|
||||
emitted_defs.insert(dst.as_u32());
|
||||
}
|
||||
I::BinOp { dst, op, lhs, rhs } => {
|
||||
let op_s = match op {
|
||||
@ -772,7 +708,6 @@ pub fn emit_mir_json_for_harness_bin(
|
||||
}
|
||||
}
|
||||
insts.push(obj);
|
||||
emitted_defs.insert(dst.as_u32());
|
||||
}
|
||||
I::Compare { dst, op, lhs, rhs } => {
|
||||
let op_s = match op {
|
||||
@ -784,7 +719,6 @@ pub fn emit_mir_json_for_harness_bin(
|
||||
C::Ge => ">=",
|
||||
};
|
||||
insts.push(json!({"op":"compare","operation": op_s, "lhs": lhs.as_u32(), "rhs": rhs.as_u32(), "dst": dst.as_u32()}));
|
||||
emitted_defs.insert(dst.as_u32());
|
||||
}
|
||||
I::Call {
|
||||
dst,
|
||||
@ -853,7 +787,6 @@ pub fn emit_mir_json_for_harness_bin(
|
||||
}
|
||||
insts.push(obj);
|
||||
if let Some(d) = dst.map(|v| v.as_u32()) {
|
||||
emitted_defs.insert(d);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
@ -889,7 +822,6 @@ pub fn emit_mir_json_for_harness_bin(
|
||||
}
|
||||
insts.push(obj);
|
||||
if let Some(d) = dst.map(|v| v.as_u32()) {
|
||||
emitted_defs.insert(d);
|
||||
}
|
||||
}
|
||||
I::BoxCall {
|
||||
@ -921,7 +853,6 @@ pub fn emit_mir_json_for_harness_bin(
|
||||
}
|
||||
insts.push(obj);
|
||||
if let Some(d) = dst.map(|v| v.as_u32()) {
|
||||
emitted_defs.insert(d);
|
||||
}
|
||||
}
|
||||
I::NewBox {
|
||||
@ -931,7 +862,6 @@ pub fn emit_mir_json_for_harness_bin(
|
||||
} => {
|
||||
let args_a: Vec<_> = args.iter().map(|v| json!(v.as_u32())).collect();
|
||||
insts.push(json!({"op":"newbox","type": box_type, "args": args_a, "dst": dst.as_u32()}));
|
||||
emitted_defs.insert(dst.as_u32());
|
||||
}
|
||||
I::Branch {
|
||||
condition,
|
||||
@ -949,10 +879,7 @@ pub fn emit_mir_json_for_harness_bin(
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
// Append delayed copies after their sources
|
||||
for (d, s) in delayed_copies {
|
||||
insts.push(json!({"op":"copy","dst": d, "src": s}));
|
||||
}
|
||||
// Phase 131-13: Terminator emitted inline (no delayed copies)
|
||||
if let Some(term) = &bb.terminator {
|
||||
match term {
|
||||
I::Return { value } => insts.push(json!({"op":"ret","value": value.map(|v| v.as_u32())})),
|
||||
|
||||
Reference in New Issue
Block a user