Added more optimizations in regards to function invocations and backing
up and restoring registers
This commit is contained in:
@@ -1115,43 +1115,26 @@ impl<'a> Compiler<'a> {
|
||||
Some(name.span),
|
||||
)?;
|
||||
|
||||
for register in active_registers {
|
||||
let VariableLocation::Stack(stack_offset) = stack
|
||||
.get_location_of(&Cow::from(format!("temp_{register}")), None)
|
||||
.map_err(Error::Scope)?
|
||||
else {
|
||||
// This shouldn't happen if we just added it
|
||||
return Err(Error::Unknown(
|
||||
format!("Failed to recover temp_{register}"),
|
||||
Some(name.span),
|
||||
));
|
||||
};
|
||||
// cleanup spilled temporary variables
|
||||
let total_stack_usage = stack.stack_offset();
|
||||
let saved_regs_count = active_registers.len() as u16;
|
||||
|
||||
if total_stack_usage > saved_regs_count {
|
||||
let spill_amount = total_stack_usage - saved_regs_count;
|
||||
self.write_instruction(
|
||||
Instruction::Sub(
|
||||
Operand::Register(VariableScope::TEMP_STACK_REGISTER),
|
||||
Operand::StackPointer,
|
||||
Operand::Number(stack_offset.into()),
|
||||
),
|
||||
Some(name.span),
|
||||
)?;
|
||||
|
||||
self.write_instruction(
|
||||
Instruction::Get(
|
||||
Operand::Register(register),
|
||||
Operand::Device(Cow::from("db")),
|
||||
Operand::Register(VariableScope::TEMP_STACK_REGISTER),
|
||||
Operand::StackPointer,
|
||||
Operand::Number(spill_amount.into()),
|
||||
),
|
||||
Some(name.span),
|
||||
)?;
|
||||
}
|
||||
|
||||
if stack.stack_offset() > 0 {
|
||||
// restore the registers in reverse order from the stack, now using `pop`
|
||||
for register in active_registers.iter().rev() {
|
||||
self.write_instruction(
|
||||
Instruction::Sub(
|
||||
Operand::StackPointer,
|
||||
Operand::StackPointer,
|
||||
Operand::Number(Decimal::from(stack.stack_offset())),
|
||||
),
|
||||
Instruction::Pop(Operand::Register(*register)),
|
||||
Some(name.span),
|
||||
)?;
|
||||
}
|
||||
@@ -2735,33 +2718,49 @@ impl<'a> Compiler<'a> {
|
||||
|
||||
self.write_instruction(Instruction::LabelDef(return_label.clone()), Some(span))?;
|
||||
|
||||
self.write_instruction(
|
||||
Instruction::Sub(
|
||||
Operand::Register(VariableScope::TEMP_STACK_REGISTER),
|
||||
Operand::StackPointer,
|
||||
Operand::Number(ra_stack_offset.into()),
|
||||
),
|
||||
Some(span),
|
||||
)?;
|
||||
if ra_stack_offset == 1 {
|
||||
self.write_instruction(Instruction::Pop(Operand::ReturnAddress), Some(span))?;
|
||||
|
||||
self.write_instruction(
|
||||
Instruction::Get(
|
||||
Operand::ReturnAddress,
|
||||
Operand::Device(Cow::from("db")),
|
||||
Operand::Register(VariableScope::TEMP_STACK_REGISTER),
|
||||
),
|
||||
Some(span),
|
||||
)?;
|
||||
|
||||
if block_scope.stack_offset() > 0 {
|
||||
let remaining_cleanup = block_scope.stack_offset() - 1;
|
||||
if remaining_cleanup > 0 {
|
||||
self.write_instruction(
|
||||
Instruction::Sub(
|
||||
Operand::StackPointer,
|
||||
Operand::StackPointer,
|
||||
Operand::Number(remaining_cleanup.into()),
|
||||
),
|
||||
Some(span),
|
||||
)?;
|
||||
}
|
||||
} else {
|
||||
self.write_instruction(
|
||||
Instruction::Sub(
|
||||
Operand::Register(VariableScope::TEMP_STACK_REGISTER),
|
||||
Operand::StackPointer,
|
||||
Operand::StackPointer,
|
||||
Operand::Number(block_scope.stack_offset().into()),
|
||||
Operand::Number(ra_stack_offset.into()),
|
||||
),
|
||||
Some(span),
|
||||
)?;
|
||||
|
||||
self.write_instruction(
|
||||
Instruction::Get(
|
||||
Operand::ReturnAddress,
|
||||
Operand::Device(Cow::from("db")),
|
||||
Operand::Register(VariableScope::TEMP_STACK_REGISTER),
|
||||
),
|
||||
Some(span),
|
||||
)?;
|
||||
|
||||
if block_scope.stack_offset() > 0 {
|
||||
self.write_instruction(
|
||||
Instruction::Sub(
|
||||
Operand::StackPointer,
|
||||
Operand::StackPointer,
|
||||
Operand::Number(block_scope.stack_offset().into()),
|
||||
),
|
||||
Some(span),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
self.write_instruction(Instruction::Jump(Operand::ReturnAddress), Some(span))?;
|
||||
|
||||
Reference in New Issue
Block a user