Implement Expr::StructAtIndex for wasm dev backend

This commit is contained in:
Brian Carroll 2021-11-14 19:06:04 +00:00
parent 4aa6ec1d64
commit 29d355c4d6
3 changed files with 97 additions and 13 deletions

View file

@ -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)),
} }
} }

View file

@ -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(

View file

@ -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!(