Replace ! with a function call writei

This commit is contained in:
2024-03-19 09:35:50 +01:00
parent e7d8f9116a
commit c210c55a17
25 changed files with 315 additions and 159 deletions

View File

@ -76,9 +76,8 @@ namespace elna::riscv
return reinterpret_cast<const std::byte *>(&this->representation) + sizeof(this->representation);
}
visitor::visitor(std::function<void(const std::string&, const std::byte *, std::size_t)> write_text,
std::function<std::string_view(const std::byte *, std::size_t)> write_read_only)
: write_text(write_text), write_read_only(write_read_only)
visitor::visitor(std::shared_ptr<source::writer> writer)
: writer(writer)
{
}
@ -127,40 +126,67 @@ namespace elna::riscv
void visitor::visit(source::program *program)
{
this->writer->sink("printf");
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));
this->references.push_back(reference());
this->references.back().name = format_string;
this->references.back().offset = writer->size() + instructions.size() * 4;
this->references.back().target = address_t::high20;
this->instructions.push_back(instruction(base_opcode::lui).u(x_register::a5, 0));
this->references.push_back(reference());
this->references.back().name = format_string;
this->references.back().offset = writer->size() + instructions.size() * 4;
this->references.back().target = address_t::lower12i;
this->instructions.push_back(instruction(base_opcode::opImm)
.i(x_register::a0, funct3_t::addi, x_register::a5, 0));
this->references.push_back(reference());
this->references.back().name = "printf";
this->references.back().offset = writer->size() + instructions.size() * 4;
this->references.back().target = address_t::text;
this->instructions.push_back(instruction(base_opcode::auipc).u(x_register::ra, 0));
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));
this->writer->sink("writei", reinterpret_cast<const std::byte *>(this->instructions.data()),
this->instructions.size() * sizeof(instruction));
this->instructions.clear();
visit(dynamic_cast<source::block *>(program));
write_text("main", reinterpret_cast<const std::byte *>(this->instructions.data()),
this->writer->sink("main", reinterpret_cast<const std::byte *>(this->instructions.data()),
this->instructions.size() * sizeof(instruction));
}
void visitor::visit(source::bang_statement *statement)
void visitor::visit(source::call_statement *statement)
{
statement->body().accept(this);
statement->arguments().accept(this);
// Print the result.
this->instructions.push_back(instruction(base_opcode::opImm)
.i(x_register::a1, funct3_t::addi, x_register::a0, 0));
auto format_string = write_read_only(reinterpret_cast<const std::byte *>("%d\n\0"), 4);
this->references.push_back(reference());
this->references.back().name = format_string;
this->references.back().offset = instructions.size() * 4;
this->references.back().target = address_t::high20;
this->instructions.push_back(instruction(base_opcode::lui).u(x_register::a5, 0));
this->references.push_back(reference());
this->references.back().name = format_string;
this->references.back().offset = instructions.size() * 4;
this->references.back().target = address_t::lower12i;
this->instructions.push_back(instruction(base_opcode::opImm)
.i(x_register::a0, funct3_t::addi, x_register::a5, 0));
this->references.push_back(reference());
this->references.back().name = "printf";
this->references.back().offset = instructions.size() * 4;
this->references.back().target = address_t::text;
this->instructions.push_back(instruction(base_opcode::auipc).u(x_register::ra, 0));
this->instructions.push_back(instruction(base_opcode::jalr)
.i(x_register::ra, funct3_t::jalr, x_register::ra, 0));
.i(x_register::ra, funct3_t::jalr, x_register::ra, -instructions.size() * 4 - 40));
}
void visitor::visit(source::question_mark_statement *statement)
@ -171,23 +197,23 @@ namespace elna::riscv
this->instructions.push_back(instruction(base_opcode::opImm)
.i(x_register::a1, funct3_t::addi, x_register::a0, 0));
auto format_string = write_read_only(reinterpret_cast<const std::byte *>("%d\n\0"), 4);
auto format_string = this->writer->sink(reinterpret_cast<const std::byte *>("%d\n\0"), 4);
this->references.push_back(reference());
this->references.back().name = format_string;
this->references.back().offset = instructions.size() * 4;
this->references.back().offset = writer->size() + instructions.size() * 4;
this->references.back().target = address_t::high20;
this->instructions.push_back(instruction(base_opcode::lui).u(x_register::a5, 0));
this->references.push_back(reference());
this->references.back().name = format_string;
this->references.back().offset = instructions.size() * 4;
this->references.back().offset = writer->size() + instructions.size() * 4;
this->references.back().target = address_t::lower12i;
this->instructions.push_back(instruction(base_opcode::opImm)
.i(x_register::a0, funct3_t::addi, x_register::a5, 0));
this->references.push_back(reference());
this->references.back().name = "printf";
this->references.back().offset = instructions.size() * 4;
this->references.back().offset = writer->size() + instructions.size() * 4;
this->references.back().target = address_t::text;
this->instructions.push_back(instruction(base_opcode::auipc).u(x_register::ra, 0));
this->instructions.push_back(instruction(base_opcode::jalr)
@ -224,7 +250,7 @@ namespace elna::riscv
instructions.push_back(instruction(base_opcode::branch));
statement->body().accept(this);
instructions[before_branch]
.b((instructions.size() - before_branch) * 4 - 3, funct3_t::beq, x_register::zero, free_register);
.b((instructions.size() - before_branch) * 4, funct3_t::beq, x_register::zero, free_register);
}
void visitor::visit(source::while_statement *statement)