#[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"); } }