예제 #1
0
StatementPtr StatementList::preOptimize(AnalysisResultConstPtr ar) {
  bool del = false;
  bool changed = false;
  for (unsigned int i = 0; i < m_stmts.size(); i++) {
    StatementPtr &s = m_stmts[i];
    if (del) {
      switch (s->getKindOf()) {
      case Statement::KindOfBlockStatement:
      case Statement::KindOfIfBranchStatement:
      case Statement::KindOfIfStatement:
      case Statement::KindOfWhileStatement:
      case Statement::KindOfDoStatement:
      case Statement::KindOfForStatement:
      case Statement::KindOfSwitchStatement:
      case Statement::KindOfCaseStatement:
      case Statement::KindOfBreakStatement:
      case Statement::KindOfContinueStatement:
      case Statement::KindOfReturnStatement:
      case Statement::KindOfGlobalStatement:
      case Statement::KindOfStaticStatement:
      case Statement::KindOfEchoStatement:
      case Statement::KindOfUnsetStatement:
      case Statement::KindOfExpStatement:
      case Statement::KindOfForEachStatement:
      case Statement::KindOfCatchStatement:
      case Statement::KindOfTryStatement:
      case Statement::KindOfThrowStatement:
        removeElement(i--);
        changed = true;
        continue;
      default:
        break;
      }
    }

    if (s) {
      if (Option::EliminateDeadCode) {
        if (s->is(KindOfBreakStatement) ||
            s->is(KindOfContinueStatement) ||
            s->is(KindOfReturnStatement) ||
            s->is(KindOfThrowStatement)) {
          del = true;
        } else if (s->is(KindOfExpStatement)) {
          ExpressionPtr e =
            dynamic_pointer_cast<ExpStatement>(s)->getExpression();
          if (!e->hasEffect()) {
            removeElement(i--);
            changed = true;
          }
        } else if (s->hasReachableLabel()) {
          del = false;
        }
      }
    }
  }

  if (mergeConcatAssign()) changed = true;
  return changed ? static_pointer_cast<Statement>(shared_from_this())
                 : StatementPtr();
}
예제 #2
0
void FunctionScope::outputCPPEffectiveArguments(ExpressionListPtr params,
                                                CodeGenerator &cg,
                                                AnalysisResultPtr ar) {
  int paramCount = params ? params->getCount() : 0;
  for (int i = 0; i < paramCount; i++) {
    ExpressionPtr param = (*params)[i];
    if (param->hasEffect()) {
      param->outputCPP(cg, ar);
      cg.printf(", ");
    }
  }
}
예제 #3
0
bool ExpressionList::hasNonArrayCreateValue(
  bool arrayElements /* = true */, unsigned int start /* = 0 */) const {
  for (unsigned int i = start; i < m_exps.size(); i++) {
    ExpressionPtr value = m_exps[i];
    if (arrayElements) {
      ArrayPairExpressionPtr ap =
        dynamic_pointer_cast<ArrayPairExpression>(m_exps[i]);
      value = ap->getValue();
    }
    ASSERT(value);
    if (value->hasContext(RefValue) ||
        (value->hasEffect() && !value->isTemporary())) {
      return true;
    }
  }
  return false;
}
예제 #4
0
StatementPtr IfStatement::postOptimize(AnalysisResultConstPtr ar) {
  // we cannot optimize away the code inside if statement, because
  // there may be a goto that goes into if statement.
  if (hasReachableLabel()) {
    return StatementPtr();
  }

  bool changed = false;
  for (int i = 0; i < m_stmts->getCount(); i++) {
    IfBranchStatementPtr branch =
      dynamic_pointer_cast<IfBranchStatement>((*m_stmts)[i]);
    ExpressionPtr condition = branch->getCondition();
    if (!branch->getStmt() || !branch->getStmt()->hasImpl()) {
      if (!condition ||
          (i == m_stmts->getCount() - 1 &&
           !condition->hasEffect())) {
        // remove else branch without C++ implementation.
        m_stmts->removeElement(i);
        changed = true;
      } else if (condition->is(Expression::KindOfConstantExpression)) {
        ConstantExpressionPtr exp =
          dynamic_pointer_cast<ConstantExpression>(condition);
        // Remove if (false) branch without C++ implementation.
        // if (true) branch without C++ implementation is kept unless
        // it is the last branch. In general we cannot let a if (true)
        // branch short-circuit the rest branches which if removed may
        // cause g++ to complain unreferenced variables.
        if (exp->isBoolean()) {
          if (!exp->getBooleanValue() ||
              (exp->getBooleanValue() && i == m_stmts->getCount() - 1)) {
            m_stmts->removeElement(i);
            changed = true;
            i--;
          }
        }
      }
    }
  }
  if (m_stmts->getCount() == 0) {
    return NULL_STATEMENT();
  } else {
    return changed ? static_pointer_cast<Statement>(shared_from_this())
                   : StatementPtr();
  }
}
예제 #5
0
bool StatementList::mergeConcatAssign() {
  if (Option::LocalCopyProp) {
    return false;
  } else {
    // check for vector string concat assignment such as
    //   $space = " ";
    //   $a .= "hello";
    //   $a .= $space;
    //   $a .= "world!";
    // turn into (for constant folding and concat sequence)
    //   $a .= " " . "hello " . $space . "world!";
    unsigned int i = 0;
    bool merged = false;
    do {
      std::string lhsName;
      int length = 0;
      for (; i < m_stmts.size(); i++) {
        StatementPtr stmt = m_stmts[i];
        if (!stmt->is(Statement::KindOfExpStatement)) break;
        ExpStatementPtr expStmt = dynamic_pointer_cast<ExpStatement>(stmt);
        ExpressionPtr exp = expStmt->getExpression();

        // check the first assignment
        if (exp->is(Expression::KindOfAssignmentExpression)) {
          AssignmentExpressionPtr assignment_exp =
            dynamic_pointer_cast<AssignmentExpression>(exp);
          ExpressionPtr variable = assignment_exp->getVariable();
          ExpressionPtr value = assignment_exp->getValue();
          std::string variableName = variable->getText();
          if (variableName.find("->") != std::string::npos) break;
          if (value->hasEffect()) break;
          // cannot turn $a .= $b; a .= $a into $a .= $b . $a;
          if (value->getText().find(variableName) != std::string::npos) break;
          if (lhsName.empty()) {
            lhsName = variable->getText();
            length++;
            continue;
          } else {
            break;
          }
        } else if (!exp->is(Expression::KindOfBinaryOpExpression)) {
          break;
        }
        BinaryOpExpressionPtr binaryOpExp =
          dynamic_pointer_cast<BinaryOpExpression>(exp);
        if (binaryOpExp->getOp() != T_CONCAT_EQUAL) break;
        ExpressionPtr exp1 = binaryOpExp->getExp1();
        std::string exp1Text = exp1->getText();
        if (exp1Text.find("->") != std::string::npos) break;
        ExpressionPtr exp2 = binaryOpExp->getExp2();
        if (exp2->hasEffect()) break;
        if (exp2->getText().find(exp1Text) != std::string::npos) break;
        if (lhsName.empty()) {
          lhsName = exp1Text;
          length++;
        } else if (lhsName == exp1Text) {
          length++;
        } else {
          break;
        }
      }
      if (length > 1) {
        // replace m_stmts[j] to m_stmts[i - 1] with a new statement
        unsigned j = i - length;
        ExpStatementPtr expStmt;
        ExpressionPtr exp;
        BinaryOpExpressionPtr binaryOpExp;
        ExpressionPtr var;
        ExpressionPtr exp1;
        ExpressionPtr exp2;
        bool isAssignment = false;
        expStmt = dynamic_pointer_cast<ExpStatement>(m_stmts[j++]);
        exp = expStmt->getExpression();
        if (exp->is(Expression::KindOfAssignmentExpression)) {
          isAssignment = true;
          AssignmentExpressionPtr assignment_exp =
            dynamic_pointer_cast<AssignmentExpression>(exp);
          var = assignment_exp->getVariable();
          exp1 = assignment_exp->getValue();
        } else {
          binaryOpExp = dynamic_pointer_cast<BinaryOpExpression>(exp);
          var = binaryOpExp->getExp1();
          exp1 = binaryOpExp->getExp2();
        }

        for (; j < i; j++) {
          expStmt = dynamic_pointer_cast<ExpStatement>(m_stmts[j]);
          exp = expStmt->getExpression();
          binaryOpExp = dynamic_pointer_cast<BinaryOpExpression>(exp);
          exp2 = binaryOpExp->getExp2();
          exp1 = BinaryOpExpressionPtr
            (new BinaryOpExpression(getScope(), getLocation(),
                                    Expression::KindOfBinaryOpExpression,
                                    exp1, exp2, '.'));
        }
        if (isAssignment) {
          exp = AssignmentExpressionPtr
            (new AssignmentExpression(exp->getScope(), exp->getLocation(),
                                      Expression::KindOfAssignmentExpression,
                                      var, exp1,
                                      false));
        } else {
          exp = BinaryOpExpressionPtr
            (new BinaryOpExpression(getScope(), getLocation(),
                                    Expression::KindOfBinaryOpExpression,
                                    var, exp1, T_CONCAT_EQUAL));
        }
        expStmt = ExpStatementPtr
          (new ExpStatement(getScope(), getLocation(),
                            Statement::KindOfExpStatement, exp));

        m_stmts[i - length] = expStmt;
        for (j = i - (length - 1); i > j; i--) removeElement(j);
        merged = true;
      } else if (length == 0) {
        i++;
      }
    } while (i < m_stmts.size());
    return merged;
  }
}
예제 #6
0
StatementPtr IfStatement::preOptimize(AnalysisResultConstPtr ar) {
  if (ar->getPhase() < AnalysisResult::FirstPreOptimize) {
    return StatementPtr();
  }

  // we cannot optimize away the code inside if statement, because
  // there may be a goto that goes into if statement.
  if (hasReachableLabel()) {
    return StatementPtr();
  }

  bool changed = false;
  int i;
  int j;
  Variant value;
  bool hoist = false;
  for (i = 0; i < m_stmts->getCount(); i++) {
    IfBranchStatementPtr branch =
      dynamic_pointer_cast<IfBranchStatement>((*m_stmts)[i]);
    ExpressionPtr condition = branch->getCondition();
    if (!condition) {
      StatementPtr stmt = branch->getStmt();
      if (stmt) {
        if (!i &&
            ((getFunctionScope() && !getFunctionScope()->inPseudoMain()) ||
             !stmt->hasDecl())) {
          hoist = true;
          break;
        }
        if (stmt->is(KindOfIfStatement)) {
          StatementListPtr sub_stmts =
            dynamic_pointer_cast<IfStatement>(stmt)->m_stmts;
          m_stmts->removeElement(i);
          changed = true;
          for (j = 0; j < sub_stmts->getCount(); j++) {
            m_stmts->insertElement((*sub_stmts)[j], i++);
          }
        }
      }
      break;
    } else if (condition->getEffectiveScalar(value)) {
      if (value.toBoolean()) {
        hoist = !i &&
          ((getFunctionScope() && !getFunctionScope()->inPseudoMain()) ||
           !branch->hasDecl());
        break;
      } else if (!condition->hasEffect()) {
        m_stmts->removeElement(i--);
        changed = true;
      } else if (branch->getStmt()) {
        branch->clearStmt();
        changed = true;
      }
    }
  }

  if (!changed && i && i == m_stmts->getCount()) return StatementPtr();

  // either else branch or if (true) branch without further declarations

  i++;
  while (i < m_stmts->getCount()) {
    m_stmts->removeElement(i);
    changed = true;
  }

  // if there is only one branch left, return stmt.
  if (hoist) {
    IfBranchStatementPtr branch =
      dynamic_pointer_cast<IfBranchStatement>((*m_stmts)[0]);
    return branch->getStmt() ? branch->getStmt() : NULL_STATEMENT();
  } else if (m_stmts->getCount() == 0) {
    return NULL_STATEMENT();
  } else {
    return changed ? static_pointer_cast<Statement>(shared_from_this())
                   : StatementPtr();
  }
}
예제 #7
0
StatementPtr StatementList::preOptimize(AnalysisResultConstPtr ar) {
    bool del = false;
    bool changed = false;
    for (unsigned int i = 0; i < m_stmts.size(); i++) {
        StatementPtr &s = m_stmts[i];
        if (del) {
            if (s->hasReachableLabel()) {
                del = false;
            } else {
                switch (s->getKindOf()) {
                case Statement::KindOfBlockStatement:
                case Statement::KindOfIfBranchStatement:
                case Statement::KindOfIfStatement:
                case Statement::KindOfWhileStatement:
                case Statement::KindOfDoStatement:
                case Statement::KindOfForStatement:
                case Statement::KindOfSwitchStatement:
                case Statement::KindOfCaseStatement:
                case Statement::KindOfBreakStatement:
                case Statement::KindOfContinueStatement:
                case Statement::KindOfReturnStatement:
                case Statement::KindOfGlobalStatement:
                case Statement::KindOfStaticStatement:
                case Statement::KindOfEchoStatement:
                case Statement::KindOfUnsetStatement:
                case Statement::KindOfExpStatement:
                case Statement::KindOfForEachStatement:
                case Statement::KindOfCatchStatement:
                case Statement::KindOfTryStatement:
                case Statement::KindOfThrowStatement:
                    removeElement(i--);
                    changed = true;
                    continue;
                default:
                    break;
                }
            }
        }

        if (s) {
            if (s->is(KindOfStatementList) && !s->hasDecl()) {
                StatementListPtr stmts(static_pointer_cast<StatementList>(s));
                removeElement(i);
                m_stmts.insert(m_stmts.begin() + i,
                               stmts->m_stmts.begin(), stmts->m_stmts.end());
                i--;
                changed = true;
                continue;
            } else if (s->is(KindOfBlockStatement)) {
                BlockStatementPtr bs(static_pointer_cast<BlockStatement>(s));
                StatementListPtr stmts(bs->getStmts());
                if (!stmts) {
                    removeElement(i--);
                    changed = true;
                    continue;
                } else {
                    FunctionScopePtr fs(getFunctionScope());
                    if (fs && (!fs->inPseudoMain() || !stmts->hasDecl())) {
                        removeElement(i);
                        m_stmts.insert(m_stmts.begin() + i,
                                       stmts->m_stmts.begin(), stmts->m_stmts.end());
                        i--;
                        changed = true;
                        continue;
                    }
                }
            } else if (Option::EliminateDeadCode) {
                if (s->is(KindOfBreakStatement) ||
                        s->is(KindOfContinueStatement) ||
                        s->is(KindOfReturnStatement) ||
                        s->is(KindOfThrowStatement)) {
                    del = true;
                } else if (s->is(KindOfExpStatement)) {
                    ExpressionPtr e =
                        dynamic_pointer_cast<ExpStatement>(s)->getExpression();
                    if (!e->hasEffect() && !e->isNoRemove()) {
                        removeElement(i--);
                        changed = true;
                    }
                }
            }
        }
    }

    if (mergeConcatAssign()) changed = true;
    return changed ? static_pointer_cast<Statement>(shared_from_this())
           : StatementPtr();
}