コード例 #1
0
bool ListAssignment::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar,
                                  int state) {
  ASSERT(m_array);

  if (!cg.inExpression()) return true;

  if (m_variables) {
    preOutputVariables(cg, ar, m_variables->hasEffect() ||
                       m_array->hasEffect() ? FixOrder : 0);
  }
  m_array->preOutputCPP(cg, ar, 0);

  bool isArray = false, notArray = false;
  bool simpleVar = m_array->is(KindOfSimpleVariable) &&
    !static_pointer_cast<SimpleVariable>(m_array)->getAlwaysStash();
  bool needsUse = false;
  if (TypePtr type = m_array->getActualType()) {
    isArray = type->is(Type::KindOfArray);
    notArray = !isArray &&
      (type->isPrimitive() ||
       m_rhsKind == Null ||
      (m_rhsKind == Checked && (type->is(Type::KindOfString) ||
                                type->is(Type::KindOfObject))));
  }
  cg.wrapExpressionBegin();
  if (outputLineMap(cg, ar)) cg_printf("0);\n");
  if (notArray && isUnused()) {
    if (m_array->outputCPPUnneeded(cg, ar)) cg_printf(";\n");
    m_cppTemp = "null";
  } else {
    m_cppTemp = genCPPTemp(cg, ar);
    needsUse = simpleVar || m_array->isTemporary();
    const char *decl;
    if (isArray && m_array->getCPPType()->is(Type::KindOfArray)) {
      decl = needsUse ? "CArrRef" : "Array";
    } else {
      decl = needsUse ? "CVarRef" : "Variant";
    }
    cg_printf("%s %s((", decl, m_cppTemp.c_str());
    m_array->outputCPP(cg, ar);
    cg_printf("));\n");
  }
  std::string tmp;
  if (notArray) {
    tmp = "null_variant";
    if (needsUse) cg_printf("id(%s);\n", m_cppTemp.c_str());
    needsUse = false;
  } else if (m_rhsKind != Checked || isArray) {
    tmp = m_cppTemp;
  } else {
    tmp = genCPPTemp(cg, ar);
    cg_printf("CVarRef %s(f_is_array(%s)?%s:null_variant);\n",
              tmp.c_str(), m_cppTemp.c_str(), m_cppTemp.c_str());
    needsUse = true;
  }
  if (!outputCPPAssignment(cg, ar, tmp, simpleVar) && needsUse) {
    cg_printf("id(%s);\n", tmp.c_str());
  }

  return true;
}
コード例 #2
0
bool DynamicFunctionCall::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar,
    int state) {
  bool nonStatic = !m_class && m_className.empty();
  if (!nonStatic && !m_class && !m_classScope && !isRedeclared())
    return FunctionCall::preOutputCPP(cg, ar, state);
  // Short circuit out if inExpression() returns false
  if (!cg.inExpression()) return true;

  if (m_class) {
    m_class->preOutputCPP(cg, ar, state);
  }

  m_nameExp->preOutputCPP(cg, ar, state);

  cg.wrapExpressionBegin();
  m_ciTemp = cg.createNewLocalId(shared_from_this());
  bool lsb = false;

  if (!m_classScope && !m_className.empty() && m_cppTemp.empty() &&
      !isSelf() && ! isParent() && !isStatic()) {
    // Create a temporary to hold the class name, in case it is not a
    // StaticString.
    m_clsNameTemp = cg.createNewLocalId(shared_from_this());
    cg_printf("CStrRef clsName%d(", m_clsNameTemp);
    cg_printString(m_origClassName, ar, shared_from_this());
    cg_printf(");\n");
  }

  if (nonStatic) {
    cg_printf("const CallInfo *cit%d;\n", m_ciTemp);
    cg_printf("void *vt%d;\n", m_ciTemp);
    cg_printf("get_call_info_or_fail(cit%d, vt%d, ", m_ciTemp, m_ciTemp);
  } else {
    cg_printf("MethodCallPackage mcp%d;\n", m_ciTemp);
    if (m_class) {
      if (m_class->is(KindOfScalarExpression)) {
        ASSERT(strcasecmp(dynamic_pointer_cast<ScalarExpression>(m_class)->
                          getString().c_str(), "static") == 0);
        cg_printf("mcp%d.staticMethodCall(", m_ciTemp);
        cg_printf("\"static\"");
        lsb = true;
      } else {
        cg_printf("mcp%d.dynamicNamedCall(", m_ciTemp);
        m_class->outputCPP(cg, ar);
      }
      cg_printf(", ");
    } else if (m_classScope) {
      cg_printf("mcp%d.staticMethodCall(\"%s\", ", m_ciTemp,
                m_classScope->getId(cg).c_str());
    } else {
      cg_printf("mcp%d.staticMethodCall(\"%s\", ", m_ciTemp,
                m_className.c_str());
    }
  }

  if (m_nameExp->is(Expression::KindOfSimpleVariable)) {
    m_nameExp->outputCPP(cg, ar);
  } else {
    cg_printf("(");
    m_nameExp->outputCPP(cg, ar);
    cg_printf(")");
  }

  if (!nonStatic) {
    cg_printf(");\n");
    if (lsb) cg_printf("mcp%d.lateStaticBind(info);\n");
    cg_printf("const CallInfo *&cit%d = mcp%d.ci;\n", m_ciTemp, m_ciTemp);
    if (m_classScope) {
      cg_printf("%s%s::%sget_call_info(mcp%d",
                Option::ClassPrefix, m_classScope->getId(cg).c_str(),
                Option::ObjectStaticPrefix, m_ciTemp, m_className.c_str());
    } else if (isRedeclared()) {
      cg_printf("g->%s%s->%sget_call_info(mcp%d",
                Option::ClassStaticsObjectPrefix, m_className.c_str(),
                Option::ObjectStaticPrefix, m_ciTemp, m_className.c_str());
    }
  }
  if (nonStatic || !m_class) {
    cg_printf(");\n");
  }
  if (m_params && m_params->getCount() > 0) {
    cg.pushCallInfo(m_ciTemp);
    m_params->preOutputCPP(cg, ar, state);
    cg.popCallInfo();
  }

  cg.pushCallInfo(m_ciTemp);
  preOutputStash(cg, ar, state);
  cg.popCallInfo();
  if (!(state & FixOrder)) {
    cg_printf("id(%s);\n", cppTemp().c_str());
  }
  return true;
}
コード例 #3
0
bool ExpressionList::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar,
                                  int state) {
  if (m_kind == ListKindParam && !m_arrayElements) {
    return Expression::preOutputCPP(cg, ar, state|StashKidVars);
  }

  unsigned n = m_exps.size();
  bool inExpression = cg.inExpression();
  if (!inExpression && (state & FixOrder)) {
    return true;
  }

  cg.setInExpression(false);
  bool ret = false;
  if (m_arrayElements) {
    /*
     * would like to do:
     *  ret = Expression::preOutputCPP(cg, ar, state);
     * but icc has problems with the generated code.
     */
    ret = hasEffect();
  } else if (n > 1 && m_kind == ListKindLeft) {
    ret = true;
  } else {
    for (unsigned int i = 0; i < n; i++) {
      if (m_exps[i]->preOutputCPP(cg, ar, 0)) {
        ret = true;
        break;
      }
    }
  }

  if (!inExpression) return ret;

  cg.setInExpression(true);
  if (!ret) {
    if (state & FixOrder) {
      preOutputStash(cg, ar, state);
      return true;
    }
    return false;
  }

  cg.wrapExpressionBegin();
  if (m_arrayElements) {
    setCPPTemp(genCPPTemp(cg, ar));
    outputCPPInternal(cg, ar, true, true);
  } else {
    unsigned ix = m_kind == ListKindLeft ? 0 : n - 1;
    for (unsigned int i = 0; i < n; i++) {
      ExpressionPtr e = m_exps[i];
      e->preOutputCPP(cg, ar, 0);
      if (i != ix) {
        if (e->outputCPPUnneeded(cg, ar)) {
          cg_printf(";\n");
        }
        e->setCPPTemp("/**/");
      } else if (e->hasCPPTemp() && Type::SameType(e->getType(), getType())) {
        setCPPTemp(e->cppTemp());
      } else if (!i && n > 1) {
        e->Expression::preOutputStash(cg, ar, state | FixOrder);
        if (!(state & FixOrder)) {
          cg_printf("id(%s);\n", e->cppTemp().c_str());
        }
        setCPPTemp(e->cppTemp());
      }
    }
  }
  return true;
}
コード例 #4
0
bool NewObjectExpression::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar,
                                       int state) {
  string &cname = isSelf() || isParent() ? m_name : m_origName;
  if (m_name.empty() || !m_classScope || m_dynamic) {
    // Short circuit out if inExpression() returns false
    if (!cg.inExpression()) return true;

    if (m_nameExp) m_nameExp->preOutputCPP(cg, ar, state);
    cg.wrapExpressionBegin();
    m_ciTemp = cg.createNewLocalId(shared_from_this());
    m_objectTemp = cg.createNewLocalId(shared_from_this());
    cg_printf("Object obj%d(", m_objectTemp);
    if (isRedeclared()) {
      bool outsideClass = !isPresent();
      if (outsideClass) {
        ClassScope::OutputVolatileCheckBegin(cg, ar, getScope(), cname);
      }
      cg_printf("g->%s%s->createOnly()", Option::ClassStaticsObjectPrefix,
                m_name.c_str());
      if (outsideClass) {
        ClassScope::OutputVolatileCheckEnd(cg);
      }
    } else {
      cg_printf("create_object_only(");
      if (!cname.empty()) {
        cg_printf("\"%s\"", cname.c_str());
      } else if (m_nameExp->is(Expression::KindOfSimpleVariable)) {
        m_nameExp->outputCPP(cg, ar);
      } else {
        cg_printf("(");
        m_nameExp->outputCPP(cg, ar);
        cg_printf(")");
      }
      cg_printf(")");
    }
    cg_printf(");\n");
    cg_printf("MethodCallPackage mcp%d;\n", m_ciTemp,
        m_objectTemp);
    cg_printf("mcp%d.construct(obj%d);\n", m_ciTemp, m_objectTemp);
    cg_printf("const CallInfo *cit%d = mcp%d.ci;\n", m_ciTemp, m_ciTemp);

    if (m_params && m_params->getCount() > 0) {
      cg.pushCallInfo(m_ciTemp);
      m_params->preOutputCPP(cg, ar, state);
      cg.popCallInfo();
    }
    cg_printf("(cit%d->getMeth())(mcp%d, ", m_ciTemp, m_ciTemp);
    if (m_params && m_params->getOutputCount()) {
      cg.pushCallInfo(m_ciTemp);
      FunctionScope::OutputCPPArguments(m_params, m_funcScope,
                                        cg, ar, -1, false);
      cg.popCallInfo();
    } else {
      cg_printf("Array()");
    }
    cg_printf(");\n");

    if (state & FixOrder) {
      cg.pushCallInfo(m_ciTemp);
      preOutputStash(cg, ar, state);
      cg.popCallInfo();
    }

    if (hasCPPTemp() && !(state & FixOrder)) {
      cg_printf("id(%s);\n", cppTemp().c_str());
    }
    return true;
  } else {
    bool tempRcvr = true;

    bool paramEffect = false;
    if (m_params && m_params->getCount() > 0) {
      for (int i = m_params->getCount(); i--; ) {
        if (!(*m_params)[i]->isScalar()) {
          paramEffect = true;
          break;
        }
      }
    }

    if (!paramEffect) {
      tempRcvr = false;
    }

    if (tempRcvr && cg.inExpression()) {
      bool outsideClass = !isPresent();
      cg.wrapExpressionBegin();
      m_receiverTemp = genCPPTemp(cg, ar);
      cg_printf("%s%s %s = ",
                Option::SmartPtrPrefix, m_classScope->getId(cg).c_str(),
                m_receiverTemp.c_str());
      if (outsideClass) {
        m_classScope->outputVolatileCheckBegin(cg, ar, getScope(), cname);
      }
      cg_printf("NEWOBJ(%s%s)()",
                Option::ClassPrefix, m_classScope->getId(cg).c_str());
      if (outsideClass) {
        m_classScope->outputVolatileCheckEnd(cg);
      }
      cg_printf(";\n");
    }

    bool tempParams = FunctionCall::preOutputCPP(cg, ar, state);
    return tempRcvr || tempParams;
  }
}
コード例 #5
0
bool ObjectMethodExpression::preOutputCPP(CodeGenerator &cg,
    AnalysisResultPtr ar, int state) {
  if (!m_name.empty() && m_valid && m_object->getType()->isSpecificObject()) {
    return FunctionCall::preOutputCPP(cg, ar, state);
  }
  // Short circuit out if inExpression() returns false
  if (!cg.inExpression()) return true;
  m_ciTemp = cg.createNewId(shared_from_this());

  cg.wrapExpressionBegin();
  bool isThis = m_object->isThis();
  if (!isThis) {
    m_object->preOutputCPP(cg, ar, state);
  }
  if (m_name.empty()) {
    m_nameExp->preOutputCPP(cg, ar, state);
  }
  const MethodSlot *ms = NULL;
  if (!m_name.empty()) {
    ConstructPtr self = shared_from_this();
    ms = ar->getOrAddMethodSlot(m_name, self);
  }
  cg_printf("MethodCallPackage mcp%d;\n", m_ciTemp);
  if (ms) {
    cg_printf("mcp%d.methodCallWithIndex((", m_ciTemp);
  } else {
    cg_printf("mcp%d.methodCall((", m_ciTemp);
  }
  if (isThis) {
    cg_printf("GET_THIS()");
  } else {
    outputCPPObject(cg, ar);
  }
  cg_printf("), ");
  if (!m_name.empty()) {
    uint64 hash = hash_string_i(m_name.c_str());
    cg_printString(m_origName, ar, shared_from_this());
    if (ms) {
      cg_printf(", %s", ms->runObjParam().c_str());
    }
    cg_printf(", 0x%016llXLL);\n", hash);
  } else {
    m_nameExp->outputCPP(cg, ar);
    cg_printf(", -1);\n");
  }
  cg_printf("const CallInfo *cit%d  __attribute__((__unused__)) ="
      " mcp%d.ci;\n", m_ciTemp, m_ciTemp);

  if (m_params && m_params->getCount() > 0) {
    cg.pushCallInfo(m_ciTemp);
    m_params->preOutputCPP(cg, ar, state);
    cg.popCallInfo();
  }

  if (state & FixOrder) {
    cg.pushCallInfo(m_ciTemp);
    preOutputStash(cg, ar, state);
    cg.popCallInfo();
  }
  if (hasCPPTemp() && !(state & FixOrder)) {
    cg_printf("id(%s);\n", cppTemp().c_str());
  }
  return true;
}
コード例 #6
0
bool BinaryOpExpression::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar,
                                      int state) {
  if (isOpEqual()) return Expression::preOutputCPP(cg, ar, state);
  bool effect2 = m_exp2->hasEffect();
  const char *prefix = 0;
  if (effect2 || m_exp1->hasEffect()) {
    ExpressionPtr self = static_pointer_cast<Expression>(shared_from_this());
    ExpressionPtrVec ev;
    bool hasVoid = false;
    int numConcat = 0;
    bool ok = false;
    if (m_op == '.') {
      numConcat = getConcatList(ev, self, hasVoid);
      ok = hasVoid ||
           (numConcat > MAX_CONCAT_ARGS &&
            (!Option::GenConcat ||
             cg.getOutput() == CodeGenerator::SystemCPP));
    } else if (effect2 && m_op == T_CONCAT_EQUAL) {
      prefix = stringBufferPrefix(cg, ar, m_exp1);
      ok = prefix;
      if (!ok) {
        if (m_exp1->is(KindOfSimpleVariable)) {
          ok = true;
          ev.push_back(m_exp1);
          numConcat++;
        }
      }
      numConcat += getConcatList(ev, m_exp2, hasVoid);
    }
    if (ok) {
      if (!cg.inExpression()) return true;

      cg.wrapExpressionBegin();
      std::string buf;
      if (prefix) {
        SimpleVariablePtr sv(static_pointer_cast<SimpleVariable>(m_exp1));
        buf = stringBufferName(Option::TempPrefix, prefix,
                               sv->getName().c_str());
        m_cppTemp = "/**/";
      } else if (numConcat) {
        buf = m_cppTemp = genCPPTemp(cg, ar);
        buf += "_buf";
        cg_printf("StringBuffer %s;\n", buf.c_str());
      } else {
        m_cppTemp = "\"\"";
      }

      for (size_t i = 0; i < ev.size(); i++) {
        ExpressionPtr exp = ev[i];
        bool is_void = !exp->getActualType();
        exp->preOutputCPP(cg, ar, 0);
        if (!is_void) {
          cg_printf("%s.append(", buf.c_str());
          outputStringExpr(cg, ar, exp, true);
          cg_printf(")");
        } else {
          exp->outputCPPUnneeded(cg, ar);
        }
        cg_printf(";\n");
      }

      if (numConcat && !prefix) {
        cg_printf("CStrRef %s(%s.detach());\n",
                  m_cppTemp.c_str(), buf.c_str());
        if (m_op == T_CONCAT_EQUAL) {
          m_exp1->outputCPP(cg, ar);
          cg_printf(" = %s;\n", m_cppTemp.c_str());
        }
      }
      return true;
    }
  }

  if (!isShortCircuitOperator()) {
    return Expression::preOutputCPP(cg, ar, state);
  }

  if (!effect2) {
    return m_exp1->preOutputCPP(cg, ar, state);
  }

  bool fix_e1 = m_exp1->preOutputCPP(cg, ar, 0);
  if (!cg.inExpression()) {
    return fix_e1 || m_exp2->preOutputCPP(cg, ar, 0);
  }

  cg.setInExpression(false);
  bool fix_e2 = m_exp2->preOutputCPP(cg, ar, 0);
  cg.setInExpression(true);

  if (fix_e2) {
    cg.wrapExpressionBegin();
    std::string tmp = genCPPTemp(cg, ar);
    cg_printf("bool %s = (", tmp.c_str());
    m_exp1->outputCPP(cg, ar);
    cg_printf(");\n");
    cg_indentBegin("if (%s%s) {\n",
                   m_op == T_LOGICAL_OR || m_op == T_BOOLEAN_OR ? "!" : "",
                   tmp.c_str());
    m_exp2->preOutputCPP(cg, ar, 0);
    cg_printf("%s = (", tmp.c_str());
    m_exp2->outputCPP(cg, ar);
    cg_printf(");\n");
    cg_indentEnd("}\n");
    m_cppTemp = tmp;
  } else if (state & FixOrder) {
    preOutputStash(cg, ar, state);
    fix_e1 = true;
  }
  return fix_e1 || fix_e2;
}
コード例 #7
0
bool ExpressionList::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar,
                                  int state) {
  if (m_kind == ListKindParam && !m_arrayElements) {
    return Expression::preOutputCPP(cg, ar, state|StashKidVars);
  }

  unsigned n = m_exps.size();
  bool inExpression = cg.inExpression();
  if (!inExpression && (state & FixOrder)) {
    return true;
  }

  cg.setInExpression(false);
  bool ret = false;
  if (m_arrayElements) {
    /*
     * would like to do:
     *  ret = Expression::preOutputCPP(cg, ar, state);
     * but icc has problems with the generated code.
     */
    ret = hasEffect();
  } else if (n > 1 && m_kind == ListKindLeft) {
    ret = true;
  } else {
    for (unsigned int i = 0; i < n; i++) {
      if (m_exps[i]->preOutputCPP(cg, ar, 0)) {
        ret = true;
        break;
      }
    }
    if (!ret) {
      ExpressionPtr e = m_exps[n - 1];
      if (hasContext(LValue) && !hasAnyContext(RefValue|InvokeArgument) &&
          !(e->hasContext(LValue) &&
            !e->hasAnyContext(RefValue|InvokeArgument))) {
        ret = true;
      } else if (hasContext(RefValue) &&
                 !e->hasAllContext(LValue|ReturnContext) &&
                 !e->hasContext(RefValue)) {
        ret = true;
      }
    }
  }

  if (!inExpression) return ret;

  cg.setInExpression(true);
  if (!ret) {
    if (state & FixOrder) {
      preOutputStash(cg, ar, state);
      return true;
    }
    return false;
  }

  cg.wrapExpressionBegin();
  if (m_arrayElements) {
    setCPPTemp(genCPPTemp(cg, ar));
    outputCPPInternal(cg, ar, true, true);
  } else {
    unsigned ix = isUnused() ? (unsigned)-1 :
      m_kind == ListKindLeft ? 0 : n - 1;
    for (unsigned int i = 0; i < n; i++) {
      ExpressionPtr e = m_exps[i];
      if (i != ix) e->setUnused(true);
      e->preOutputCPP(cg, ar, i == ix ? state : 0);
      if (i != ix) {
        if (e->outputCPPUnneeded(cg, ar)) {
          cg_printf(";\n");
        }
        e->setCPPTemp("/**/");
        continue;
      }
      /*
        We inlined a by-value function into the rhs of a by-ref assignment.
      */
      bool noRef = hasContext(RefValue) &&
        !e->hasAllContext(LValue|ReturnContext) &&
        !e->hasContext(RefValue) &&
        !e->isTemporary() &&
        Type::IsMappedToVariant(e->getActualType());
      /*
        If we need a non-const reference, but the expression is
        going to generate a const reference, fix it
      */
      bool lvSwitch =
        hasContext(LValue) && !hasAnyContext(RefValue|InvokeArgument) &&
        !(e->hasContext(LValue) &&
          !e->hasAnyContext(RefValue|InvokeArgument));

      if (e->hasAllContext(LValue|ReturnContext) && i + 1 == n) {
        e->clearContext(ReturnContext);
      }

      if (noRef || lvSwitch || (!i && n > 1)) {
        e->Expression::preOutputStash(cg, ar, state | FixOrder | StashAll);
        if (!(state & FixOrder)) {
          cg_printf("id(%s);\n", e->cppTemp().c_str());
        }
      }
      if (e->hasCPPTemp() &&
          Type::SameType(e->getGenType(), getGenType())) {
        string t = e->cppTemp();
        if (noRef) {
          cg_printf("CVarRef %s_nr = wrap_variant(%s);\n",
                    t.c_str(), t.c_str());
          t += "_nr";
        }

        if (lvSwitch) {
          cg_printf("Variant &%s_lv = const_cast<Variant&>(%s);\n",
                    t.c_str(), t.c_str());
          t += "_lv";
        }
        setCPPTemp(t);
      }
    }
  }
  return true;
}
コード例 #8
0
bool DynamicFunctionCall::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar,
                                       int state) {
    bool nonStatic = !m_class && m_className.empty();
    if (!nonStatic && !m_class && !m_classScope && !isRedeclared()) {
        // call to an unknown class
        // set m_noStatic to avoid pointlessly wrapping the call
        // in STATIC_CLASS_NAME_CALL()
        m_noStatic = true;
        cg.pushCallInfo(-1);
        bool ret = FunctionCall::preOutputCPP(cg, ar, state);
        cg.popCallInfo();
        return ret;
    }
    // Short circuit out if inExpression() returns false
    if (!cg.inExpression()) return true;

    cg.wrapExpressionBegin();

    m_ciTemp = cg.createNewLocalId(shared_from_this());

    if (!m_classScope && !m_className.empty() && m_cppTemp.empty() &&
            !isSelf() && ! isParent() && !isStatic()) {
        // Create a temporary to hold the class name, in case it is not a
        // StaticString.
        m_clsNameTemp = cg.createNewLocalId(shared_from_this());
        cg_printf("CStrRef clsName%d(", m_clsNameTemp);
        cg_printString(m_origClassName, ar, shared_from_this());
        cg_printf(");\n");
    }

    if (m_class) {
        int s = m_class->hasEffect() || m_nameExp->hasEffect() ?
                FixOrder : 0;
        m_class->preOutputCPP(cg, ar, s);
    }
    m_nameExp->preOutputCPP(cg, ar, 0);

    if (nonStatic) {
        cg_printf("const CallInfo *cit%d;\n", m_ciTemp);
        cg_printf("void *vt%d;\n", m_ciTemp);
        cg_printf("get_call_info_or_fail(cit%d, vt%d, ", m_ciTemp, m_ciTemp);

        if (m_nameExp->is(Expression::KindOfSimpleVariable)) {
            m_nameExp->outputCPP(cg, ar);
        } else {
            cg_printf("(");
            m_nameExp->outputCPP(cg, ar);
            cg_printf(")");
        }
        cg_printf(");\n");
    } else {
        cg_printf("MethodCallPackage mcp%d;\n", m_ciTemp);
        if (m_class) {
            if (m_class->is(KindOfScalarExpression)) {
                ASSERT(strcasecmp(dynamic_pointer_cast<ScalarExpression>(m_class)->
                                  getString().c_str(), "static") == 0);
                cg_printf("CStrRef cls%d = "
                          "FrameInjection::GetStaticClassName(fi.getThreadInfo())",
                          m_ciTemp);
            } else {
                cg_printf("C%sRef cls%d = ",
                          m_class->getActualType() &&
                          m_class->getActualType()->is(Type::KindOfString) ?
                          "Str" : "Var", m_ciTemp);
                m_class->outputCPP(cg, ar);
            }
        } else if (m_classScope) {
            cg_printf("CStrRef cls%d = ", m_ciTemp);
            cg_printString(m_classScope->getId(), ar, shared_from_this());
        } else {
            cg_printf("CStrRef cls%d = ", m_ciTemp);
            cg_printString(m_className, ar, shared_from_this());
        }
        cg_printf(";\n");

        cg_printf("CStrRef mth%d = ", m_ciTemp);
        if (m_nameExp->is(Expression::KindOfSimpleVariable)) {
            m_nameExp->outputCPP(cg, ar);
        } else {
            cg_printf("(");
            m_nameExp->outputCPP(cg, ar);
            cg_printf(")");
        }
        cg_printf(";\n");

        bool dynamic = true;
        if (!m_class) {
            ClassScopeRawPtr origClass = getOriginalClass();
            if (!origClass) {
                dynamic = false;
            } else {
                FunctionScopeRawPtr origFunc = getOriginalFunction();
                if (origFunc) {
                    if (origFunc->isStatic() ||
                            (m_classScope != origClass &&
                             (m_className.empty() || !origClass->derivesFrom(
                                  ar, m_className, true, true)))) {
                        dynamic = false;
                    }
                }
            }
        }

        if (dynamic) {
            if ((m_class && (!m_class->getActualType() ||
                             !m_class->getActualType()->is(Type::KindOfString))) ||
                    !getOriginalFunction() ||
                    !getOriginalClass() ||
                    getOriginalFunction()->isStatic()) {
                cg_printf("mcp%d.dynamicNamedCall(cls%d, mth%d);\n",
                          m_ciTemp, m_ciTemp, m_ciTemp);
            } else {
                cg_printf("mcp%d.isObj = true;\n", m_ciTemp);
                cg_printf("mcp%d.rootObj = this;\n", m_ciTemp);
                cg_printf("mcp%d.name = &mth%d;\n", m_ciTemp, m_ciTemp);
                cg_printf("o_get_call_info_ex(cls%d, mcp%d);\n", m_ciTemp, m_ciTemp);
            }
        } else {
            cg_printf("mcp%d.staticMethodCall(cls%d, mth%d);\n",
                      m_ciTemp,
                      m_ciTemp, m_ciTemp);

            if (m_classScope) {
                cg_printf("%s%s.%sget_call_info(mcp%d);\n",
                          Option::ClassStaticsCallbackPrefix,
                          m_classScope->getId().c_str(),
                          Option::ObjectStaticPrefix, m_ciTemp);
            } else if (isRedeclared()) {
                cg_printf("g->%s%s->%sget_call_info(mcp%d);\n",
                          Option::ClassStaticsCallbackPrefix, m_className.c_str(),
                          Option::ObjectStaticPrefix, m_ciTemp);
            } else {
                assert(false);
            }
        }
        cg_printf("const CallInfo *cit%d = mcp%d.ci;\n", m_ciTemp, m_ciTemp);
    }

    if (m_params && m_params->getCount() > 0) {
        cg.pushCallInfo(m_ciTemp);
        m_params->preOutputCPP(cg, ar, 0);
        cg.popCallInfo();
    }

    if (state & FixOrder) {
        cg.pushCallInfo(m_ciTemp);
        preOutputStash(cg, ar, state);
        cg.popCallInfo();
    }

    return true;
}
コード例 #9
0
ファイル: qop_expression.cpp プロジェクト: AviMoto/hiphop-php
bool QOpExpression::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar,
                                 int state) {
  if (!hasEffect()) {
    return Expression::preOutputCPP(cg, ar, state);
  }

  bool fix_condition = m_condition->preOutputCPP(cg, ar, 0);
  if (!cg.inExpression()) {
    return fix_condition || (state & FixOrder) ||
      (!m_expYes || m_expYes->preOutputCPP(cg, ar, 0)) ||
      m_expNo->preOutputCPP(cg, ar, 0);
  }

  cg.setInExpression(false);
  bool fix_yes = (!m_expYes || m_expYes->preOutputCPP(cg, ar, 0));
  bool fix_no = m_expNo->preOutputCPP(cg, ar, 0);
  cg.setInExpression(true);

  if (fix_yes || fix_no) {
    cg.wrapExpressionBegin();
    if (isUnused()) {
      cg_printf("if (");
      wrapBoolean(cg, ar, m_condition);
      cg_indentBegin(") {\n");
      if (m_expYes) {
        m_expYes->preOutputCPP(cg, ar, 0);
        if (m_expYes->outputCPPUnneeded(cg, ar)) cg_printf(";\n");
      }
      cg_indentEnd("\n");
      cg_indentBegin("} else {\n");
      m_expNo->preOutputCPP(cg, ar, 0);
      if (m_expNo->outputCPPUnneeded(cg, ar)) cg_printf(";\n");
      cg_indentEnd("}\n");
      m_cppValue = "null_variant";
    } else {
      std::string tmp = genCPPTemp(cg, ar);

      if (m_expYes) {
        TypePtr typeYes = m_expYes->getActualType();
        TypePtr typeNo = m_expNo->getActualType();
        TypePtr type =
          typeYes && typeNo && Type::SameType(typeYes, typeNo) &&
          !typeYes->is(Type::KindOfVariant) &&
          m_expYes->isLiteralString() == m_expNo->isLiteralString() ?
          typeYes : Type::Variant;

        type->outputCPPDecl(cg, ar, getScope());
        cg_printf(" %s;\n", tmp.c_str());
        cg_printf("if (");
        wrapBoolean(cg, ar, m_condition);
        cg_indentBegin(") {\n");
        m_expYes->preOutputCPP(cg, ar, 0);
        cg_printf("%s = (", tmp.c_str());
        m_expYes->outputCPP(cg, ar);
        cg_indentEnd(");\n");
      } else {
        TypePtr typeYes = m_condition->getActualType();
        TypePtr typeNo = m_expNo->getActualType();
        TypePtr type =
          typeYes && typeNo && Type::SameType(typeYes, typeNo) &&
          !typeYes->is(Type::KindOfVariant) &&
          m_condition->isLiteralString() == m_expNo->isLiteralString() ?
          typeYes : Type::Variant;

        type->outputCPPDecl(cg, ar, getScope());
        cg_printf(" %s = ", tmp.c_str());
        m_condition->outputCPP(cg, ar);
        cg_printf(";\n");
        cg_printf("if (toBoolean(%s)) {\n", tmp.c_str());
      }

      cg_indentBegin("} else {\n");
      m_expNo->preOutputCPP(cg, ar, 0);
      cg_printf("%s = (", tmp.c_str());
      m_expNo->outputCPP(cg, ar);
      cg_printf(");\n");
      cg_indentEnd("}\n");
      m_cppValue = tmp;
    }
  } else if (state & FixOrder) {
    preOutputStash(cg, ar, state);
    return true;
  }
  return false;
}
コード例 #10
0
bool ObjectMethodExpression::preOutputCPP(CodeGenerator &cg,
                                          AnalysisResultPtr ar, int state) {
  if (!m_name.empty() && m_valid && m_object->getType()->isSpecificObject()) {
    if (m_object->hasEffect()) {
      if (cg.inExpression()) {
        m_object->preOutputCPP(cg, ar, FixOrder);
        if (m_params) m_params->preOutputCPP(cg, ar, 0);
        if (state & FixOrder) {
          preOutputStash(cg, ar, state);
        }
      }
      return true;
    }
    return FunctionCall::preOutputCPP(cg, ar, state);
  }
  // Short circuit out if inExpression() returns false
  if (!cg.inExpression()) return true;
  cg.wrapExpressionBegin();
  m_ciTemp = cg.createNewLocalId(shared_from_this());

  if (outputLineMap(cg, ar)) cg_printf("0);\n");

  bool isThis = m_object->isThis();
  if (!isThis) {
    int s = 0;
    if (m_name.empty() &&
        m_nameExp->hasEffect() && !m_object->isScalar()) {
      s = FixOrder;
    }
    m_object->preOutputCPP(cg, ar, s);
  }
  if (m_name.empty()) {
    m_nameExp->preOutputCPP(cg, ar, 0);
  }
  const MethodSlot *ms = NULL;
  if (!m_name.empty()) {
    ConstructPtr self = shared_from_this();
    ms = ar->getOrAddMethodSlot(m_name, self);
  }
  cg_printf("MethodCallPackage mcp%d;\n", m_ciTemp);

  if (!isThis) {
    TypePtr t = m_object->getType();
    if (t && t->is(Type::KindOfObject)) {
      cg_printf("CObjRef obj%d = ", m_ciTemp);
    } else {
      cg_printf("CVarRef obj%d = ", m_ciTemp);
    }
    outputCPPObject(cg, ar);
    cg_printf(";\n");
  }
  if (m_name.empty()) {
    cg_printf("CStrRef mth%d = ", m_ciTemp);
    m_nameExp->outputCPP(cg, ar);
    cg_printf(";\n");
  }

  if (ms) {
    cg_printf("mcp%d.methodCallWithIndex((", m_ciTemp);
  } else {
    cg_printf("mcp%d.methodCall((", m_ciTemp);
  }
  if (isThis) {
    if (!getClassScope() || getClassScope()->derivedByDynamic() ||
        !static_pointer_cast<SimpleVariable>(m_object)->isGuardedThis()) {
      cg_printf("GET_THIS_VALID()");
    } else {
      cg_printf("this");
    }
  } else {
    cg_printf("obj%d", m_ciTemp);
  }
  cg_printf("), ");
  if (!m_name.empty()) {
    uint64 hash = hash_string_i(m_name.c_str());
    cg_printString(m_origName, ar, shared_from_this());
    if (ms) {
      cg_printf(", %s", ms->runObjParam().c_str());
    }
    cg_printf(", 0x%016llXLL);\n", hash);
  } else {
    cg_printf("mth%d, -1);\n", m_ciTemp);
  }
  cg_printf("const CallInfo *cit%d ATTRIBUTE_UNUSED = mcp%d.ci;\n",
            m_ciTemp, m_ciTemp);

  if (m_params && m_params->getCount() > 0) {
    cg.pushCallInfo(m_ciTemp);
    m_params->preOutputCPP(cg, ar, 0);
    cg.popCallInfo();
  }

  if (state & FixOrder) {
    cg.pushCallInfo(m_ciTemp);
    preOutputStash(cg, ar, state);
    cg.popCallInfo();
  }

  return true;
}
コード例 #11
0
bool NewObjectExpression::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar,
                                       int state) {
  if (m_classScope &&
      (m_classScope->isAbstract() ||
       m_classScope->isInterface() ||
       m_classScope->isTrait())) {
    return false;
  }

  string &cname = isSelf() || isParent() ? m_name : m_origName;
  if (m_name.empty() || !m_classScope || m_dynamic) {
    // Short circuit out if inExpression() returns false
    if (!cg.inExpression()) return true;

    if (m_nameExp) m_nameExp->preOutputCPP(cg, ar, 0);
    cg.wrapExpressionBegin();
    m_ciTemp = cg.createNewLocalId(shared_from_this());
    m_objectTemp = cg.createNewLocalId(shared_from_this());
    cg_printf("Object obj%d(", m_objectTemp);
    if (isRedeclared()) {
      bool outsideClass = !isPresent();
      if (outsideClass) {
        ClassScope::OutputVolatileCheckBegin(cg, ar, getScope(), cname);
      }
      cg_printf("g->%s%s->createOnly()", Option::ClassStaticsCallbackPrefix,
                m_name.c_str());
      if (outsideClass) {
        ClassScope::OutputVolatileCheckEnd(cg);
      }
    } else {
      cg_printf("create_object_only(");
      if (isStatic()) {
        cg_printf("FrameInjection::GetStaticClassName(fi.getThreadInfo())");
      } else if (!cname.empty()) {
        cg_printString(cname, ar, getScope(), true);
      } else if (m_nameExp->is(Expression::KindOfSimpleVariable)) {
        m_nameExp->outputCPP(cg, ar);
      } else {
        cg_printf("(");
        m_nameExp->outputCPP(cg, ar);
        cg_printf(")");
      }
      cg_printf(")");
    }
    cg_printf(");\n");
    cg_printf("MethodCallPackage mcp%d;\n", m_ciTemp);
    cg_printf("mcp%d.construct(obj%d);\n", m_ciTemp, m_objectTemp);
    cg_printf("const CallInfo *cit%d = mcp%d.ci;\n", m_ciTemp, m_ciTemp);

    int pcount = m_params ? m_params->getCount() : 0;
    if (pcount > 0) {
      cg.pushCallInfo(m_ciTemp);
      m_params->preOutputCPP(cg, ar, 0);
      cg.popCallInfo();
    }

    cg_printf("(cit%d->", m_ciTemp);
    outputDynamicCall(cg, ar, true);
    cg_printf(";\n");

    if (state & FixOrder) {
      cg.pushCallInfo(m_ciTemp);
      preOutputStash(cg, ar, state);
      cg.popCallInfo();
    }

    return true;
  } else {
    bool tempRcvr = true;

    bool paramEffect = false;
    if (m_params && m_params->getCount() > 0) {
      for (int i = m_params->getCount(); i--; ) {
        if (!(*m_params)[i]->isScalar()) {
          paramEffect = true;
          break;
        }
      }
    }

    if (!paramEffect) {
      tempRcvr = false;
    }

    if (tempRcvr && cg.inExpression()) {
      bool outsideClass = !isPresent();
      cg.wrapExpressionBegin();
      m_receiverTemp = genCPPTemp(cg, ar);
      cg_printf("%s%s %s = ",
                Option::SmartPtrPrefix, m_classScope->getId().c_str(),
                m_receiverTemp.c_str());
      if (outsideClass) {
        m_classScope->outputVolatileCheckBegin(cg, ar, getScope(), cname);
      }
      cg_printf("%s%s()",
                Option::CreateObjectOnlyPrefix,
                m_classScope->getId().c_str());
      if (outsideClass) {
        m_classScope->outputVolatileCheckEnd(cg);
      }
      cg_printf(";\n");
    }

    bool tempParams = FunctionCall::preOutputCPP(cg, ar, state);
    return tempRcvr || tempParams;
  }
}
コード例 #12
0
bool DynamicFunctionCall::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar,
    int state) {
  bool nonStatic = !m_class && m_className.empty();
  if (!nonStatic && !m_class && !m_classScope && !isRedeclared()) {
    // call to an unknown class
    // set m_noStatic to avoid pointlessly wrapping the call
    // in STATIC_CLASS_NAME_CALL()
    m_noStatic = true;
    return FunctionCall::preOutputCPP(cg, ar, state);
  }
  // Short circuit out if inExpression() returns false
  if (!cg.inExpression()) return true;

  cg.wrapExpressionBegin();

  m_ciTemp = cg.createNewLocalId(shared_from_this());
  bool lsb = false;

  if (!m_classScope && !m_className.empty() && m_cppTemp.empty() &&
      !isSelf() && ! isParent() && !isStatic()) {
    // Create a temporary to hold the class name, in case it is not a
    // StaticString.
    m_clsNameTemp = cg.createNewLocalId(shared_from_this());
    cg_printf("CStrRef clsName%d(", m_clsNameTemp);
    cg_printString(m_origClassName, ar, shared_from_this());
    cg_printf(");\n");
  }

  if (m_class) {
    int s = m_class->hasEffect() || m_nameExp->hasEffect() ?
      FixOrder : 0;
    m_class->preOutputCPP(cg, ar, s);
  }
  m_nameExp->preOutputCPP(cg, ar, 0);

  if (nonStatic) {
    cg_printf("const CallInfo *cit%d;\n", m_ciTemp);
    cg_printf("void *vt%d;\n", m_ciTemp);
    cg_printf("get_call_info_or_fail(cit%d, vt%d, ", m_ciTemp, m_ciTemp);

    if (m_nameExp->is(Expression::KindOfSimpleVariable)) {
      m_nameExp->outputCPP(cg, ar);
    } else {
      cg_printf("(");
      m_nameExp->outputCPP(cg, ar);
      cg_printf(")");
    }
  } else {
    cg_printf("MethodCallPackage mcp%d;\n", m_ciTemp);
    if (m_class) {
      if (m_class->is(KindOfScalarExpression)) {
        ASSERT(strcasecmp(dynamic_pointer_cast<ScalarExpression>(m_class)->
                          getString().c_str(), "static") == 0);
        cg_printf("CStrRef cls%d = ", m_ciTemp);
        cg_printString("static", ar, shared_from_this());
        lsb = true;
      } else {
        cg_printf("CVarRef cls%d = ", m_ciTemp);
        m_class->outputCPP(cg, ar);
      }
    } else if (m_classScope) {
      cg_printf("CStrRef cls%d = ", m_ciTemp);
      cg_printString(m_classScope->getId(), ar, shared_from_this());
    } else {
      cg_printf("CStrRef cls%d = ", m_ciTemp);
      cg_printString(m_className, ar, shared_from_this());
    }
    cg_printf(";\n");

    cg_printf("CStrRef mth%d = ", m_ciTemp);
    if (m_nameExp->is(Expression::KindOfSimpleVariable)) {
      m_nameExp->outputCPP(cg, ar);
    } else {
      cg_printf("(");
      m_nameExp->outputCPP(cg, ar);
      cg_printf(")");
    }
    cg_printf(";\n");

    if (m_class) {
      if (m_class->is(KindOfScalarExpression)) {
        cg_printf("mcp%d.staticMethodCall(cls%d, mth%d",
                  m_ciTemp, m_ciTemp, m_ciTemp);
      } else {
        cg_printf("mcp%d.dynamicNamedCall(cls%d, mth%d",
                  m_ciTemp, m_ciTemp, m_ciTemp);
      }
    } else {
      cg_printf("mcp%d.staticMethodCall(cls%d, mth%d",
                m_ciTemp, m_ciTemp, m_ciTemp);
    }
  }

  if (!nonStatic) {
    cg_printf(");\n");
    if (lsb) cg_printf("mcp%d.lateStaticBind(fi.getThreadInfo());\n", m_ciTemp);
    cg_printf("const CallInfo *&cit%d = mcp%d.ci;\n", m_ciTemp, m_ciTemp);
    if (m_classScope) {
      cg_printf("%s%s.%sget_call_info(mcp%d",
                Option::ClassStaticsCallbackPrefix,
                m_classScope->getId().c_str(),
                Option::ObjectStaticPrefix, m_ciTemp);
    } else if (isRedeclared()) {
      cg_printf("g->%s%s->%sget_call_info(mcp%d",
                Option::ClassStaticsCallbackPrefix, m_className.c_str(),
                Option::ObjectStaticPrefix, m_ciTemp);
    }
  }
  if (nonStatic || !m_class) {
    cg_printf(");\n");
  }
  if (m_params && m_params->getCount() > 0) {
    cg.pushCallInfo(m_ciTemp);
    m_params->preOutputCPP(cg, ar, 0);
    cg.popCallInfo();
  }

  if (state & FixOrder) {
    cg.pushCallInfo(m_ciTemp);
    preOutputStash(cg, ar, state);
    cg.popCallInfo();
  }

  return true;
}
コード例 #13
0
bool UnaryOpExpression::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar,
                                     int state) {

  if (m_op == T_ISSET && m_exp && m_exp->is(Expression::KindOfExpressionList)) {
    ExpressionListPtr exps = dynamic_pointer_cast<ExpressionList>(m_exp);
    int count = exps->getCount();
    if (count > 1) {
      bool fix_e1 = (*exps)[0]->preOutputCPP(cg, ar, 0);
      bool inExpression = cg.inExpression();
      cg.setInExpression(false);
      bool fix_en = false;
      for (int i = 1; i < count; i++) {
        if ((*exps)[i]->preOutputCPP(cg, ar, 0)) {
          fix_en = true;
          break;
        }
      }
      cg.setInExpression(inExpression);
      if (inExpression && fix_en) {
        cg.wrapExpressionBegin();
        std::string tmp = genCPPTemp(cg, ar);
        cg_printf("bool %s = (", tmp.c_str());
        (*exps)[0]->outputCPPExistTest(cg, ar, m_op);
        cg_printf(");\n");
        for (int i = 1; i < count; i++) {
          cg_indentBegin("if (%s) {\n", tmp.c_str());
          ExpressionPtr e = (*exps)[i];
          e->preOutputCPP(cg, ar, 0);
          cg_printf("%s = (", tmp.c_str());
          e->outputCPPExistTest(cg, ar, m_op);
          cg_printf(");\n");
        }
        for (int i = 1; i < count; i++) {
          cg_indentEnd("}\n");
        }
        m_cppTemp = tmp;
      } else if (state & FixOrder) {
        preOutputStash(cg, ar, state);
        fix_e1 = true;
      }
      return fix_e1 || fix_en;
    }
  }

  if (m_op == '@') {
    if (isUnused()) m_exp->setUnused(true);
    bool doit = (state & FixOrder) || m_exp->hasEffect();
    if (doit && cg.inExpression()) {
      cg.wrapExpressionBegin();
      std::string tmp = genCPPTemp(cg, ar);
      cg_printf("Silencer %s(true);\n", tmp.c_str());
      m_exp->preOutputCPP(cg, ar, 0);
      this->preOutputStash(cg, ar, state | FixOrder | StashAll);
      cg_printf("%s.disable();\n", tmp.c_str());
    }
    return doit;
  } else if (m_op == T_PRINT && m_exp && !m_exp->hasEffect()) {
    ExpressionPtrVec ev;
    bool hasVoid = false;
    if (BinaryOpExpression::getConcatList(ev, m_exp, hasVoid) > 1 ||
        hasVoid ) {

      if (!cg.inExpression()) return true;
      cg.wrapExpressionBegin();
      for (int i = 0, s = ev.size(); i < s; i++) {
        ExpressionPtr e = ev[i];
        e->preOutputCPP(cg, ar, 0);
        cg_printf("print(");
        e->outputCPP(cg, ar);
        cg_printf(");\n");
      }
      m_cppTemp = "id(1)";
      return true;
    }
  }

  if (m_op == T_CLASS || m_op == T_FUNCTION) {
    if (cg.inExpression()) {
      cg.wrapExpressionBegin();
      m_definedScope->outputCPPDef(cg);
      setCPPTemp("id(0)");
    }
    return true;
  }

  return Expression::preOutputCPP(cg, ar, state);
}