Support multiple function arguments

This commit is contained in:
2024-03-29 11:01:19 +01:00
parent 90430c47f4
commit 5cf0863e0a
8 changed files with 137 additions and 50 deletions

View File

@ -1,4 +1,5 @@
#include "elna/backend/riscv.hpp"
#include <cassert>
#include <memory>
namespace elna::riscv
@ -168,15 +169,15 @@ namespace elna::riscv
void visitor::epilogue(const std::size_t stack_size)
{
this->instructions[0].i(x_register::sp, funct3_t::addi, x_register::sp, -stack_size);
this->instructions[1].s(stack_size - 4, funct3_t::sw, x_register::sp, x_register::s0);
this->instructions[2].s(stack_size - 8, funct3_t::sw, x_register::sp, x_register::ra);
this->instructions[1].s(0, funct3_t::sw, x_register::sp, x_register::s0);
this->instructions[2].s(4, funct3_t::sw, x_register::sp, x_register::ra);
this->instructions[3].i(x_register::s0, funct3_t::addi, x_register::sp, stack_size);
// Epilogue.
this->instructions.push_back(instruction(base_opcode::load)
.i(x_register::s0, funct3_t::lw, x_register::sp, stack_size - 4));
.i(x_register::s0, funct3_t::lw, x_register::sp, 0));
this->instructions.push_back(instruction(base_opcode::load)
.i(x_register::ra, funct3_t::lw, x_register::sp, stack_size - 8));
.i(x_register::ra, funct3_t::lw, x_register::sp, 4));
this->instructions.push_back(instruction(base_opcode::opImm)
.i(x_register::sp, funct3_t::addi, x_register::sp, stack_size));
this->instructions.push_back(instruction(base_opcode::jalr)
@ -226,16 +227,20 @@ namespace elna::riscv
this->instructions.push_back(instruction(base_opcode::op)
.r(x_register::a0, funct3_t::_and, x_register::zero, x_register::zero));
epilogue(static_cast<std::uint32_t>(this->variable_counter * 4 + 8 + main_symbol->stack_size()));
epilogue(static_cast<std::uint32_t>(this->variable_counter * 4 + 8 + main_symbol->local_stack_size));
this->writer->sink("main", reinterpret_cast<const std::byte *>(this->instructions.data()),
this->instructions.size() * sizeof(instruction));
}
void visitor::visit(source::call_statement *statement)
{
std::size_t argument_offset{ 0 };
for (auto& argument : statement->arguments())
{
argument->accept(this);
this->instructions.push_back(instruction(base_opcode::store)
.s(argument_offset, funct3_t::sw, x_register::sp, x_register::a0));
argument_offset += 4;
}
relocate(statement->name(), address_t::text);
this->instructions.push_back(instruction(base_opcode::auipc).u(x_register::ra, 0));
@ -297,10 +302,17 @@ namespace elna::riscv
else if (auto variable_symbol = std::dynamic_pointer_cast<source::variable_info>(symbol))
{
this->instructions.push_back(
instruction(base_opcode::store)
instruction(base_opcode::load)
.i(free_register, funct3_t::lw, x_register::s0, variable_symbol->offset)
);
}
else if (auto parameter_symbol = std::dynamic_pointer_cast<source::parameter_info>(symbol))
{
this->instructions.push_back(
instruction(base_opcode::load)
.i(free_register, funct3_t::lw, x_register::s0, parameter_symbol->offset)
);
}
}
void visitor::visit(source::binary_expression *expression)