PageRenderTime 43ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/hphp/compiler/statement/if_statement.cpp

http://github.com/facebook/hiphop-php
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
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010-2016 Facebook, Inc. (http://www.facebook.com) |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. */
  16. #include "hphp/compiler/statement/if_statement.h"
  17. #include "hphp/compiler/statement/if_branch_statement.h"
  18. #include "hphp/compiler/statement/statement_list.h"
  19. #include "hphp/compiler/expression/constant_expression.h"
  20. #include "hphp/compiler/statement/block_statement.h"
  21. #include "hphp/compiler/analysis/function_scope.h"
  22. #include "hphp/runtime/base/type-variant.h"
  23. using namespace HPHP;
  24. ///////////////////////////////////////////////////////////////////////////////
  25. // constructors/destructors
  26. IfStatement::IfStatement
  27. (STATEMENT_CONSTRUCTOR_PARAMETERS, StatementListPtr stmts)
  28. : Statement(STATEMENT_CONSTRUCTOR_PARAMETER_VALUES(IfStatement)),
  29. m_stmts(stmts), m_hasCondCSE(false) {
  30. }
  31. StatementPtr IfStatement::clone() {
  32. IfStatementPtr stmt(new IfStatement(*this));
  33. stmt->m_stmts = Clone(m_stmts);
  34. return stmt;
  35. }
  36. int IfStatement::getRecursiveCount() const {
  37. return m_stmts->getRecursiveCount();
  38. }
  39. ///////////////////////////////////////////////////////////////////////////////
  40. // parser functions
  41. ///////////////////////////////////////////////////////////////////////////////
  42. // static analysis functions
  43. void IfStatement::analyzeProgram(AnalysisResultPtr ar) {
  44. if (m_stmts) m_stmts->analyzeProgram(ar);
  45. }
  46. bool IfStatement::hasDecl() const {
  47. return m_stmts && m_stmts->hasDecl();
  48. }
  49. bool IfStatement::hasRetExp() const {
  50. return m_stmts && m_stmts->hasRetExp();
  51. }
  52. ConstructPtr IfStatement::getNthKid(int n) const {
  53. switch (n) {
  54. case 0:
  55. return m_stmts;
  56. default:
  57. assert(false);
  58. break;
  59. }
  60. return ConstructPtr();
  61. }
  62. int IfStatement::getKidCount() const {
  63. return 1;
  64. }
  65. void IfStatement::setNthKid(int n, ConstructPtr cp) {
  66. switch (n) {
  67. case 0:
  68. m_stmts = dynamic_pointer_cast<StatementList>(cp);
  69. break;
  70. default:
  71. assert(false);
  72. break;
  73. }
  74. }
  75. StatementPtr IfStatement::preOptimize(AnalysisResultConstPtr ar) {
  76. if (ar->getPhase() < AnalysisResult::FirstPreOptimize) {
  77. return StatementPtr();
  78. }
  79. // we cannot optimize away the code inside if statement, because
  80. // there may be a goto that goes into if statement.
  81. if (hasReachableLabel()) {
  82. return StatementPtr();
  83. }
  84. bool changed = false;
  85. int i;
  86. int j;
  87. Variant value;
  88. bool hoist = false;
  89. for (i = 0; i < m_stmts->getCount(); i++) {
  90. auto branch = dynamic_pointer_cast<IfBranchStatement>((*m_stmts)[i]);
  91. ExpressionPtr condition = branch->getCondition();
  92. if (!condition) {
  93. StatementPtr stmt = branch->getStmt();
  94. if (stmt) {
  95. if (!i &&
  96. ((getFunctionScope() && !getFunctionScope()->inPseudoMain()) ||
  97. !stmt->hasDecl())) {
  98. hoist = true;
  99. break;
  100. }
  101. if (stmt->is(KindOfIfStatement)) {
  102. auto sub_stmts = dynamic_pointer_cast<IfStatement>(stmt)->m_stmts;
  103. m_stmts->removeElement(i);
  104. changed = true;
  105. for (j = 0; j < sub_stmts->getCount(); j++) {
  106. m_stmts->insertElement((*sub_stmts)[j], i++);
  107. }
  108. }
  109. }
  110. break;
  111. } else if (condition->getEffectiveScalar(value)) {
  112. if (value.toBoolean()) {
  113. hoist = !i &&
  114. ((getFunctionScope() && !getFunctionScope()->inPseudoMain()) ||
  115. !branch->hasDecl());
  116. break;
  117. } else if (!condition->hasEffect()) {
  118. m_stmts->removeElement(i--);
  119. changed = true;
  120. } else if (branch->getStmt()) {
  121. branch->clearStmt();
  122. changed = true;
  123. }
  124. }
  125. }
  126. if (!changed && i && i == m_stmts->getCount()) return StatementPtr();
  127. // either else branch or if (true) branch without further declarations
  128. i++;
  129. while (i < m_stmts->getCount()) {
  130. m_stmts->removeElement(i);
  131. changed = true;
  132. }
  133. // if there is only one branch left, return stmt.
  134. if (hoist) {
  135. auto branch = dynamic_pointer_cast<IfBranchStatement>((*m_stmts)[0]);
  136. return branch->getStmt() ? branch->getStmt() : NULL_STATEMENT();
  137. } else if (m_stmts->getCount() == 0) {
  138. return NULL_STATEMENT();
  139. } else {
  140. return changed ? static_pointer_cast<Statement>(shared_from_this())
  141. : StatementPtr();
  142. }
  143. }
  144. ///////////////////////////////////////////////////////////////////////////////
  145. // code generation functions
  146. void IfStatement::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
  147. for (int i = 0; i < m_stmts->getCount(); i++) {
  148. if (i > 0) cg_printf("else");
  149. (*m_stmts)[i]->outputPHP(cg, ar);
  150. }
  151. }