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(); }
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(", "); } } }
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; }
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(); } }
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; } }
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(); } }
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(); }