Returning records on the stack from Wasm dev backend!

This commit is contained in:
Brian Carroll 2021-09-28 08:06:59 +01:00
parent 39fda3e675
commit 02bb9028ef
5 changed files with 504 additions and 410 deletions

View file

@ -1,10 +1,10 @@
use parity_wasm::elements::{Instruction, Instruction::*, ValueType};
use parity_wasm::elements::ValueType;
use roc_mono::layout::{Layout, UnionLayout};
use crate::{copy_memory, LocalId, ALIGN_1, ALIGN_2, ALIGN_4, ALIGN_8, PTR_SIZE, PTR_TYPE};
use crate::{PTR_SIZE, PTR_TYPE};
// See README for background information on Wasm locals, memory and function calls
#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum WasmLayout {
// Primitive number value. Just a Wasm local, without any stack memory.
// For example, Roc i8 is represented as Wasm i32. Store the type and the original size.
@ -79,81 +79,4 @@ impl WasmLayout {
_ => 0,
}
}
#[allow(dead_code)]
fn load(&self, offset: u32) -> Result<Instruction, String> {
use crate::layout::WasmLayout::*;
use ValueType::*;
match self {
LocalOnly(I32, 4) => Ok(I32Load(ALIGN_4, offset)),
LocalOnly(I32, 2) => Ok(I32Load16S(ALIGN_2, offset)),
LocalOnly(I32, 1) => Ok(I32Load8S(ALIGN_1, offset)),
LocalOnly(I64, 8) => Ok(I64Load(ALIGN_8, offset)),
LocalOnly(F64, 8) => Ok(F64Load(ALIGN_8, offset)),
LocalOnly(F32, 4) => Ok(F32Load(ALIGN_4, offset)),
// TODO: Come back to this when we need to access fields of structs
// LocalOnly(F32, 2) => Ok(), // convert F16 to F32 (lowlevel function? Wasm-only?)
// StackMemory(size) => Ok(), // would this be some kind of memcpy in the IR?
HeapMemory => {
if PTR_TYPE == I64 {
Ok(I64Load(ALIGN_8, offset))
} else {
Ok(I32Load(ALIGN_4, offset))
}
}
_ => Err(format!(
"Failed to generate load instruction for WasmLayout {:?}",
self
)),
}
}
#[allow(dead_code)]
pub fn store(&self, offset: u32, instructions: &mut Vec<Instruction>) -> Result<(), String> {
use crate::layout::WasmLayout::*;
use ValueType::*;
let mut result = Ok(());
match self {
LocalOnly(I32, 4) => instructions.push(I32Store(ALIGN_4, offset)),
LocalOnly(I32, 2) => instructions.push(I32Store16(ALIGN_2, offset)),
LocalOnly(I32, 1) => instructions.push(I32Store8(ALIGN_1, offset)),
LocalOnly(I64, 8) => instructions.push(I64Store(ALIGN_8, offset)),
LocalOnly(F64, 8) => instructions.push(F64Store(ALIGN_8, offset)),
LocalOnly(F32, 4) => instructions.push(F32Store(ALIGN_4, offset)),
StackMemory {
size,
alignment_bytes,
} => {
// TODO
// Need extra arguments for this case that we don't need for primitives.
// Maybe it should be somewhere we have more relevant context?
// Come back to it when we need to insert things into structs.
let from_ptr = LocalId(0); // TODO
let to_ptr = LocalId(0); // TODO
copy_memory(instructions, from_ptr, to_ptr, *size, *alignment_bytes)?;
}
HeapMemory => {
if PTR_TYPE == I64 {
instructions.push(I64Store(ALIGN_8, offset));
} else {
instructions.push(I32Store(ALIGN_4, offset));
}
}
_ => {
result = Err(format!(
"Failed to generate store instruction for WasmLayout {:?}",
self
));
}
}
result
}
}