#![cfg(feature = "jit")]
use fusevm::{ChunkBuilder, JitCompiler, Op};
#[test]
fn block_jit_awk_sin_float_slot_matches_libm() {
use fusevm::SlotKind;
let mut b = ChunkBuilder::new();
b.emit(Op::GetSlot(0), 1);
b.emit(Op::AwkSin, 1);
b.emit(Op::Dup, 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::Pop, 1);
let chunk = b.build();
let jit = JitCompiler::new();
assert!(
jit.is_block_eligible(&chunk),
"AwkSin must be block-eligible"
);
let kinds = [SlotKind::Float];
let mut slots = vec![0.5f64.to_bits() as i64; 1];
let _ = jit
.try_run_block_eager_kinded(&chunk, &mut slots, &kinds)
.expect("AwkSin float-slot chunk must compile");
assert_eq!(
f64::from_bits(slots[0] as u64),
0.5f64.sin(),
"block JIT sin libcall must match libm"
);
}
#[test]
fn block_jit_awk_atan2_float_slots_match_libm() {
use fusevm::SlotKind;
let mut b = ChunkBuilder::new();
b.emit(Op::GetSlot(0), 1);
b.emit(Op::GetSlot(1), 1);
b.emit(Op::AwkAtan2, 1);
b.emit(Op::Dup, 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::Pop, 1);
let chunk = b.build();
let jit = JitCompiler::new();
assert!(jit.is_block_eligible(&chunk));
let kinds = [SlotKind::Float, SlotKind::Float];
let mut slots = vec![1.0f64.to_bits() as i64, 2.0f64.to_bits() as i64];
let _ = jit
.try_run_block_eager_kinded(&chunk, &mut slots, &kinds)
.expect("AwkAtan2 float-slot chunk must compile");
assert_eq!(
f64::from_bits(slots[0] as u64),
1.0f64.atan2(2.0),
"block JIT atan2 libcall must match libm (y=1, x=2)"
);
}
#[test]
fn block_jit_typed_returns_exact_float_result() {
use fusevm::{BlockNum, SlotKind};
let mut b = ChunkBuilder::new();
b.emit(Op::GetSlot(0), 1);
b.emit(Op::LoadFloat(1.5), 1);
b.emit(Op::Mul, 1);
b.emit(Op::LoadFloat(2.0), 1);
b.emit(Op::Add, 1);
let chunk = b.build();
let jit = JitCompiler::new();
assert!(jit.is_block_eligible(&chunk));
let kinds = [SlotKind::Float];
let mut slots = vec![4.0f64.to_bits() as i64; 1];
let out = jit
.try_run_block_eager_typed_kinded(&chunk, &mut slots, &kinds)
.expect("float-result chunk must compile");
match out {
BlockNum::Float(v) => assert_eq!(v, 4.0 * 1.5 + 2.0, "exact float result preserved"),
BlockNum::Int(n) => panic!("expected Float, got Int({n})"),
}
let mut slots2 = vec![4.0f64.to_bits() as i64; 1];
let truncated = jit
.try_run_block_eager_kinded(&chunk, &mut slots2, &kinds)
.expect("compile");
assert_eq!(
truncated,
(4.0 * 1.5 + 2.0) as i64,
"i64 entry truncates float"
);
}
#[test]
fn block_jit_awk_div_mod_float_slots_compute() {
use fusevm::SlotKind;
let run = |op: Op| -> f64 {
let mut b = ChunkBuilder::new();
b.emit(Op::GetSlot(0), 1);
b.emit(Op::GetSlot(1), 1);
b.emit(op.clone(), 1);
b.emit(Op::Dup, 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::Pop, 1);
let chunk = b.build();
let jit = JitCompiler::new();
assert!(
jit.is_block_eligible(&chunk),
"{op:?} must be block-eligible"
);
let kinds = [SlotKind::Float, SlotKind::Float];
let mut slots = vec![17.0f64.to_bits() as i64, 5.0f64.to_bits() as i64];
jit.try_run_block_eager_kinded(&chunk, &mut slots, &kinds)
.unwrap_or_else(|| panic!("{op:?} float-slot chunk must compile"));
f64::from_bits(slots[0] as u64)
};
assert_eq!(run(Op::AwkDivJit), 17.0 / 5.0, "17 / 5");
assert_eq!(run(Op::AwkModJit), 17.0 % 5.0, "17 % 5");
}
#[test]
fn block_jit_awk_div_mod_nonzero_no_trap() {
use fusevm::SlotKind;
let mut b = ChunkBuilder::new();
b.emit(Op::GetSlot(0), 1);
b.emit(Op::GetSlot(1), 1);
b.emit(Op::AwkDivJit, 1);
b.emit(Op::Dup, 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::Pop, 1);
let chunk = b.build();
let jit = JitCompiler::new();
let kinds = [SlotKind::Float, SlotKind::Float];
let mut slots = vec![10.0f64.to_bits() as i64, 4.0f64.to_bits() as i64];
jit.try_run_block_eager_kinded(&chunk, &mut slots, &kinds)
.expect("div chunk must compile");
assert_eq!(f64::from_bits(slots[0] as u64), 2.5);
}
#[test]
fn block_jit_awk_and_or_xor_float_slots_match_scalar() {
use fusevm::SlotKind;
let run = |op: Op| -> f64 {
let mut b = ChunkBuilder::new();
b.emit(Op::GetSlot(0), 1);
b.emit(Op::GetSlot(1), 1);
b.emit(op.clone(), 1);
b.emit(Op::Dup, 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::Pop, 1);
let chunk = b.build();
let jit = JitCompiler::new();
assert!(
jit.is_block_eligible(&chunk),
"{op:?} must be block-eligible"
);
let kinds = [SlotKind::Float, SlotKind::Float];
let mut slots = vec![12.0f64.to_bits() as i64, 10.0f64.to_bits() as i64];
jit.try_run_block_eager_kinded(&chunk, &mut slots, &kinds)
.unwrap_or_else(|| panic!("{op:?} float-slot chunk must compile"));
f64::from_bits(slots[0] as u64)
};
assert_eq!(run(Op::AwkAnd(2)), 8.0, "and(12,10)");
assert_eq!(run(Op::AwkOr(2)), 14.0, "or(12,10)");
assert_eq!(run(Op::AwkXor(2)), 6.0, "xor(12,10)");
}
#[test]
fn block_jit_awk_and_saturates_like_awkrs() {
use fusevm::SlotKind;
let mut b = ChunkBuilder::new();
b.emit(Op::GetSlot(0), 1);
b.emit(Op::GetSlot(0), 1);
b.emit(Op::AwkAnd(2), 1);
b.emit(Op::Dup, 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::Pop, 1);
let chunk = b.build();
let jit = JitCompiler::new();
let kinds = [SlotKind::Float];
let mut slots = vec![1e30f64.to_bits() as i64];
jit.try_run_block_eager_kinded(&chunk, &mut slots, &kinds)
.expect("saturating and() must compile");
let want = ((1e30f64.trunc() as i64) & (1e30f64.trunc() as i64)) as f64;
assert_eq!(f64::from_bits(slots[0] as u64), want);
}
#[test]
fn block_jit_sum_loop() {
let mut b = ChunkBuilder::new();
b.emit(Op::PushFrame, 1);
b.emit(Op::LoadInt(0), 1);
b.emit(Op::SetSlot(0), 1); b.emit(Op::LoadInt(0), 1);
b.emit(Op::SetSlot(1), 1); b.emit(Op::GetSlot(0), 1);
b.emit(Op::GetSlot(1), 1);
b.emit(Op::Add, 1);
b.emit(Op::SetSlot(0), 1); b.emit(Op::PreIncSlotVoid(1), 1); b.emit(Op::SlotLtIntJumpIfFalse(1, 100, 12), 1);
b.emit(Op::Jump(5), 1);
b.emit(Op::GetSlot(0), 1);
let chunk = b.build();
let jit = JitCompiler::new();
assert!(jit.is_block_eligible(&chunk));
let mut slots = vec![0i64; 4];
let result = jit.try_run_block_eager(&chunk, &mut slots).unwrap();
assert_eq!(result, 4950);
}
#[test]
fn block_jit_accum_sum_loop() {
let mut b = ChunkBuilder::new();
b.emit(Op::PushFrame, 1);
b.emit(Op::LoadInt(0), 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::LoadInt(0), 1);
b.emit(Op::SetSlot(1), 1);
b.emit(Op::AccumSumLoop(0, 1, 1000), 1);
b.emit(Op::GetSlot(0), 1);
let chunk = b.build();
let jit = JitCompiler::new();
assert!(jit.is_block_eligible(&chunk));
let mut slots = vec![0i64; 4];
let result = jit.try_run_block_eager(&chunk, &mut slots).unwrap();
assert_eq!(result, 499500);
}
#[test]
fn block_jit_conditional() {
let mut b = ChunkBuilder::new();
b.emit(Op::PushFrame, 1);
b.emit(Op::LoadInt(1), 1); b.emit(Op::JumpIfFalse(6), 1); b.emit(Op::LoadInt(42), 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::Jump(8), 1); b.emit(Op::LoadInt(99), 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::GetSlot(0), 1);
let chunk = b.build();
let jit = JitCompiler::new();
assert!(jit.is_block_eligible(&chunk));
let mut slots = vec![0i64; 4];
let result = jit.try_run_block_eager(&chunk, &mut slots).unwrap();
assert_eq!(result, 42);
}
#[test]
fn block_jit_conditional_false() {
let mut b = ChunkBuilder::new();
b.emit(Op::PushFrame, 1);
b.emit(Op::LoadInt(0), 1); b.emit(Op::JumpIfFalse(6), 1);
b.emit(Op::LoadInt(42), 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::Jump(8), 1);
b.emit(Op::LoadInt(99), 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::GetSlot(0), 1);
let chunk = b.build();
let jit = JitCompiler::new();
let mut slots = vec![0i64; 4];
let result = jit.try_run_block_eager(&chunk, &mut slots).unwrap();
assert_eq!(result, 99);
}
#[test]
fn block_jit_ternary_merge_carries_stack() {
let build_chunk = |cond: i64| {
let mut b = ChunkBuilder::new();
b.emit(Op::PushFrame, 1);
b.emit(Op::LoadInt(cond), 1); b.emit(Op::JumpIfFalse(5), 1); b.emit(Op::LoadInt(42), 1); b.emit(Op::Jump(6), 1); b.emit(Op::LoadInt(99), 1); b.emit(Op::SetSlot(0), 1); b.emit(Op::GetSlot(0), 1); b.build()
};
let jit = JitCompiler::new();
let chunk_t = build_chunk(1);
assert!(jit.is_block_eligible(&chunk_t));
let mut slots = vec![0i64; 4];
let result = jit
.try_run_block_eager(&chunk_t, &mut slots)
.expect("ternary-merge chunk must block-JIT compile (true)");
assert_eq!(result, 42, "cond=true must yield 42");
let chunk_f = build_chunk(0);
let mut slots = vec![0i64; 4];
let result = jit
.try_run_block_eager(&chunk_f, &mut slots)
.expect("ternary-merge chunk must block-JIT compile (false)");
assert_eq!(result, 99, "cond=false must yield 99");
}
#[test]
fn block_jit_ternary_as_return_jumps_to_end() {
let build_chunk = |cond: i64| {
let mut b = ChunkBuilder::new();
b.emit(Op::PushFrame, 1); b.emit(Op::LoadInt(cond), 1); b.emit(Op::JumpIfFalse(5), 1); b.emit(Op::LoadInt(42), 1); b.emit(Op::Jump(6), 1); b.emit(Op::LoadInt(99), 1); b.build()
};
let jit = JitCompiler::new();
let chunk_t = build_chunk(1);
assert!(jit.is_block_eligible(&chunk_t));
let mut slots = vec![0i64; 4];
let result = jit
.try_run_block_eager(&chunk_t, &mut slots)
.expect("ternary-as-return chunk must block-JIT compile (true)");
assert_eq!(result, 42);
let chunk_f = build_chunk(0);
let mut slots = vec![0i64; 4];
let result = jit
.try_run_block_eager(&chunk_f, &mut slots)
.expect("ternary-as-return chunk must block-JIT compile (false)");
assert_eq!(result, 99);
}
#[test]
fn block_jit_fused_backedge() {
let mut b = ChunkBuilder::new();
b.emit(Op::PushFrame, 1);
b.emit(Op::LoadInt(0), 1);
b.emit(Op::SetSlot(0), 1); b.emit(Op::LoadInt(0), 1);
b.emit(Op::SetSlot(1), 1); b.emit(Op::AddAssignSlotVoid(0, 1), 1); b.emit(Op::SlotIncLtIntJumpBack(1, 50, 5), 1); b.emit(Op::GetSlot(0), 1);
let chunk = b.build();
let jit = JitCompiler::new();
assert!(jit.is_block_eligible(&chunk));
let mut slots = vec![0i64; 4];
let result = jit.try_run_block_eager(&chunk, &mut slots).unwrap();
assert_eq!(result, 1225);
}
#[test]
fn block_jit_ineligible_with_print() {
let mut b = ChunkBuilder::new();
b.emit(Op::LoadInt(42), 1);
b.emit(Op::Print(1), 1); let chunk = b.build();
let jit = JitCompiler::new();
assert!(!jit.is_block_eligible(&chunk));
}
#[test]
fn partial_jit_finds_eligible_region() {
let mut b = ChunkBuilder::new();
b.emit(Op::PushFrame, 1);
b.emit(Op::LoadInt(0), 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::LoadInt(0), 1);
b.emit(Op::SetSlot(1), 1);
b.emit(Op::AccumSumLoop(0, 1, 100), 1);
b.emit(Op::GetSlot(0), 1);
b.emit(Op::Print(1), 1); b.emit(Op::GetSlot(0), 1);
let chunk = b.build();
let jit = JitCompiler::new();
assert!(!jit.is_block_eligible(&chunk));
let region = jit
.find_jit_region(&chunk)
.expect("should find eligible region");
assert_eq!(region, (0, 7));
}
#[test]
fn partial_jit_compiles_extracted_region() {
let mut b = ChunkBuilder::new();
b.emit(Op::PushFrame, 1);
b.emit(Op::LoadInt(0), 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::LoadInt(0), 1);
b.emit(Op::SetSlot(1), 1);
b.emit(Op::AccumSumLoop(0, 1, 100), 1);
b.emit(Op::GetSlot(0), 1);
b.emit(Op::Print(1), 1);
let chunk = b.build();
let jit = JitCompiler::new();
let (start, end) = jit.find_jit_region(&chunk).unwrap();
let sub_chunk = jit.extract_region(&chunk, start, end);
assert!(jit.is_block_eligible(&sub_chunk));
let mut slots = vec![0i64; 4];
let result = jit.try_run_block_eager(&sub_chunk, &mut slots).unwrap();
assert_eq!(result, 4950); }
#[test]
fn partial_jit_rebases_jumps() {
let mut b = ChunkBuilder::new();
b.emit(Op::PushFrame, 1);
b.emit(Op::LoadInt(0), 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::LoadInt(1), 1); b.emit(Op::JumpIfFalse(7), 1); b.emit(Op::LoadInt(42), 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::GetSlot(0), 1);
let chunk = b.build();
let jit = JitCompiler::new();
let (start, end) = jit.find_jit_region(&chunk).unwrap();
let sub_chunk = jit.extract_region(&chunk, start, end);
for op in &sub_chunk.ops {
if let Op::JumpIfFalse(t) = op {
assert_eq!(*t, 7 - start);
}
}
let mut slots = vec![0i64; 4];
let result = jit.try_run_block_eager(&sub_chunk, &mut slots).unwrap();
assert_eq!(result, 42);
}
#[test]
fn block_jit_slots_written_back() {
let mut b = ChunkBuilder::new();
b.emit(Op::PushFrame, 1);
b.emit(Op::LoadInt(0), 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::LoadInt(0), 1);
b.emit(Op::SetSlot(1), 1);
b.emit(Op::AccumSumLoop(0, 1, 10), 1);
b.emit(Op::GetSlot(0), 1);
let chunk = b.build();
let jit = JitCompiler::new();
let mut slots = vec![0i64; 4];
let _ = jit.try_run_block_eager(&chunk, &mut slots);
assert_eq!(slots[0], 45); assert_eq!(slots[1], 10); }
fn unique_sum_loop(limit: i32) -> fusevm::Chunk {
let mut b = ChunkBuilder::new();
b.emit(Op::PushFrame, 1);
b.emit(Op::LoadInt(0), 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::LoadInt(0), 1);
b.emit(Op::SetSlot(1), 1);
b.emit(Op::GetSlot(0), 1);
b.emit(Op::GetSlot(1), 1);
b.emit(Op::Add, 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::PreIncSlotVoid(1), 1);
b.emit(Op::SlotLtIntJumpIfFalse(1, limit, 12), 1);
b.emit(Op::Jump(5), 1);
b.emit(Op::GetSlot(0), 1);
b.build()
}
#[test]
fn block_threshold_is_configurable() {
use fusevm::TraceJitConfig;
let jit = JitCompiler::new();
jit.set_config(TraceJitConfig {
block_threshold: 1,
..TraceJitConfig::defaults()
});
let chunk = unique_sum_loop(37);
let mut slots = vec![0i64; 4];
assert_eq!(
jit.try_run_block(&chunk, &mut slots),
None,
"first call is below threshold 1"
);
assert_eq!(
jit.try_run_block(&chunk, &mut slots),
Some(666),
"second call should compile and run with block_threshold=1"
);
jit.set_config(TraceJitConfig {
block_threshold: 5,
..TraceJitConfig::defaults()
});
let chunk2 = unique_sum_loop(38);
let mut slots2 = vec![0i64; 4];
assert_eq!(jit.try_run_block(&chunk2, &mut slots2), None);
assert_eq!(jit.try_run_block(&chunk2, &mut slots2), None);
}
#[test]
fn block_jit_awk_int_truncates_float() {
let mut b = ChunkBuilder::new();
b.emit(Op::PushFrame, 1);
b.emit(Op::LoadFloat(3.7), 1);
b.emit(Op::AwkInt, 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::LoadFloat(-2.9), 1);
b.emit(Op::AwkInt, 1);
b.emit(Op::SetSlot(1), 1);
b.emit(Op::GetSlot(0), 1);
let chunk = b.build();
let jit = JitCompiler::new();
assert!(
jit.is_block_eligible(&chunk),
"AwkInt must be block-eligible"
);
let mut slots = vec![0i64; 4];
let result = jit.try_run_block_eager(&chunk, &mut slots).unwrap();
assert_eq!(result, 3, "int(3.7) == 3");
assert_eq!(slots[1], -2, "int(-2.9) == -2 (toward zero)");
}
#[test]
fn block_jit_awk_mkbool_returns_one_or_zero() {
use fusevm::SlotKind;
let mut b = ChunkBuilder::new();
b.emit(Op::PushFrame, 1);
b.emit(Op::LoadFloat(3.7), 1);
b.emit(Op::AwkMkbool, 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::LoadFloat(0.0), 1);
b.emit(Op::AwkMkbool, 1);
b.emit(Op::SetSlot(1), 1);
b.emit(Op::LoadFloat(-1.5), 1);
b.emit(Op::AwkMkbool, 1);
b.emit(Op::SetSlot(2), 1);
b.emit(Op::GetSlot(0), 1);
let chunk = b.build();
let jit = JitCompiler::new();
assert!(
jit.is_block_eligible(&chunk),
"AwkMkbool must be block-eligible"
);
let kinds = [
SlotKind::Float,
SlotKind::Float,
SlotKind::Float,
SlotKind::Float,
];
let mut slots = vec![0i64; 4];
jit.try_run_block_eager_kinded(&chunk, &mut slots, &kinds)
.expect("block JIT must compile");
assert_eq!(f64::from_bits(slots[0] as u64), 1.0, "mkbool(3.7) == 1.0");
assert_eq!(f64::from_bits(slots[1] as u64), 0.0, "mkbool(0.0) == 0.0");
assert_eq!(
f64::from_bits(slots[2] as u64),
1.0,
"mkbool(-1.5) == 1.0 (nonzero)"
);
}
#[test]
fn block_jit_awk_int_in_loop_matches_scalar() {
let mut b = ChunkBuilder::new();
b.emit(Op::PushFrame, 1);
b.emit(Op::LoadFloat(0.0), 1);
b.emit(Op::SetSlot(0), 1); b.emit(Op::LoadFloat(0.0), 1);
b.emit(Op::SetSlot(1), 1); b.emit(Op::GetSlot(0), 1);
b.emit(Op::GetSlot(1), 1);
b.emit(Op::LoadFloat(0.9), 1);
b.emit(Op::Add, 1);
b.emit(Op::AwkInt, 1); b.emit(Op::Add, 1);
b.emit(Op::SetSlot(0), 1); b.emit(Op::GetSlot(1), 1);
b.emit(Op::LoadFloat(1.0), 1);
b.emit(Op::Add, 1);
b.emit(Op::SetSlot(1), 1); b.emit(Op::GetSlot(1), 1);
b.emit(Op::LoadFloat(10.0), 1);
b.emit(Op::NumLt, 1);
b.emit(Op::JumpIfTrue(5), 1);
b.emit(Op::GetSlot(0), 1);
let chunk = b.build();
let jit = JitCompiler::new();
assert!(jit.is_block_eligible(&chunk));
let mut slots = vec![0i64; 4];
let result = jit.try_run_block_eager(&chunk, &mut slots).unwrap();
assert_eq!(result, 45);
}
#[test]
fn block_jit_awk_sqrt_jit_positive_matches_libm() {
use fusevm::SlotKind;
let mut b = ChunkBuilder::new();
b.emit(Op::GetSlot(0), 1);
b.emit(Op::AwkSqrtJit, 1);
b.emit(Op::Dup, 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::Pop, 1);
let chunk = b.build();
let jit = JitCompiler::new();
assert!(jit.is_block_eligible(&chunk));
let kinds = [SlotKind::Float];
let mut slots = vec![16.0f64.to_bits() as i64];
jit.try_run_block_eager_kinded(&chunk, &mut slots, &kinds)
.expect("AwkSqrtJit chunk must compile");
assert_eq!(f64::from_bits(slots[0] as u64), 4.0);
}
#[test]
fn block_jit_awk_sqrt_jit_negative_yields_nan() {
use fusevm::SlotKind;
let mut b = ChunkBuilder::new();
b.emit(Op::GetSlot(0), 1);
b.emit(Op::AwkSqrtJit, 1);
b.emit(Op::Dup, 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::Pop, 1);
let chunk = b.build();
let jit = JitCompiler::new();
let kinds = [SlotKind::Float];
let mut slots = vec![(-1.0f64).to_bits() as i64];
jit.try_run_block_eager_kinded(&chunk, &mut slots, &kinds)
.expect("AwkSqrtJit chunk must compile");
assert!(f64::from_bits(slots[0] as u64).is_nan());
}
#[test]
fn block_jit_awk_log_jit_e_yields_one() {
use fusevm::SlotKind;
let mut b = ChunkBuilder::new();
b.emit(Op::GetSlot(0), 1);
b.emit(Op::AwkLogJit, 1);
b.emit(Op::Dup, 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::Pop, 1);
let chunk = b.build();
let jit = JitCompiler::new();
let kinds = [SlotKind::Float];
let mut slots = vec![std::f64::consts::E.to_bits() as i64];
jit.try_run_block_eager_kinded(&chunk, &mut slots, &kinds)
.expect("AwkLogJit chunk must compile");
assert!((f64::from_bits(slots[0] as u64) - 1.0).abs() < 1e-10);
}
#[test]
fn block_jit_awk_lshift_jit_computes_shift() {
use fusevm::SlotKind;
let mut b = ChunkBuilder::new();
b.emit(Op::GetSlot(0), 1);
b.emit(Op::GetSlot(1), 1);
b.emit(Op::AwkLshiftJit, 1);
b.emit(Op::Dup, 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::Pop, 1);
let chunk = b.build();
let jit = JitCompiler::new();
let kinds = [SlotKind::Float, SlotKind::Float];
let mut slots = vec![1.0f64.to_bits() as i64, 4.0f64.to_bits() as i64];
jit.try_run_block_eager_kinded(&chunk, &mut slots, &kinds)
.expect("AwkLshiftJit chunk must compile");
assert_eq!(f64::from_bits(slots[0] as u64), 16.0);
}
#[test]
fn block_jit_awk_rshift_jit_computes_shift() {
use fusevm::SlotKind;
let mut b = ChunkBuilder::new();
b.emit(Op::GetSlot(0), 1);
b.emit(Op::GetSlot(1), 1);
b.emit(Op::AwkRshiftJit, 1);
b.emit(Op::Dup, 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::Pop, 1);
let chunk = b.build();
let jit = JitCompiler::new();
let kinds = [SlotKind::Float, SlotKind::Float];
let mut slots = vec![16.0f64.to_bits() as i64, 2.0f64.to_bits() as i64];
jit.try_run_block_eager_kinded(&chunk, &mut slots, &kinds)
.expect("AwkRshiftJit chunk must compile");
assert_eq!(f64::from_bits(slots[0] as u64), 4.0);
}
#[test]
fn block_jit_awk_compl_jit_negates_bits() {
use fusevm::SlotKind;
let mut b = ChunkBuilder::new();
b.emit(Op::GetSlot(0), 1);
b.emit(Op::AwkComplJit, 1);
b.emit(Op::Dup, 1);
b.emit(Op::SetSlot(0), 1);
b.emit(Op::Pop, 1);
let chunk = b.build();
let jit = JitCompiler::new();
let kinds = [SlotKind::Float];
let mut slots = vec![15.0f64.to_bits() as i64];
jit.try_run_block_eager_kinded(&chunk, &mut slots, &kinds)
.expect("AwkComplJit chunk must compile");
assert_eq!(f64::from_bits(slots[0] as u64), -16.0);
}