Files
hakorune/src/tests/llvm_bitops_test.rs
nyash-codex 7a1a4bd964 refactor(mir): loop_builder.rs モジュール化 - 6ファイルに分割
## リファクタリング内容

### ファイル構造変更
- `src/mir/loop_builder.rs` (1515行) 削除
- `src/mir/loop_builder/` ディレクトリ新設(6ファイル、1529行)

### 新規モジュール構成

1. **mod.rs** (6,293行 → 実際は約150行)
   - モジュール定義とre-export
   - LoopBuilder構造体定義

2. **loop_form.rs** (25,988行 → 実際は約650行)
   - メインループlowering pipeline
   - デバッグ/実験フラグ集約

3. **if_lowering.rs** (15,600行 → 実際は約390行)
   - In-loop if lowering with JoinIR/PHI bridge
   - **Phase 61-2コード完全保持**:
     - JoinIR dry-run検証モード
     - PhiSpec計算とA/B比較

4. **phi_ops.rs** (12,844行 → 実際は約320行)
   - PHI emit helpers
   - LoopFormOps/PhiBuilderOps impls

5. **control.rs** (4,261行 → 実際は約107行)
   - break/continue capture
   - predecessor bookkeeping

6. **statements.rs** (1,673行 → 実際は約42行)
   - loop-body statement lowering entry point

7. **README.md** (752行 → 実際は約19行)
   - モジュール責務とサブモジュール説明

### 設計原則

- **責務分離**: CFG構築/PHI生成/制御フロー/文処理を分離
- **Phase 61-2保持**: if_lowering.rsにJoinIR dry-run完全移行
- **phi_core委譲**: PHI構築ロジックは`phi_core`に委譲

## テスト結果

- Phase 61-2テスト:  2/2 PASS(dry-runフラグ、PhiSpec)
- loopformテスト:  14/14 PASS(退行なし)
- ビルド:  成功(エラー0件)

## 統計

- **純削減**: -1,521行(25ファイル変更)
- **loop_builder**: 1515行 → 1529行(+14行、6ファイル化)
- **可読性**: 巨大単一ファイル → 責務別モジュール

## ChatGPT設計・Claude確認

大規模リファクタリングをChatGPTが実施、Claudeが検証完了。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 12:44:40 +09:00

182 lines
5.0 KiB
Rust

#[test]
fn llvm_bitops_compile_and_exec() {
use crate::backend::VM;
use crate::mir::{
BasicBlockId, BinaryOp, ConstValue, FunctionSignature, MirFunction, MirInstruction,
MirModule, MirType,
};
// Build MIR: compute sum of bitwise/shift ops -> 48
let sig = FunctionSignature {
name: "Main.main".into(),
params: vec![],
return_type: MirType::Integer,
effects: Default::default(),
};
let mut f = MirFunction::new(sig, BasicBlockId::new(0));
let bb = f.entry_block;
// Constants
let c5 = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::Const {
dst: c5,
value: ConstValue::Integer(5),
});
let c3 = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::Const {
dst: c3,
value: ConstValue::Integer(3),
});
let c2 = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::Const {
dst: c2,
value: ConstValue::Integer(2),
});
let c1 = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::Const {
dst: c1,
value: ConstValue::Integer(1),
});
let c32 = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::Const {
dst: c32,
value: ConstValue::Integer(32),
});
let c5_sh = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::Const {
dst: c5_sh,
value: ConstValue::Integer(5),
});
let c3_sh = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::Const {
dst: c3_sh,
value: ConstValue::Integer(3),
});
// a = 5 & 3 -> 1
let a = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::BinOp {
dst: a,
op: BinaryOp::BitAnd,
lhs: c5,
rhs: c3,
});
// b = 5 | 2 -> 7
let b = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::BinOp {
dst: b,
op: BinaryOp::BitOr,
lhs: c5,
rhs: c2,
});
// c = 5 ^ 1 -> 4
let c = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::BinOp {
dst: c,
op: BinaryOp::BitXor,
lhs: c5,
rhs: c1,
});
// d = 1 << 5 -> 32
let d = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::BinOp {
dst: d,
op: BinaryOp::Shl,
lhs: c1,
rhs: c5_sh,
});
// e = 32 >> 3 -> 4
let e = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::BinOp {
dst: e,
op: BinaryOp::Shr,
lhs: c32,
rhs: c3_sh,
});
// sum = a + b + c + d + e
let t1 = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::BinOp {
dst: t1,
op: BinaryOp::Add,
lhs: a,
rhs: b,
});
let t2 = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::BinOp {
dst: t2,
op: BinaryOp::Add,
lhs: t1,
rhs: c,
});
let t3 = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::BinOp {
dst: t3,
op: BinaryOp::Add,
lhs: t2,
rhs: d,
});
let sum = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::BinOp {
dst: sum,
op: BinaryOp::Add,
lhs: t3,
rhs: e,
});
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::Return { value: Some(sum) });
let mut m = MirModule::new("bitops".into());
m.add_function(f);
// VM executes to 48
let mut vm = VM::new();
let out = vm.execute_module(&m).expect("vm exec");
assert_eq!(out.to_string_box().value, "48");
// LLVM: ensure lowering/emit succeeds; compile_and_execute should also return 48 (via MIR interpreter fallback)
#[cfg(feature = "llvm-inkwell-legacy")]
{
use crate::backend::llvm;
let tmp = format!(
"{}/target/aot_objects/test_bitops",
env!("CARGO_MANIFEST_DIR")
);
llvm::compile_to_object(&m, &format!("{}.o", tmp)).expect("llvm emit");
let out2 = llvm::compile_and_execute(&m, &tmp).expect("llvm compile&exec");
assert_eq!(out2.to_string_box().value, "48");
}
}