/hphp/compiler/statement/if_statement.cpp
C++ | 175 lines | 124 code | 24 blank | 27 comment | 34 complexity | e162d5d65c5591280597b861a230ca63 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-2-Clause, BSD-3-Clause, MPL-2.0-no-copyleft-exception, MIT, LGPL-2.0, Apache-2.0
- /*
- +----------------------------------------------------------------------+
- | HipHop for PHP |
- +----------------------------------------------------------------------+
- | Copyright (c) 2010-2016 Facebook, Inc. (http://www.facebook.com) |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- */
- #include "hphp/compiler/statement/if_statement.h"
- #include "hphp/compiler/statement/if_branch_statement.h"
- #include "hphp/compiler/statement/statement_list.h"
- #include "hphp/compiler/expression/constant_expression.h"
- #include "hphp/compiler/statement/block_statement.h"
- #include "hphp/compiler/analysis/function_scope.h"
- #include "hphp/runtime/base/type-variant.h"
- using namespace HPHP;
- ///////////////////////////////////////////////////////////////////////////////
- // constructors/destructors
- IfStatement::IfStatement
- (STATEMENT_CONSTRUCTOR_PARAMETERS, StatementListPtr stmts)
- : Statement(STATEMENT_CONSTRUCTOR_PARAMETER_VALUES(IfStatement)),
- m_stmts(stmts), m_hasCondCSE(false) {
- }
- StatementPtr IfStatement::clone() {
- IfStatementPtr stmt(new IfStatement(*this));
- stmt->m_stmts = Clone(m_stmts);
- return stmt;
- }
- int IfStatement::getRecursiveCount() const {
- return m_stmts->getRecursiveCount();
- }
- ///////////////////////////////////////////////////////////////////////////////
- // parser functions
- ///////////////////////////////////////////////////////////////////////////////
- // static analysis functions
- void IfStatement::analyzeProgram(AnalysisResultPtr ar) {
- if (m_stmts) m_stmts->analyzeProgram(ar);
- }
- bool IfStatement::hasDecl() const {
- return m_stmts && m_stmts->hasDecl();
- }
- bool IfStatement::hasRetExp() const {
- return m_stmts && m_stmts->hasRetExp();
- }
- ConstructPtr IfStatement::getNthKid(int n) const {
- switch (n) {
- case 0:
- return m_stmts;
- default:
- assert(false);
- break;
- }
- return ConstructPtr();
- }
- int IfStatement::getKidCount() const {
- return 1;
- }
- void IfStatement::setNthKid(int n, ConstructPtr cp) {
- switch (n) {
- case 0:
- m_stmts = dynamic_pointer_cast<StatementList>(cp);
- break;
- default:
- assert(false);
- break;
- }
- }
- 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++) {
- auto 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)) {
- auto 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) {
- auto 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();
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- // code generation functions
- void IfStatement::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
- for (int i = 0; i < m_stmts->getCount(); i++) {
- if (i > 0) cg_printf("else");
- (*m_stmts)[i]->outputPHP(cg, ar);
- }
- }