add List.getUnsafe

This commit is contained in:
Brendan Hansknecht 2022-02-19 17:07:53 -08:00
parent c47209c54a
commit f8e12da809
3 changed files with 64 additions and 4 deletions

View file

@ -897,6 +897,39 @@ impl<
fn build_list_len(&mut self, dst: &Symbol, list: &Symbol) {
self.storage_manager.list_len(&mut self.buf, dst, list);
}
fn build_list_get_unsafe(
&mut self,
dst: &Symbol,
list: &Symbol,
index: &Symbol,
ret_layout: &Layout<'a>,
) {
let (base_offset, _) = self.storage_manager.stack_offset_and_size(list);
let index_reg = self
.storage_manager
.load_to_general_reg(&mut self.buf, index);
let ret_stack_size = ret_layout.stack_size(self.storage_manager.target_info());
// TODO: This can be optimized with smarter instructions.
// Also can probably be moved into storage manager at least partly.
self.storage_manager.with_tmp_general_reg(
&mut self.buf,
|storage_manager, buf, list_ptr| {
ASM::mov_reg64_base32(buf, list_ptr, base_offset as i32);
storage_manager.with_tmp_general_reg(buf, |storage_manager, buf, tmp| {
ASM::mov_reg64_imm64(buf, tmp, ret_stack_size as i64);
ASM::imul_reg64_reg64_reg64(buf, tmp, tmp, index_reg);
ASM::add_reg64_reg64_reg64(buf, tmp, tmp, list_ptr);
match ret_layout {
single_register_integers!() if ret_stack_size == 8 => {
let dst_reg = storage_manager.claim_general_reg(buf, dst);
ASM::mov_reg64_mem64_offset32(buf, dst_reg, list_ptr, 0);
}
x => internal_error!("Loading list element with layout: {:?}", x),
}
});
},
);
}
fn build_ptr_cast(&mut self, dst: &Symbol, src: &Symbol) {
// We may not strictly need an instruction here.
@ -1073,12 +1106,19 @@ impl<
}
#[macro_export]
macro_rules! sign_extended_builtins {
macro_rules! sign_extended_int_builtins {
() => {
Builtin::Int(IntWidth::I8 | IntWidth::I16 | IntWidth::I32 | IntWidth::I64 | IntWidth::I128)
};
}
#[macro_export]
macro_rules! zero_extended_int_builtins {
() => {
Builtin::Int(IntWidth::U8 | IntWidth::U16 | IntWidth::U32 | IntWidth::U64 | IntWidth::U128)
};
}
#[macro_export]
macro_rules! single_register_int_builtins {
() => {

View file

@ -1,6 +1,6 @@
use crate::{
generic64::{Assembler, CallConv, RegTrait},
sign_extended_builtins, single_register_floats, single_register_int_builtins,
sign_extended_int_builtins, single_register_floats, single_register_int_builtins,
single_register_integers, single_register_layouts, Env,
};
use bumpalo::collections::Vec;
@ -181,6 +181,10 @@ impl<
self.fn_call_stack_size = 0;
}
pub fn target_info(&self) -> TargetInfo {
self.target_info
}
pub fn stack_size(&self) -> u32 {
self.stack_size
}
@ -551,7 +555,7 @@ impl<
size,
sign_extend: matches!(
layout,
Layout::Builtin(sign_extended_builtins!())
Layout::Builtin(sign_extended_int_builtins!())
),
}
} else {
@ -598,7 +602,7 @@ impl<
Stack(ReferencedPrimitive {
base_offset: union_offset + id_offset as i32,
size,
sign_extend: matches!(id_builtin, sign_extended_builtins!()),
sign_extend: matches!(id_builtin, sign_extended_int_builtins!()),
}),
);
}

View file

@ -558,6 +558,14 @@ trait Backend<'a> {
);
self.build_list_len(sym, &args[0])
}
LowLevel::ListGetUnsafe => {
debug_assert_eq!(
2,
args.len(),
"ListLen: expected to have exactly two arguments"
);
self.build_list_get_unsafe(sym, &args[0], &args[1], ret_layout)
}
LowLevel::ListSet => self.build_fn_call(
sym,
bitcode::LIST_SET.to_string(),
@ -703,6 +711,14 @@ trait Backend<'a> {
/// build_list_len returns the length of a list.
fn build_list_len(&mut self, dst: &Symbol, list: &Symbol);
/// build_list_get_unsafe loads the element from the list at the index.
fn build_list_get_unsafe(
&mut self,
dst: &Symbol,
list: &Symbol,
index: &Symbol,
ret_layout: &Layout<'a>,
);
/// build_refcount_getptr loads the pointer to the reference count of src into dst.
fn build_ptr_cast(&mut self, dst: &Symbol, src: &Symbol);