void DataFlowWalker::processAccessChainLA(ListAssignmentPtr la) { ExpressionList &lhs = *la->getVariables().get(); for (int i = lhs.getCount(); i--; ) { ExpressionPtr ep = lhs[i]; if (ep) { if (ep->is(Expression::KindOfListAssignment)) { processAccessChainLA(static_pointer_cast<ListAssignment>(ep)); } else { processAccessChain(ep); processAccess(ep); } } } }
void AliasManager::collectAliasInfoRecur(ConstructPtr cs) { if (!cs) { return; } if (StatementPtr s = dpc(Statement, cs)) { switch (s->getKindOf()) { case Statement::KindOfFunctionStatement: case Statement::KindOfMethodStatement: case Statement::KindOfClassStatement: case Statement::KindOfInterfaceStatement: return; default: break; } } int nkid = cs->getKidCount(); for (int i = 0; i < nkid; i++) { ConstructPtr kid = cs->getNthKid(i); if (kid) { collectAliasInfoRecur(kid); } } if (ExpressionPtr e = dpc(Expression, cs)) { int context = e->getContext(); switch (e->getKindOf()) { case Expression::KindOfAssignmentExpression: { AssignmentExpressionPtr ae = spc(AssignmentExpression, e); ExpressionPtr var = ae->getVariable(); ExpressionPtr val = ae->getValue(); if (var->is(Expression::KindOfSimpleVariable)) { const std::string &name = spc(SimpleVariable, var)->getName(); AliasInfo &ai = m_aliasInfo[name]; if (val->getContext() & Expression::RefValue) { ai.setIsRefTo(); m_variables->addUsed(name); } else { Expression::checkUsed(m_arp, var, val); } } } break; case Expression::KindOfListAssignment: { ListAssignmentPtr la = spc(ListAssignment, e); ExpressionListPtr vars = la->getVariables(); for (int i = vars->getCount(); i--; ) { ExpressionPtr v = (*vars)[i]; if (v && v->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr sv = spc(SimpleVariable, v); m_variables->addUsed(sv->getName()); } } } break; case Expression::KindOfSimpleVariable: { const std::string &name = spc(SimpleVariable, e)->getName(); if (context & Expression::RefValue) { AliasInfo &ai = m_aliasInfo[name]; ai.addRefLevel(0); } if (!(context & (Expression::AssignmentLHS | Expression::UnsetContext))) { m_variables->addUsed(name); } } break; case Expression::KindOfDynamicVariable: if (context & Expression::RefValue) { m_wildRefs = true; } break; case Expression::KindOfArrayElementExpression: { int n = 1; while (n < 10 && e->is(Expression::KindOfArrayElementExpression)) { e = spc(ArrayElementExpression, e)->getVariable(); } if (e->is(Expression::KindOfSimpleVariable)) { const std::string &name = spc(SimpleVariable, e)->getName(); if (context & Expression::RefValue) { AliasInfo &ai = m_aliasInfo[name]; ai.addRefLevel(n); } m_variables->addUsed(name); // need this for UnsetContext } } break; case Expression::KindOfObjectPropertyExpression: { e = spc(ObjectPropertyExpression, e)->getObject(); if (e->is(Expression::KindOfSimpleVariable)) { const std::string &name = spc(SimpleVariable, e)->getName(); if (context & Expression::RefValue) { AliasInfo &ai = m_aliasInfo[name]; ai.addRefLevel(1); } m_variables->addUsed(name); // need this for UnsetContext } } break; default: break; } } else { StatementPtr s = spc(Statement, cs); switch (s->getKindOf()) { case Statement::KindOfCatchStatement: { const std::string &name = spc(CatchStatement, s)->getVariable(); m_variables->addUsed(name); break; } default: break; } } }
int AliasManager::findInterf(ExpressionPtr rv, bool isLoad, ExpressionPtr &rep) { BucketMapEntry lvs = m_bucketMap[0]; rep = ExpressionPtr(); ExpressionPtrList::reverse_iterator it = lvs.rbegin(), end = lvs.rend(); int a; int depth = 0, min_depth = 0, max_depth = 0; while (it != end) { ExpressionPtr e = *it++; switch (e->getKindOf()) { case Expression::KindOfScalarExpression: { ScalarExpressionPtr se = spc(ScalarExpression, e); const std::string &s = se->getString(); if (s == "begin") { depth--; if (depth < min_depth) min_depth = depth; } else if (s == "end") { depth++; if (depth > max_depth) max_depth = depth; } else { assert(false); } } break; case Expression::KindOfObjectMethodExpression: case Expression::KindOfDynamicFunctionCall: case Expression::KindOfSimpleFunctionCall: case Expression::KindOfNewObjectExpression: return testAccesses(rv, e); case Expression::KindOfListAssignment: { ListAssignmentPtr la = spc(ListAssignment, e); ExpressionList &lhs = *la->getVariables().get(); for (int i = lhs.getCount(); i--; ) { ExpressionPtr ep = lhs[i]; if (ep && testAccesses(ep, rv) != DisjointAccess) { return InterfAccess; } } break; } case Expression::KindOfObjectPropertyExpression: case Expression::KindOfConstantExpression: case Expression::KindOfSimpleVariable: case Expression::KindOfDynamicVariable: case Expression::KindOfArrayElementExpression: case Expression::KindOfStaticMemberExpression: a = testAccesses(e, rv); if (a == DisjointAccess) { continue; } if (a == SameAccess) { if (isLoad) { // The value of an earlier load is available // if it dominates this one if (depth > min_depth) { a = InterfAccess; } } else { // The assignment definitely hits the load // if it post-dominates it. if (min_depth < 0) { a = InterfAccess; } } } if (a != SameAccess && isLoad && isReadOnlyAccess(e)) { continue; } rep = e; return a; case Expression::KindOfUnaryOpExpression: a = testAccesses(spc(UnaryOpExpression,e)->getExpression(), rv); goto handle_assign; case Expression::KindOfBinaryOpExpression: a = testAccesses(spc(BinaryOpExpression,e)->getExp1(), rv); goto handle_assign; case Expression::KindOfAssignmentExpression: a = testAccesses(spc(AssignmentExpression,e)->getVariable(), rv); goto handle_assign; handle_assign: if (a == DisjointAccess) { continue; } rep = e; if (a == SameAccess) { if (isLoad) { // we can propagate the value of an assignment // to a load, provided the assignment dominates // the load. if (depth > min_depth) { a = InterfAccess; } } else { // a later assignment kills an earlier one // provided the later one post-dominates the earlier if (min_depth < 0) { a = InterfAccess; } } } return a; default: break; } } return DisjointAccess; }