///|
fn hot_test_roundtrip_body() -> Expr {
Expr::new([
Instruction::block(
BlockType::void_(),
Expr::new([
Instruction::local_get(LocalIdx::new(0)),
Instruction::if_(
BlockType::void_(),
[Instruction::nop()],
Some([Instruction::nop()]),
),
]),
),
Instruction::i32_const(I32(7)),
Instruction::return_(),
])
}
///|
test "hot_pop_values preserves stack order without touching prefix" {
let values = [1, 2, 3, 4]
let popped = hot_pop_values(values, 3)
@debug.assert_eq(popped, [2, 3, 4])
@debug.assert_eq(values, [1])
}
///|
test "hot lift and lower canonicalizes typed bodies" {
let func = hot_lift_body(
hot_test_roundtrip_body(),
HotLocals::new(param_count=1, locals=[]),
body_result_type=BlockType::val_type(ValType::i32()),
)
let lowered = hot_lower_body(func)
@debug.assert_eq(
lowered,
Expr::new([
Instruction::block(
BlockType::void_(),
Expr::new([
Instruction::local_get(LocalIdx::new(0)),
Instruction::if_(BlockType::void_(), [], Some([])),
]),
),
Instruction::i32_const(I32(7)),
Instruction::return_(),
]),
)
}
///|
test "hot root slots can be replaced directly" {
let func = hot_lift_body(
Expr::new([Instruction::nop()]),
HotLocals::new(param_count=0, locals=[]),
)
let root = hot_alloc_node(
func,
hot_make_simple_node(
HotOp::Return,
hot_type_void(func),
HOT_FLAG_TERMINATOR,
0,
0,
[],
),
)
hot_root_set(func, 0, root)
let lowered = hot_lower_body(func)
@debug.assert_eq(lowered, Expr::new([Instruction::return_()]))
}
///|
test "hot block children mutate by slot" {
let func = hot_lift_body(
Expr::new([
Instruction::block(BlockType::void_(), Expr::new([Instruction::nop()])),
]),
HotLocals::new(param_count=0, locals=[]),
)
let block = hot_root_get(func, 0)
let child = hot_alloc_node(
func,
hot_make_simple_node(
HotOp::Return,
hot_type_void(func),
HOT_FLAG_TERMINATOR,
0,
0,
[],
),
)
hot_child_set(func, block, 0, child)
let lowered = hot_lower_body(func)
@debug.assert_eq(
lowered,
Expr::new([
Instruction::block(
BlockType::void_(),
Expr::new([Instruction::return_()]),
),
]),
)
}