Support compound statements
This commit is contained in:
@ -57,6 +57,10 @@ namespace elna::riscv
|
||||
return reinterpret_cast<const std::byte *>(&this->representation) + sizeof(this->representation);
|
||||
}
|
||||
|
||||
void visitor::visit(source::declaration *declaration)
|
||||
{
|
||||
}
|
||||
|
||||
void visitor::visit(source::definition *definition)
|
||||
{
|
||||
constants[definition->identifier()] = definition->body().number();
|
||||
@ -64,60 +68,40 @@ namespace elna::riscv
|
||||
|
||||
void visitor::visit(source::block *block)
|
||||
{
|
||||
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));
|
||||
|
||||
for (const auto& block_definition : block->definitions())
|
||||
{
|
||||
block_definition->accept(this);
|
||||
}
|
||||
for (const auto& block_declaration : block->declarations())
|
||||
{
|
||||
block_declaration->accept(this);
|
||||
}
|
||||
block->body().accept(this);
|
||||
|
||||
// Prologue.
|
||||
const uint stackSize = static_cast<std::uint32_t>(variable_counter * 4 + 12);
|
||||
|
||||
std::vector<instruction> prologue{
|
||||
instruction(base_opcode::opImm)
|
||||
.i(x_register::sp, funct3_t::addi, x_register::sp, -stackSize),
|
||||
instruction(base_opcode::store)
|
||||
.s(stackSize - 4, funct3_t::sw, x_register::sp, x_register::s0),
|
||||
instruction(base_opcode::store)
|
||||
.s(stackSize - 8, funct3_t::sw, x_register::sp, x_register::ra),
|
||||
instruction(base_opcode::opImm)
|
||||
.i(x_register::s0, funct3_t::addi, x_register::sp, stackSize)
|
||||
};
|
||||
this->instructions.insert(this->instructions.cbegin(), prologue.begin(), prologue.end());
|
||||
|
||||
// Print the result.
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::a1, funct3_t::addi, x_register::a0, 0));
|
||||
this->references[0] = reference();
|
||||
this->references[0].name = ".CL0";
|
||||
this->references[0].offset = instructions.size() * 4;
|
||||
this->references[0].target = address_t::high20;
|
||||
this->instructions.push_back(instruction(base_opcode::lui).u(x_register::a5, 0));
|
||||
this->references[1] = reference();
|
||||
this->references[1].name = ".CL0";
|
||||
this->references[1].offset = instructions.size() * 4;
|
||||
this->references[1].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[2] = reference();
|
||||
this->references[2].name = "printf";
|
||||
this->references[2].offset = instructions.size() * 4;
|
||||
this->references[2].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));
|
||||
// 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.
|
||||
const uint stack_size = static_cast<std::uint32_t>(variable_counter * 4 + 12);
|
||||
|
||||
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[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, stackSize - 4));
|
||||
.i(x_register::s0, funct3_t::lw, x_register::sp, stack_size - 4));
|
||||
this->instructions.push_back(instruction(base_opcode::load)
|
||||
.i(x_register::ra, funct3_t::lw, x_register::sp, stackSize - 8));
|
||||
.i(x_register::ra, funct3_t::lw, x_register::sp, stack_size - 8));
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::sp, funct3_t::addi, x_register::sp, stackSize));
|
||||
.i(x_register::sp, funct3_t::addi, x_register::sp, stack_size));
|
||||
this->instructions.push_back(instruction(base_opcode::jalr)
|
||||
.i(x_register::zero, funct3_t::jalr, x_register::ra, 0));
|
||||
}
|
||||
@ -125,6 +109,42 @@ namespace elna::riscv
|
||||
void visitor::visit(source::bang_statement *statement)
|
||||
{
|
||||
statement->body().accept(this);
|
||||
|
||||
// Print the result.
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::a1, funct3_t::addi, x_register::a0, 0));
|
||||
|
||||
this->references.push_back(reference());
|
||||
this->references.back().name = ".CL0";
|
||||
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 = ".CL0";
|
||||
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));
|
||||
}
|
||||
|
||||
void visitor::visit(source::compound_statement *statement)
|
||||
{
|
||||
for (auto& nested_statement : statement->statements())
|
||||
{
|
||||
nested_statement->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
void visitor::visit(source::assignment_statement *statement)
|
||||
{
|
||||
}
|
||||
|
||||
void visitor::visit(source::variable_expression *variable)
|
||||
|
@ -32,8 +32,6 @@ namespace elna::riscv
|
||||
|
||||
// Create string table writer
|
||||
ELFIO::string_section_accessor stra(str_sec);
|
||||
// Add label name
|
||||
ELFIO::Elf32_Word str_index = stra.add_string("msg");
|
||||
|
||||
// Create read only data section
|
||||
ELFIO::section* ro_sec = writer.sections.add(".rodata");
|
||||
@ -50,15 +48,6 @@ namespace elna::riscv
|
||||
sym_sec->set_entry_size(writer.get_default_entry_size(ELFIO::SHT_SYMTAB));
|
||||
sym_sec->set_link(str_sec->get_index());
|
||||
|
||||
// Create symbol table writer
|
||||
ELFIO::symbol_section_accessor syma(writer, sym_sec);
|
||||
auto label_sym = syma.add_symbol(stra, ".CL0", 0x00000000, strlen("%d\n") + 1,
|
||||
ELFIO::STB_LOCAL, ELFIO::STT_NOTYPE, 0, ro_sec->get_index());
|
||||
syma.add_symbol(stra, "main", 0x00000000, instructions_size,
|
||||
ELFIO::STB_GLOBAL, ELFIO::STT_FUNC, 0, text_sec->get_index());
|
||||
auto printf_sym = syma.add_symbol(stra, "printf", 0x00000000, 0,
|
||||
ELFIO::STB_GLOBAL, ELFIO::STT_NOTYPE, 0, ELFIO::SHN_UNDEF);
|
||||
|
||||
// Create relocation table section
|
||||
ELFIO::section* rel_sec = writer.sections.add(".rel.text");
|
||||
rel_sec->set_type(ELFIO::SHT_REL);
|
||||
@ -68,15 +57,35 @@ namespace elna::riscv
|
||||
rel_sec->set_link(sym_sec->get_index());
|
||||
rel_sec->set_flags(ELFIO::SHF_ALLOC);
|
||||
|
||||
// Create relocation table writer
|
||||
// Create symbol relocation table writers
|
||||
ELFIO::symbol_section_accessor syma(writer, sym_sec);
|
||||
ELFIO::relocation_section_accessor rela(writer, rel_sec);
|
||||
// Add relocation entry (adjust address at offset 11)
|
||||
rela.add_entry(_visitor->references[0].offset, label_sym, 26 /* ELFIO::R_RISCV_HI20 */);
|
||||
rela.add_entry(_visitor->references[0].offset, label_sym, 51 /* ELFIO::R_RISCV_RELAX */);
|
||||
rela.add_entry(_visitor->references[1].offset, label_sym, 27 /* ELFIO::R_RISCV_LO12_I */);
|
||||
rela.add_entry(_visitor->references[1].offset, label_sym, 51 /* ELFIO::R_RISCV_RELAX */);
|
||||
rela.add_entry(_visitor->references[2].offset, printf_sym, 18 /* ELFIO::R_RISCV_CALL */);
|
||||
rela.add_entry(_visitor->references[2].offset, printf_sym, 51 /* ELFIO::R_RISCV_RELAX */);
|
||||
ELFIO::Elf_Word digit_symbol = syma.add_symbol(stra, ".CL0", 0x00000000, strlen("%d\n") + 1,
|
||||
ELFIO::STB_LOCAL, ELFIO::STT_NOTYPE, 0, ro_sec->get_index());
|
||||
ELFIO::Elf_Word printf_symbol = syma.add_symbol(stra, "printf", 0x00000000, 0,
|
||||
ELFIO::STB_GLOBAL, ELFIO::STT_NOTYPE, 0, ELFIO::SHN_UNDEF);
|
||||
|
||||
for (auto& reference : _visitor->references)
|
||||
{
|
||||
// The loop assumes that address_t::lower12i always follows address_t::high20.
|
||||
switch (reference.target)
|
||||
{
|
||||
case address_t::high20:
|
||||
rela.add_entry(reference.offset, digit_symbol, 26 /* ELFIO::R_RISCV_HI20 */);
|
||||
rela.add_entry(reference.offset, digit_symbol, 51 /* ELFIO::R_RISCV_RELAX */);
|
||||
break;
|
||||
case address_t::lower12i:
|
||||
rela.add_entry(reference.offset, digit_symbol, 27 /* ELFIO::R_RISCV_LO12_I */);
|
||||
rela.add_entry(reference.offset, digit_symbol, 51 /* ELFIO::R_RISCV_RELAX */);
|
||||
break;
|
||||
case address_t::text:
|
||||
rela.add_entry(reference.offset, printf_symbol, 18 /* ELFIO::R_RISCV_CALL */);
|
||||
rela.add_entry(reference.offset, printf_symbol, 51 /* ELFIO::R_RISCV_RELAX */);
|
||||
break;
|
||||
}
|
||||
}
|
||||
syma.add_symbol(stra, "main", 0x00000000, instructions_size,
|
||||
ELFIO::STB_GLOBAL, ELFIO::STT_FUNC, 0, text_sec->get_index());
|
||||
|
||||
// Create ELF object file
|
||||
writer.save(out_file);
|
||||
|
Reference in New Issue
Block a user