mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 04:08:19 +00:00
Merge remote-tracking branch 'origin/trunk' into list-unreachable
This commit is contained in:
commit
762258ae20
58 changed files with 926 additions and 2075 deletions
|
@ -1304,35 +1304,49 @@ impl<'a> WasmBackend<'a> {
|
|||
storage: &StoredValue,
|
||||
fields: &'a [Symbol],
|
||||
) {
|
||||
if matches!(layout, Layout::Struct { .. }) {
|
||||
match storage {
|
||||
StoredValue::StackMemory { location, size, .. } => {
|
||||
if *size > 0 {
|
||||
let (local_id, struct_offset) =
|
||||
location.local_and_offset(self.storage.stack_frame_pointer);
|
||||
let mut field_offset = struct_offset;
|
||||
for field in fields.iter() {
|
||||
field_offset += self.storage.copy_value_to_memory(
|
||||
&mut self.code_builder,
|
||||
local_id,
|
||||
field_offset,
|
||||
*field,
|
||||
);
|
||||
match layout {
|
||||
Layout::Struct { .. } => {
|
||||
match storage {
|
||||
StoredValue::StackMemory { location, size, .. } => {
|
||||
if *size > 0 {
|
||||
let (local_id, struct_offset) =
|
||||
location.local_and_offset(self.storage.stack_frame_pointer);
|
||||
let mut field_offset = struct_offset;
|
||||
for field in fields.iter() {
|
||||
field_offset += self.storage.copy_value_to_memory(
|
||||
&mut self.code_builder,
|
||||
local_id,
|
||||
field_offset,
|
||||
*field,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Zero-size struct. No code to emit.
|
||||
// These values are purely conceptual, they only exist internally in the compiler
|
||||
}
|
||||
} else {
|
||||
// Zero-size struct. No code to emit.
|
||||
// These values are purely conceptual, they only exist internally in the compiler
|
||||
}
|
||||
_ => {
|
||||
internal_error!("Cannot create struct {:?} with storage {:?}", sym, storage)
|
||||
}
|
||||
};
|
||||
}
|
||||
Layout::LambdaSet(lambdaset) => {
|
||||
self.expr_struct(sym, &lambdaset.runtime_representation(), storage, fields)
|
||||
}
|
||||
_ => {
|
||||
if !fields.is_empty() {
|
||||
// Struct expression but not Struct layout => single element. Copy it.
|
||||
let field_storage = self.storage.get(&fields[0]).to_owned();
|
||||
self.storage.clone_value(
|
||||
&mut self.code_builder,
|
||||
storage,
|
||||
&field_storage,
|
||||
fields[0],
|
||||
);
|
||||
} else {
|
||||
// Empty record. Nothing to do.
|
||||
}
|
||||
_ => internal_error!("Cannot create struct {:?} with storage {:?}", sym, storage),
|
||||
};
|
||||
} else if !fields.is_empty() {
|
||||
// Struct expression but not Struct layout => single element. Copy it.
|
||||
let field_storage = self.storage.get(&fields[0]).to_owned();
|
||||
self.storage
|
||||
.clone_value(&mut self.code_builder, storage, &field_storage, fields[0]);
|
||||
} else {
|
||||
// Empty record. Nothing to do.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -217,6 +217,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
match self.lowlevel {
|
||||
// Str
|
||||
StrConcat => self.load_args_and_call_zig(backend, bitcode::STR_CONCAT),
|
||||
StrToScalars => self.load_args_and_call_zig(backend, bitcode::STR_TO_SCALARS),
|
||||
StrJoinWith => self.load_args_and_call_zig(backend, bitcode::STR_JOIN_WITH),
|
||||
StrIsEmpty => match backend.storage.get(&self.arguments[0]) {
|
||||
StoredValue::StackMemory { location, .. } => {
|
||||
|
@ -230,8 +231,8 @@ impl<'a> LowLevelCall<'a> {
|
|||
_ => internal_error!("invalid storage for Str"),
|
||||
},
|
||||
StrStartsWith => self.load_args_and_call_zig(backend, bitcode::STR_STARTS_WITH),
|
||||
StrStartsWithCodePt => {
|
||||
self.load_args_and_call_zig(backend, bitcode::STR_STARTS_WITH_CODE_PT)
|
||||
StrStartsWithScalar => {
|
||||
self.load_args_and_call_zig(backend, bitcode::STR_STARTS_WITH_SCALAR)
|
||||
}
|
||||
StrEndsWith => self.load_args_and_call_zig(backend, bitcode::STR_ENDS_WITH),
|
||||
StrSplit => {
|
||||
|
@ -288,8 +289,8 @@ impl<'a> LowLevelCall<'a> {
|
|||
|
||||
ListIsUnique => self.load_args_and_call_zig(backend, bitcode::LIST_IS_UNIQUE),
|
||||
|
||||
ListMap | ListMap2 | ListMap3 | ListMap4 | ListMapWithIndex | ListWalk
|
||||
| ListWalkUntil | ListWalkBackwards | ListSortWith | ListFindUnsafe | DictWalk => {
|
||||
ListMap | ListMap2 | ListMap3 | ListMap4 | ListMapWithIndex | ListSortWith
|
||||
| DictWalk => {
|
||||
internal_error!("HigherOrder lowlevels should not be handled here")
|
||||
}
|
||||
|
||||
|
@ -556,7 +557,50 @@ impl<'a> LowLevelCall<'a> {
|
|||
|
||||
backend.call_host_fn_after_loading_args(bitcode::LIST_SUBLIST, 8, false);
|
||||
}
|
||||
ListDropAt => todo!("{:?}", self.lowlevel),
|
||||
ListDropAt => {
|
||||
// List.dropAt : List elem, Nat -> List elem
|
||||
let list: Symbol = self.arguments[0];
|
||||
let drop_index: Symbol = self.arguments[1];
|
||||
|
||||
let elem_layout = unwrap_list_elem_layout(self.ret_layout);
|
||||
let (elem_width, elem_align) = elem_layout.stack_size_and_alignment(TARGET_INFO);
|
||||
|
||||
// The refcount function receives a pointer to an element in the list
|
||||
// This is the same as a Struct containing the element
|
||||
let in_memory_layout = Layout::Struct {
|
||||
field_order_hash: FieldOrderHash::from_ordered_fields(&[]),
|
||||
field_layouts: backend.env.arena.alloc([*elem_layout]),
|
||||
};
|
||||
let dec_fn = backend.get_refcount_fn_index(in_memory_layout, HelperOp::Dec);
|
||||
let dec_fn_ptr = backend.get_fn_ptr(dec_fn);
|
||||
|
||||
// Zig arguments Wasm types
|
||||
// (return pointer) i32
|
||||
// list: RocList, i64, i32
|
||||
// element_width: usize, i32
|
||||
// alignment: u32, i32
|
||||
// drop_index: usize, i32
|
||||
// dec: Dec, i32
|
||||
|
||||
// Load the return pointer and the list
|
||||
backend.storage.load_symbols_for_call(
|
||||
backend.env.arena,
|
||||
&mut backend.code_builder,
|
||||
&[list],
|
||||
self.ret_symbol,
|
||||
&WasmLayout::new(&self.ret_layout),
|
||||
CallConv::Zig,
|
||||
);
|
||||
|
||||
backend.code_builder.i32_const(elem_width as i32);
|
||||
backend.code_builder.i32_const(elem_align as i32);
|
||||
backend
|
||||
.storage
|
||||
.load_symbols(&mut backend.code_builder, &[drop_index]);
|
||||
backend.code_builder.i32_const(dec_fn_ptr);
|
||||
|
||||
backend.call_host_fn_after_loading_args(bitcode::LIST_DROP_AT, 6, false);
|
||||
}
|
||||
ListSwap => {
|
||||
// List.swap : List elem, Nat, Nat -> List elem
|
||||
let list: Symbol = self.arguments[0];
|
||||
|
@ -2028,15 +2072,7 @@ pub fn call_higher_order_lowlevel<'a>(
|
|||
*owns_captured_environment,
|
||||
),
|
||||
|
||||
ListMapWithIndex { .. }
|
||||
| ListWalk { .. }
|
||||
| ListWalkUntil { .. }
|
||||
| ListWalkBackwards { .. }
|
||||
| ListSortWith { .. }
|
||||
| ListAny { .. }
|
||||
| ListAll { .. }
|
||||
| ListFindUnsafe { .. }
|
||||
| DictWalk { .. } => todo!("{:?}", op),
|
||||
ListMapWithIndex { .. } | ListSortWith { .. } | DictWalk { .. } => todo!("{:?}", op),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,11 +3,12 @@ use roc_std::{RocDec, RocList, RocOrder, RocStr};
|
|||
pub trait Wasm32Sized: Sized {
|
||||
const SIZE_OF_WASM: usize;
|
||||
const ALIGN_OF_WASM: usize;
|
||||
const ACTUAL_WIDTH: usize = if (Self::SIZE_OF_WASM % Self::ALIGN_OF_WASM) == 0 {
|
||||
Self::SIZE_OF_WASM
|
||||
} else {
|
||||
Self::SIZE_OF_WASM + (Self::ALIGN_OF_WASM - (Self::SIZE_OF_WASM % Self::ALIGN_OF_WASM))
|
||||
};
|
||||
const ACTUAL_WIDTH: usize =
|
||||
if (Self::ALIGN_OF_WASM == 0) || (Self::SIZE_OF_WASM % Self::ALIGN_OF_WASM) == 0 {
|
||||
Self::SIZE_OF_WASM
|
||||
} else {
|
||||
Self::SIZE_OF_WASM + (Self::ALIGN_OF_WASM - (Self::SIZE_OF_WASM % Self::ALIGN_OF_WASM))
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! wasm32_sized_primitive {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue