gen_wasm: Get rid of individual locals for values in stack memory

All values in stack memory can share the stack frame pointer,
with different offsets.

This avoids having to generate initialisation code for individual
pointers we used to have. It should also make things more efficient
when the runtime compiles Wasm to machine code. It can just assign
the stack frame pointer to a single CPU register and leave it there.

The original idea was to make params and local variables work the same.
(A struct param will be passed as a pointer to caller stack memory.)
But now I don't think that's worth it. Some match expressions get more
awkward this way but we might be able to refactor that to be nicer.
This commit is contained in:
Brian Carroll 2021-10-02 15:12:25 +01:00
parent 4aa2452e01
commit ffa6ff0a62
3 changed files with 134 additions and 97 deletions

View file

@ -1,4 +1,4 @@
use crate::{copy_memory, LocalId, ALIGN_1, ALIGN_2, ALIGN_4, ALIGN_8};
use crate::{LocalId, MemoryCopy, ALIGN_1, ALIGN_2, ALIGN_4, ALIGN_8};
use parity_wasm::elements::{Instruction, Instruction::*, ValueType};
#[derive(Debug, Clone)]
@ -14,7 +14,6 @@ pub enum SymbolStorage {
size: u32,
},
VarStackMemory {
local_id: LocalId,
size: u32,
offset: u32,
alignment_bytes: u32,
@ -30,12 +29,12 @@ pub enum SymbolStorage {
}
impl SymbolStorage {
pub fn local_id(&self) -> LocalId {
pub fn local_id(&self, stack_frame_pointer: Option<LocalId>) -> LocalId {
match self {
Self::ParamPrimitive { local_id, .. } => *local_id,
Self::ParamStackMemory { local_id, .. } => *local_id,
Self::VarPrimitive { local_id, .. } => *local_id,
Self::VarStackMemory { local_id, .. } => *local_id,
Self::VarStackMemory { .. } => stack_frame_pointer.unwrap(),
Self::VarHeapMemory { local_id, .. } => *local_id,
}
}
@ -60,6 +59,16 @@ impl SymbolStorage {
}
}
pub fn address_offset(&self) -> Option<u32> {
match self {
Self::ParamStackMemory { .. } => Some(0),
Self::VarStackMemory { offset, .. } => Some(*offset),
Self::ParamPrimitive { .. } => None,
Self::VarPrimitive { .. } => None,
Self::VarHeapMemory { .. } => None,
}
}
pub fn stack_size_and_alignment(&self) -> (u32, u32) {
match self {
Self::VarStackMemory {
@ -82,6 +91,7 @@ impl SymbolStorage {
instructions: &mut Vec<Instruction>,
to_pointer: LocalId,
to_offset: u32,
stack_frame_pointer: Option<LocalId>,
) -> u32 {
match self {
Self::ParamPrimitive {
@ -117,21 +127,34 @@ impl SymbolStorage {
local_id,
size,
alignment_bytes,
} => {
let copy = MemoryCopy {
from_ptr: *local_id,
from_offset: 0,
to_ptr: to_pointer,
to_offset,
size: *size,
alignment_bytes: *alignment_bytes,
};
copy.generate(instructions);
*size
}
| Self::VarStackMemory {
local_id,
Self::VarStackMemory {
size,
alignment_bytes,
offset,
..
} => {
copy_memory(
instructions,
*local_id,
to_pointer,
*size,
*alignment_bytes,
let copy = MemoryCopy {
from_ptr: stack_frame_pointer.unwrap(),
from_offset: *offset,
to_ptr: to_pointer,
to_offset,
);
size: *size,
alignment_bytes: *alignment_bytes,
};
copy.generate(instructions);
*size
}