Support procedure calls without arguments
This commit is contained in:
@ -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)
|
||||
|
@ -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();
|
||||
|
Reference in New Issue
Block a user