elna/source/optimizer.cpp

268 lines
8.7 KiB
C++

#include "elna/source/optimizer.hpp"
#include <cassert>
namespace elna::source
{
quadruple::quadruple(const quadruple_operator operation, std::shared_ptr<operand> operand1,
std::shared_ptr<operand> operand2, std::shared_ptr<operand> operand3)
: m_operation(operation), m_operand1(operand1), m_operand2(operand2), m_operand3(operand3)
{
}
quadruple_operator quadruple::operation() const noexcept
{
return m_operation;
}
std::shared_ptr<operand> quadruple::operand1()
{
return m_operand1;
}
std::shared_ptr<operand> quadruple::operand2()
{
return m_operand2;
}
std::shared_ptr<operand> quadruple::operand3()
{
return m_operand3;
}
intermediate_code::intermediate_code()
{
clear();
}
void intermediate_code::emplace_back(const quadruple_operator operation, std::shared_ptr<operand> operand1,
std::shared_ptr<operand> operand2, std::shared_ptr<operand> operand3)
{
this->instructions.emplace_back(operation, operand1, operand2, operand3);
}
void intermediate_code::clear()
{
this->instructions.clear();
std::uint32_t variable_counter = 1;
std::uint32_t label_counter = 0;
}
std::vector<quadruple>::iterator intermediate_code::begin()
{
return this->instructions.begin();
}
std::vector<quadruple>::iterator intermediate_code::end()
{
return this->instructions.end();
}
std::int32_t intermediate_code::variable_counter() const noexcept
{
return m_variable_counter;
}
std::int32_t intermediate_code::increment_variable() noexcept
{
return m_variable_counter++;
}
std::int32_t intermediate_code::label_counter() const noexcept
{
return m_label_counter;
}
std::int32_t intermediate_code::increment_label() noexcept
{
return m_label_counter++;
}
intermediate_code_generator::intermediate_code_generator(std::shared_ptr<symbol_table> table)
: table(table)
{
}
quadruple_operator intermediate_code_generator::convert(const binary_operator operation) const
{
switch (operation)
{
case binary_operator::sum:
return quadruple_operator::add;
case binary_operator::subtraction:
return quadruple_operator::sub;
case binary_operator::multiplication:
return quadruple_operator::mul;
case binary_operator::division:
return quadruple_operator::div;
case binary_operator::equals:
return quadruple_operator::eq;
case source::binary_operator::not_equals:
return quadruple_operator::neq;
case source::binary_operator::less:
return quadruple_operator::lt;
case source::binary_operator::greater_equal:
return quadruple_operator::ge;
case source::binary_operator::greater:
return quadruple_operator::gt;
case source::binary_operator::less_equal:
return quadruple_operator::le;
default:
assert(false);
}
}
quadruple_operator intermediate_code_generator::convert(const unary_operator operation) const
{
switch (operation)
{
case unary_operator::reference:
return quadruple_operator::ref;
case unary_operator::dereference:
return quadruple_operator::load;
default:
assert(false);
}
}
void intermediate_code_generator::visit(source::declaration *declaration)
{
}
void intermediate_code_generator::visit(source::constant_definition *definition)
{
}
void intermediate_code_generator::visit(procedure_definition *definition)
{
this->current.emplace_back(quadruple_operator::start);
definition->body().accept(this);
this->current.emplace_back(quadruple_operator::stop);
code[definition->identifier()] = std::move(this->current);
this->current.clear();
}
std::unordered_map<std::string, intermediate_code>::iterator intermediate_code_generator::begin()
{
return code.begin();
}
std::unordered_map<std::string, intermediate_code>::iterator intermediate_code_generator::end()
{
return code.end();
}
void intermediate_code_generator::visit(block *block)
{
block->body().accept(this);
}
void intermediate_code_generator::visit(program *program)
{
for (auto& definition : program->definitions())
{
definition->accept(this);
}
this->current.emplace_back(quadruple_operator::start);
program->body().accept(this);
this->current.emplace_back(quadruple_operator::stop);
code["main"] = std::move(this->current);
}
void intermediate_code_generator::visit(call_statement *statement)
{
for (auto& argument : statement->arguments())
{
argument->accept(this);
this->current.emplace_back(quadruple_operator::param, argument->place, nullptr, nullptr);
}
this->current.emplace_back(quadruple_operator::call,
std::make_shared<variable_operand>(statement->name()),
std::make_shared<integer_operand>(statement->arguments().size()));
}
void intermediate_code_generator::visit(assign_statement *statement)
{
statement->rvalue().accept(this);
this->current.emplace_back(quadruple_operator::assign, statement->rvalue().place, nullptr,
std::make_shared<variable_operand>(statement->lvalue()));
}
void intermediate_code_generator::visit(if_statement *statement)
{
statement->prerequisite().accept(this);
auto end_label = std::make_shared<label_operand>(this->current.increment_label());
this->current.emplace_back(quadruple_operator::beqz, statement->prerequisite().place, nullptr, end_label);
statement->body().accept(this);
this->current.emplace_back(quadruple_operator::label, nullptr, nullptr, end_label);
}
void intermediate_code_generator::visit(while_statement *statement)
{
auto condition_label = std::make_shared<label_operand>(this->current.increment_label());
this->current.emplace_back(quadruple_operator::label, nullptr, nullptr, condition_label);
statement->prerequisite().accept(this);
auto end_label = std::make_shared<label_operand>(this->current.increment_label());
this->current.emplace_back(quadruple_operator::beqz, statement->prerequisite().place, nullptr, end_label);
statement->body().accept(this);
this->current.emplace_back(quadruple_operator::j, nullptr, nullptr, condition_label);
this->current.emplace_back(quadruple_operator::label, nullptr, nullptr, end_label);
}
void intermediate_code_generator::visit(type_expression *type)
{
}
void intermediate_code_generator::visit(variable_expression *variable)
{
auto symbol = table->lookup(variable->name());
if (auto constant_symbol = std::dynamic_pointer_cast<source::constant_info>(symbol))
{
variable->place = std::make_shared<integer_operand>(constant_symbol->value());
}
else
{
variable->place = std::make_shared<variable_operand>(variable->name());
}
}
void intermediate_code_generator::visit(binary_expression *expression)
{
expression->lhs().accept(this);
auto left = expression->lhs().place;
expression->rhs().accept(this);
auto right = expression->rhs().place;
auto operation = convert(expression->operation());
auto new_place = std::make_shared<temporary_variable>(this->current.increment_variable());
this->current.emplace_back(operation, left, right, new_place);
expression->place = new_place;
}
void intermediate_code_generator::visit(unary_expression *expression)
{
expression->operand().accept(this);
auto operation = convert(expression->operation());
auto new_place = std::make_shared<temporary_variable>(this->current.increment_variable());
this->current.emplace_back(operation, expression->operand().place, nullptr, new_place);
expression->place = new_place;
}
void intermediate_code_generator::visit(integer_literal *number)
{
number->place = std::make_shared<integer_operand>(number->number());
}
void intermediate_code_generator::visit(boolean_literal *number)
{
number->place = std::make_shared<integer_operand>(number->boolean());
}
}