Implement first intrinsics for output
This commit is contained in:
parent
263b868a45
commit
7e5f7f492d
@ -81,11 +81,112 @@ namespace elna::riscv
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void visitor::generate_intrinsics()
|
||||||
|
{
|
||||||
|
this->writer->sink("printf");
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
|
||||||
|
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)
|
||||||
|
.b(8, funct3_t::bne, x_register::zero, x_register::a0));
|
||||||
|
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||||
|
.i(x_register::a1, funct3_t::addi, x_register::zero, 'f'));
|
||||||
|
|
||||||
|
relocate(format_string, address_t::high20);
|
||||||
|
this->instructions.push_back(instruction(base_opcode::lui).u(x_register::a5, 0));
|
||||||
|
relocate(format_string, address_t::lower12i);
|
||||||
|
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||||
|
.i(x_register::a0, funct3_t::addi, x_register::a5, 0));
|
||||||
|
|
||||||
|
relocate("printf", 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("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));
|
||||||
|
|
||||||
|
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||||
|
.i(x_register::a1, funct3_t::addi, x_register::a0, 0));
|
||||||
|
|
||||||
|
relocate(format_string, address_t::high20);
|
||||||
|
this->instructions.push_back(instruction(base_opcode::lui).u(x_register::a5, 0));
|
||||||
|
relocate(format_string, address_t::lower12i);
|
||||||
|
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||||
|
.i(x_register::a0, funct3_t::addi, x_register::a5, 0));
|
||||||
|
|
||||||
|
relocate("printf", 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void visitor::relocate(std::string_view name, address_t target)
|
||||||
|
{
|
||||||
|
this->references.push_back(reference());
|
||||||
|
this->references.back().name = name;
|
||||||
|
this->references.back().offset = writer->size() + instructions.size() * 4;
|
||||||
|
this->references.back().target = target;
|
||||||
|
}
|
||||||
|
|
||||||
void visitor::visit(source::declaration *declaration)
|
void visitor::visit(source::declaration *declaration)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitor::visit(source::definition *definition)
|
void visitor::visit(source::constant_definition *definition)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void visitor::visit(source::procedure_definition *definition)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,51 +227,8 @@ namespace elna::riscv
|
|||||||
|
|
||||||
void visitor::visit(source::program *program)
|
void visitor::visit(source::program *program)
|
||||||
{
|
{
|
||||||
this->writer->sink("printf");
|
generate_intrinsics();
|
||||||
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));
|
visit(dynamic_cast<source::block *>(program));
|
||||||
this->writer->sink("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));
|
this->instructions.size() * sizeof(instruction));
|
||||||
@ -180,41 +238,7 @@ namespace elna::riscv
|
|||||||
{
|
{
|
||||||
statement->arguments().accept(this);
|
statement->arguments().accept(this);
|
||||||
|
|
||||||
// Print the result.
|
relocate(statement->name(), address_t::text);
|
||||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
|
||||||
.i(x_register::a1, funct3_t::addi, x_register::a0, 0));
|
|
||||||
|
|
||||||
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, -instructions.size() * 4 - 40));
|
|
||||||
}
|
|
||||||
|
|
||||||
void visitor::visit(source::question_mark_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));
|
|
||||||
|
|
||||||
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 = 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::auipc).u(x_register::ra, 0));
|
||||||
this->instructions.push_back(instruction(base_opcode::jalr)
|
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, 0));
|
||||||
@ -242,15 +266,15 @@ namespace elna::riscv
|
|||||||
|
|
||||||
void visitor::visit(source::if_statement *statement)
|
void visitor::visit(source::if_statement *statement)
|
||||||
{
|
{
|
||||||
const auto free_register = this->register_in_use ? x_register::a0 : x_register::t0;
|
|
||||||
|
|
||||||
statement->prerequisite().accept(this);
|
statement->prerequisite().accept(this);
|
||||||
|
|
||||||
|
const auto free_register = this->register_in_use ? x_register::a0 : x_register::t0;
|
||||||
|
|
||||||
auto before_branch = instructions.size();
|
auto before_branch = instructions.size();
|
||||||
instructions.push_back(instruction(base_opcode::branch));
|
instructions.push_back(instruction(base_opcode::branch));
|
||||||
statement->body().accept(this);
|
statement->body().accept(this);
|
||||||
instructions[before_branch]
|
instructions[before_branch]
|
||||||
.b((instructions.size() - before_branch) * 4, funct3_t::beq, x_register::zero, free_register);
|
.b((instructions.size() - before_branch) * 4 - 4, funct3_t::beq, x_register::zero, free_register);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitor::visit(source::while_statement *statement)
|
void visitor::visit(source::while_statement *statement)
|
||||||
|
@ -204,22 +204,19 @@ namespace elna::riscv
|
|||||||
|
|
||||||
for (auto& reference : _visitor.references)
|
for (auto& reference : _visitor.references)
|
||||||
{
|
{
|
||||||
ELFIO::Elf_Word relocated_symbol{ 0 };
|
ELFIO::Elf_Word relocated_symbol = lookup(syma, reference.name);
|
||||||
|
|
||||||
switch (reference.target)
|
switch (reference.target)
|
||||||
{
|
{
|
||||||
case address_t::high20:
|
case address_t::high20:
|
||||||
relocated_symbol = lookup(syma, reference.name);
|
|
||||||
rela.add_entry(reference.offset, relocated_symbol, 26 /* ELFIO::R_RISCV_HI20 */);
|
rela.add_entry(reference.offset, relocated_symbol, 26 /* ELFIO::R_RISCV_HI20 */);
|
||||||
rela.add_entry(reference.offset, relocated_symbol, 51 /* ELFIO::R_RISCV_RELAX */);
|
rela.add_entry(reference.offset, relocated_symbol, 51 /* ELFIO::R_RISCV_RELAX */);
|
||||||
break;
|
break;
|
||||||
case address_t::lower12i:
|
case address_t::lower12i:
|
||||||
relocated_symbol = lookup(syma, reference.name);
|
|
||||||
rela.add_entry(reference.offset, relocated_symbol, 27 /* ELFIO::R_RISCV_LO12_I */);
|
rela.add_entry(reference.offset, relocated_symbol, 27 /* ELFIO::R_RISCV_LO12_I */);
|
||||||
rela.add_entry(reference.offset, relocated_symbol, 51 /* ELFIO::R_RISCV_RELAX */);
|
rela.add_entry(reference.offset, relocated_symbol, 51 /* ELFIO::R_RISCV_RELAX */);
|
||||||
break;
|
break;
|
||||||
case address_t::text:
|
case address_t::text:
|
||||||
relocated_symbol = lookup(syma, "printf");
|
|
||||||
rela.add_entry(reference.offset, relocated_symbol, 18 /* ELFIO::R_RISCV_CALL */);
|
rela.add_entry(reference.offset, relocated_symbol, 18 /* ELFIO::R_RISCV_CALL */);
|
||||||
rela.add_entry(reference.offset, relocated_symbol, 51 /* ELFIO::R_RISCV_RELAX */);
|
rela.add_entry(reference.offset, relocated_symbol, 51 /* ELFIO::R_RISCV_RELAX */);
|
||||||
break;
|
break;
|
||||||
|
@ -160,10 +160,13 @@ namespace elna::riscv
|
|||||||
class visitor final : public source::parser_visitor
|
class visitor final : public source::parser_visitor
|
||||||
{
|
{
|
||||||
std::shared_ptr<source::writer> writer;
|
std::shared_ptr<source::writer> writer;
|
||||||
|
|
||||||
public:
|
|
||||||
std::vector<instruction> instructions;
|
std::vector<instruction> instructions;
|
||||||
bool register_in_use{ true };
|
bool register_in_use{ true };
|
||||||
|
|
||||||
|
void generate_intrinsics();
|
||||||
|
void relocate(std::string_view name, address_t target);
|
||||||
|
|
||||||
|
public:
|
||||||
std::uint32_t variable_counter = 1;
|
std::uint32_t variable_counter = 1;
|
||||||
std::vector<reference> references;
|
std::vector<reference> references;
|
||||||
std::shared_ptr<source::symbol_table> table;
|
std::shared_ptr<source::symbol_table> table;
|
||||||
@ -171,9 +174,9 @@ namespace elna::riscv
|
|||||||
visitor(std::shared_ptr<source::writer> writer);
|
visitor(std::shared_ptr<source::writer> writer);
|
||||||
|
|
||||||
virtual void visit(source::declaration *declaration) override;
|
virtual void visit(source::declaration *declaration) override;
|
||||||
virtual void visit(source::definition *definition) override;
|
virtual void visit(source::constant_definition *definition) override;
|
||||||
|
virtual void visit(source::procedure_definition *definition) override;
|
||||||
virtual void visit(source::call_statement *statement) override;
|
virtual void visit(source::call_statement *statement) override;
|
||||||
virtual void visit(source::question_mark_statement *statement) override;
|
|
||||||
virtual void visit(source::compound_statement *statement) override;
|
virtual void visit(source::compound_statement *statement) override;
|
||||||
virtual void visit(source::assign_statement *statement) override;
|
virtual void visit(source::assign_statement *statement) override;
|
||||||
virtual void visit(source::if_statement *statement) override;
|
virtual void visit(source::if_statement *statement) override;
|
||||||
|
@ -70,11 +70,11 @@ namespace elna::source
|
|||||||
end,
|
end,
|
||||||
assignment,
|
assignment,
|
||||||
colon,
|
colon,
|
||||||
question_mark,
|
|
||||||
when,
|
when,
|
||||||
then,
|
then,
|
||||||
_while,
|
_while,
|
||||||
_do
|
_do,
|
||||||
|
procedure
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,9 +15,9 @@ namespace elna::source
|
|||||||
};
|
};
|
||||||
|
|
||||||
class declaration;
|
class declaration;
|
||||||
class definition;
|
class constant_definition;
|
||||||
|
class procedure_definition;
|
||||||
class call_statement;
|
class call_statement;
|
||||||
class question_mark_statement;
|
|
||||||
class compound_statement;
|
class compound_statement;
|
||||||
class assign_statement;
|
class assign_statement;
|
||||||
class if_statement;
|
class if_statement;
|
||||||
@ -32,9 +32,9 @@ namespace elna::source
|
|||||||
struct parser_visitor
|
struct parser_visitor
|
||||||
{
|
{
|
||||||
virtual void visit(declaration *) = 0;
|
virtual void visit(declaration *) = 0;
|
||||||
virtual void visit(definition *) = 0;
|
virtual void visit(constant_definition *) = 0;
|
||||||
|
virtual void visit(procedure_definition *) = 0;
|
||||||
virtual void visit(call_statement *) = 0;
|
virtual void visit(call_statement *) = 0;
|
||||||
virtual void visit(question_mark_statement *) = 0;
|
|
||||||
virtual void visit(compound_statement *) = 0;
|
virtual void visit(compound_statement *) = 0;
|
||||||
virtual void visit(assign_statement *) = 0;
|
virtual void visit(assign_statement *) = 0;
|
||||||
virtual void visit(if_statement *) = 0;
|
virtual void visit(if_statement *) = 0;
|
||||||
@ -50,9 +50,9 @@ namespace elna::source
|
|||||||
struct empty_visitor : parser_visitor
|
struct empty_visitor : parser_visitor
|
||||||
{
|
{
|
||||||
virtual void visit(declaration *declaration) override;
|
virtual void visit(declaration *declaration) override;
|
||||||
virtual void visit(definition *definition) override;
|
virtual void visit(constant_definition *definition) override;
|
||||||
|
virtual void visit(procedure_definition *definition) override;
|
||||||
virtual void visit(call_statement *statement) override;
|
virtual void visit(call_statement *statement) override;
|
||||||
virtual void visit(question_mark_statement *statement) override;
|
|
||||||
virtual void visit(compound_statement *statement) override;
|
virtual void visit(compound_statement *statement) override;
|
||||||
virtual void visit(assign_statement *statement) override;
|
virtual void visit(assign_statement *statement) override;
|
||||||
virtual void visit(if_statement *) override;
|
virtual void visit(if_statement *) override;
|
||||||
@ -82,10 +82,6 @@ namespace elna::source
|
|||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
class condition : public node
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable declaration.
|
* Variable declaration.
|
||||||
*/
|
*/
|
||||||
@ -106,16 +102,36 @@ namespace elna::source
|
|||||||
class definition : public node
|
class definition : public node
|
||||||
{
|
{
|
||||||
std::string m_identifier;
|
std::string m_identifier;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
definition(const std::string& identifier);
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::string& identifier() noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
class constant_definition : public definition
|
||||||
|
{
|
||||||
std::unique_ptr<integer_literal> m_body;
|
std::unique_ptr<integer_literal> m_body;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
definition(const std::string& identifier, std::unique_ptr<integer_literal>&& body);
|
constant_definition(const std::string& identifier, std::unique_ptr<integer_literal>&& body);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
std::string& identifier() noexcept;
|
|
||||||
integer_literal& body();
|
integer_literal& body();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class procedure_definition : public definition
|
||||||
|
{
|
||||||
|
std::unique_ptr<block> m_body;
|
||||||
|
|
||||||
|
public:
|
||||||
|
procedure_definition(const std::string& identifier, std::unique_ptr<block>&& body);
|
||||||
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
|
block& body();
|
||||||
|
};
|
||||||
|
|
||||||
class call_statement : public statement
|
class call_statement : public statement
|
||||||
{
|
{
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
@ -129,17 +145,6 @@ namespace elna::source
|
|||||||
expression& arguments();
|
expression& arguments();
|
||||||
};
|
};
|
||||||
|
|
||||||
class question_mark_statement : public statement
|
|
||||||
{
|
|
||||||
std::unique_ptr<condition> m_body;
|
|
||||||
|
|
||||||
public:
|
|
||||||
question_mark_statement(std::unique_ptr<condition>&& body);
|
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
|
||||||
|
|
||||||
condition& body();
|
|
||||||
};
|
|
||||||
|
|
||||||
class compound_statement : public statement
|
class compound_statement : public statement
|
||||||
{
|
{
|
||||||
std::vector<std::unique_ptr<statement>> m_statements;
|
std::vector<std::unique_ptr<statement>> m_statements;
|
||||||
@ -167,27 +172,27 @@ namespace elna::source
|
|||||||
|
|
||||||
class if_statement : public statement
|
class if_statement : public statement
|
||||||
{
|
{
|
||||||
std::unique_ptr<condition> m_prerequisite;
|
std::unique_ptr<expression> m_prerequisite;
|
||||||
std::unique_ptr<statement> m_body;
|
std::unique_ptr<statement> m_body;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
if_statement(std::unique_ptr<condition>&& prerequisite, std::unique_ptr<statement>&& body);
|
if_statement(std::unique_ptr<expression>&& prerequisite, std::unique_ptr<statement>&& body);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
condition& prerequisite();
|
expression& prerequisite();
|
||||||
statement& body();
|
statement& body();
|
||||||
};
|
};
|
||||||
|
|
||||||
class while_statement : public statement
|
class while_statement : public statement
|
||||||
{
|
{
|
||||||
std::unique_ptr<condition> m_prerequisite;
|
std::unique_ptr<expression> m_prerequisite;
|
||||||
std::unique_ptr<statement> m_body;
|
std::unique_ptr<statement> m_body;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
while_statement(std::unique_ptr<condition>&& prerequisite, std::unique_ptr<statement>&& body);
|
while_statement(std::unique_ptr<expression>&& prerequisite, std::unique_ptr<statement>&& body);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
condition& prerequisite();
|
expression& prerequisite();
|
||||||
statement& body();
|
statement& body();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -230,7 +235,7 @@ namespace elna::source
|
|||||||
std::int32_t number() const noexcept;
|
std::int32_t number() const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
class boolean_literal : public condition
|
class boolean_literal : public expression
|
||||||
{
|
{
|
||||||
bool m_boolean;
|
bool m_boolean;
|
||||||
|
|
||||||
@ -273,12 +278,10 @@ namespace elna::source
|
|||||||
std::unique_ptr<expression> parse_factor();
|
std::unique_ptr<expression> parse_factor();
|
||||||
std::unique_ptr<expression> parse_term();
|
std::unique_ptr<expression> parse_term();
|
||||||
std::unique_ptr<expression> parse_expression();
|
std::unique_ptr<expression> parse_expression();
|
||||||
std::unique_ptr<condition> parse_condition();
|
std::unique_ptr<constant_definition> parse_constant_definition();
|
||||||
std::unique_ptr<definition> parse_definition();
|
|
||||||
std::unique_ptr<declaration> parse_declaration();
|
std::unique_ptr<declaration> parse_declaration();
|
||||||
std::unique_ptr<statement> parse_statement();
|
std::unique_ptr<statement> parse_statement();
|
||||||
std::unique_ptr<call_statement> parse_call_statement();
|
std::unique_ptr<call_statement> parse_call_statement();
|
||||||
std::unique_ptr<question_mark_statement> parse_question_mark_statement();
|
|
||||||
std::unique_ptr<compound_statement> parse_compound_statement();
|
std::unique_ptr<compound_statement> parse_compound_statement();
|
||||||
std::unique_ptr<assign_statement> parse_assign_statement();
|
std::unique_ptr<assign_statement> parse_assign_statement();
|
||||||
std::unique_ptr<if_statement> parse_if_statement();
|
std::unique_ptr<if_statement> parse_if_statement();
|
||||||
|
@ -9,7 +9,7 @@ namespace elna::source
|
|||||||
std::shared_ptr<symbol_table> table;
|
std::shared_ptr<symbol_table> table;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void visit(definition *definition) override;
|
void visit(constant_definition *definition) override;
|
||||||
void visit(declaration *declaration) override;
|
void visit(declaration *declaration) override;
|
||||||
void visit(block *block) override;
|
void visit(block *block) override;
|
||||||
};
|
};
|
||||||
|
@ -350,10 +350,6 @@ namespace elna::source
|
|||||||
{
|
{
|
||||||
tokens.emplace_back(token::type::comma, iterator.position());
|
tokens.emplace_back(token::type::comma, iterator.position());
|
||||||
}
|
}
|
||||||
else if (*iterator == '?')
|
|
||||||
{
|
|
||||||
tokens.emplace_back(token::type::question_mark, iterator.position());
|
|
||||||
}
|
|
||||||
else if (*iterator == '.')
|
else if (*iterator == '.')
|
||||||
{
|
{
|
||||||
tokens.emplace_back(token::type::dot, iterator.position());
|
tokens.emplace_back(token::type::dot, iterator.position());
|
||||||
@ -407,6 +403,10 @@ namespace elna::source
|
|||||||
{
|
{
|
||||||
tokens.emplace_back(token::type::boolean, 0, iterator.position());
|
tokens.emplace_back(token::type::boolean, 0, iterator.position());
|
||||||
}
|
}
|
||||||
|
else if (word == "proc")
|
||||||
|
{
|
||||||
|
tokens.emplace_back(token::type::procedure, 0, iterator.position());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tokens.emplace_back(token::type::identifier, word.c_str(), iterator.position());
|
tokens.emplace_back(token::type::identifier, word.c_str(), iterator.position());
|
||||||
|
@ -7,7 +7,12 @@ namespace elna::source
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(definition *definition)
|
void empty_visitor::visit(constant_definition *definition)
|
||||||
|
{
|
||||||
|
definition->body().accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void empty_visitor::visit(procedure_definition *definition)
|
||||||
{
|
{
|
||||||
definition->body().accept(this);
|
definition->body().accept(this);
|
||||||
}
|
}
|
||||||
@ -17,11 +22,6 @@ namespace elna::source
|
|||||||
statement->arguments().accept(this);
|
statement->arguments().accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(question_mark_statement *statement)
|
|
||||||
{
|
|
||||||
statement->body().accept(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void empty_visitor::visit(compound_statement *statement)
|
void empty_visitor::visit(compound_statement *statement)
|
||||||
{
|
{
|
||||||
for (auto& nested_statement : statement->statements())
|
for (auto& nested_statement : statement->statements())
|
||||||
@ -95,24 +95,19 @@ namespace elna::source
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string& declaration::identifier() noexcept
|
|
||||||
{
|
|
||||||
return m_identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
definition::definition(const std::string& identifier, std::unique_ptr<integer_literal>&& body)
|
|
||||||
: m_identifier(std::move(identifier)), m_body(std::move(body))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void declaration::accept(parser_visitor *visitor)
|
void declaration::accept(parser_visitor *visitor)
|
||||||
{
|
{
|
||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void definition::accept(parser_visitor *visitor)
|
std::string& declaration::identifier() noexcept
|
||||||
|
{
|
||||||
|
return m_identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
definition::definition(const std::string& identifier)
|
||||||
|
: m_identifier(identifier)
|
||||||
{
|
{
|
||||||
visitor->visit(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string& definition::identifier() noexcept
|
std::string& definition::identifier() noexcept
|
||||||
@ -120,7 +115,32 @@ namespace elna::source
|
|||||||
return m_identifier;
|
return m_identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
integer_literal& definition::body()
|
constant_definition::constant_definition(const std::string& identifier, std::unique_ptr<integer_literal>&& body)
|
||||||
|
: definition(identifier), m_body(std::move(body))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void constant_definition::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
integer_literal& constant_definition::body()
|
||||||
|
{
|
||||||
|
return *m_body;
|
||||||
|
}
|
||||||
|
|
||||||
|
procedure_definition::procedure_definition(const std::string& identifier, std::unique_ptr<block>&& body)
|
||||||
|
: definition(identifier), m_body(std::move(body))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void procedure_definition::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
block& procedure_definition::body()
|
||||||
{
|
{
|
||||||
return *m_body;
|
return *m_body;
|
||||||
}
|
}
|
||||||
@ -279,21 +299,6 @@ namespace elna::source
|
|||||||
return *m_body;
|
return *m_body;
|
||||||
}
|
}
|
||||||
|
|
||||||
question_mark_statement::question_mark_statement(std::unique_ptr<condition>&& body)
|
|
||||||
: m_body(std::move(body))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void question_mark_statement::accept(parser_visitor *visitor)
|
|
||||||
{
|
|
||||||
visitor->visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
condition& question_mark_statement::body()
|
|
||||||
{
|
|
||||||
return *m_body;
|
|
||||||
}
|
|
||||||
|
|
||||||
compound_statement::compound_statement(std::vector<std::unique_ptr<statement>>&& statements)
|
compound_statement::compound_statement(std::vector<std::unique_ptr<statement>>&& statements)
|
||||||
: m_statements(std::move(statements))
|
: m_statements(std::move(statements))
|
||||||
{
|
{
|
||||||
@ -329,7 +334,7 @@ namespace elna::source
|
|||||||
return *m_rvalue;
|
return *m_rvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if_statement::if_statement(std::unique_ptr<condition>&& prerequisite, std::unique_ptr<statement>&& body)
|
if_statement::if_statement(std::unique_ptr<expression>&& prerequisite, std::unique_ptr<statement>&& body)
|
||||||
: m_prerequisite(std::move(prerequisite)), m_body(std::move(body))
|
: m_prerequisite(std::move(prerequisite)), m_body(std::move(body))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -339,7 +344,7 @@ namespace elna::source
|
|||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
condition& if_statement::prerequisite()
|
expression& if_statement::prerequisite()
|
||||||
{
|
{
|
||||||
return *m_prerequisite;
|
return *m_prerequisite;
|
||||||
}
|
}
|
||||||
@ -349,7 +354,7 @@ namespace elna::source
|
|||||||
return *m_body;
|
return *m_body;
|
||||||
}
|
}
|
||||||
|
|
||||||
while_statement::while_statement(std::unique_ptr<condition>&& prerequisite, std::unique_ptr<statement>&& body)
|
while_statement::while_statement(std::unique_ptr<expression>&& prerequisite, std::unique_ptr<statement>&& body)
|
||||||
: m_prerequisite(std::move(prerequisite)), m_body(std::move(body))
|
: m_prerequisite(std::move(prerequisite)), m_body(std::move(body))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -359,7 +364,7 @@ namespace elna::source
|
|||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
condition& while_statement::prerequisite()
|
expression& while_statement::prerequisite()
|
||||||
{
|
{
|
||||||
return *m_prerequisite;
|
return *m_prerequisite;
|
||||||
}
|
}
|
||||||
@ -407,6 +412,12 @@ namespace elna::source
|
|||||||
++iterator;
|
++iterator;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
else if (iterator->of() == source::token::token::type::boolean)
|
||||||
|
{
|
||||||
|
auto result = std::make_unique<boolean_literal>(iterator->number());
|
||||||
|
++iterator;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
else if (iterator->of() == source::token::type::left_paren)
|
else if (iterator->of() == source::token::type::left_paren)
|
||||||
{
|
{
|
||||||
++iterator;
|
++iterator;
|
||||||
@ -458,18 +469,7 @@ namespace elna::source
|
|||||||
return term;
|
return term;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<condition> parser::parse_condition()
|
std::unique_ptr<constant_definition> parser::parse_constant_definition()
|
||||||
{
|
|
||||||
if (iterator->of() == source::token::token::type::boolean)
|
|
||||||
{
|
|
||||||
auto result = std::make_unique<boolean_literal>(iterator->number());
|
|
||||||
++iterator;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<definition> parser::parse_definition()
|
|
||||||
{
|
{
|
||||||
auto definition_identifier = iterator.advance(token::type::identifier);
|
auto definition_identifier = iterator.advance(token::type::identifier);
|
||||||
|
|
||||||
@ -484,7 +484,7 @@ namespace elna::source
|
|||||||
|
|
||||||
if (iterator->of() == source::token::type::number)
|
if (iterator->of() == source::token::type::number)
|
||||||
{
|
{
|
||||||
auto result = std::make_unique<definition>(definition_identifier.value().get().identifier(),
|
auto result = std::make_unique<constant_definition>(definition_identifier.value().get().identifier(),
|
||||||
std::make_unique<integer_literal>(iterator->number()));
|
std::make_unique<integer_literal>(iterator->number()));
|
||||||
++iterator;
|
++iterator;
|
||||||
return result;
|
return result;
|
||||||
@ -519,10 +519,6 @@ namespace elna::source
|
|||||||
{
|
{
|
||||||
return parse_call_statement();
|
return parse_call_statement();
|
||||||
}
|
}
|
||||||
else if (iterator.current(token::type::question_mark))
|
|
||||||
{
|
|
||||||
return parse_question_mark_statement();
|
|
||||||
}
|
|
||||||
else if (iterator.current(token::type::begin))
|
else if (iterator.current(token::type::begin))
|
||||||
{
|
{
|
||||||
return parse_compound_statement();
|
return parse_compound_statement();
|
||||||
@ -555,21 +551,6 @@ namespace elna::source
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<question_mark_statement> parser::parse_question_mark_statement()
|
|
||||||
{
|
|
||||||
if (!iterator.advance(token::type::question_mark))
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
auto question_mark_body = parse_condition();
|
|
||||||
|
|
||||||
if (question_mark_body != nullptr)
|
|
||||||
{
|
|
||||||
return std::make_unique<question_mark_statement>(std::move(question_mark_body));
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<compound_statement> parser::parse_compound_statement()
|
std::unique_ptr<compound_statement> parser::parse_compound_statement()
|
||||||
{
|
{
|
||||||
if (!iterator.advance(token::type::begin))
|
if (!iterator.advance(token::type::begin))
|
||||||
@ -624,7 +605,7 @@ namespace elna::source
|
|||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto condition = parse_condition();
|
auto condition = parse_expression();
|
||||||
|
|
||||||
if (condition == nullptr || !iterator.skip(token::type::then))
|
if (condition == nullptr || !iterator.skip(token::type::then))
|
||||||
{
|
{
|
||||||
@ -645,7 +626,7 @@ namespace elna::source
|
|||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto condition = parse_condition();
|
auto condition = parse_expression();
|
||||||
|
|
||||||
if (condition == nullptr || !iterator.skip(token::type::_do))
|
if (condition == nullptr || !iterator.skip(token::type::_do))
|
||||||
{
|
{
|
||||||
@ -671,7 +652,7 @@ namespace elna::source
|
|||||||
++iterator; // Skip const.
|
++iterator; // Skip const.
|
||||||
|
|
||||||
std::unique_ptr<definition> parsed_definition;
|
std::unique_ptr<definition> parsed_definition;
|
||||||
while ((parsed_definition = parse_definition()) != nullptr)
|
while ((parsed_definition = parse_constant_definition()) != nullptr)
|
||||||
{
|
{
|
||||||
definitions.push_back(std::move(parsed_definition));
|
definitions.push_back(std::move(parsed_definition));
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
namespace elna::source
|
namespace elna::source
|
||||||
{
|
{
|
||||||
void name_analysis_visitor::visit(definition *definition)
|
void name_analysis_visitor::visit(constant_definition *definition)
|
||||||
{
|
{
|
||||||
this->table->enter(definition->identifier(),
|
this->table->enter(definition->identifier(),
|
||||||
std::make_shared<constant_info>(constant_info(definition->body().number())));
|
std::make_shared<constant_info>(constant_info(definition->body().number())));
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
1
|
t
|
||||||
0
|
f
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
begin
|
begin
|
||||||
? True;
|
writeb(True);
|
||||||
? False
|
writeb(False)
|
||||||
end.
|
end.
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
write(5 - 4)
|
writei(5 - 4)
|
||||||
.
|
.
|
||||||
|
@ -114,9 +114,8 @@ namespace elna
|
|||||||
|
|
||||||
boost::asio::io_service io_service;
|
boost::asio::io_service io_service;
|
||||||
std::future<std::string> buffer;
|
std::future<std::string> buffer;
|
||||||
boost::process::child spike(
|
boost::process::child qemu(
|
||||||
"/opt/riscv/bin/spike", "--isa=RV32IMAC",
|
boost::process::search_path("qemu-riscv32"),
|
||||||
"/opt/riscv/riscv32-unknown-elf/bin/pk",
|
|
||||||
test_binary.string(),
|
test_binary.string(),
|
||||||
boost::process::std_out > buffer,
|
boost::process::std_out > buffer,
|
||||||
boost::process::std_err > buffer,
|
boost::process::std_err > buffer,
|
||||||
@ -124,7 +123,7 @@ namespace elna
|
|||||||
);
|
);
|
||||||
io_service.run();
|
io_service.run();
|
||||||
|
|
||||||
return test_result{ test_status::successful, spike.exit_code(), buffer.get() };
|
return test_result{ test_status::successful, qemu.exit_code(), buffer.get() };
|
||||||
}
|
}
|
||||||
|
|
||||||
static test_results run_in_path(const std::filesystem::path test_directory)
|
static test_results run_in_path(const std::filesystem::path test_directory)
|
||||||
|
Loading…
Reference in New Issue
Block a user