mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 07:14:46 +00:00
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:
parent
4aa2452e01
commit
ffa6ff0a62
3 changed files with 134 additions and 97 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue