Generate code for loops
This commit is contained in:
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
104
include/elna/source/optimizer.hpp
Normal file
104
include/elna/source/optimizer.hpp
Normal 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;
|
||||
};
|
||||
}
|
@ -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.
|
||||
|
@ -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.
|
||||
|
Reference in New Issue
Block a user