mirror of
https://github.com/roc-lang/roc.git
synced 2025-11-01 21:40:58 +00:00
Merge remote-tracking branch 'origin/trunk' into roc-std-platform
This commit is contained in:
commit
792936066c
139 changed files with 3832 additions and 1506 deletions
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue