mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 07:14:46 +00:00
repl: move wasm32_test_result to gen_wasm, and extract Wasm32Sized from FromWasm32Memory
This commit is contained in:
parent
70e19053f0
commit
e9871947d3
7 changed files with 96 additions and 63 deletions
|
@ -4,6 +4,10 @@ mod low_level;
|
|||
mod storage;
|
||||
pub mod wasm_module;
|
||||
|
||||
// Helpers for interfacing to a Wasm module from outside
|
||||
pub mod wasm32_sized;
|
||||
pub mod wasm32_test_result;
|
||||
|
||||
use bumpalo::{self, collections::Vec, Bump};
|
||||
|
||||
use roc_collections::all::{MutMap, MutSet};
|
||||
|
|
78
compiler/gen_wasm/src/wasm32_sized.rs
Normal file
78
compiler/gen_wasm/src/wasm32_sized.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
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))
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! wasm32_sized_primitive {
|
||||
($($type_name:ident ,)+) => {
|
||||
$(
|
||||
impl Wasm32Sized for $type_name {
|
||||
const SIZE_OF_WASM: usize = core::mem::size_of::<$type_name>();
|
||||
const ALIGN_OF_WASM: usize = core::mem::align_of::<$type_name>();
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
wasm32_sized_primitive!(
|
||||
u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, f32, f64, bool, RocDec, RocOrder,
|
||||
);
|
||||
|
||||
impl Wasm32Sized for () {
|
||||
const SIZE_OF_WASM: usize = 0;
|
||||
const ALIGN_OF_WASM: usize = 0;
|
||||
}
|
||||
|
||||
impl Wasm32Sized for RocStr {
|
||||
const SIZE_OF_WASM: usize = 8;
|
||||
const ALIGN_OF_WASM: usize = 4;
|
||||
}
|
||||
|
||||
impl<T: Wasm32Sized> Wasm32Sized for RocList<T> {
|
||||
const SIZE_OF_WASM: usize = 8;
|
||||
const ALIGN_OF_WASM: usize = 4;
|
||||
}
|
||||
|
||||
impl<T: Wasm32Sized> Wasm32Sized for &'_ T {
|
||||
const SIZE_OF_WASM: usize = 4;
|
||||
const ALIGN_OF_WASM: usize = 4;
|
||||
}
|
||||
|
||||
impl<T: Wasm32Sized, const N: usize> Wasm32Sized for [T; N] {
|
||||
const SIZE_OF_WASM: usize = N * T::SIZE_OF_WASM;
|
||||
const ALIGN_OF_WASM: usize = T::ALIGN_OF_WASM;
|
||||
}
|
||||
|
||||
impl Wasm32Sized for usize {
|
||||
const SIZE_OF_WASM: usize = 4;
|
||||
const ALIGN_OF_WASM: usize = 4;
|
||||
}
|
||||
|
||||
impl<T: Wasm32Sized, U: Wasm32Sized> Wasm32Sized 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);
|
||||
}
|
||||
|
||||
impl<T: Wasm32Sized, U: Wasm32Sized, V: Wasm32Sized> Wasm32Sized 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);
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
183
compiler/gen_wasm/src/wasm32_test_result.rs
Normal file
183
compiler/gen_wasm/src/wasm32_test_result.rs
Normal file
|
@ -0,0 +1,183 @@
|
|||
use bumpalo::collections::Vec;
|
||||
|
||||
use crate::wasm32_sized::Wasm32Sized;
|
||||
use crate::wasm_module::{
|
||||
linking::SymInfo, linking::WasmObjectSymbol, Align, CodeBuilder, Export, ExportType, LocalId,
|
||||
Signature, ValueType, WasmModule,
|
||||
};
|
||||
use roc_std::{RocDec, RocList, RocOrder, RocStr};
|
||||
|
||||
pub trait Wasm32TestResult {
|
||||
fn insert_test_wrapper<'a>(
|
||||
arena: &'a bumpalo::Bump,
|
||||
module: &mut WasmModule<'a>,
|
||||
wrapper_name: &str,
|
||||
main_function_index: u32,
|
||||
) {
|
||||
let index = module.import.function_count
|
||||
+ module.code.preloaded_count
|
||||
+ module.code.code_builders.len() as u32;
|
||||
|
||||
module.add_function_signature(Signature {
|
||||
param_types: Vec::with_capacity_in(0, arena),
|
||||
ret_type: Some(ValueType::I32),
|
||||
});
|
||||
|
||||
module.export.append(Export {
|
||||
name: arena.alloc_slice_copy(wrapper_name.as_bytes()),
|
||||
ty: ExportType::Func,
|
||||
index,
|
||||
});
|
||||
|
||||
let linker_symbol = SymInfo::Function(WasmObjectSymbol::Defined {
|
||||
flags: 0,
|
||||
index,
|
||||
name: wrapper_name.to_string(),
|
||||
});
|
||||
module.linking.symbol_table.push(linker_symbol);
|
||||
|
||||
let mut code_builder = CodeBuilder::new(arena);
|
||||
Self::build_wrapper_body(&mut code_builder, main_function_index);
|
||||
module.code.code_builders.push(code_builder);
|
||||
}
|
||||
|
||||
fn build_wrapper_body(code_builder: &mut CodeBuilder, main_function_index: u32);
|
||||
}
|
||||
|
||||
macro_rules! build_wrapper_body_primitive {
|
||||
($store_instruction: ident, $align: expr) => {
|
||||
fn build_wrapper_body(code_builder: &mut CodeBuilder, main_function_index: u32) {
|
||||
let frame_pointer_id = LocalId(0);
|
||||
let frame_pointer = Some(frame_pointer_id);
|
||||
let local_types = &[ValueType::I32];
|
||||
let frame_size = 8;
|
||||
// Main's symbol index is the same as its function index, since the first symbols we created were for procs
|
||||
let main_symbol_index = main_function_index;
|
||||
|
||||
code_builder.get_local(frame_pointer_id);
|
||||
code_builder.call(main_function_index, main_symbol_index, 0, true);
|
||||
code_builder.$store_instruction($align, 0);
|
||||
code_builder.get_local(frame_pointer_id);
|
||||
|
||||
code_builder.build_fn_header_and_footer(local_types, frame_size, frame_pointer);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! wasm_test_result_primitive {
|
||||
($type_name: ident, $store_instruction: ident, $align: expr) => {
|
||||
impl Wasm32TestResult for $type_name {
|
||||
build_wrapper_body_primitive!($store_instruction, $align);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn build_wrapper_body_stack_memory(
|
||||
code_builder: &mut CodeBuilder,
|
||||
main_function_index: u32,
|
||||
size: usize,
|
||||
) {
|
||||
let local_id = LocalId(0);
|
||||
let local_types = &[ValueType::I32];
|
||||
let frame_pointer = Some(local_id);
|
||||
// Main's symbol index is the same as its function index, since the first symbols we created were for procs
|
||||
let main_symbol_index = main_function_index;
|
||||
|
||||
code_builder.get_local(local_id);
|
||||
code_builder.call(main_function_index, main_symbol_index, 0, true);
|
||||
code_builder.get_local(local_id);
|
||||
code_builder.build_fn_header_and_footer(local_types, size as i32, frame_pointer);
|
||||
}
|
||||
|
||||
macro_rules! wasm_test_result_stack_memory {
|
||||
($type_name: ident) => {
|
||||
impl Wasm32TestResult for $type_name {
|
||||
fn build_wrapper_body(code_builder: &mut CodeBuilder, main_function_index: u32) {
|
||||
build_wrapper_body_stack_memory(
|
||||
code_builder,
|
||||
main_function_index,
|
||||
$type_name::ACTUAL_WIDTH,
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
wasm_test_result_primitive!(bool, i32_store8, Align::Bytes1);
|
||||
wasm_test_result_primitive!(RocOrder, i32_store8, Align::Bytes1);
|
||||
|
||||
wasm_test_result_primitive!(u8, i32_store8, Align::Bytes1);
|
||||
wasm_test_result_primitive!(i8, i32_store8, Align::Bytes1);
|
||||
wasm_test_result_primitive!(u16, i32_store16, Align::Bytes2);
|
||||
wasm_test_result_primitive!(i16, i32_store16, Align::Bytes2);
|
||||
wasm_test_result_primitive!(u32, i32_store, Align::Bytes4);
|
||||
wasm_test_result_primitive!(i32, i32_store, Align::Bytes4);
|
||||
wasm_test_result_primitive!(u64, i64_store, Align::Bytes8);
|
||||
wasm_test_result_primitive!(i64, i64_store, Align::Bytes8);
|
||||
wasm_test_result_primitive!(usize, i32_store, Align::Bytes4);
|
||||
|
||||
wasm_test_result_primitive!(f32, f32_store, Align::Bytes4);
|
||||
wasm_test_result_primitive!(f64, f64_store, Align::Bytes8);
|
||||
|
||||
wasm_test_result_stack_memory!(u128);
|
||||
wasm_test_result_stack_memory!(i128);
|
||||
wasm_test_result_stack_memory!(RocDec);
|
||||
wasm_test_result_stack_memory!(RocStr);
|
||||
|
||||
impl<T: Wasm32TestResult> Wasm32TestResult for RocList<T> {
|
||||
fn build_wrapper_body(code_builder: &mut CodeBuilder, main_function_index: u32) {
|
||||
build_wrapper_body_stack_memory(code_builder, main_function_index, 12)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Wasm32TestResult> Wasm32TestResult for &'_ T {
|
||||
build_wrapper_body_primitive!(i32_store, Align::Bytes4);
|
||||
}
|
||||
|
||||
impl<T, const N: usize> Wasm32TestResult for [T; N]
|
||||
where
|
||||
T: Wasm32TestResult + Wasm32Sized,
|
||||
{
|
||||
fn build_wrapper_body(code_builder: &mut CodeBuilder, main_function_index: u32) {
|
||||
build_wrapper_body_stack_memory(code_builder, main_function_index, N * T::ACTUAL_WIDTH)
|
||||
}
|
||||
}
|
||||
|
||||
impl Wasm32TestResult for () {
|
||||
fn build_wrapper_body(code_builder: &mut CodeBuilder, main_function_index: u32) {
|
||||
// Main's symbol index is the same as its function index, since the first symbols we created were for procs
|
||||
let main_symbol_index = main_function_index;
|
||||
code_builder.call(main_function_index, main_symbol_index, 0, false);
|
||||
code_builder.get_global(0);
|
||||
code_builder.build_fn_header_and_footer(&[], 0, None);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Wasm32TestResult for (T, U)
|
||||
where
|
||||
T: Wasm32TestResult + Wasm32Sized,
|
||||
U: Wasm32TestResult + Wasm32Sized,
|
||||
{
|
||||
fn build_wrapper_body(code_builder: &mut CodeBuilder, main_function_index: u32) {
|
||||
build_wrapper_body_stack_memory(
|
||||
code_builder,
|
||||
main_function_index,
|
||||
T::ACTUAL_WIDTH + U::ACTUAL_WIDTH,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U, V> Wasm32TestResult for (T, U, V)
|
||||
where
|
||||
T: Wasm32TestResult + Wasm32Sized,
|
||||
U: Wasm32TestResult + Wasm32Sized,
|
||||
V: Wasm32TestResult + Wasm32Sized,
|
||||
{
|
||||
fn build_wrapper_body(code_builder: &mut CodeBuilder, main_function_index: u32) {
|
||||
build_wrapper_body_stack_memory(
|
||||
code_builder,
|
||||
main_function_index,
|
||||
T::ACTUAL_WIDTH + U::ACTUAL_WIDTH + V::ACTUAL_WIDTH,
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue