mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
Make better use of Layout methods for GetTagId
This commit is contained in:
parent
b1a2a3ba07
commit
044a2015bb
1 changed files with 23 additions and 52 deletions
|
@ -1,6 +1,7 @@
|
||||||
use bumpalo::{self, collections::Vec};
|
use bumpalo::{self, collections::Vec};
|
||||||
|
|
||||||
use code_builder::Align;
|
use code_builder::Align;
|
||||||
|
use roc_builtins::bitcode::IntWidth;
|
||||||
use roc_collections::all::MutMap;
|
use roc_collections::all::MutMap;
|
||||||
use roc_module::low_level::LowLevel;
|
use roc_module::low_level::LowLevel;
|
||||||
use roc_module::symbol::{Interns, Symbol};
|
use roc_module::symbol::{Interns, Symbol};
|
||||||
|
@ -653,7 +654,7 @@ impl<'a> WasmBackend<'a> {
|
||||||
Expr::GetTagId {
|
Expr::GetTagId {
|
||||||
structure,
|
structure,
|
||||||
union_layout,
|
union_layout,
|
||||||
} => self.build_get_tag_id(*structure, union_layout, storage),
|
} => self.build_get_tag_id(*structure, union_layout),
|
||||||
|
|
||||||
Expr::UnionAtIndex {
|
Expr::UnionAtIndex {
|
||||||
structure,
|
structure,
|
||||||
|
@ -771,44 +772,24 @@ impl<'a> WasmBackend<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
structure: Symbol,
|
structure: Symbol,
|
||||||
union_layout: &UnionLayout<'a>,
|
union_layout: &UnionLayout<'a>,
|
||||||
tag_id_storage: &StoredValue,
|
|
||||||
) {
|
) {
|
||||||
use UnionLayout::*;
|
use UnionLayout::*;
|
||||||
|
|
||||||
// Variables to control shared logic
|
|
||||||
let mut wrapped_tags: Option<&[&[Layout]]> = None;
|
|
||||||
let mut get_pointer_bits = false;
|
|
||||||
let mut need_to_close_block = false;
|
let mut need_to_close_block = false;
|
||||||
|
|
||||||
match union_layout {
|
match union_layout {
|
||||||
NonRecursive(tags) => {
|
NonRecursive(_) => {}
|
||||||
wrapped_tags = Some(*tags);
|
Recursive(_) => {}
|
||||||
}
|
|
||||||
Recursive(tags) => {
|
|
||||||
if union_layout.stores_tag_id_as_data(PTR_SIZE) {
|
|
||||||
wrapped_tags = Some(*tags);
|
|
||||||
} else {
|
|
||||||
get_pointer_bits = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NonNullableUnwrapped(_) => {
|
NonNullableUnwrapped(_) => {
|
||||||
self.code_builder.i32_const(0);
|
self.code_builder.i32_const(0);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
NullableWrapped {
|
NullableWrapped { nullable_id, .. } => {
|
||||||
nullable_id,
|
|
||||||
other_tags,
|
|
||||||
} => {
|
|
||||||
self.storage
|
self.storage
|
||||||
.load_symbols(&mut self.code_builder, &[structure]);
|
.load_symbols(&mut self.code_builder, &[structure]);
|
||||||
self.code_builder.i32_eqz();
|
self.code_builder.i32_eqz();
|
||||||
self.code_builder.if_(BlockType::Value(ValueType::I32));
|
self.code_builder.if_(BlockType::Value(ValueType::I32));
|
||||||
self.code_builder.i32_const(*nullable_id as i32);
|
self.code_builder.i32_const(*nullable_id as i32);
|
||||||
self.code_builder.else_();
|
self.code_builder.else_();
|
||||||
if union_layout.stores_tag_id_as_data(PTR_SIZE) {
|
|
||||||
wrapped_tags = Some(*other_tags);
|
|
||||||
} else {
|
|
||||||
get_pointer_bits = true;
|
|
||||||
}
|
|
||||||
need_to_close_block = true;
|
need_to_close_block = true;
|
||||||
}
|
}
|
||||||
NullableUnwrapped { nullable_id, .. } => {
|
NullableUnwrapped { nullable_id, .. } => {
|
||||||
|
@ -821,37 +802,27 @@ impl<'a> WasmBackend<'a> {
|
||||||
self.code_builder.i32_const(!(*nullable_id) as i32);
|
self.code_builder.i32_const(!(*nullable_id) as i32);
|
||||||
self.code_builder.end();
|
self.code_builder.end();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Logic shared between different union layouts
|
|
||||||
|
|
||||||
if let Some(tags) = wrapped_tags {
|
|
||||||
// Fields are wrapped with a tag ID at the end
|
|
||||||
|
|
||||||
let (id_type, id_size) =
|
|
||||||
if let StoredValue::VirtualMachineStack {
|
|
||||||
value_type, size, ..
|
|
||||||
} = tag_id_storage
|
|
||||||
{
|
|
||||||
(value_type, size)
|
|
||||||
} else {
|
|
||||||
internal_error!("Unexpected storage for tag ID {:?}", tag_id_storage);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let (id_offset, id_align_bytes) = Self::union_fields_size_and_alignment(tags);
|
if union_layout.stores_tag_id_as_data(PTR_SIZE) {
|
||||||
let id_align = Align::from(id_align_bytes);
|
let (total_size, total_alignment) =
|
||||||
|
Layout::Union(*union_layout).stack_size_and_alignment(PTR_SIZE);
|
||||||
|
let id_offset = total_size - total_alignment;
|
||||||
|
let id_align = Align::from(total_alignment);
|
||||||
|
|
||||||
self.storage
|
self.storage
|
||||||
.load_symbols(&mut self.code_builder, &[structure]);
|
.load_symbols(&mut self.code_builder, &[structure]);
|
||||||
|
|
||||||
match (id_type, id_size) {
|
match union_layout.tag_id_builtin() {
|
||||||
(ValueType::I32, 1) => self.code_builder.i32_load8_u(id_align, id_offset),
|
Builtin::Bool | Builtin::Int(IntWidth::U8) => {
|
||||||
(ValueType::I32, 2) => self.code_builder.i32_load16_u(id_align, id_offset),
|
self.code_builder.i32_load8_u(id_align, id_offset)
|
||||||
(ValueType::I32, 4) => self.code_builder.i32_load(id_align, id_offset),
|
|
||||||
(ValueType::I64, 8) => self.code_builder.i64_load(id_align, id_offset),
|
|
||||||
_ => internal_error!("Invalid tag ID: type={:?} size={}", id_type, id_size),
|
|
||||||
}
|
}
|
||||||
} else if get_pointer_bits {
|
Builtin::Int(IntWidth::U16) => self.code_builder.i32_load16_u(id_align, id_offset),
|
||||||
|
Builtin::Int(IntWidth::U32) => self.code_builder.i32_load(id_align, id_offset),
|
||||||
|
Builtin::Int(IntWidth::U64) => self.code_builder.i64_load(id_align, id_offset),
|
||||||
|
x => internal_error!("Unexpected layout for tag union id {:?}", x),
|
||||||
|
}
|
||||||
|
} else if union_layout.stores_tag_id_in_pointer(PTR_SIZE) {
|
||||||
self.storage
|
self.storage
|
||||||
.load_symbols(&mut self.code_builder, &[structure]);
|
.load_symbols(&mut self.code_builder, &[structure]);
|
||||||
self.code_builder.i32_const(3);
|
self.code_builder.i32_const(3);
|
||||||
|
@ -912,7 +883,7 @@ impl<'a> WasmBackend<'a> {
|
||||||
let from_ptr = if stores_tag_id_in_pointer {
|
let from_ptr = if stores_tag_id_in_pointer {
|
||||||
let ptr = self.storage.create_anonymous_local(ValueType::I32);
|
let ptr = self.storage.create_anonymous_local(ValueType::I32);
|
||||||
self.code_builder.get_local(tag_local_id);
|
self.code_builder.get_local(tag_local_id);
|
||||||
self.code_builder.i32_const(-4);
|
self.code_builder.i32_const(-4); // 11111111...1100
|
||||||
self.code_builder.i32_and();
|
self.code_builder.i32_and();
|
||||||
self.code_builder.set_local(ptr);
|
self.code_builder.set_local(ptr);
|
||||||
ptr
|
ptr
|
||||||
|
@ -1254,7 +1225,7 @@ impl<'a> WasmBackend<'a> {
|
||||||
|
|
||||||
/// Debug utility
|
/// Debug utility
|
||||||
///
|
///
|
||||||
/// if _debug_current_proc_is("#UserApp_foo_1") {
|
/// if self._debug_current_proc_is("#UserApp_foo_1") {
|
||||||
/// self.code_builder._debug_assert_i32(0x1234);
|
/// self.code_builder._debug_assert_i32(0x1234);
|
||||||
/// }
|
/// }
|
||||||
fn _debug_current_proc_is(&self, linker_name: &'static str) -> bool {
|
fn _debug_current_proc_is(&self, linker_name: &'static str) -> bool {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue