📄 optimize.cc
字号:
////////////////////////////////////////////////////////////////////////////////// optimize.cc -- procedures for AST optimization//// The main entry point in this file is optimize_syntax_tree.// It should do all sorts of machine-independent optimizations.//// At the moment, all it does is evaluate constant expressions// (unsafely: there's no check for overflow!) and detect subroutines// with no local variables (makes stack allocation easier).//#include "tokens.h"#include "symtab.h"#include "attributes.h"#include "optimize.h"bool evaluate_consts = true;static se_procedure_t * current_procedure = NULL;////////////////////////////////////////////////////////////////////////////////// Every node a syntax tree must implement the optimize member function.// Optimize should perform any optimizations that in can (including calling// optimize for each of its children) and should then return either a pointer// to itself or to another node which will replace it. We use this// replacement options in cases such as a binary operation on two constants// which replaces itself with a single constant.//syntax_tree_t *syntax_tree_t::optimize(void){ return this;}syntax_tree_t *st_token_t::optimize(void){ return this;}syntax_tree_t *st_identifier_t::optimize(void){ if (symbol_entry == input_symbol && current_procedure != NULL) current_procedure->not_leaf(); if (se_constant_t *con = dynamic_cast<se_constant_t *>(symbol_entry)) { // cast will fail (return NULL) if we're not a constant st_number_t *n = new st_number_t(attributes, con->get_value()); delete this; return n; } return this;}syntax_tree_t *st_number_t::optimize(void){ return this;}syntax_tree_t *st_operator_t::optimize(void){ return this;}syntax_tree_t *st_unary_op_t::optimize(void){ st_number_t * number; operand = optimize_syntax_tree(operand); if (evaluate_consts && (number = dynamic_cast<st_number_t *>(operand))) { // cast will fail (return NULL) if operand isn't a constant // Replace ourselves with the NUMBER constant. st_number_t * n = NULL; int value; token_attrib_t t = op->get_attributes(); switch (t.get_minor()) { case MIN_MINUS: value = -number->get_value(); n = new st_number_t(t, value); break; case MIN_ODD: value = number->get_value() & 1; n = new st_number_t(t, value); break; } if (n) { delete this; return n; } } return this;}syntax_tree_t *st_binary_op_t::optimize(void){ st_number_t * left_number; st_number_t * right_number; left_operand = optimize_syntax_tree(left_operand); right_operand = optimize_syntax_tree(right_operand); if (evaluate_consts && (left_number = dynamic_cast<st_number_t *>(left_operand)) && (right_number = dynamic_cast<st_number_t *>(right_operand))) { // casts may fail (return NULL) if operands are not constants // Replace ourselves with the NUMBER constant. st_number_t * n = NULL; int value; token_attrib_t t = op->get_attributes(); switch (t.get_minor()) { case MIN_PLUS: value = left_number->get_value() + right_number->get_value(); n = new st_number_t(t, value); break; case MIN_MINUS: value = left_number->get_value() - right_number->get_value(); n = new st_number_t(t, value); break; case MIN_TIMES: value = left_number->get_value() * right_number->get_value(); n = new st_number_t(t, value); break; case MIN_SLASH: if (right_number->get_value() == 0) issue_error (location, "Division by zero"); else { value = left_number->get_value() / right_number->get_value(); n = new st_number_t(t, value); } break; case MIN_EQ: value = left_number->get_value() == right_number->get_value(); n = new st_number_t(t, value); break; case MIN_NE: value = left_number->get_value() != right_number->get_value(); n = new st_number_t(t, value); break; case MIN_LT: value = left_number->get_value() < right_number->get_value(); n = new st_number_t(t, value); break; case MIN_LE: value = left_number->get_value() <= right_number->get_value(); n = new st_number_t(t, value); break; case MIN_GT: value = left_number->get_value() > right_number->get_value(); n = new st_number_t(t, value); break; case MIN_GE: value = left_number->get_value() >= right_number->get_value(); n = new st_number_t(t, value); break; default: break; } //case if (n != NULL) { delete this; return n; } } return this;}syntax_tree_t *st_statement_t::optimize(void){ next_statement = optimize_syntax_tree(next_statement); return this;}syntax_tree_t *st_assignment_t::optimize(void){ left_side = dynamic_cast<st_identifier_t *>(optimize_syntax_tree(left_side)); // cast should never fail right_side = optimize_syntax_tree(right_side); if (left_side->get_symbol() == output_symbol && current_procedure != NULL) current_procedure->not_leaf(); next_statement = optimize_syntax_tree(next_statement); return this;}syntax_tree_t *st_while_t::optimize(void){ condition = optimize_syntax_tree(condition); body = optimize_syntax_tree(body); next_statement = optimize_syntax_tree(next_statement); return this;}syntax_tree_t *st_if_t::optimize(void){ condition = optimize_syntax_tree(condition); body = optimize_syntax_tree(body); next_statement = optimize_syntax_tree(next_statement); return this;}syntax_tree_t *st_call_t::optimize(void){ procedure = dynamic_cast<st_identifier_t *>(optimize_syntax_tree(procedure)); // cast should never fail if (current_procedure != NULL) current_procedure->not_leaf(); next_statement = optimize_syntax_tree(next_statement); return this;}syntax_tree_t *st_declaration_t::optimize(void){ next_declaration = optimize_syntax_tree(next_declaration); return this;}syntax_tree_t *st_constant_t::optimize(void){ value = dynamic_cast<st_number_t *>(optimize_syntax_tree(value)); // cast should never fail next_declaration = optimize_syntax_tree(next_declaration); return this;}syntax_tree_t *st_variable_t::optimize(void){ if (current_procedure != NULL) current_procedure->set_locals(); next_declaration = optimize_syntax_tree(next_declaration); return this;}syntax_tree_t *st_procedure_t::optimize(void){ se_procedure_t * oldProc = current_procedure; current_procedure = dynamic_cast<se_procedure_t *>(identifier->get_symbol()); // cast should never fail block = dynamic_cast<st_block_t *>(optimize_syntax_tree(block)); // cast should never fail current_procedure = oldProc; next_declaration = optimize_syntax_tree(next_declaration); return this;}syntax_tree_t *st_block_t::optimize(void){ declarations = optimize_syntax_tree(declarations); body = optimize_syntax_tree(body); return this;}////////// Optimize the abstract syntax tree//syntax_tree_t *optimize_syntax_tree(syntax_tree_t * node){ if (node != NULL) return node->optimize(); return node;}// End of File
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -