void ListAssignment::outputCPPAssignment(CodeGenerator &cg, AnalysisResultPtr ar, const string &arrTmp) { if (!m_variables) return; for (int i = m_variables->getCount() - 1; i >= 0; --i) { ExpressionPtr exp = (*m_variables)[i]; if (exp) { if (exp->is(Expression::KindOfListAssignment)) { ListAssignmentPtr sublist = dynamic_pointer_cast<ListAssignment>(exp); string subTmp = genCPPTemp(cg, ar); cg_printf("Variant %s((ref(%s[%d])));\n", subTmp.c_str(), arrTmp.c_str(), i); sublist->outputCPPAssignment(cg, ar, subTmp); } else { bool done = false; if (exp->is(Expression::KindOfArrayElementExpression)) { ArrayElementExpressionPtr arrExp = dynamic_pointer_cast<ArrayElementExpression>(exp); if (!arrExp->isSuperGlobal() && !arrExp->isDynamicGlobal()) { arrExp->getVariable()->outputCPP(cg, ar); if (arrExp->getOffset()) { cg_printf(".set("); arrExp->getOffset()->outputCPP(cg, ar); cg_printf(", "); } else { cg_printf(".append("); } cg_printf("%s[%d]);\n", arrTmp.c_str(), i); done = true; } } else if (exp->is(Expression::KindOfObjectPropertyExpression)) { ObjectPropertyExpressionPtr var( dynamic_pointer_cast<ObjectPropertyExpression>(exp)); if (!var->isValid()) { var->outputCPPObject(cg, ar); cg_printf("o_set("); var->outputCPPProperty(cg, ar); cg_printf(", %s[%d], %s);\n", arrTmp.c_str(), i, getClassScope() ? "s_class_name" : "empty_string"); done = true; } } if (!done) { exp->outputCPP(cg, ar); if (arrTmp == "null") { cg_printf(" = null;\n"); } else { cg_printf(" = %s[%d];\n", arrTmp.c_str(), i); } } } } } }
void ListAssignment::outputCPPAssignment(CodeGenerator &cg, AnalysisResultPtr ar, const string &arrTmp) { if (!m_variables) return; for (int i = m_variables->getCount() - 1; i >= 0; --i) { ExpressionPtr exp = (*m_variables)[i]; if (exp) { if (exp->is(Expression::KindOfListAssignment)) { ListAssignmentPtr sublist = dynamic_pointer_cast<ListAssignment>(exp); string subTmp = genCPPTemp(cg, ar); cg.printf("Variant %s((ref(%s.rvalAt(%d))));\n", subTmp.c_str(), arrTmp.c_str(), i); sublist->outputCPPAssignment(cg, ar, subTmp); } else { bool done = false; if (exp->is(Expression::KindOfArrayElementExpression)) { ArrayElementExpressionPtr arrExp = dynamic_pointer_cast<ArrayElementExpression>(exp); if (!arrExp->isSuperGlobal() && !arrExp->isDynamicGlobal()) { arrExp->getVariable()->outputCPP(cg, ar); if (arrExp->getOffset()) { cg.printf(".set("); arrExp->getOffset()->outputCPP(cg, ar); cg.printf(", "); } else { cg.printf(".append("); } cg.printf("%s.rvalAt(%d));\n", arrTmp.c_str(), i); done = true; } } if (!done) { exp->outputCPP(cg, ar); if (arrTmp == "null") { cg.printf(" = null;\n"); } else { cg.printf(" = %s.rvalAt(%d);\n", arrTmp.c_str(), i); } } } } } }
void ListAssignment::setLValue() { if (m_variables) { for (int i = 0; i < m_variables->getCount(); i++) { ExpressionPtr exp = (*m_variables)[i]; if (exp) { if (exp->is(Expression::KindOfListAssignment)) { ListAssignmentPtr sublist = dynamic_pointer_cast<ListAssignment>(exp); sublist->setLValue(); } else { // Magic contexts I took from assignment expression exp->setContext(Expression::DeepAssignmentLHS); exp->setContext(Expression::AssignmentLHS); exp->setContext(Expression::LValue); exp->setContext(Expression::NoLValueWrapper); } } } } }
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; }