use crate::Result;
use crate::operand_stack::OperandStack;
use cranelift::codegen::ir::{FuncRef, MemFlags};
use cranelift::prelude::{FunctionBuilder, InstBuilder, types};
use ristretto_classfile::attributes::ArrayType;
pub(crate) fn newarray(
function_builder: &mut FunctionBuilder,
stack: &mut OperandStack,
atype: &ArrayType,
malloc: FuncRef,
) -> Result<()> {
let count = stack.pop_int(function_builder)?;
let element_size = match atype {
ArrayType::Boolean | ArrayType::Byte => 1,
ArrayType::Char | ArrayType::Short => 2,
ArrayType::Float | ArrayType::Int => 4,
ArrayType::Double | ArrayType::Long => 8,
};
let element_size_val = function_builder.ins().iconst(types::I64, element_size);
let count_i64 = function_builder.ins().uextend(types::I64, count);
let data_size = function_builder.ins().imul(count_i64, element_size_val);
let header_size = function_builder.ins().iconst(types::I64, 8);
let total_size = function_builder.ins().iadd(header_size, data_size);
let call = function_builder.ins().call(malloc, &[total_size]);
let array_ptr = function_builder.inst_results(call)[0];
function_builder
.ins()
.store(MemFlags::trusted(), count_i64, array_ptr, 0);
stack.push_long(function_builder, array_ptr)?;
Ok(())
}
pub(crate) fn arraylength(
function_builder: &mut FunctionBuilder,
stack: &mut OperandStack,
) -> Result<()> {
let array_ref = stack.pop_long(function_builder)?;
let length_i64 = function_builder
.ins()
.load(types::I64, MemFlags::trusted(), array_ref, 0);
let length = function_builder.ins().ireduce(types::I32, length_i64);
stack.push_int(function_builder, length)?;
Ok(())
}