Merge remote-tracking branch 'origin/trunk' into roc-std-platform

This commit is contained in:
Folkert 2022-08-07 13:28:03 +02:00
commit 792936066c
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
139 changed files with 3832 additions and 1506 deletions

View file

@ -715,7 +715,7 @@ impl<'a> WasmBackend<'a> {
let mut current_stmt = stmt;
while let Stmt::Let(sym, expr, layout, following) = current_stmt {
if DEBUG_SETTINGS.let_stmt_ir {
println!("let {:?} = {}", sym, expr.to_pretty(200)); // ignore `following`! Too confusing otherwise.
print!("\nlet {:?} = {}", sym, expr.to_pretty(200));
}
let kind = match following {
@ -1479,7 +1479,14 @@ impl<'a> WasmBackend<'a> {
// length of the list
self.code_builder.get_local(stack_local_id);
self.code_builder.i32_const(elems.len() as i32);
self.code_builder.i32_store(Align::Bytes4, stack_offset + 4);
self.code_builder
.i32_store(Align::Bytes4, stack_offset + 4 * Builtin::WRAPPER_LEN);
// capacity of the list
self.code_builder.get_local(stack_local_id);
self.code_builder.i32_const(elems.len() as i32);
self.code_builder
.i32_store(Align::Bytes4, stack_offset + 4 * Builtin::WRAPPER_CAPACITY);
let mut elem_offset = 0;
@ -1521,12 +1528,14 @@ impl<'a> WasmBackend<'a> {
if let StoredValue::StackMemory { location, .. } = storage {
let (local_id, offset) = location.local_and_offset(self.storage.stack_frame_pointer);
// This is a minor cheat.
// What we want to write to stack memory is { elements: null, length: 0 }
// But instead of two 32-bit stores, we can do a single 64-bit store.
// Store 12 bytes of zeros { elements: null, length: 0, capacity: 0 }
debug_assert_eq!(Builtin::LIST_WORDS, 3);
self.code_builder.get_local(local_id);
self.code_builder.i64_const(0);
self.code_builder.i64_store(Align::Bytes4, offset);
self.code_builder.get_local(local_id);
self.code_builder.i32_const(0);
self.code_builder.i32_store(Align::Bytes4, offset + 8);
} else {
internal_error!("Unexpected storage for {:?}", sym)
}
@ -1566,13 +1575,24 @@ impl<'a> WasmBackend<'a> {
StoredValue::Local { local_id, .. } => {
// Tag is stored as a heap pointer.
if let Some(reused) = maybe_reused {
// Reuse an existing heap allocation
// Reuse an existing heap allocation, if one is available (not NULL at runtime)
self.storage.load_symbols(&mut self.code_builder, &[reused]);
self.code_builder.if_();
{
self.storage.load_symbols(&mut self.code_builder, &[reused]);
self.code_builder.set_local(local_id);
}
self.code_builder.else_();
{
self.allocate_with_refcount(Some(data_size), data_alignment, 1);
self.code_builder.set_local(local_id);
}
self.code_builder.end();
} else {
// Call the allocator to get a memory address.
self.allocate_with_refcount(Some(data_size), data_alignment, 1);
self.code_builder.set_local(local_id);
}
self.code_builder.set_local(local_id);
(local_id, 0)
}
StoredValue::VirtualMachineStack { .. } => {
@ -1618,7 +1638,7 @@ impl<'a> WasmBackend<'a> {
self.code_builder.i64_store(id_align, id_offset);
}
}
} else if stores_tag_id_in_pointer {
} else if stores_tag_id_in_pointer && tag_id != 0 {
self.code_builder.get_local(local_id);
self.code_builder.i32_const(tag_id as i32);
self.code_builder.i32_or();

View file

@ -256,7 +256,7 @@ pub struct WasmDebugSettings {
pub const DEBUG_SETTINGS: WasmDebugSettings = WasmDebugSettings {
proc_start_end: false && cfg!(debug_assertions),
user_procs_ir: false && cfg!(debug_assertions), // Note: we also have `ROC_PRINT_IR_AFTER_SPECIALIZATION=1 cargo test-gen-wasm`
user_procs_ir: false && cfg!(debug_assertions), // Note: we also have `ROC_PRINT_IR_AFTER_REFCOUNT=1 cargo test-gen-wasm`
helper_procs_ir: false && cfg!(debug_assertions),
let_stmt_ir: false && cfg!(debug_assertions),
instructions: false && cfg!(debug_assertions),

View file

@ -13,7 +13,7 @@ use crate::backend::{ProcLookupData, ProcSource, WasmBackend};
use crate::layout::{CallConv, StackMemoryFormat, WasmLayout};
use crate::storage::{AddressValue, StackMemoryLocation, StoredValue};
use crate::wasm_module::{Align, LocalId, ValueType};
use crate::TARGET_INFO;
use crate::{PTR_TYPE, TARGET_INFO};
/// Number types used for Wasm code gen
/// Unlike other enums, this contains no details about layout or storage.
@ -368,25 +368,27 @@ impl<'a> LowLevelCall<'a> {
location.local_and_offset(backend.storage.stack_frame_pointer);
backend.code_builder.get_local(fp);
backend.code_builder.i32_load(Align::Bytes4, offset);
} else {
internal_error!("Lists are always stored in stack memory");
}
// Target element heap pointer
// Get pointer to target element and save it to a local var
backend.code_builder.i32_add(); // base + index*size
let elem_local = backend.storage.create_anonymous_local(PTR_TYPE);
backend.code_builder.set_local(elem_local);
// Copy to stack
// Copy element value from heap to stack
backend.storage.copy_value_from_memory(
&mut backend.code_builder,
self.ret_symbol,
AddressValue::Loaded,
AddressValue::NotLoaded(elem_local),
0,
);
// Increment refcount
if self.ret_layout.is_refcounted() {
let inc_fn = backend.get_refcount_fn_index(self.ret_layout, HelperOp::Inc);
backend
.storage
.load_symbols(&mut backend.code_builder, &[self.ret_symbol]);
backend.code_builder.get_local(elem_local);
backend.code_builder.i32_const(1);
backend.code_builder.call(inc_fn, 2, false);
}
@ -2350,7 +2352,13 @@ fn list_map_n<'a>(
// If we have lists of different lengths, we may need to decrement
let num_wasm_args = if arg_elem_layouts.len() > 1 {
for el in arg_elem_layouts.iter() {
let idx = backend.get_refcount_fn_index(*el, HelperOp::Dec);
// The dec function will be passed a pointer to the element within the list, not the element itself!
// Here we wrap the layout in a Struct to ensure we get the right code gen
let el_ptr = Layout::Struct {
field_order_hash: FieldOrderHash::from_ordered_fields(&[]),
field_layouts: backend.env.arena.alloc([*el]),
};
let idx = backend.get_refcount_fn_index(el_ptr, HelperOp::Dec);
let ptr = backend.get_fn_ptr(idx);
backend.code_builder.i32_const(ptr);
}

View file

@ -621,7 +621,7 @@ impl<'a> Storage<'a> {
to_symbol: Symbol,
from_addr: AddressValue,
from_offset: u32,
) -> u32 {
) {
let to_storage = self.get(&to_symbol).to_owned();
match to_storage {
StoredValue::StackMemory {
@ -656,7 +656,6 @@ impl<'a> Storage<'a> {
alignment_bytes,
},
);
size
}
StoredValue::VirtualMachineStack {
@ -690,8 +689,6 @@ impl<'a> Storage<'a> {
if let StoredValue::Local { local_id, .. } = to_storage {
code_builder.set_local(local_id);
}
size
}
}
}