use crate::{ElementSegmentIdx, InstructionSet, TableIdx, TrapCode};
use rwasm_fuel_policy::{TABLE_ELEMS_PER_FUEL, TABLE_ELEMS_PER_FUEL_LOG2};
impl InstructionSet {
pub const MSH_TABLE_INIT_CHECKED: u32 = 2;
pub const MSH_TABLE_GROW_CHECKED: u32 = 2;
pub const MSH_TABLE_FILL_CHECKED: u32 = 2;
pub const MSH_TABLE_COPY_CHECKED: u32 = 2;
pub fn op_table_init_checked(
&mut self,
segment_index: ElementSegmentIdx,
table_index: TableIdx,
length: u32,
offset: u32,
inject_fuel_check: bool,
) {
self.op_local_get(1); self.op_local_get(3); self.op_i32_add(); self.op_i32_const(length); self.op_i32_gt_s(); self.op_br_if_eqz(2);
self.op_trap(TrapCode::TableOutOfBounds);
if offset > 0 {
self.op_i32_const(offset);
self.op_local_get(3);
self.op_i32_add();
self.op_local_set(2);
}
if inject_fuel_check {
self.op_local_get(1); self.op_i32_const(TABLE_ELEMS_PER_FUEL - 1); self.op_i32_add();
self.op_i32_const(TABLE_ELEMS_PER_FUEL_LOG2); self.op_i32_shr_u(); self.op_consume_fuel_stack();
}
self.op_table_init(segment_index);
self.op_table_get(table_index);
}
pub fn op_table_grow_checked(
&mut self,
table_idx: TableIdx,
limit_check: Option<u32>,
inject_fuel_check: bool,
) {
if let Some(limit) = limit_check {
self.op_local_get(1); self.op_table_size(table_idx); self.op_i32_add(); self.op_i32_const(limit); self.op_i32_gt_s(); self.op_br_if_eqz(5);
self.op_drop();
self.op_drop();
self.op_i32_const(u32::MAX);
self.op_br(if inject_fuel_check { 8 } else { 2 });
}
if inject_fuel_check {
self.op_local_get(1); self.op_i32_const(TABLE_ELEMS_PER_FUEL - 1); self.op_i32_add();
self.op_i32_const(TABLE_ELEMS_PER_FUEL_LOG2); self.op_i32_shr_u(); self.op_consume_fuel_stack();
}
self.op_table_grow(table_idx);
}
pub fn op_table_fill_checked(&mut self, table_idx: TableIdx, inject_fuel_check: bool) {
if inject_fuel_check {
self.op_local_get(1); self.op_i32_const(TABLE_ELEMS_PER_FUEL - 1); self.op_i32_add();
self.op_i32_const(TABLE_ELEMS_PER_FUEL_LOG2); self.op_i32_shr_u(); self.op_consume_fuel_stack();
}
self.op_table_fill(table_idx);
}
pub fn op_table_copy_checked(
&mut self,
dst_table_idx: TableIdx,
src_table_idx: TableIdx,
inject_fuel_check: bool,
) {
if inject_fuel_check {
self.op_local_get(1); self.op_i32_const(TABLE_ELEMS_PER_FUEL - 1); self.op_i32_add();
self.op_i32_const(TABLE_ELEMS_PER_FUEL_LOG2); self.op_i32_shr_u(); self.op_consume_fuel_stack();
}
self.op_table_copy(dst_table_idx, src_table_idx);
}
}