Support procedure calls without arguments

This commit is contained in:
2024-03-26 23:04:20 +01:00
parent f2a20c2825
commit 44e32760ca
13 changed files with 317 additions and 113 deletions

View File

@ -76,8 +76,9 @@ namespace elna::riscv
return reinterpret_cast<const std::byte *>(&this->representation) + sizeof(this->representation);
}
visitor::visitor(std::shared_ptr<source::writer> writer)
: writer(writer)
visitor::visitor(std::shared_ptr<source::writer> writer,
std::shared_ptr<source::symbol_table> table)
: writer(writer), table(table)
{
}
@ -87,15 +88,7 @@ namespace elna::riscv
{
auto format_string = this->writer->sink(reinterpret_cast<const std::byte *>("%c\n\0"), 4);
this->instructions.push_back(instruction(base_opcode::opImm)
.i(x_register::sp, funct3_t::addi, x_register::sp, -8));
this->instructions.push_back(instruction(base_opcode::store)
.s(4, funct3_t::sw, x_register::sp, x_register::s0));
this->instructions.push_back(instruction(base_opcode::store)
.s(0, funct3_t::sw, x_register::sp, x_register::ra));
this->instructions.push_back(instruction(base_opcode::opImm)
.i(x_register::s0, funct3_t::addi, x_register::sp, -8));
prologue();
this->instructions.push_back(instruction(base_opcode::opImm)
.i(x_register::a1, funct3_t::addi, x_register::zero, 't'));
this->instructions.push_back(instruction(base_opcode::branch)
@ -114,32 +107,16 @@ namespace elna::riscv
this->instructions.push_back(instruction(base_opcode::jalr)
.i(x_register::ra, funct3_t::jalr, x_register::ra, 0));
this->instructions.push_back(instruction(base_opcode::load)
.i(x_register::s0, funct3_t::lw, x_register::sp, 4));
this->instructions.push_back(instruction(base_opcode::load)
.i(x_register::ra, funct3_t::lw, x_register::sp, 0));
this->instructions.push_back(instruction(base_opcode::opImm)
.i(x_register::sp, funct3_t::addi, x_register::sp, 8));
this->instructions.push_back(instruction(base_opcode::jalr)
.i(x_register::zero, funct3_t::jalr, x_register::ra, 0));
epilogue(8);
this->writer->sink("writeb", reinterpret_cast<const std::byte *>(this->instructions.data()),
this->instructions.size() * sizeof(instruction));
this->instructions.clear();
}
{
auto format_string = this->writer->sink(reinterpret_cast<const std::byte *>("%d\n\0"), 4);
this->instructions.push_back(instruction(base_opcode::opImm)
.i(x_register::sp, funct3_t::addi, x_register::sp, -8));
this->instructions.push_back(instruction(base_opcode::store)
.s(4, funct3_t::sw, x_register::sp, x_register::s0));
this->instructions.push_back(instruction(base_opcode::store)
.s(0, funct3_t::sw, x_register::sp, x_register::ra));
this->instructions.push_back(instruction(base_opcode::opImm)
.i(x_register::s0, funct3_t::addi, x_register::sp, -8));
prologue();
this->instructions.push_back(instruction(base_opcode::opImm)
.i(x_register::a1, funct3_t::addi, x_register::a0, 0));
@ -154,18 +131,10 @@ namespace elna::riscv
this->instructions.push_back(instruction(base_opcode::jalr)
.i(x_register::ra, funct3_t::jalr, x_register::ra, 0));
this->instructions.push_back(instruction(base_opcode::load)
.i(x_register::s0, funct3_t::lw, x_register::sp, 4));
this->instructions.push_back(instruction(base_opcode::load)
.i(x_register::ra, funct3_t::lw, x_register::sp, 0));
this->instructions.push_back(instruction(base_opcode::opImm)
.i(x_register::sp, funct3_t::addi, x_register::sp, 8));
this->instructions.push_back(instruction(base_opcode::jalr)
.i(x_register::zero, funct3_t::jalr, x_register::ra, 0));
epilogue(8);
this->writer->sink("writei", reinterpret_cast<const std::byte *>(this->instructions.data()),
this->instructions.size() * sizeof(instruction));
this->instructions.clear();
}
}
@ -186,29 +155,16 @@ namespace elna::riscv
{
}
void visitor::visit(source::procedure_definition *definition)
{
}
void visitor::visit(source::block *block)
void visitor::prologue()
{
this->instructions.push_back(instruction(base_opcode::opImm));
this->instructions.push_back(instruction(base_opcode::store));
this->instructions.push_back(instruction(base_opcode::store));
this->instructions.push_back(instruction(base_opcode::opImm));
}
table = block->table();
block->body().accept(this);
// Set the return value (0).
this->instructions.push_back(instruction(base_opcode::op)
.r(x_register::a0, funct3_t::_and, x_register::zero, x_register::zero));
// Prologue.
auto main_symbol =
std::dynamic_pointer_cast<source::procedure_info>(table->lookup("main"));
const uint stack_size = static_cast<std::uint32_t>(variable_counter * 4 + 8 + main_symbol->stack_size());
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);
@ -225,19 +181,60 @@ namespace elna::riscv
.i(x_register::zero, funct3_t::jalr, x_register::ra, 0));
}
void visitor::visit(source::procedure_definition *definition)
{
prologue();
auto main_symbol =
std::dynamic_pointer_cast<source::procedure_info>(this->table->lookup(definition->identifier()));
this->table = main_symbol->scope();
definition->body().accept(this);
this->table = main_symbol->scope()->scope();
// Set the return value (0).
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>(variable_counter * 4 + 8 + main_symbol->stack_size()));
this->writer->sink(definition->identifier(),
reinterpret_cast<const std::byte *>(this->instructions.data()),
this->instructions.size() * sizeof(instruction));
this->instructions.clear();
}
void visitor::visit(source::block *block)
{
block->body().accept(this);
}
void visitor::visit(source::program *program)
{
generate_intrinsics();
for (auto& definition : program->definitions())
{
definition->accept(this);
}
prologue();
visit(dynamic_cast<source::block *>(program));
auto main_symbol =
std::dynamic_pointer_cast<source::procedure_info>(this->table->lookup("main"));
program->body().accept(this);
// Set the return value (0).
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>(variable_counter * 4 + 8 + main_symbol->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)
{
statement->arguments().accept(this);
for (auto& argument : statement->arguments())
{
argument->accept(this);
}
relocate(statement->name(), address_t::text);
this->instructions.push_back(instruction(base_opcode::auipc).u(x_register::ra, 0));
this->instructions.push_back(instruction(base_opcode::jalr)

View File

@ -146,7 +146,8 @@ namespace elna::riscv
return -1;
}
void riscv32_elf(source::program *ast, const std::filesystem::path& out_file)
void riscv32_elf(source::program *ast, std::shared_ptr<source::symbol_table> table,
const std::filesystem::path& out_file)
{
ELFIO::elfio writer;
@ -197,7 +198,7 @@ namespace elna::riscv
ELFIO::relocation_section_accessor rela(writer, rel_sec);
auto _writer = std::make_shared<elfio_writer>(text_sec, ro_sec, syma, stra);
visitor _visitor{ _writer };
visitor _visitor{ _writer, table };
_visitor.visit(ast);
syma.arrange_local_symbols();