use crate::instruction::ThrowContext;
use crate::instruction::object::{array_load, array_store};
use crate::local_variables::LocalVariables;
use crate::operand_stack::OperandStack;
use crate::runtime_helpers::RuntimeHelpers;
use crate::{Result, jit_value};
use cranelift::codegen::ir::{MemFlagsData, Value};
use cranelift::prelude::{FunctionBuilder, InstBuilder, types};
pub(crate) fn iconst_m1(
function_builder: &mut FunctionBuilder,
stack: &mut OperandStack,
) -> Result<()> {
let constant = function_builder.ins().iconst(types::I32, -1);
stack.push_int(function_builder, constant)?;
Ok(())
}
pub(crate) fn iconst_0(
function_builder: &mut FunctionBuilder,
stack: &mut OperandStack,
) -> Result<()> {
let constant = function_builder.ins().iconst(types::I32, 0);
stack.push_int(function_builder, constant)?;
Ok(())
}
pub(crate) fn iconst_1(
function_builder: &mut FunctionBuilder,
stack: &mut OperandStack,
) -> Result<()> {
let constant = function_builder.ins().iconst(types::I32, 1);
stack.push_int(function_builder, constant)?;
Ok(())
}
pub(crate) fn iconst_2(
function_builder: &mut FunctionBuilder,
stack: &mut OperandStack,
) -> Result<()> {
let constant = function_builder.ins().iconst(types::I32, 2);
stack.push_int(function_builder, constant)?;
Ok(())
}
pub(crate) fn iconst_3(
function_builder: &mut FunctionBuilder,
stack: &mut OperandStack,
) -> Result<()> {
let constant = function_builder.ins().iconst(types::I32, 3);
stack.push_int(function_builder, constant)?;
Ok(())
}
pub(crate) fn iconst_4(
function_builder: &mut FunctionBuilder,
stack: &mut OperandStack,
) -> Result<()> {
let constant = function_builder.ins().iconst(types::I32, 4);
stack.push_int(function_builder, constant)?;
Ok(())
}
pub(crate) fn iconst_5(
function_builder: &mut FunctionBuilder,
stack: &mut OperandStack,
) -> Result<()> {
let constant = function_builder.ins().iconst(types::I32, 5);
stack.push_int(function_builder, constant)?;
Ok(())
}
pub(crate) fn iload(
function_builder: &mut FunctionBuilder,
locals: &mut LocalVariables,
stack: &mut OperandStack,
index: u8,
) -> Result<()> {
let index = usize::from(index);
let value = locals.get_int(function_builder, index)?;
stack.push_int(function_builder, value)?;
Ok(())
}
pub(crate) fn iload_w(
function_builder: &mut FunctionBuilder,
locals: &mut LocalVariables,
stack: &mut OperandStack,
index: u16,
) -> Result<()> {
let index = usize::from(index);
let value = locals.get_int(function_builder, index)?;
stack.push_int(function_builder, value)?;
Ok(())
}
pub(crate) fn iload_0(
function_builder: &mut FunctionBuilder,
locals: &mut LocalVariables,
stack: &mut OperandStack,
) -> Result<()> {
let value = locals.get_int(function_builder, 0)?;
stack.push_int(function_builder, value)?;
Ok(())
}
pub(crate) fn iload_1(
function_builder: &mut FunctionBuilder,
locals: &mut LocalVariables,
stack: &mut OperandStack,
) -> Result<()> {
let value = locals.get_int(function_builder, 1)?;
stack.push_int(function_builder, value)?;
Ok(())
}
pub(crate) fn iload_2(
function_builder: &mut FunctionBuilder,
locals: &mut LocalVariables,
stack: &mut OperandStack,
) -> Result<()> {
let value = locals.get_int(function_builder, 2)?;
stack.push_int(function_builder, value)?;
Ok(())
}
pub(crate) fn iload_3(
function_builder: &mut FunctionBuilder,
locals: &mut LocalVariables,
stack: &mut OperandStack,
) -> Result<()> {
let value = locals.get_int(function_builder, 3)?;
stack.push_int(function_builder, value)?;
Ok(())
}
pub(crate) fn istore(
function_builder: &mut FunctionBuilder,
locals: &mut LocalVariables,
stack: &mut OperandStack,
index: u8,
) -> Result<()> {
let value = stack.pop_int(function_builder)?;
let index = usize::from(index);
locals.set_int(function_builder, index, value)?;
Ok(())
}
pub(crate) fn istore_w(
function_builder: &mut FunctionBuilder,
locals: &mut LocalVariables,
stack: &mut OperandStack,
index: u16,
) -> Result<()> {
let value = stack.pop_int(function_builder)?;
let index = usize::from(index);
locals.set_int(function_builder, index, value)?;
Ok(())
}
pub(crate) fn istore_0(
function_builder: &mut FunctionBuilder,
locals: &mut LocalVariables,
stack: &mut OperandStack,
) -> Result<()> {
let value = stack.pop_int(function_builder)?;
locals.set_int(function_builder, 0, value)?;
Ok(())
}
pub(crate) fn istore_1(
function_builder: &mut FunctionBuilder,
locals: &mut LocalVariables,
stack: &mut OperandStack,
) -> Result<()> {
let value = stack.pop_int(function_builder)?;
locals.set_int(function_builder, 1, value)?;
Ok(())
}
pub(crate) fn istore_2(
function_builder: &mut FunctionBuilder,
locals: &mut LocalVariables,
stack: &mut OperandStack,
) -> Result<()> {
let value = stack.pop_int(function_builder)?;
locals.set_int(function_builder, 2, value)?;
Ok(())
}
pub(crate) fn istore_3(
function_builder: &mut FunctionBuilder,
locals: &mut LocalVariables,
stack: &mut OperandStack,
) -> Result<()> {
let value = stack.pop_int(function_builder)?;
locals.set_int(function_builder, 3, value)?;
Ok(())
}
pub(crate) fn iaload(
function_builder: &mut FunctionBuilder,
stack: &mut OperandStack,
helpers: &RuntimeHelpers,
context_pointer: Value,
throw_context: &ThrowContext<'_>,
) -> Result<()> {
let value = array_load(
function_builder,
stack,
helpers,
context_pointer,
throw_context,
helpers.iaload,
)?;
stack.push_int(function_builder, value)?;
Ok(())
}
pub(crate) fn iastore(
function_builder: &mut FunctionBuilder,
stack: &mut OperandStack,
helpers: &RuntimeHelpers,
context_pointer: Value,
throw_context: &ThrowContext<'_>,
) -> Result<()> {
let value = stack.pop_int(function_builder)?;
array_store(
function_builder,
stack,
helpers,
context_pointer,
throw_context,
helpers.iastore,
value,
)
}
pub(crate) fn iadd(function_builder: &mut FunctionBuilder, stack: &mut OperandStack) -> Result<()> {
let value2 = stack.pop_int(function_builder)?;
let value1 = stack.pop_int(function_builder)?;
let value = function_builder.ins().iadd(value1, value2);
stack.push_int(function_builder, value)?;
Ok(())
}
pub(crate) fn isub(function_builder: &mut FunctionBuilder, stack: &mut OperandStack) -> Result<()> {
let value2 = stack.pop_int(function_builder)?;
let value1 = stack.pop_int(function_builder)?;
let value = function_builder.ins().isub(value1, value2);
stack.push_int(function_builder, value)?;
Ok(())
}
pub(crate) fn imul(function_builder: &mut FunctionBuilder, stack: &mut OperandStack) -> Result<()> {
let value2 = stack.pop_int(function_builder)?;
let value1 = stack.pop_int(function_builder)?;
let value = function_builder.ins().imul(value1, value2);
stack.push_int(function_builder, value)?;
Ok(())
}
pub(crate) fn idiv(function_builder: &mut FunctionBuilder, stack: &mut OperandStack) -> Result<()> {
let value2 = stack.pop_int(function_builder)?;
let value1 = stack.pop_int(function_builder)?;
let value = function_builder.ins().sdiv(value1, value2);
stack.push_int(function_builder, value)?;
Ok(())
}
pub(crate) fn irem(function_builder: &mut FunctionBuilder, stack: &mut OperandStack) -> Result<()> {
let value2 = stack.pop_int(function_builder)?;
let value1 = stack.pop_int(function_builder)?;
let value = function_builder.ins().srem(value1, value2);
stack.push_int(function_builder, value)?;
Ok(())
}
pub(crate) fn ineg(function_builder: &mut FunctionBuilder, stack: &mut OperandStack) -> Result<()> {
let value = stack.pop_int(function_builder)?;
let value = function_builder.ins().ineg(value);
stack.push_int(function_builder, value)?;
Ok(())
}
pub(crate) fn ishl(function_builder: &mut FunctionBuilder, stack: &mut OperandStack) -> Result<()> {
let value2 = stack.pop_int(function_builder)?;
let value1 = stack.pop_int(function_builder)?;
let mask = function_builder.ins().iconst(types::I32, 0x1f);
let value2 = function_builder.ins().band(value2, mask);
let value = function_builder.ins().ishl(value1, value2);
stack.push_int(function_builder, value)?;
Ok(())
}
pub(crate) fn ishr(function_builder: &mut FunctionBuilder, stack: &mut OperandStack) -> Result<()> {
let value2 = stack.pop_int(function_builder)?;
let value1 = stack.pop_int(function_builder)?;
let mask = function_builder.ins().iconst(types::I32, 0x1f);
let value2 = function_builder.ins().band(value2, mask);
let value = function_builder.ins().sshr(value1, value2);
stack.push_int(function_builder, value)?;
Ok(())
}
pub(crate) fn iushr(
function_builder: &mut FunctionBuilder,
stack: &mut OperandStack,
) -> Result<()> {
let value2 = stack.pop_int(function_builder)?;
let value1 = stack.pop_int(function_builder)?;
let mask = function_builder.ins().iconst(types::I32, 0x1f);
let value2 = function_builder.ins().band(value2, mask);
let value = function_builder.ins().ushr(value1, value2);
stack.push_int(function_builder, value)?;
Ok(())
}
pub(crate) fn iand(function_builder: &mut FunctionBuilder, stack: &mut OperandStack) -> Result<()> {
let value2 = stack.pop_int(function_builder)?;
let value1 = stack.pop_int(function_builder)?;
let value = function_builder.ins().band(value1, value2);
stack.push_int(function_builder, value)?;
Ok(())
}
pub(crate) fn ior(function_builder: &mut FunctionBuilder, stack: &mut OperandStack) -> Result<()> {
let value2 = stack.pop_int(function_builder)?;
let value1 = stack.pop_int(function_builder)?;
let value = function_builder.ins().bor(value1, value2);
stack.push_int(function_builder, value)?;
Ok(())
}
pub(crate) fn ixor(function_builder: &mut FunctionBuilder, stack: &mut OperandStack) -> Result<()> {
let value2 = stack.pop_int(function_builder)?;
let value1 = stack.pop_int(function_builder)?;
let value = function_builder.ins().bxor(value1, value2);
stack.push_int(function_builder, value)?;
Ok(())
}
pub(crate) fn iinc(
function_builder: &mut FunctionBuilder,
locals: &mut LocalVariables,
index: u8,
constant: i8,
) -> Result<()> {
let index = usize::from(index);
let value = locals.get_int(function_builder, index)?;
let constant = i64::from(constant);
let value = function_builder.ins().iadd_imm_s(value, constant);
locals.set_int(function_builder, index, value)?;
Ok(())
}
pub(crate) fn iinc_w(
function_builder: &mut FunctionBuilder,
locals: &mut LocalVariables,
index: u16,
constant: i16,
) -> Result<()> {
let index = usize::from(index);
let value = locals.get_int(function_builder, index)?;
let constant = i64::from(constant);
let value = function_builder.ins().iadd_imm_s(value, constant);
locals.set_int(function_builder, index, value)?;
Ok(())
}
pub(crate) fn ireturn(
function_builder: &mut FunctionBuilder,
stack: &mut OperandStack,
return_pointer: Value,
) -> Result<()> {
let value = stack.pop_int(function_builder)?;
let value = function_builder.ins().sextend(types::I64, value);
let discriminate = i64::from(jit_value::I32);
let discriminate = function_builder.ins().iconst(types::I8, discriminate);
function_builder
.ins()
.store(MemFlagsData::new(), discriminate, return_pointer, 0);
function_builder
.ins()
.store(MemFlagsData::new(), value, return_pointer, 8);
function_builder.ins().return_(&[]);
Ok(())
}