#include "elna/source/optimizer.hpp" #include namespace elna::source { quadruple::quadruple(const quadruple_operator operation, std::shared_ptr operand1, std::shared_ptr operand2, std::shared_ptr 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 quadruple::operand1() { return m_operand1; } std::shared_ptr quadruple::operand2() { return m_operand2; } std::shared_ptr quadruple::operand3() { return m_operand3; } intermediate_code::intermediate_code() { clear(); } void intermediate_code::emplace_back(const quadruple_operator operation, std::shared_ptr operand1, std::shared_ptr operand2, std::shared_ptr operand3) { this->instructions.emplace_back(operation, operand1, operand2, operand3); } void intermediate_code::clear() { this->instructions.clear(); this->m_variable_counter = 1; this->m_label_counter = 0; } std::vector::iterator intermediate_code::begin() { return this->instructions.begin(); } std::vector::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 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::iterator intermediate_code_generator::begin() { return code.begin(); } std::unordered_map::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["_start"] = 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(statement->name()), std::make_shared(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(statement->lvalue())); } void intermediate_code_generator::visit(if_statement *statement) { statement->prerequisite().accept(this); auto end_label = std::make_shared(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(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(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(symbol)) { variable->place = std::make_shared(constant_symbol->value()); } else { variable->place = std::make_shared(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(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(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(number->number()); } void intermediate_code_generator::visit(boolean_literal *number) { number->place = std::make_shared(number->boolean()); } }