mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
wasm backend struggles
This commit is contained in:
parent
9c85fb90d3
commit
51f3752c94
7 changed files with 262 additions and 35 deletions
|
@ -1084,7 +1084,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
|
|||
tag_id,
|
||||
union_layout,
|
||||
index,
|
||||
} => todo!(),
|
||||
} => self.expr_union_field_ptr_at_index(*structure, *tag_id, union_layout, *index, sym),
|
||||
|
||||
Expr::ExprBox { symbol: arg_sym } => self.expr_box(sym, *arg_sym, layout, storage),
|
||||
|
||||
|
@ -1878,11 +1878,81 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
|
|||
);
|
||||
}
|
||||
|
||||
fn expr_union_field_ptr_at_index(
|
||||
&mut self,
|
||||
structure: Symbol,
|
||||
tag_id: TagIdIntType,
|
||||
union_layout: &UnionLayout<'a>,
|
||||
index: u64,
|
||||
symbol: Symbol,
|
||||
) {
|
||||
use UnionLayout::*;
|
||||
|
||||
debug_assert!(!union_layout.tag_is_null(tag_id));
|
||||
|
||||
let tag_index = tag_id as usize;
|
||||
let field_layouts = match union_layout {
|
||||
NonRecursive(tags) => tags[tag_index],
|
||||
Recursive(tags) => tags[tag_index],
|
||||
NonNullableUnwrapped(layouts) => *layouts,
|
||||
NullableWrapped {
|
||||
other_tags,
|
||||
nullable_id,
|
||||
} => {
|
||||
let index = if tag_index > *nullable_id as usize {
|
||||
tag_index - 1
|
||||
} else {
|
||||
tag_index
|
||||
};
|
||||
other_tags[index]
|
||||
}
|
||||
NullableUnwrapped { other_fields, .. } => *other_fields,
|
||||
};
|
||||
|
||||
let field_offset: u32 = field_layouts
|
||||
.iter()
|
||||
.take(index as usize)
|
||||
.map(|field_layout| self.layout_interner.stack_size(*field_layout))
|
||||
.sum();
|
||||
|
||||
// Get pointer and offset to the tag's data
|
||||
let structure_storage = self.storage.get(&structure).to_owned();
|
||||
let stored_with_local = self.storage.ensure_value_has_local(
|
||||
&mut self.code_builder,
|
||||
structure,
|
||||
structure_storage,
|
||||
);
|
||||
let (tag_local_id, tag_offset) = match stored_with_local {
|
||||
StoredValue::StackMemory { location, .. } => {
|
||||
location.local_and_offset(self.storage.stack_frame_pointer)
|
||||
}
|
||||
StoredValue::Local { local_id, .. } => (local_id, 0),
|
||||
StoredValue::VirtualMachineStack { .. } => {
|
||||
internal_error!("{:?} should have a local variable", structure)
|
||||
}
|
||||
};
|
||||
|
||||
let stores_tag_id_in_pointer = union_layout.stores_tag_id_in_pointer(TARGET_INFO);
|
||||
|
||||
let from_addr_val = if stores_tag_id_in_pointer {
|
||||
self.code_builder.get_local(tag_local_id);
|
||||
self.code_builder.i32_const(-4); // 11111111...1100
|
||||
self.code_builder.i32_and();
|
||||
AddressValue::Loaded
|
||||
} else {
|
||||
AddressValue::NotLoaded(tag_local_id)
|
||||
};
|
||||
|
||||
let from_offset = tag_offset + field_offset;
|
||||
|
||||
self.code_builder.i32_const(from_offset as i32)
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* Box
|
||||
*******************************************************************/
|
||||
|
||||
fn expr_box(
|
||||
pub(crate) fn expr_box(
|
||||
&mut self,
|
||||
ret_sym: Symbol,
|
||||
arg_sym: Symbol,
|
||||
|
@ -1915,7 +1985,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
|
|||
.copy_value_to_memory(&mut self.code_builder, ptr_local_id, 0, arg_sym);
|
||||
}
|
||||
|
||||
fn expr_unbox(&mut self, ret_sym: Symbol, arg_sym: Symbol) {
|
||||
pub(crate) fn expr_unbox(&mut self, ret_sym: Symbol, arg_sym: Symbol) {
|
||||
let (from_addr_val, from_offset) = match self.storage.get(&arg_sym) {
|
||||
StoredValue::VirtualMachineStack { .. } => {
|
||||
self.storage
|
||||
|
|
|
@ -249,7 +249,7 @@ pub const DEBUG_SETTINGS: WasmDebugSettings = WasmDebugSettings {
|
|||
let_stmt_ir: false && cfg!(debug_assertions),
|
||||
instructions: false && cfg!(debug_assertions),
|
||||
storage_map: false && cfg!(debug_assertions),
|
||||
keep_test_binary: false && cfg!(debug_assertions), // see also ROC_WRITE_FINAL_WASM
|
||||
keep_test_binary: true && cfg!(debug_assertions), // see also ROC_WRITE_FINAL_WASM
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -11,7 +11,7 @@ use roc_mono::low_level::HigherOrder;
|
|||
|
||||
use crate::backend::{ProcLookupData, ProcSource, WasmBackend};
|
||||
use crate::layout::{CallConv, StackMemoryFormat, WasmLayout};
|
||||
use crate::storage::{AddressValue, StackMemoryLocation, StoredValue};
|
||||
use crate::storage::{AddressValue, StackMemoryLocation, StoredValue, StoredVarKind};
|
||||
use crate::PTR_TYPE;
|
||||
use roc_wasm_module::{Align, LocalId, ValueType};
|
||||
|
||||
|
@ -1960,9 +1960,81 @@ impl<'a> LowLevelCall<'a> {
|
|||
backend.storage.load_symbols(code_builder, self.arguments);
|
||||
}
|
||||
|
||||
PtrStore => todo!("{:?}", self.lowlevel),
|
||||
PtrLoad => todo!("{:?}", self.lowlevel),
|
||||
PtrToStackValue => todo!("{:?}", self.lowlevel),
|
||||
PtrStore => {
|
||||
// PtrStore : Ptr a, a -> {}
|
||||
let ptr_sym = self.arguments[0];
|
||||
let value_sym = self.arguments[1];
|
||||
let layout = self.ret_layout;
|
||||
|
||||
// create a local variable for the heap pointer
|
||||
let ptr_local_id = match backend.storage.ensure_value_has_local(
|
||||
&mut backend.code_builder,
|
||||
ptr_sym,
|
||||
self.ret_storage.clone(),
|
||||
) {
|
||||
StoredValue::Local { local_id, .. } => local_id,
|
||||
StoredValue::StackMemory { location, .. } => {
|
||||
location
|
||||
.local_and_offset(backend.storage.stack_frame_pointer)
|
||||
.0
|
||||
}
|
||||
other => internal_error!(
|
||||
"Struct should be allocated in stack memory, but it's in {:?}",
|
||||
other
|
||||
),
|
||||
};
|
||||
|
||||
dbg!(ptr_local_id);
|
||||
|
||||
// store the pointer value from the value stack into the local variable
|
||||
backend.code_builder.set_local(ptr_local_id);
|
||||
|
||||
// copy the argument to the pointer address
|
||||
backend.storage.copy_value_to_memory(
|
||||
&mut backend.code_builder,
|
||||
ptr_local_id,
|
||||
0,
|
||||
value_sym,
|
||||
);
|
||||
}
|
||||
PtrLoad => backend.expr_unbox(self.ret_symbol, self.arguments[0]),
|
||||
PtrToStackValue => {
|
||||
let arg = self.arguments[0];
|
||||
let arg_layout = backend.storage.symbol_layouts.get(&arg).unwrap();
|
||||
|
||||
let (size, alignment_bytes) = backend
|
||||
.layout_interner
|
||||
.stack_size_and_alignment(*arg_layout);
|
||||
|
||||
let (frame_ptr, offset) = backend
|
||||
.storage
|
||||
.allocate_anonymous_stack_memory(size, alignment_bytes);
|
||||
|
||||
backend.storage.copy_value_to_memory(
|
||||
&mut backend.code_builder,
|
||||
frame_ptr,
|
||||
offset,
|
||||
arg,
|
||||
);
|
||||
|
||||
// create a local variable for the pointer
|
||||
let ptr_local_id = match backend.storage.ensure_value_has_local(
|
||||
&mut backend.code_builder,
|
||||
self.ret_symbol,
|
||||
self.ret_storage.clone(),
|
||||
) {
|
||||
StoredValue::Local { local_id, .. } => local_id,
|
||||
_ => internal_error!("A pointer will always be an i32"),
|
||||
};
|
||||
|
||||
// store the pointer value from the value stack into the local variable
|
||||
dbg!(offset, size, alignment_bytes);
|
||||
|
||||
backend.code_builder.get_local(frame_ptr);
|
||||
backend.code_builder.i32_const(offset as i32);
|
||||
backend.code_builder.i32_add();
|
||||
backend.code_builder.set_local(ptr_local_id);
|
||||
}
|
||||
|
||||
Hash => todo!("{:?}", self.lowlevel),
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue