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

@ -121,36 +121,40 @@ fn encode_alignment(bytes: u32) -> u32 {
}
}
fn copy_memory(
instructions: &mut Vec<Instruction>,
pub struct MemoryCopy {
from_ptr: LocalId,
from_offset: u32,
to_ptr: LocalId,
to_offset: u32,
size: u32,
alignment_bytes: u32,
offset: u32,
) {
let alignment_flag = encode_alignment(alignment_bytes);
let mut current_offset = offset;
while size - current_offset >= 8 {
instructions.push(GetLocal(to_ptr.0));
instructions.push(GetLocal(from_ptr.0));
instructions.push(I64Load(alignment_flag, current_offset));
instructions.push(I64Store(alignment_flag, current_offset));
current_offset += 8;
}
if size - current_offset >= 4 {
instructions.push(GetLocal(to_ptr.0));
instructions.push(GetLocal(from_ptr.0));
instructions.push(I32Load(alignment_flag, current_offset));
instructions.push(I32Store(alignment_flag, current_offset));
current_offset += 4;
}
while size - current_offset > 0 {
instructions.push(GetLocal(to_ptr.0));
instructions.push(GetLocal(from_ptr.0));
instructions.push(I32Load8U(alignment_flag, current_offset));
instructions.push(I32Store8(alignment_flag, current_offset));
current_offset += 1;
}
impl MemoryCopy {
pub fn generate(&self, instructions: &mut Vec<Instruction>) {
let alignment_flag = encode_alignment(self.alignment_bytes);
let mut i = 0;
while self.size - i >= 8 {
instructions.push(GetLocal(self.to_ptr.0));
instructions.push(GetLocal(self.from_ptr.0));
instructions.push(I64Load(alignment_flag, i + self.from_offset));
instructions.push(I64Store(alignment_flag, i + self.to_offset));
i += 8;
}
if self.size - i >= 4 {
instructions.push(GetLocal(self.to_ptr.0));
instructions.push(GetLocal(self.from_ptr.0));
instructions.push(I32Load(alignment_flag, i + self.from_offset));
instructions.push(I32Store(alignment_flag, i + self.to_offset));
i += 4;
}
while self.size - i > 0 {
instructions.push(GetLocal(self.to_ptr.0));
instructions.push(GetLocal(self.from_ptr.0));
instructions.push(I32Load8U(alignment_flag, i + self.from_offset));
instructions.push(I32Store8(alignment_flag, i + self.to_offset));
i += 1;
}
}
}