use crate::Result;
use crate::instruction::{
ThrowContext, emit_bci, emit_null_check, emit_pending_exception_check, single_inst_result,
};
use crate::operand_stack::OperandStack;
use crate::runtime_helpers::RuntimeHelpers;
use cranelift::codegen::ir::Value;
use cranelift::prelude::{FunctionBuilder, InstBuilder};
use ristretto_classfile::attributes::ArrayType;
pub(crate) fn newarray(
function_builder: &mut FunctionBuilder,
stack: &mut OperandStack,
atype: &ArrayType,
context_pointer: Value,
helpers: &RuntimeHelpers,
) -> Result<()> {
let count = stack.pop_int(function_builder)?;
let helper = match atype {
ArrayType::Boolean => helpers.new_bool_array,
ArrayType::Byte => helpers.new_byte_array,
ArrayType::Char => helpers.new_char_array,
ArrayType::Short => helpers.new_short_array,
ArrayType::Int => helpers.new_int_array,
ArrayType::Long => helpers.new_long_array,
ArrayType::Float => helpers.new_float_array,
ArrayType::Double => helpers.new_double_array,
};
let call = function_builder
.ins()
.call(helper, &[context_pointer, count]);
let array_ptr = single_inst_result(function_builder, call)?;
stack.push_object(function_builder, array_ptr)?;
Ok(())
}
pub(crate) fn arraylength(
function_builder: &mut FunctionBuilder,
stack: &mut OperandStack,
helpers: &RuntimeHelpers,
context_pointer: Value,
throw_context: &ThrowContext<'_>,
) -> Result<()> {
let array_ref = stack.pop_object(function_builder)?;
emit_null_check(
function_builder,
stack,
helpers,
context_pointer,
throw_context,
array_ref,
)?;
let bci = emit_bci(function_builder, throw_context);
let call = function_builder
.ins()
.call(helpers.arraylength, &[context_pointer, bci, array_ref]);
let length = single_inst_result(function_builder, call)?;
emit_pending_exception_check(
function_builder,
stack,
helpers,
context_pointer,
throw_context,
)?;
stack.push_int(function_builder, length)?;
Ok(())
}