mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
Implement Expr::StructAtIndex for wasm dev backend
This commit is contained in:
parent
4aa6ec1d64
commit
29d355c4d6
3 changed files with 97 additions and 13 deletions
|
@ -22,8 +22,8 @@ use crate::wasm_module::{
|
||||||
LocalId, Signature, SymInfo, ValueType,
|
LocalId, Signature, SymInfo, ValueType,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
copy_memory, CopyMemoryConfig, Env, BUILTINS_IMPORT_MODULE_NAME, MEMORY_NAME, PTR_TYPE,
|
copy_memory, CopyMemoryConfig, Env, BUILTINS_IMPORT_MODULE_NAME, MEMORY_NAME, PTR_SIZE,
|
||||||
STACK_POINTER_GLOBAL_ID, STACK_POINTER_NAME,
|
PTR_TYPE, STACK_POINTER_GLOBAL_ID, STACK_POINTER_NAME,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The memory address where the constants data will be loaded during module instantiation.
|
/// The memory address where the constants data will be loaded during module instantiation.
|
||||||
|
@ -540,6 +540,29 @@ impl<'a> WasmBackend<'a> {
|
||||||
|
|
||||||
Expr::Struct(fields) => self.create_struct(sym, layout, fields),
|
Expr::Struct(fields) => self.create_struct(sym, layout, fields),
|
||||||
|
|
||||||
|
Expr::StructAtIndex {
|
||||||
|
index,
|
||||||
|
field_layouts,
|
||||||
|
structure,
|
||||||
|
} => {
|
||||||
|
if let StoredValue::StackMemory { location, .. } = self.storage.get(structure) {
|
||||||
|
let (local_id, mut offset) =
|
||||||
|
location.local_and_offset(self.storage.stack_frame_pointer);
|
||||||
|
for field in field_layouts.iter().take(*index as usize) {
|
||||||
|
offset += field.stack_size(PTR_SIZE);
|
||||||
|
}
|
||||||
|
self.storage.copy_value_from_memory(
|
||||||
|
&mut self.code_builder,
|
||||||
|
*sym,
|
||||||
|
local_id,
|
||||||
|
offset,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
unreachable!("Unexpected storage for {:?}", structure)
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
x => Err(format!("Expression is not yet implemented {:?}", x)),
|
x => Err(format!("Expression is not yet implemented {:?}", x)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -319,6 +319,67 @@ impl<'a> Storage<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generate code to copy a StoredValue from an arbitrary memory location
|
||||||
|
/// (defined by a pointer and offset).
|
||||||
|
pub fn copy_value_from_memory(
|
||||||
|
&mut self,
|
||||||
|
code_builder: &mut CodeBuilder,
|
||||||
|
to_symbol: Symbol,
|
||||||
|
from_ptr: LocalId,
|
||||||
|
from_offset: u32,
|
||||||
|
) -> u32 {
|
||||||
|
let to_storage = self.get(&to_symbol).to_owned();
|
||||||
|
match to_storage {
|
||||||
|
StoredValue::StackMemory {
|
||||||
|
location,
|
||||||
|
size,
|
||||||
|
alignment_bytes,
|
||||||
|
} => {
|
||||||
|
let (to_ptr, to_offset) = location.local_and_offset(self.stack_frame_pointer);
|
||||||
|
copy_memory(
|
||||||
|
code_builder,
|
||||||
|
CopyMemoryConfig {
|
||||||
|
from_ptr,
|
||||||
|
from_offset,
|
||||||
|
to_ptr,
|
||||||
|
to_offset,
|
||||||
|
size,
|
||||||
|
alignment_bytes,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
size
|
||||||
|
}
|
||||||
|
|
||||||
|
StoredValue::VirtualMachineStack {
|
||||||
|
value_type, size, ..
|
||||||
|
}
|
||||||
|
| StoredValue::Local {
|
||||||
|
value_type, size, ..
|
||||||
|
} => {
|
||||||
|
use crate::wasm_module::Align::*;
|
||||||
|
|
||||||
|
code_builder.get_local(from_ptr);
|
||||||
|
match (value_type, size) {
|
||||||
|
(ValueType::I64, 8) => code_builder.i64_load(Bytes8, from_offset),
|
||||||
|
(ValueType::I32, 4) => code_builder.i32_load(Bytes4, from_offset),
|
||||||
|
(ValueType::I32, 2) => code_builder.i32_load16_s(Bytes2, from_offset),
|
||||||
|
(ValueType::I32, 1) => code_builder.i32_load8_s(Bytes1, from_offset),
|
||||||
|
(ValueType::F32, 4) => code_builder.f32_load(Bytes4, from_offset),
|
||||||
|
(ValueType::F64, 8) => code_builder.f64_load(Bytes8, from_offset),
|
||||||
|
_ => {
|
||||||
|
panic!("Cannot store {:?} with alignment of {:?}", value_type, size);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let StoredValue::Local { local_id, .. } = to_storage {
|
||||||
|
code_builder.set_local(local_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Generate code to copy from one StoredValue to another
|
/// Generate code to copy from one StoredValue to another
|
||||||
/// Copies the _entire_ value. For struct fields etc., see `copy_value_to_memory`
|
/// Copies the _entire_ value. For struct fields etc., see `copy_value_to_memory`
|
||||||
pub fn clone_value(
|
pub fn clone_value(
|
||||||
|
|
|
@ -11,7 +11,7 @@ use crate::helpers::wasm::assert_evals_to;
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
fn basic_record() {
|
fn basic_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -45,7 +45,7 @@ fn basic_record() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
fn f64_record() {
|
fn f64_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -137,7 +137,7 @@ fn fn_record() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
fn def_record() {
|
fn def_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -192,7 +192,7 @@ fn when_on_record() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
fn when_record_with_guard_pattern() {
|
fn when_record_with_guard_pattern() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -207,7 +207,7 @@ fn when_record_with_guard_pattern() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
fn let_with_record_pattern() {
|
fn let_with_record_pattern() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -223,7 +223,7 @@ fn let_with_record_pattern() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
fn record_guard_pattern() {
|
fn record_guard_pattern() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -239,7 +239,7 @@ fn record_guard_pattern() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
fn twice_record_access() {
|
fn twice_record_access() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -254,7 +254,7 @@ fn twice_record_access() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-dev"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn empty_record() {
|
fn empty_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -873,7 +873,7 @@ fn update_single_element_record() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
fn booleans_in_record() {
|
fn booleans_in_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!("{ x: 1 == 1, y: 1 == 1 }"),
|
indoc!("{ x: 1 == 1, y: 1 == 1 }"),
|
||||||
|
@ -908,7 +908,7 @@ fn alignment_in_record() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
fn blue_and_present() {
|
fn blue_and_present() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -927,7 +927,7 @@ fn blue_and_present() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
fn blue_and_absent() {
|
fn blue_and_absent() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue