mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 23:31:12 +00:00
rename wasm -> wasm32
This commit is contained in:
parent
d323869e7f
commit
f8809a3eef
7 changed files with 295 additions and 232 deletions
30
Cargo.lock
generated
30
Cargo.lock
generated
|
@ -2570,6 +2570,12 @@ dependencies = [
|
||||||
"syn 1.0.72",
|
"syn 1.0.72",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parity-wasm"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "be5e13c266502aadf83426d87d81a0f5d1ef45b8027f5a471c360abfe4bfae92"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
|
@ -3642,6 +3648,29 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "roc_gen_wasm"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"indoc 0.3.6",
|
||||||
|
"libc",
|
||||||
|
"parity-wasm",
|
||||||
|
"pretty_assertions 0.5.1",
|
||||||
|
"roc_builtins",
|
||||||
|
"roc_can",
|
||||||
|
"roc_collections",
|
||||||
|
"roc_load",
|
||||||
|
"roc_module",
|
||||||
|
"roc_mono",
|
||||||
|
"roc_std",
|
||||||
|
"roc_types",
|
||||||
|
"target-lexicon",
|
||||||
|
"tempfile",
|
||||||
|
"wasmer",
|
||||||
|
"wasmer-wasi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "roc_ident"
|
name = "roc_ident"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -4348,6 +4377,7 @@ dependencies = [
|
||||||
"roc_collections",
|
"roc_collections",
|
||||||
"roc_constrain",
|
"roc_constrain",
|
||||||
"roc_gen_llvm",
|
"roc_gen_llvm",
|
||||||
|
"roc_gen_wasm",
|
||||||
"roc_load",
|
"roc_load",
|
||||||
"roc_module",
|
"roc_module",
|
||||||
"roc_mono",
|
"roc_mono",
|
||||||
|
|
|
@ -20,6 +20,7 @@ members = [
|
||||||
"compiler/load",
|
"compiler/load",
|
||||||
"compiler/gen_llvm",
|
"compiler/gen_llvm",
|
||||||
"compiler/gen_dev",
|
"compiler/gen_dev",
|
||||||
|
"compiler/gen_wasm",
|
||||||
"compiler/build",
|
"compiler/build",
|
||||||
"compiler/arena_pool",
|
"compiler/arena_pool",
|
||||||
"compiler/test_gen",
|
"compiler/test_gen",
|
||||||
|
|
29
compiler/gen_wasm/Cargo.toml
Normal file
29
compiler/gen_wasm/Cargo.toml
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
[package]
|
||||||
|
name = "roc_gen_wasm"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
roc_collections = { path = "../collections" }
|
||||||
|
roc_module = { path = "../module" }
|
||||||
|
roc_mono = { path = "../mono" }
|
||||||
|
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||||
|
parity-wasm = "0.42"
|
||||||
|
|
||||||
|
roc_std = { path = "../../roc_std" }
|
||||||
|
wasmer = "2.0.0"
|
||||||
|
wasmer-wasi = "2.0.0"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
roc_can = { path = "../can" }
|
||||||
|
roc_builtins = { path = "../builtins" }
|
||||||
|
roc_load = { path = "../load" }
|
||||||
|
roc_types = { path = "../types" }
|
||||||
|
roc_module = { path = "../module" }
|
||||||
|
indoc = "0.3.3"
|
||||||
|
pretty_assertions = "0.5.1"
|
||||||
|
libc = "0.2"
|
||||||
|
target-lexicon = "0.12.2"
|
||||||
|
tempfile = "3.1.0"
|
230
compiler/gen_wasm/src/from_wasm32_memory.rs
Normal file
230
compiler/gen_wasm/src/from_wasm32_memory.rs
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
use roc_std::{RocDec, RocList, RocOrder, RocStr};
|
||||||
|
|
||||||
|
pub trait FromWasm32Memory: 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))
|
||||||
|
};
|
||||||
|
|
||||||
|
fn decode(memory: &wasmer::Memory, offset: u32) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! from_wasm_memory_primitive_decode {
|
||||||
|
($type_name:ident) => {
|
||||||
|
const SIZE_OF_WASM: usize = core::mem::size_of::<$type_name>();
|
||||||
|
const ALIGN_OF_WASM: usize = core::mem::align_of::<$type_name>();
|
||||||
|
|
||||||
|
fn decode(memory: &wasmer::Memory, offset: u32) -> Self {
|
||||||
|
use core::mem::MaybeUninit;
|
||||||
|
|
||||||
|
let mut output: MaybeUninit<Self> = MaybeUninit::uninit();
|
||||||
|
let width = std::mem::size_of::<Self>();
|
||||||
|
|
||||||
|
let ptr = output.as_mut_ptr();
|
||||||
|
let raw_ptr = ptr as *mut u8;
|
||||||
|
let slice = unsafe { std::slice::from_raw_parts_mut(raw_ptr, width) };
|
||||||
|
|
||||||
|
let ptr: wasmer::WasmPtr<u8, wasmer::Array> = wasmer::WasmPtr::new(offset as u32);
|
||||||
|
let foobar = (ptr.deref(memory, 0, width as u32)).unwrap();
|
||||||
|
let wasm_slice = unsafe { std::mem::transmute(foobar) };
|
||||||
|
|
||||||
|
slice.copy_from_slice(wasm_slice);
|
||||||
|
|
||||||
|
unsafe { output.assume_init() }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! from_wasm_memory_primitive {
|
||||||
|
($($type_name:ident ,)+) => {
|
||||||
|
$(
|
||||||
|
impl FromWasm32Memory for $type_name {
|
||||||
|
from_wasm_memory_primitive_decode!($type_name);
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
from_wasm_memory_primitive!(
|
||||||
|
u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, f32, f64, bool, RocDec, RocOrder,
|
||||||
|
);
|
||||||
|
|
||||||
|
impl FromWasm32Memory for () {
|
||||||
|
const SIZE_OF_WASM: usize = 0;
|
||||||
|
const ALIGN_OF_WASM: usize = 0;
|
||||||
|
|
||||||
|
fn decode(_: &wasmer::Memory, _: u32) -> Self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromWasm32Memory for RocStr {
|
||||||
|
const SIZE_OF_WASM: usize = 8;
|
||||||
|
const ALIGN_OF_WASM: usize = 4;
|
||||||
|
|
||||||
|
fn decode(memory: &wasmer::Memory, offset: u32) -> Self {
|
||||||
|
let bytes = <u64 as FromWasm32Memory>::decode(memory, offset);
|
||||||
|
|
||||||
|
let length = (bytes >> 32) as u32;
|
||||||
|
let elements = bytes as u32;
|
||||||
|
|
||||||
|
if length == 0 {
|
||||||
|
RocStr::default()
|
||||||
|
} else if (length as i32) < 0 {
|
||||||
|
// this is a small string
|
||||||
|
let last_byte = bytes.to_ne_bytes()[7];
|
||||||
|
let actual_length = (last_byte ^ 0b1000_0000) as usize;
|
||||||
|
|
||||||
|
let slice = &bytes.to_ne_bytes()[..actual_length as usize];
|
||||||
|
RocStr::from_slice(slice)
|
||||||
|
} else {
|
||||||
|
// this is a big string
|
||||||
|
let ptr: wasmer::WasmPtr<u8, wasmer::Array> = wasmer::WasmPtr::new(elements);
|
||||||
|
let foobar = (ptr.deref(memory, 0, length)).unwrap();
|
||||||
|
let wasm_slice = unsafe { std::mem::transmute(foobar) };
|
||||||
|
|
||||||
|
RocStr::from_slice(wasm_slice)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: FromWasm32Memory + Clone> FromWasm32Memory for RocList<T> {
|
||||||
|
const SIZE_OF_WASM: usize = 8;
|
||||||
|
const ALIGN_OF_WASM: usize = 4;
|
||||||
|
|
||||||
|
fn decode(memory: &wasmer::Memory, offset: u32) -> Self {
|
||||||
|
let bytes = <u64 as FromWasm32Memory>::decode(memory, offset);
|
||||||
|
|
||||||
|
let length = (bytes >> 32) as u32;
|
||||||
|
let elements = bytes as u32;
|
||||||
|
|
||||||
|
let mut items = Vec::with_capacity(length as usize);
|
||||||
|
|
||||||
|
for i in 0..length {
|
||||||
|
let item = <T as FromWasm32Memory>::decode(
|
||||||
|
memory,
|
||||||
|
elements + i * <T as FromWasm32Memory>::SIZE_OF_WASM as u32,
|
||||||
|
);
|
||||||
|
items.push(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
RocList::from_slice(&items)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: FromWasm32Memory + Clone> FromWasm32Memory for &'_ [T] {
|
||||||
|
const SIZE_OF_WASM: usize = 8;
|
||||||
|
const ALIGN_OF_WASM: usize = 4;
|
||||||
|
|
||||||
|
fn decode(memory: &wasmer::Memory, offset: u32) -> Self {
|
||||||
|
let bytes = <u64 as FromWasm32Memory>::decode(memory, offset);
|
||||||
|
|
||||||
|
let length = (bytes >> 32) as u32;
|
||||||
|
let elements = bytes as u32;
|
||||||
|
|
||||||
|
let ptr: wasmer::WasmPtr<u8, wasmer::Array> = wasmer::WasmPtr::new(elements);
|
||||||
|
let width = <T as FromWasm32Memory>::SIZE_OF_WASM as u32 * length;
|
||||||
|
let foobar = (ptr.deref(memory, 0, width)).unwrap();
|
||||||
|
let wasm_slice =
|
||||||
|
unsafe { std::slice::from_raw_parts(foobar as *const _ as *const _, length as usize) };
|
||||||
|
|
||||||
|
wasm_slice
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: FromWasm32Memory> FromWasm32Memory for &'_ T {
|
||||||
|
const SIZE_OF_WASM: usize = 4;
|
||||||
|
const ALIGN_OF_WASM: usize = 4;
|
||||||
|
|
||||||
|
fn decode(memory: &wasmer::Memory, offset: u32) -> Self {
|
||||||
|
let elements = <u32 as FromWasm32Memory>::decode(memory, offset);
|
||||||
|
|
||||||
|
let actual = <T as FromWasm32Memory>::decode(memory, elements);
|
||||||
|
|
||||||
|
let b = Box::new(actual);
|
||||||
|
|
||||||
|
std::boxed::Box::<T>::leak(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: FromWasm32Memory + Clone, const N: usize> FromWasm32Memory for [T; N] {
|
||||||
|
const SIZE_OF_WASM: usize = N * T::SIZE_OF_WASM;
|
||||||
|
const ALIGN_OF_WASM: usize = T::ALIGN_OF_WASM;
|
||||||
|
|
||||||
|
fn decode(memory: &wasmer::Memory, offset: u32) -> Self {
|
||||||
|
let ptr: wasmer::WasmPtr<u8, wasmer::Array> = wasmer::WasmPtr::new(offset);
|
||||||
|
let width = <T as FromWasm32Memory>::SIZE_OF_WASM as u32 * N as u32;
|
||||||
|
let foobar = (ptr.deref(memory, 0, width)).unwrap();
|
||||||
|
let wasm_slice: &[T; N] = unsafe { &*(foobar as *const _ as *const [T; N]) };
|
||||||
|
|
||||||
|
wasm_slice.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromWasm32Memory for usize {
|
||||||
|
const SIZE_OF_WASM: usize = 4;
|
||||||
|
const ALIGN_OF_WASM: usize = 4;
|
||||||
|
|
||||||
|
fn decode(memory: &wasmer::Memory, offset: u32) -> Self {
|
||||||
|
<u32 as FromWasm32Memory>::decode(memory, offset) as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: FromWasm32Memory, U: FromWasm32Memory> FromWasm32Memory for (T, U) {
|
||||||
|
const SIZE_OF_WASM: usize = T::SIZE_OF_WASM + U::SIZE_OF_WASM;
|
||||||
|
const ALIGN_OF_WASM: usize = max2(T::SIZE_OF_WASM, U::SIZE_OF_WASM);
|
||||||
|
|
||||||
|
fn decode(memory: &wasmer::Memory, offset: u32) -> Self {
|
||||||
|
assert!(
|
||||||
|
T::ALIGN_OF_WASM >= U::ALIGN_OF_WASM,
|
||||||
|
"this function does not handle alignment"
|
||||||
|
);
|
||||||
|
|
||||||
|
let t = <T as FromWasm32Memory>::decode(memory, offset);
|
||||||
|
|
||||||
|
let u = <U as FromWasm32Memory>::decode(memory, offset + T::ACTUAL_WIDTH as u32);
|
||||||
|
|
||||||
|
(t, u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn max2(a: usize, b: usize) -> usize {
|
||||||
|
if a > b {
|
||||||
|
a
|
||||||
|
} else {
|
||||||
|
b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn max3(a: usize, b: usize, c: usize) -> usize {
|
||||||
|
max2(max2(a, b), c)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: FromWasm32Memory, U: FromWasm32Memory, V: FromWasm32Memory> FromWasm32Memory for (T, U, V) {
|
||||||
|
const SIZE_OF_WASM: usize = T::SIZE_OF_WASM + U::SIZE_OF_WASM + V::SIZE_OF_WASM;
|
||||||
|
const ALIGN_OF_WASM: usize = max3(T::SIZE_OF_WASM, U::SIZE_OF_WASM, V::SIZE_OF_WASM);
|
||||||
|
|
||||||
|
fn decode(memory: &wasmer::Memory, offset: u32) -> Self {
|
||||||
|
assert!(
|
||||||
|
T::ALIGN_OF_WASM >= U::ALIGN_OF_WASM,
|
||||||
|
"this function does not handle alignment"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
U::ALIGN_OF_WASM >= V::ALIGN_OF_WASM,
|
||||||
|
"this function does not handle alignment"
|
||||||
|
);
|
||||||
|
|
||||||
|
let t = <T as FromWasm32Memory>::decode(memory, offset);
|
||||||
|
|
||||||
|
let u = <U as FromWasm32Memory>::decode(memory, offset + T::ACTUAL_WIDTH as u32);
|
||||||
|
|
||||||
|
let v = <V as FromWasm32Memory>::decode(
|
||||||
|
memory,
|
||||||
|
offset + T::ACTUAL_WIDTH as u32 + U::ACTUAL_WIDTH as u32,
|
||||||
|
);
|
||||||
|
|
||||||
|
(t, u, v)
|
||||||
|
}
|
||||||
|
}
|
1
compiler/gen_wasm/src/lib.rs
Normal file
1
compiler/gen_wasm/src/lib.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub mod from_wasm32_memory;
|
|
@ -23,6 +23,7 @@ roc_can = { path = "../can" }
|
||||||
roc_parse = { path = "../parse" }
|
roc_parse = { path = "../parse" }
|
||||||
roc_build = { path = "../build" }
|
roc_build = { path = "../build" }
|
||||||
roc_std = { path = "../../roc_std" }
|
roc_std = { path = "../../roc_std" }
|
||||||
|
roc_gen_wasm = { path = "../gen_wasm" }
|
||||||
im = "14" # im and im-rc should always have the same version!
|
im = "14" # im and im-rc should always have the same version!
|
||||||
im-rc = "14" # im and im-rc should always have the same version!
|
im-rc = "14" # im and im-rc should always have the same version!
|
||||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||||
|
|
|
@ -6,9 +6,9 @@ use roc_can::builtins::builtin_defs_map;
|
||||||
use roc_can::def::Def;
|
use roc_can::def::Def;
|
||||||
use roc_collections::all::{MutMap, MutSet};
|
use roc_collections::all::{MutMap, MutSet};
|
||||||
use roc_gen_llvm::llvm::externs::add_default_roc_externs;
|
use roc_gen_llvm::llvm::externs::add_default_roc_externs;
|
||||||
|
use roc_gen_wasm::from_wasm32_memory::FromWasm32Memory;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_mono::ir::OptLevel;
|
use roc_mono::ir::OptLevel;
|
||||||
use roc_std::{RocDec, RocList, RocOrder, RocStr};
|
|
||||||
use roc_types::subs::VarStore;
|
use roc_types::subs::VarStore;
|
||||||
use target_lexicon::Triple;
|
use target_lexicon::Triple;
|
||||||
|
|
||||||
|
@ -500,7 +500,7 @@ fn fake_wasm_main_function(_: u32, _: u32) -> u32 {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn assert_wasm_evals_to_help<T>(src: &str, ignore_problems: bool) -> Result<T, String>
|
pub fn assert_wasm_evals_to_help<T>(src: &str, ignore_problems: bool) -> Result<T, String>
|
||||||
where
|
where
|
||||||
T: FromWasmMemory,
|
T: FromWasm32Memory,
|
||||||
{
|
{
|
||||||
let arena = bumpalo::Bump::new();
|
let arena = bumpalo::Bump::new();
|
||||||
let context = inkwell::context::Context::create();
|
let context = inkwell::context::Context::create();
|
||||||
|
@ -534,7 +534,7 @@ where
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let output = <T as crate::helpers::eval::FromWasmMemory>::decode(
|
let output = <T as crate::helpers::eval::FromWasm32Memory>::decode(
|
||||||
memory,
|
memory,
|
||||||
// skip the RocCallResult tag id
|
// skip the RocCallResult tag id
|
||||||
address as u32 + 8,
|
address as u32 + 8,
|
||||||
|
@ -643,232 +643,3 @@ macro_rules! assert_non_opt_evals_to {
|
||||||
$crate::assert_llvm_evals_to!($src, $expected, $ty, $transform);
|
$crate::assert_llvm_evals_to!($src, $expected, $ty, $transform);
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FromWasmMemory: 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))
|
|
||||||
};
|
|
||||||
|
|
||||||
fn decode(memory: &wasmer::Memory, offset: u32) -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! from_wasm_memory_primitive_decode {
|
|
||||||
($type_name:ident) => {
|
|
||||||
const SIZE_OF_WASM: usize = core::mem::size_of::<$type_name>();
|
|
||||||
const ALIGN_OF_WASM: usize = core::mem::align_of::<$type_name>();
|
|
||||||
|
|
||||||
fn decode(memory: &wasmer::Memory, offset: u32) -> Self {
|
|
||||||
use core::mem::MaybeUninit;
|
|
||||||
|
|
||||||
let mut output: MaybeUninit<Self> = MaybeUninit::uninit();
|
|
||||||
let width = std::mem::size_of::<Self>();
|
|
||||||
|
|
||||||
let ptr = output.as_mut_ptr();
|
|
||||||
let raw_ptr = ptr as *mut u8;
|
|
||||||
let slice = unsafe { std::slice::from_raw_parts_mut(raw_ptr, width) };
|
|
||||||
|
|
||||||
let ptr: wasmer::WasmPtr<u8, wasmer::Array> = wasmer::WasmPtr::new(offset as u32);
|
|
||||||
let foobar = (ptr.deref(memory, 0, width as u32)).unwrap();
|
|
||||||
let wasm_slice = unsafe { std::mem::transmute(foobar) };
|
|
||||||
|
|
||||||
slice.copy_from_slice(wasm_slice);
|
|
||||||
|
|
||||||
unsafe { output.assume_init() }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! from_wasm_memory_primitive {
|
|
||||||
($($type_name:ident ,)+) => {
|
|
||||||
$(
|
|
||||||
impl FromWasmMemory for $type_name {
|
|
||||||
from_wasm_memory_primitive_decode!($type_name);
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
from_wasm_memory_primitive!(
|
|
||||||
u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, f32, f64, bool, RocDec, RocOrder,
|
|
||||||
);
|
|
||||||
|
|
||||||
impl FromWasmMemory for () {
|
|
||||||
const SIZE_OF_WASM: usize = 0;
|
|
||||||
const ALIGN_OF_WASM: usize = 0;
|
|
||||||
|
|
||||||
fn decode(_: &wasmer::Memory, _: u32) -> Self {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromWasmMemory for RocStr {
|
|
||||||
const SIZE_OF_WASM: usize = 8;
|
|
||||||
const ALIGN_OF_WASM: usize = 4;
|
|
||||||
|
|
||||||
fn decode(memory: &wasmer::Memory, offset: u32) -> Self {
|
|
||||||
let bytes = <u64 as FromWasmMemory>::decode(memory, offset);
|
|
||||||
|
|
||||||
let length = (bytes >> 32) as u32;
|
|
||||||
let elements = bytes as u32;
|
|
||||||
|
|
||||||
if length == 0 {
|
|
||||||
RocStr::default()
|
|
||||||
} else if (length as i32) < 0 {
|
|
||||||
// this is a small string
|
|
||||||
let last_byte = bytes.to_ne_bytes()[7];
|
|
||||||
let actual_length = (last_byte ^ 0b1000_0000) as usize;
|
|
||||||
|
|
||||||
let slice = &bytes.to_ne_bytes()[..actual_length as usize];
|
|
||||||
RocStr::from_slice(slice)
|
|
||||||
} else {
|
|
||||||
// this is a big string
|
|
||||||
let ptr: wasmer::WasmPtr<u8, wasmer::Array> = wasmer::WasmPtr::new(elements);
|
|
||||||
let foobar = (ptr.deref(memory, 0, length)).unwrap();
|
|
||||||
let wasm_slice = unsafe { std::mem::transmute(foobar) };
|
|
||||||
|
|
||||||
RocStr::from_slice(wasm_slice)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: FromWasmMemory + Clone> FromWasmMemory for RocList<T> {
|
|
||||||
const SIZE_OF_WASM: usize = 8;
|
|
||||||
const ALIGN_OF_WASM: usize = 4;
|
|
||||||
|
|
||||||
fn decode(memory: &wasmer::Memory, offset: u32) -> Self {
|
|
||||||
let bytes = <u64 as FromWasmMemory>::decode(memory, offset);
|
|
||||||
|
|
||||||
let length = (bytes >> 32) as u32;
|
|
||||||
let elements = bytes as u32;
|
|
||||||
|
|
||||||
let mut items = Vec::with_capacity(length as usize);
|
|
||||||
|
|
||||||
for i in 0..length {
|
|
||||||
let item = <T as FromWasmMemory>::decode(
|
|
||||||
memory,
|
|
||||||
elements + i * <T as FromWasmMemory>::SIZE_OF_WASM as u32,
|
|
||||||
);
|
|
||||||
items.push(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
RocList::from_slice(&items)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: FromWasmMemory + Clone> FromWasmMemory for &'_ [T] {
|
|
||||||
const SIZE_OF_WASM: usize = 8;
|
|
||||||
const ALIGN_OF_WASM: usize = 4;
|
|
||||||
|
|
||||||
fn decode(memory: &wasmer::Memory, offset: u32) -> Self {
|
|
||||||
let bytes = <u64 as FromWasmMemory>::decode(memory, offset);
|
|
||||||
|
|
||||||
let length = (bytes >> 32) as u32;
|
|
||||||
let elements = bytes as u32;
|
|
||||||
|
|
||||||
let ptr: wasmer::WasmPtr<u8, wasmer::Array> = wasmer::WasmPtr::new(elements);
|
|
||||||
let width = <T as FromWasmMemory>::SIZE_OF_WASM as u32 * length;
|
|
||||||
let foobar = (ptr.deref(memory, 0, width)).unwrap();
|
|
||||||
let wasm_slice =
|
|
||||||
unsafe { std::slice::from_raw_parts(foobar as *const _ as *const _, length as usize) };
|
|
||||||
|
|
||||||
wasm_slice
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: FromWasmMemory> FromWasmMemory for &'_ T {
|
|
||||||
const SIZE_OF_WASM: usize = 4;
|
|
||||||
const ALIGN_OF_WASM: usize = 4;
|
|
||||||
|
|
||||||
fn decode(memory: &wasmer::Memory, offset: u32) -> Self {
|
|
||||||
let elements = <u32 as FromWasmMemory>::decode(memory, offset);
|
|
||||||
|
|
||||||
let actual = <T as FromWasmMemory>::decode(memory, elements);
|
|
||||||
|
|
||||||
let b = Box::new(actual);
|
|
||||||
|
|
||||||
std::boxed::Box::<T>::leak(b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: FromWasmMemory + Clone, const N: usize> FromWasmMemory for [T; N] {
|
|
||||||
const SIZE_OF_WASM: usize = N * T::SIZE_OF_WASM;
|
|
||||||
const ALIGN_OF_WASM: usize = T::ALIGN_OF_WASM;
|
|
||||||
|
|
||||||
fn decode(memory: &wasmer::Memory, offset: u32) -> Self {
|
|
||||||
let ptr: wasmer::WasmPtr<u8, wasmer::Array> = wasmer::WasmPtr::new(offset);
|
|
||||||
let width = <T as FromWasmMemory>::SIZE_OF_WASM as u32 * N as u32;
|
|
||||||
let foobar = (ptr.deref(memory, 0, width)).unwrap();
|
|
||||||
let wasm_slice: &[T; N] = unsafe { &*(foobar as *const _ as *const [T; N]) };
|
|
||||||
|
|
||||||
wasm_slice.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromWasmMemory for usize {
|
|
||||||
const SIZE_OF_WASM: usize = 4;
|
|
||||||
const ALIGN_OF_WASM: usize = 4;
|
|
||||||
|
|
||||||
fn decode(memory: &wasmer::Memory, offset: u32) -> Self {
|
|
||||||
<u32 as FromWasmMemory>::decode(memory, offset) as usize
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: FromWasmMemory, U: FromWasmMemory> FromWasmMemory for (T, U) {
|
|
||||||
const SIZE_OF_WASM: usize = T::SIZE_OF_WASM + U::SIZE_OF_WASM;
|
|
||||||
const ALIGN_OF_WASM: usize = max2(T::SIZE_OF_WASM, U::SIZE_OF_WASM);
|
|
||||||
|
|
||||||
fn decode(memory: &wasmer::Memory, offset: u32) -> Self {
|
|
||||||
assert!(
|
|
||||||
T::ALIGN_OF_WASM >= U::ALIGN_OF_WASM,
|
|
||||||
"this function does not handle alignment"
|
|
||||||
);
|
|
||||||
|
|
||||||
let t = <T as FromWasmMemory>::decode(memory, offset);
|
|
||||||
|
|
||||||
let u = <U as FromWasmMemory>::decode(memory, offset + T::ACTUAL_WIDTH as u32);
|
|
||||||
|
|
||||||
(t, u)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const fn max2(a: usize, b: usize) -> usize {
|
|
||||||
if a > b {
|
|
||||||
a
|
|
||||||
} else {
|
|
||||||
b
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const fn max3(a: usize, b: usize, c: usize) -> usize {
|
|
||||||
max2(max2(a, b), c)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: FromWasmMemory, U: FromWasmMemory, V: FromWasmMemory> FromWasmMemory for (T, U, V) {
|
|
||||||
const SIZE_OF_WASM: usize = T::SIZE_OF_WASM + U::SIZE_OF_WASM + V::SIZE_OF_WASM;
|
|
||||||
const ALIGN_OF_WASM: usize = max3(T::SIZE_OF_WASM, U::SIZE_OF_WASM, V::SIZE_OF_WASM);
|
|
||||||
|
|
||||||
fn decode(memory: &wasmer::Memory, offset: u32) -> Self {
|
|
||||||
assert!(
|
|
||||||
T::ALIGN_OF_WASM >= U::ALIGN_OF_WASM,
|
|
||||||
"this function does not handle alignment"
|
|
||||||
);
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
U::ALIGN_OF_WASM >= V::ALIGN_OF_WASM,
|
|
||||||
"this function does not handle alignment"
|
|
||||||
);
|
|
||||||
|
|
||||||
let t = <T as FromWasmMemory>::decode(memory, offset);
|
|
||||||
|
|
||||||
let u = <U as FromWasmMemory>::decode(memory, offset + T::ACTUAL_WIDTH as u32);
|
|
||||||
|
|
||||||
let v = <V as FromWasmMemory>::decode(
|
|
||||||
memory,
|
|
||||||
offset + T::ACTUAL_WIDTH as u32 + U::ACTUAL_WIDTH as u32,
|
|
||||||
);
|
|
||||||
|
|
||||||
(t, u, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue