bool Expression::hasSubExpr(ExpressionPtr sub) const { if (this == sub.get()) return true; for (int i = getKidCount(); i--; ) { ExpressionPtr kid = getNthExpr(i); if (kid && kid->hasSubExpr(sub)) return true; } return false; }
bool SimpleVariable::canonCompare(ExpressionPtr e) const { return Expression::canonCompare(e) && getName() == static_cast<SimpleVariable*>(e.get())->getName(); }
bool BinaryOpExpression::canonCompare(ExpressionPtr e) const { return Expression::canonCompare(e) && getOp() == static_cast<BinaryOpExpression*>(e.get())->getOp(); }
ExpressionPtr FunctionCall::inliner(AnalysisResultConstPtr ar, ExpressionPtr obj, std::string localThis) { FunctionScopePtr fs = getFunctionScope(); if (m_noInline || !fs || fs == m_funcScope || !m_funcScope->getStmt()) { return ExpressionPtr(); } BlockScope::s_jobStateMutex.lock(); if (m_funcScope->getMark() == BlockScope::MarkProcessing) { fs->setForceRerun(true); BlockScope::s_jobStateMutex.unlock(); return ExpressionPtr(); } ReadLock lock(m_funcScope->getInlineMutex()); BlockScope::s_jobStateMutex.unlock(); if (!m_funcScope->getInlineAsExpr()) { return ExpressionPtr(); } if (m_funcScope->getInlineSameContext() && m_funcScope->getContainingClass() && m_funcScope->getContainingClass() != getClassScope()) { /* The function contains a context sensitive construct such as call_user_func (context sensitive because it could call array('parent', 'foo')) so its not safe to inline it into a different context. */ return ExpressionPtr(); } MethodStatementPtr m (dynamic_pointer_cast<MethodStatement>(m_funcScope->getStmt())); VariableTablePtr vt = fs->getVariables(); int nAct = m_params ? m_params->getCount() : 0; int nMax = m_funcScope->getMaxParamCount(); if (nAct < m_funcScope->getMinParamCount() || !m->getStmts()) { return ExpressionPtr(); } InlineCloneInfo info(m_funcScope); info.elist = ExpressionListPtr(new ExpressionList( getScope(), getLocation(), ExpressionList::ListKindWrapped)); std::ostringstream oss; oss << fs->nextInlineIndex() << "_" << m_name << "_"; std::string prefix = oss.str(); if (obj) { info.callWithThis = true; if (!obj->isThis()) { SimpleVariablePtr var (new SimpleVariable(getScope(), obj->getLocation(), prefix + "this")); var->updateSymbol(SimpleVariablePtr()); var->getSymbol()->setHidden(); var->getSymbol()->setUsed(); var->getSymbol()->setReferenced(); AssignmentExpressionPtr ae (new AssignmentExpression(getScope(), obj->getLocation(), var, obj, false)); info.elist->addElement(ae); info.sepm[var->getName()] = var; info.localThis = var->getName(); } } else { if (m_classScope) { if (!m_funcScope->isStatic()) { ClassScopeRawPtr oCls = getOriginalClass(); FunctionScopeRawPtr oFunc = getOriginalFunction(); if (oCls && !oFunc->isStatic() && (oCls == m_classScope || oCls->derivesFrom(ar, m_className, true, false))) { info.callWithThis = true; info.localThis = localThis; } } if (!isSelf() && !isParent() && !isStatic()) { info.staticClass = m_className; } } } ExpressionListPtr plist = m->getParams(); int i; for (i = 0; i < nMax || i < nAct; i++) { ParameterExpressionPtr param (i < nMax ? dynamic_pointer_cast<ParameterExpression>((*plist)[i]) : ParameterExpressionPtr()); ExpressionPtr arg = i < nAct ? (*m_params)[i] : Clone(param->defaultValue(), getScope()); SimpleVariablePtr var (new SimpleVariable(getScope(), (i < nAct ? arg.get() : this)->getLocation(), prefix + (param ? param->getName() : lexical_cast<string>(i)))); var->updateSymbol(SimpleVariablePtr()); var->getSymbol()->setHidden(); var->getSymbol()->setUsed(); var->getSymbol()->setReferenced(); bool ref = (i < nMax && m_funcScope->isRefParam(i)) || arg->hasContext(RefParameter); arg->clearContext(RefParameter); AssignmentExpressionPtr ae (new AssignmentExpression(getScope(), arg->getLocation(), var, arg, ref)); info.elist->addElement(ae); if (i < nAct && (ref || !arg->isScalar())) { info.sepm[var->getName()] = var; } } if (cloneStmtsForInline(info, m->getStmts(), prefix, ar, getFunctionScope()) <= 0) { info.elist->addElement(makeConstant(ar, "null")); } if (info.sepm.size()) { ExpressionListPtr unset_list (new ExpressionList(getScope(), getLocation())); for (StringToExpressionPtrMap::iterator it = info.sepm.begin(), end = info.sepm.end(); it != end; ++it) { ExpressionPtr var = it->second->clone(); var->clearContext((Context)(unsigned)-1); unset_list->addElement(var); } ExpressionPtr unset( new UnaryOpExpression(getScope(), getLocation(), unset_list, T_UNSET, true)); i = info.elist->getCount(); ExpressionPtr ret = (*info.elist)[--i]; if (ret->isScalar()) { info.elist->insertElement(unset, i); } else { ExpressionListPtr result_list (new ExpressionList(getScope(), getLocation(), ExpressionList::ListKindLeft)); if (ret->hasContext(LValue)) { result_list->setContext(LValue); result_list->setContext(ReturnContext); } result_list->addElement(ret); result_list->addElement(unset); (*info.elist)[i] = result_list; } } recomputeEffects(); return replaceValue(info.elist); }
static ExpressionPtr cloneForInlineRecur(InlineCloneInfo &info, ExpressionPtr exp, const std::string &prefix, AnalysisResultConstPtr ar, FunctionScopePtr scope) { exp->getOriginalScope(); // make sure to cache the original scope exp->setBlockScope(scope); for (int i = 0, n = exp->getKidCount(); i < n; i++) { if (ExpressionPtr k = exp->getNthExpr(i)) { exp->setNthKid(i, cloneForInlineRecur(info, k, prefix, ar, scope)); } } StaticClassName *scn = dynamic_cast<StaticClassName*>(exp.get()); if (scn && scn->isStatic() && !info.staticClass.empty()) { scn->resolveStatic(info.staticClass); } switch (exp->getKindOf()) { case Expression::KindOfSimpleVariable: { SimpleVariablePtr sv(dynamic_pointer_cast<SimpleVariable>(exp)); if (sv->isSuperGlobal()) break; string name; if (sv->isThis()) { if (!info.callWithThis) { if (!sv->hasContext(Expression::ObjectContext)) { exp = sv->makeConstant(ar, "null"); } else { // This will produce the wrong error // we really want a "throw_fatal" ast node. exp = sv->makeConstant(ar, "null"); } break; } if (info.localThis.empty()) break; name = info.localThis; } else { name = prefix + sv->getName(); } SimpleVariablePtr rep(new SimpleVariable( exp->getScope(), exp->getLocation(), name)); rep->copyContext(sv); rep->updateSymbol(SimpleVariablePtr()); rep->getSymbol()->setHidden(); // Conservatively set flags to prevent // the alias manager from getting confused. // On the next pass, it will correct the values, // and optimize appropriately. rep->getSymbol()->setUsed(); rep->getSymbol()->setReferenced(); if (exp->getContext() & (Expression::LValue| Expression::RefValue| Expression::RefParameter)) { info.sepm[name] = rep; } exp = rep; } break; case Expression::KindOfObjectMethodExpression: { FunctionCallPtr call( static_pointer_cast<FunctionCall>(exp)); if (call->getFuncScope() == info.func) { call->setNoInline(); } break; } case Expression::KindOfSimpleFunctionCall: { SimpleFunctionCallPtr call(static_pointer_cast<SimpleFunctionCall>(exp)); call->addLateDependencies(ar); call->setLocalThis(info.localThis); if (call->getFuncScope() == info.func) { call->setNoInline(); } } default: break; } return exp; }
void Construct::dumpNode(int spc, AnalysisResultPtr ar) { int nkid = getKidCount(); std::string name; int type = 0; std::string scontext = ""; std::string value = ""; std::string type_info = ""; unsigned id = 0; ExpressionPtr idPtr = ExpressionPtr(); int ef = 0; if (Statement *s = dynamic_cast<Statement*>(this)) { Statement::KindOf stype = s->getKindOf(); switch (stype) { case Statement::KindOfFunctionStatement: name="FunctionStatement"; break; case Statement::KindOfClassStatement: name="ClassStatement"; break; case Statement::KindOfInterfaceStatement: name="InterfaceStatement"; break; case Statement::KindOfClassVariable: name="ClassVariable"; break; case Statement::KindOfClassConstant: name="ClassConstant"; break; case Statement::KindOfMethodStatement: name="MethodStatement"; break; case Statement::KindOfStatementList: name="StatementList"; break; case Statement::KindOfBlockStatement: name="BlockStatement"; break; case Statement::KindOfIfBranchStatement: name="IfBranchStatement"; break; case Statement::KindOfIfStatement: name="IfStatement"; break; case Statement::KindOfWhileStatement: name="WhileStatement"; break; case Statement::KindOfDoStatement: name="DoStatement"; break; case Statement::KindOfForStatement: name="ForStatement"; break; case Statement::KindOfSwitchStatement: name="SwitchStatement"; break; case Statement::KindOfCaseStatement: name="CaseStatement"; break; case Statement::KindOfBreakStatement: name="BreakStatement"; break; case Statement::KindOfContinueStatement: name="ContinueStatement"; break; case Statement::KindOfReturnStatement: name="ReturnStatement"; break; case Statement::KindOfGlobalStatement: name="GlobalStatement"; break; case Statement::KindOfStaticStatement: name="StaticStatement"; break; case Statement::KindOfEchoStatement: name="EchoStatement"; break; case Statement::KindOfUnsetStatement: name="UnsetStatement"; break; case Statement::KindOfExpStatement: name="ExpStatement"; break; case Statement::KindOfForEachStatement: name="ForEachStatement"; break; case Statement::KindOfCatchStatement: name="CatchStatement"; break; case Statement::KindOfTryStatement: name="TryStatement"; break; case Statement::KindOfThrowStatement: name="ThrowStatement"; break; case Statement::KindOfGotoStatement: name="GotoStatement"; break; case Statement::KindOfLabelStatement: name="LabelStatement"; break; } type = (int)stype; } else if (Expression *e = dynamic_cast<Expression*>(this)) { id = e->getCanonID(); idPtr = e->getCanonLVal(); ef = e->getLocalEffects(); Expression::KindOf etype = e->getKindOf(); switch (etype) { case Expression::KindOfSimpleFunctionCall: name="SimpleFunctionCall"; value = static_cast<SimpleFunctionCall*>(e)->getName(); break; case Expression::KindOfSimpleVariable: name="SimpleVariable"; value = static_cast<SimpleVariable*>(e)->getName(); break; case Expression::KindOfConstantExpression: name="ConstantExpression"; value = e->getText(); break; case Expression::KindOfScalarExpression: name="ScalarExpression"; value = e->getText(); break; case Expression::KindOfExpressionList: name="ExpressionList"; break; case Expression::KindOfAssignmentExpression: name="AssignmentExpression"; break; case Expression::KindOfDynamicVariable: name="DynamicVariable"; break; case Expression::KindOfStaticMemberExpression: name="StaticMemberExpression"; break; case Expression::KindOfArrayElementExpression: name="ArrayElementExpression"; break; case Expression::KindOfDynamicFunctionCall: name="DynamicFunctionCall"; break; case Expression::KindOfObjectPropertyExpression: name="ObjectPropertyExpression"; break; case Expression::KindOfObjectMethodExpression: name="ObjectMethodExpression"; break; case Expression::KindOfListAssignment: name="ListAssignment"; break; case Expression::KindOfNewObjectExpression: name="NewObjectExpression"; break; case Expression::KindOfUnaryOpExpression: name="UnaryOpExpression"; break; case Expression::KindOfIncludeExpression: name="IncludeExpression"; break; case Expression::KindOfBinaryOpExpression: name="BinaryOpExpression"; break; case Expression::KindOfQOpExpression: name="QOpExpression"; break; case Expression::KindOfArrayPairExpression: name="ArrayPairExpression"; break; case Expression::KindOfClassConstantExpression: name="ClassConstantExpression"; break; case Expression::KindOfParameterExpression: name="ParameterExpression"; break; case Expression::KindOfModifierExpression: name="ModifierExpression"; break; case Expression::KindOfEncapsListExpression: name="EncapsListExpression"; break; case Expression::KindOfClosureExpression: name="ClosureExpression"; break; } int c = e->getContext(); if ((c & Expression::Declaration) == Expression::Declaration) { scontext += "|Declaration"; } else if (c & Expression::LValue) { scontext += "|LValue"; } if (c & Expression::NoLValueWrapper) { scontext += "|NoLValueWrapper"; } if (c & Expression::RefValue) { scontext += "|RefValue"; } if (c & Expression::RefParameter) { scontext += "|RefParameter"; } if (c & Expression::DeepReference) { scontext += "|DeepReference"; } if (c & Expression::NoRefWrapper) { scontext += "|NoRefWrapper"; } if (c & Expression::ObjectContext) { scontext += "|ObjectContext"; } if (c & Expression::InParameterExpression) { scontext += "|InParameterExpression"; } if (c & Expression::ExistContext) { scontext += "|ExistContext"; } if (c & Expression::UnsetContext) { scontext += "|UnsetContext"; } if (c & Expression::AssignmentLHS) { scontext += "|AssignmentLHS"; } if (c & Expression::DeepAssignmentLHS) { scontext += "|DeepAssignmentLHS"; } if (c & Expression::InvokeArgument) { scontext += "|InvokeArgument"; } if (c & Expression::OprLValue) { scontext += "|OprLValue"; } if (c & Expression::DeepOprLValue) { scontext += "|DeepOprLValue"; } if (c & Expression::AccessContext) { scontext += "|AccessContext"; } if (scontext != "") { scontext = " (" + scontext.substr(1) + ")"; } type = (int)etype; if (e->getActualType()) { type_info = e->getActualType()->toString(); if (e->getExpectedType()) { type_info += ":" + e->getExpectedType()->toString(); } if (e->getImplementedType()) { type_info += ";" + e->getImplementedType()->toString(); } type_info = "{" + type_info + "} "; } } else { ASSERT(FALSE); } int s = spc; while (s > 0) { int n = s > 10 ? 10 : s; std::cout << (" "+10-n); s -= n; } std::cout << "-> 0x" << hex << setfill('0') << setw(10) << (int64)this << dec; std::cout << " " << name << "(" << type << ") "; if (id) { std::cout << "id=" << id << " "; } if (idPtr) { std::cout << "idp=0x" << hex << setfill('0') << setw(10) << (int64)idPtr.get() << " "; } if (value != "") { std::cout << "[" << value << "] "; } string sef; if ((ef & UnknownEffect) == UnknownEffect) { sef = "|UnknownEffect"; } else { if (ef & IOEffect) sef += "|IOEffect"; if (ef & AssignEffect) sef += "|AssignEffect"; if (ef & GlobalEffect) sef += "|GlobalEffect"; if (ef & LocalEffect) sef += "|LocalEffect"; if (ef & ParamEffect) sef += "|ParamEffect"; if (ef & DeepParamEffect) sef += "|DeepParamEffect"; if (ef & DynamicParamEffect) sef += "|DynamicParamEffect"; if (ef & CanThrow) sef += "|CanThrow"; if (ef & AccessorEffect) sef += "|AccessorEffect"; if (ef & CreateEffect) sef += "|CreateEffect"; if (ef & DiagnosticEffect) sef += "|DiagnosticEffect"; if (ef & OtherEffect) sef += "|OtherEffect"; } if (sef != "") { sef = " (" + sef.substr(1) + ")"; } std::cout << type_info << nkid << scontext << sef; if (m_loc) { std::cout << " " << m_loc->file << ":" << m_loc->line1 << "@" << m_loc->char1; } std::cout << "\n"; }
void Construct::dumpNode(int spc, AnalysisResultConstPtr ar) { int nkid = getKidCount(); const char *name = 0; int type = 0; std::string scontext = ""; std::string value = ""; std::string type_info = ""; unsigned id = 0; ExpressionPtr idPtr = ExpressionPtr(); int ef = 0; if (Statement *s = dynamic_cast<Statement*>(this)) { Statement::KindOf stype = s->getKindOf(); name = Statement::Names[stype]; value = s->getName(); type = (int)stype; } else if (Expression *e = dynamic_cast<Expression*>(this)) { id = e->getCanonID(); idPtr = e->getCanonLVal(); ef = e->getLocalEffects(); Expression::KindOf etype = e->getKindOf(); name = Expression::Names[etype]; switch (etype) { case Expression::KindOfSimpleFunctionCall: value = static_cast<SimpleFunctionCall*>(e)->getName(); break; case Expression::KindOfSimpleVariable: value = static_cast<SimpleVariable*>(e)->getName(); break; case Expression::KindOfConstantExpression: value = e->getText(); break; case Expression::KindOfScalarExpression: value = e->getText(); break; default: break; } int c = e->getContext(); if ((c & Expression::Declaration) == Expression::Declaration) { scontext += "|Declaration"; } else if (c & Expression::LValue) { scontext += "|LValue"; } if (c & Expression::NoLValueWrapper) { scontext += "|NoLValueWrapper"; } if (c & Expression::RefValue) { scontext += "|RefValue"; } if (c & Expression::RefParameter) { scontext += "|RefParameter"; } if (c & Expression::DeepReference) { scontext += "|DeepReference"; } if (c & Expression::NoRefWrapper) { scontext += "|NoRefWrapper"; } if (c & Expression::ObjectContext) { scontext += "|ObjectContext"; } if (c & Expression::InParameterExpression) { scontext += "|InParameterExpression"; } if (c & Expression::ExistContext) { scontext += "|ExistContext"; } if (c & Expression::UnsetContext) { scontext += "|UnsetContext"; } if (c & Expression::AssignmentLHS) { scontext += "|AssignmentLHS"; } if (c & Expression::RefAssignmentLHS) { scontext += "|RefAssignmentLHS"; } if (c & Expression::DeepAssignmentLHS) { scontext += "|DeepAssignmentLHS"; } if (c & Expression::InvokeArgument) { scontext += "|InvokeArgument"; } if (c & Expression::OprLValue) { scontext += "|OprLValue"; } if (c & Expression::DeepOprLValue) { scontext += "|DeepOprLValue"; } if (c & Expression::AccessContext) { scontext += "|AccessContext"; } if (scontext != "") { scontext = " (" + scontext.substr(1) + ")"; } type = (int)etype; if (e->getActualType()) { type_info = e->getActualType()->toString(); if (e->getExpectedType()) { type_info += ":" + e->getExpectedType()->toString(); } if (e->getImplementedType()) { type_info += ";" + e->getImplementedType()->toString(); } type_info = "{" + type_info + "} "; } } else { ASSERT(FALSE); } int s = spc; while (s > 0) { int n = s > 10 ? 10 : s; std::cout << (" "+10-n); s -= n; } std::cout << "-> 0x" << hex << setfill('0') << setw(10) << (int64)this << dec; std::cout << " " << name << "(" << type << ") "; if (id) { std::cout << "id=" << id << " "; } if (idPtr) { std::cout << "idp=0x" << hex << setfill('0') << setw(10) << (int64)idPtr.get() << " "; } if (value != "") { std::cout << "[" << value << "] "; } string sef; if ((ef & UnknownEffect) == UnknownEffect) { sef = "|UnknownEffect"; } else { if (ef & IOEffect) sef += "|IOEffect"; if (ef & AssignEffect) sef += "|AssignEffect"; if (ef & GlobalEffect) sef += "|GlobalEffect"; if (ef & LocalEffect) sef += "|LocalEffect"; if (ef & ParamEffect) sef += "|ParamEffect"; if (ef & DeepParamEffect) sef += "|DeepParamEffect"; if (ef & DynamicParamEffect) sef += "|DynamicParamEffect"; if (ef & CanThrow) sef += "|CanThrow"; if (ef & AccessorEffect) sef += "|AccessorEffect"; if (ef & CreateEffect) sef += "|CreateEffect"; if (ef & DiagnosticEffect) sef += "|DiagnosticEffect"; if (ef & OtherEffect) sef += "|OtherEffect"; } if (sef != "") { sef = " (" + sef.substr(1) + ")"; } string localtered; if (Expression *e = dynamic_cast<Expression*>(this)) { localtered = e->isLocalExprAltered() ? "LocalAltered" : "NotLocalAltered"; } if (localtered != "") { localtered = " (" + localtered + ")"; } string refstr; if (dynamic_cast<SimpleVariable*>(this) != NULL) { if (isReferencedValid()) { if (isReferenced()) { refstr += "Referenced"; } else { refstr += "NotReferenced"; } } else { refstr = "NoRefInfo"; } } if (refstr != "") refstr = " (" + refstr + ")"; string objstr; if (dynamic_cast<SimpleVariable*>(this) != NULL) { if (isNeededValid()) { if (isNeeded()) { objstr += "Object"; } else { objstr += "NotObject"; } } else { objstr = "NoObjInfo"; } } if (objstr != "") objstr = " (" + objstr + ")"; std::cout << type_info << nkid << scontext << sef << localtered << refstr << objstr; if (m_loc) { std::cout << " " << m_loc->file << ":" << m_loc->line1 << "@" << m_loc->char1; } std::cout << "\n"; }