Generate code for loops

This commit is contained in:
2024-04-18 12:15:26 +02:00
parent 9c7614dd25
commit f48fae4878
13 changed files with 788 additions and 333 deletions

View File

@ -1,7 +1,7 @@
#pragma once
#include <cstdint>
#include "elna/source/parser.hpp"
#include "elna/source/optimizer.hpp"
namespace elna::riscv
{
@ -158,40 +158,6 @@ namespace elna::riscv
std::uint32_t representation{ 0 };
};
class visitor final : public source::parser_visitor
{
std::shared_ptr<source::writer> writer;
std::vector<instruction> instructions;
bool register_in_use{ true };
void generate_intrinsics();
void relocate(std::string_view name, address_t target);
void prologue();
void epilogue(const std::size_t stack_size);
public:
std::uint32_t variable_counter = 1;
std::vector<reference> references;
std::shared_ptr<source::symbol_table> table;
visitor(std::shared_ptr<source::writer> writer,
std::shared_ptr<source::symbol_table> table);
virtual void visit(source::declaration *declaration) 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::compound_statement *statement) override;
virtual void visit(source::assign_statement *statement) override;
virtual void visit(source::if_statement *statement) override;
virtual void visit(source::while_statement *statement) override;
virtual void visit(source::block *block) override;
virtual void visit(source::program *program) override;
virtual void visit(source::type_expression *variable) override;
virtual void visit(source::variable_expression *variable) override;
virtual void visit(source::binary_expression *expression) override;
virtual void visit(source::unary_expression *expression) override;
virtual void visit(source::integer_literal *number) override;
virtual void visit(source::boolean_literal *number) override;
};
std::vector<reference> generate(source::intermediate_code_generator generator,
std::shared_ptr<source::symbol_table> table, std::shared_ptr<source::writer<std::byte>> writer);
}

View File

@ -1,4 +1,7 @@
#pragma once
#include "elna/source/parser.hpp"
#include "elna/source/optimizer.hpp"
#include <filesystem>
#include <elfio/elfio.hpp>
@ -72,7 +75,7 @@ namespace elna::riscv
ELFIO::section *m_section;
};
class elfio_writer final : public source::writer
class elfio_writer final : public source::writer<std::byte>
{
ELFIO::section *text;
elfio_section_writer read_only;
@ -99,6 +102,6 @@ namespace elna::riscv
*/
std::ptrdiff_t lookup(ELFIO::symbol_section_accessor symbol_accessor, const std::string& label);
void riscv32_elf(source::program *ast, std::shared_ptr<source::symbol_table> table,
const std::filesystem::path& out_file);
void riscv32_elf(source::program *ast, source::intermediate_code_generator intermediate_code_generator,
std::shared_ptr<source::symbol_table> table, const std::filesystem::path& out_file);
}

View File

@ -0,0 +1,104 @@
#pragma once
#include "elna/source/parser.hpp"
namespace elna::source
{
enum class quadruple_operator
{
start,
stop,
add,
sub,
mul,
div,
eq,
neq,
lt,
ge,
gt,
le,
load,
ref,
beqz,
j,
label,
assign,
param,
call
};
/**
* Single instruction representation.
*/
struct quadruple
{
quadruple(const quadruple_operator operation, std::shared_ptr<operand> operand1 = nullptr,
std::shared_ptr<operand> operand2 = nullptr, std::shared_ptr<operand> operand3 = nullptr);
quadruple_operator operation() const noexcept;
std::shared_ptr<operand> operand1();
std::shared_ptr<operand> operand2();
std::shared_ptr<operand> operand3();
private:
quadruple_operator m_operation;
std::shared_ptr<operand> m_operand1;
std::shared_ptr<operand> m_operand2;
std::shared_ptr<operand> m_operand3;
};
class intermediate_code final
{
std::vector<quadruple> instructions;
std::uint32_t m_variable_counter;
std::uint32_t m_label_counter;
public:
intermediate_code();
void emplace_back(const quadruple_operator operation, std::shared_ptr<operand> operand1 = nullptr,
std::shared_ptr<operand> operand2 = nullptr, std::shared_ptr<operand> operand3 = nullptr);
void clear();
std::vector<quadruple>::iterator begin();
std::vector<quadruple>::iterator end();
std::int32_t variable_counter() const noexcept;
std::int32_t increment_variable() noexcept;
std::int32_t label_counter() const noexcept;
std::int32_t increment_label() noexcept;
};
class intermediate_code_generator final : public empty_visitor
{
std::unordered_map<std::string, intermediate_code> code;
intermediate_code current;
std::shared_ptr<symbol_table> table;
quadruple_operator convert(const binary_operator operation) const;
quadruple_operator convert(const unary_operator operation) const;
public:
intermediate_code_generator(std::shared_ptr<symbol_table> table);
std::unordered_map<std::string, intermediate_code>::iterator begin();
std::unordered_map<std::string, intermediate_code>::iterator end();
void visit(declaration *declaration) override;
void visit(constant_definition *definition) override;
void visit(procedure_definition *definition) override;
void visit(call_statement *statement) override;
void visit(assign_statement *statement) override;
void visit(if_statement *statement) override;
void visit(while_statement *statement) override;
void visit(block *block) override;
void visit(program *program) override;
void visit(type_expression *variable) override;
void visit(variable_expression *variable) override;
void visit(binary_expression *expression) override;
void visit(unary_expression *expression) override;
void visit(integer_literal *number) override;
void visit(boolean_literal *number) override;
};
}

View File

@ -89,6 +89,55 @@ namespace elna::source
virtual void visit(boolean_literal *boolean) override;
};
/**
* Operand representing a subexpression in the 3 address code.
*/
struct operand
{
public:
virtual ~operand() noexcept = 0;
};
struct integer_operand final : public operand
{
std::int32_t m_value;
public:
explicit integer_operand(const std::int32_t value);
std::int32_t value() const noexcept;
};
class variable_operand final : public operand
{
std::string m_name;
public:
explicit variable_operand(const std::string& name);
const std::string& name() const noexcept;
};
struct temporary_variable final : public operand
{
std::size_t m_counter;
public:
explicit temporary_variable(const std::size_t counter);
std::size_t counter() const noexcept;
};
struct label_operand final : public operand
{
std::size_t m_counter;
public:
explicit label_operand(const std::size_t counter);
std::size_t counter() const noexcept;
};
/**
* AST node.
*/
@ -122,6 +171,9 @@ namespace elna::source
class expression : public node
{
public:
std::shared_ptr<operand> place;
protected:
/**
* \param position Source code position.

View File

@ -301,6 +301,7 @@ namespace elna::source
std::shared_ptr<symbol_table> scope();
};
template<typename T>
struct writer
{
/**
@ -312,7 +313,7 @@ namespace elna::source
*
* \return New size of the table.
*/
virtual std::size_t sink(const std::string& label, const std::byte *data, std::size_t size) = 0;
virtual std::size_t sink(const std::string& label, const T *data, std::size_t size) = 0;
/**
* Writes data and returns a label under that the data can be accessed.
@ -322,7 +323,7 @@ namespace elna::source
*
* \return Label for the symbol.
*/
virtual std::string_view sink(const std::byte *data, std::size_t size) = 0;
virtual std::string_view sink(const T *data, std::size_t size) = 0;
/**
* Creates an external symbol.