Пример #1
0
void SimpleVariable::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  if (m_this) {
    ASSERT((getContext() & ObjectContext) == 0);
    if (hasContext(OprLValue) || hasContext(AssignmentLHS)) {
      cg_printf("throw_assign_this()");
    } else if (hasContext(DeepOprLValue) ||
               hasContext(DeepAssignmentLHS) ||
               hasContext(LValue)) {
      // $this[] op= ...; or $this[] = ...
      cg_printf("Variant(GET_THIS())");
    } else {
      ClassScopePtr cls = getOriginalClass();
      if (cls->derivedByDynamic()) {
        cg_printf("Object(GET_THIS())");
      } else {
        cg_printf("GET_THIS_TYPED(%s)", cls->getId(cg).c_str());
      }
    }
  } else if (m_superGlobal) {
    VariableTablePtr variables = getScope()->getVariables();
    string name = variables->getGlobalVariableName(cg, ar, m_name);
    cg_printf("g->%s", name.c_str());
  } else if (m_globals) {
    cg_printf("get_global_array_wrapper()");
  } else {
    const char *prefix =
      getScope()->getVariables()->getVariablePrefix(m_sym);
    cg_printf("%s%s", prefix, cg.formatLabel(m_name).c_str());
  }
}
Пример #2
0
void GlobalStatement::outputCPP(CodeGenerator &cg, AnalysisResultPtr ar) {
  if (m_dynamicGlobal) {
    cg.printf("throw_fatal(\"dynamic global\");\n");
  } else if (!ar->getScope()->inPseudoMain() || !isTopLevel()) {
    BlockScopePtr scope = ar->getScope();
    if (m_exp->getCount() > 1) cg.indentBegin("{\n");
    for (int i = 0; i < m_exp->getCount(); i++) {
      ExpressionPtr exp = (*m_exp)[i];
      if (exp->is(Expression::KindOfSimpleVariable)) {
        SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(exp);
        const string &name = var->getName();
        VariableTablePtr variables = scope->getVariables();
        if (variables->needLocalCopy(name)) {
          cg.printf("%s%s = ref(g->%s);\n",
                    Option::VariablePrefix, name.c_str(),
                    variables->getGlobalVariableName(ar, name).c_str());
        }
      }
      else {
        // type inference should have set m_dynamicGlobal to true.
        ASSERT(false);
      }
    }
    if (m_exp->getCount() > 1) cg.indentEnd("}\n");
  }
}
void GlobalStatement::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  BlockScopePtr scope = getScope();
  if (m_exp->getCount() > 1) cg_indentBegin("{\n");
  for (int i = 0; i < m_exp->getCount(); i++) {
    ExpressionPtr exp = (*m_exp)[i];
    if (exp->is(Expression::KindOfSimpleVariable)) {
      SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(exp);
      const string &name = var->getName();
      VariableTablePtr variables = scope->getVariables();
      if (variables->needLocalCopy(name)) {
        cg_printf("%s%s = ref(g->%s);\n",
                  Option::VariablePrefix, name.c_str(),
                  variables->getGlobalVariableName(cg, ar, name).c_str());
      }
    } else if (exp->is(Expression::KindOfDynamicVariable)) {
      DynamicVariablePtr var = dynamic_pointer_cast<DynamicVariable>(exp);
      ExpressionPtr exp = var->getSubExpression();
      exp->outputCPPBegin(cg, ar);
      int id = cg.createNewLocalId(shared_from_this());
      cg_printf("CStrRef dgv_%d((", id);
      exp->outputCPP(cg, ar);
      cg_printf("));\n");
      cg_printf("variables->get(dgv_%d) = ref(g->get(dgv_%d));\n", id, id);
      exp->outputCPPEnd(cg, ar);
    } else {
      assert(false);
    }
  }
  if (m_exp->getCount() > 1) cg_indentEnd("}\n");
}
std::string SimpleVariable::getAssignableCPPVariable(AnalysisResultPtr ar)
  const {
  VariableTablePtr variables = getScope()->getVariables();
  if (m_this) {
    if (!hasAnyContext(OprLValue | AssignmentLHS) &&
        variables->getAttribute(VariableTable::ContainsLDynamicVariable)) {
      ASSERT(m_sym);
      const string &namePrefix = getNamePrefix();
      return namePrefix + variables->getVariablePrefix(m_sym) + "this";
    }
    return "";
  } else if (m_superGlobal) {
    const string &name = variables->getGlobalVariableName(ar, m_name);
    return string("g->") + name.c_str();
  } else if (m_globals) {
    return "get_global_array_wrapper()";
  } else {
    ASSERT(m_sym);
    const string &prefix0 = getNamePrefix();
    const char *prefix1 =
      getScope()->getVariables()->getVariablePrefix(m_sym);
    return prefix0 + prefix1 +
           CodeGenerator::FormatLabel(m_name);
  }
}
Пример #5
0
void ArrayElementExpression::outputCPPExistTest(CodeGenerator &cg,
        AnalysisResultPtr ar, int op) {
    switch (op) {
    case T_ISSET:
        cg_printf("isset(");
        break;
    case T_EMPTY:
        cg_printf("empty(");
        break;
    default:
        ASSERT(false);
    }

    if (m_global) {
        if (!m_globalName.empty()) {
            VariableTablePtr variables = getScope()->getVariables();
            string name = variables->getGlobalVariableName(cg, ar, m_globalName);
            cg_printf("g->%s", name.c_str());
        } else {
            cg_printf("((LVariableTable *)g)->get(");
            m_offset->outputCPP(cg, ar);
            cg_printf(")");
        }
    } else {
        m_variable->outputCPP(cg, ar);
        cg_printf(", ");
        m_offset->outputCPP(cg, ar);
        ScalarExpressionPtr sc =
            dynamic_pointer_cast<ScalarExpression>(m_offset);
        if (sc) {
            if (sc->isLiteralString()) {
                String s(sc->getLiteralString());
                int64 n;
                if (!s.get()->isStrictlyInteger(n)) {
                    cg_printf(", true"); // skip toKey() at run time
                }
            }
        }
    }
    cg_printf(")");
}
Пример #6
0
void SimpleVariable::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  if (m_this) {
    ASSERT((getContext() & ObjectContext) == 0);
    if (hasContext(LValue)) {
      // LValue and not ObjectContext must be $this = or $this[..] =
      // Wrap with Variant to avoid compiler error
      cg_printf("Variant(GET_THIS())");
    } else {
      cg_printf("GET_THIS()");
    }
  } else if (m_superGlobal) {
    VariableTablePtr variables = ar->getScope()->getVariables();
    string name = variables->getGlobalVariableName(cg, ar, m_name);
    cg_printf("g->%s", name.c_str());
  } else if (m_globals) {
    cg_printf("get_global_array_wrapper()");
  } else {
    const char *prefix =
      ar->getScope()->getVariables()->getVariablePrefix(ar, m_name);
    cg_printf("%s%s", prefix, cg.formatLabel(m_name).c_str());
  }
}
void ArrayElementExpression::outputCPPImpl(CodeGenerator &cg,
                                           AnalysisResultPtr ar) {
  if (m_global) {
    if (!m_globalName.empty()) {
      VariableTablePtr variables = ar->getScope()->getVariables();
      string name = variables->getGlobalVariableName(cg, ar, m_globalName);
      cg_printf("g->%s", name.c_str());
    } else {
      cg_printf("get_variable_table()->get(");
      m_offset->outputCPP(cg, ar);
      cg_printf(")");
    }
  } else {
    TypePtr type = m_variable->getActualType();
    if (hasContext(UnsetContext)) {
      cg_printf("unsetLval(");
      m_variable->outputCPP(cg, ar);
      cg_printf(", ");
    } else {
      if (m_variable->is(Expression::KindOfScalarExpression) ||
          (type && (type->isInteger() ||
                    type->is(Type::KindOfDouble) ||
                    type->is(Type::KindOfObject) ||
                    type->is(Type::KindOfBoolean)))) {
        cg_printf(type && type->is(Type::KindOfString) ? "((String)" :
                  "((Variant)");
        m_variable->outputCPP(cg, ar);
        cg_printf(")");
      } else {
        m_variable->outputCPP(cg, ar);
      }
    }
    if (m_offset) {
      bool lvalAt = false;
      bool rvalAt = false;
      if (hasContext(UnsetContext)) {
        // do nothing
      } else if (m_context & InvokeArgument) {
        cg_printf(".refvalAt(");
      } else if (m_context & (LValue|RefValue)) {
        cg_printf(".lvalAt(");
        lvalAt = true;
      } else {
        cg_printf(".rvalAt(");
        rvalAt = true;
      }
      m_offset->outputCPP(cg, ar);
      if (!type || !type->is(Type::KindOfString)) {
        bool prehashed = false;
        ScalarExpressionPtr sc =
          dynamic_pointer_cast<ScalarExpression>(m_offset);
        if (sc) {
          int64 hash = sc->getHash();
          if (hash >= 0) {
            cg_printf(", 0x%016llXLL", hash);
            prehashed = true;
          }
        }
        if (!prehashed) {
          cg_printf(", -1");
        }
        if (rvalAt) {
          if (!hasContext(ExistContext)) {
            cg_printf(", true"); // raise undefined index error
          } else {
            cg_printf(", false");
          }
        } else if (lvalAt) {
          if (hasContext(ObjectContext)) {
            // object target might not trigger an array copy
            cg_printf(", true");
          } else {
            cg_printf(", false");
          }
        }
        if (!hasContext(UnsetContext) && sc && sc->isLiteralString()) {
          String s(sc->getLiteralString());
          int64 n;
          if (!s.get()->isStrictlyInteger(n)) {
            cg_printf(", true"); // skip toKey() at run time
          }
        }
      }
      cg_printf(")");
    } else {
      cg_printf(".lvalAt()");
    }
  }
}
void ArrayElementExpression::outputCPPImpl(CodeGenerator &cg,
                                           AnalysisResultPtr ar) {
  if (m_global) {
    if (!m_globalName.empty()) {
      VariableTablePtr variables = getScope()->getVariables();
      string name = variables->getGlobalVariableName(cg, ar, m_globalName);
      cg_printf("g->%s", name.c_str());
    } else {
      cg_printf("((LVariableTable *)g)->get(");
      m_offset->outputCPP(cg, ar);
      cg_printf(")");
    }
  } else {
    TypePtr type = m_variable->getActualType();
    if (hasContext(UnsetContext)) {
      cg_printf("unsetLval(");
      m_variable->outputCPP(cg, ar);
      cg_printf(", ");
    } else {
      if (m_variable->is(Expression::KindOfScalarExpression) ||
          (type && (type->isInteger() ||
                    type->is(Type::KindOfDouble) ||
                    type->is(Type::KindOfObject) ||
                    type->is(Type::KindOfBoolean)))) {
        cg_printf(type && type->is(Type::KindOfString) ? "((String)" :
                  "((Variant)");
        m_variable->outputCPP(cg, ar);
        cg_printf(")");
      } else {
        TypePtr act;
        if (!m_variable->hasCPPTemp() && m_variable->getImplementedType() &&
            type->is(Type::KindOfArray) &&
            !Type::SameType(m_variable->getImplementedType(), type)) {
          act = type;
          type = m_variable->getImplementedType();
          m_variable->setActualType(m_variable->getImplementedType());
        }
        m_variable->outputCPP(cg, ar);
        if (act) {
          m_variable->setActualType(act);
        }
      }
    }
    if (m_offset) {
      bool lvalAt = false;
      bool rvalAt = false;
      bool byRef = false;
      bool arrRef = false;
      const char *sep = ", AccessFlags::";
      if (hasContext(UnsetContext)) {
        // do nothing
      } else if (hasContext(InvokeArgument) && cg.callInfoTop() != -1) {
        cg_printf(".argvalAt(cit%d->isRef(%d), ", cg.callInfoTop(), m_argNum);
      } else if (m_context & (LValue|RefValue|DeepReference)) {
        cg_printf(".lvalAt(");
        lvalAt = true;
      } else {
        byRef = (m_context & AccessContext) &&
          (!type || !type->is(Type::KindOfString));
        arrRef = byRef && type && type->is(Type::KindOfArray);
        cg_printf(".rval%s%s(",
                  arrRef || !byRef ? "At" : "", byRef ? "Ref" : "");
        rvalAt = true;
      }
      m_offset->outputCPP(cg, ar);
      if (!type || !type->is(Type::KindOfString)) {
        if (rvalAt) {
          if (byRef && !arrRef) {
            const string &tmp = cg.getReferenceTemp();
            cg_printf(", %s", tmp.empty() ? "Variant()" : tmp.c_str());
          }
          if (!hasContext(ExistContext)) {
            cg_printf(", AccessFlags::Error"); // raise undefined index error
            sep = "_";
          }
        } else if (lvalAt) {
          if (hasContext(AccessContext)) {
            // Dont copy the array if the element is an object, or
            // is referenced.
            // This is safe in AccessContext (the parent is an ArrayElement,
            // or an ObjectProperty) because applying [] to an object will
            // either invoke OffsetGet, or fatal, and modifications to a
            // referenced element would be reflected in all copies
            // of the array anyway.
            cg_printf(", AccessFlags::CheckExist");
            sep = "_";
          }
        }
        ScalarExpressionPtr sc =
          dynamic_pointer_cast<ScalarExpression>(m_offset);
        if (!hasContext(UnsetContext) && sc && sc->isLiteralString()) {
          String s(sc->getLiteralString());
          int64 n;
          if (!s.get()->isStrictlyInteger(n)) {
            if (lvalAt || rvalAt) {
              cg_printf("%sKey", sep);
            } else {
              cg_printf(", true"); // skip toKey() at run time
            }
          }
        }
      }
      cg_printf(")");
    } else {
      cg_printf(".lvalAt()");
    }
  }
}
void SimpleVariable::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  VariableTablePtr variables = getScope()->getVariables();
  if (m_this) {
    ASSERT((getContext() & ObjectContext) == 0);
    if (hasContext(OprLValue) || hasContext(AssignmentLHS)) {
      cg_printf("throw_assign_this()");
      return;
    }
    if (variables->getAttribute(VariableTable::ContainsLDynamicVariable)) {
      ASSERT(m_sym);
      const string &namePrefix = getNamePrefix();
      cg_printf("%s%sthis",
                namePrefix.c_str(),
                variables->getVariablePrefix(m_sym));
    } else if (hasContext(DeepOprLValue) ||
               hasContext(DeepAssignmentLHS) ||
               hasContext(LValue)) {
      // $this[] op= ...; or $this[] = ...
      cg_printf("Variant(GET_THIS())");
    } else {
      ClassScopePtr cls = getOriginalClass();
      if (!cls || cls->derivedByDynamic()) {
        cg_printf("Object(GET_THIS())");
      } else {
        cg_printf("GET_THIS_TYPED(%s)", cls->getId().c_str());
      }
    }
  } else if (m_superGlobal) {
    const string &name = variables->getGlobalVariableName(ar, m_name);
    cg_printf("g->%s", name.c_str());
  } else if (m_globals) {
    cg_printf("get_global_array_wrapper()");
  } else {
    ASSERT(m_sym);
    bool sw = false;
    if (m_sym->isShrinkWrapped() &&
        m_context == Declaration) {
      ASSERT(!getFunctionScope()->isGenerator());
      TypePtr type = m_sym->getFinalType();
      type->outputCPPDecl(cg, ar, getScope());
      sw = true;
      cg_printf(" ");
    }
    const string &prefix0 = getNamePrefix();
    const char *prefix1   = variables->getVariablePrefix(m_sym);
    cg_printf("%s%s%s",
              prefix0.c_str(),
              prefix1,
              CodeGenerator::FormatLabel(m_name).c_str());
    if (m_originalSym) {
      cg.printf(" /* %s */", m_originalSym->getName().c_str());
    }
    if (sw) {
      TypePtr type = m_sym->getFinalType();
      const char *initializer = type->getCPPInitializer();
      if (initializer) {
        cg_printf(" = %s", initializer);
      }
    }
  }
}
void ArrayElementExpression::outputCPPImpl(CodeGenerator &cg,
                                           AnalysisResultPtr ar) {
  if (m_global) {
    if (!m_globalName.empty()) {
      VariableTablePtr variables = getScope()->getVariables();
      string name = variables->getGlobalVariableName(ar, m_globalName);
      cg_printf("g->%s", name.c_str());
    } else {
      cg_printf("((LVariableTable *)g)->get(");
      m_offset->outputCPP(cg, ar);
      cg_printf(")");
    }
  } else {
    TypePtr type = m_variable->getType();
    if (hasContext(UnsetContext)) {
      cg_printf("unsetLval(");
      m_variable->outputCPP(cg, ar);
      cg_printf(", ");
    } else {
      if (m_variable->is(Expression::KindOfScalarExpression) ||
          (type && (type->isInteger() ||
                    type->is(Type::KindOfDouble) ||
                    type->is(Type::KindOfObject) ||
                    type->is(Type::KindOfBoolean)))) {
        cg_printf(type && type->is(Type::KindOfString) ? "((String)" :
                  "((Variant)");
        m_variable->outputCPP(cg, ar);
        cg_printf(")");
      } else {
        m_variable->outputCPP(cg, ar);
      }
    }
    if (m_offset) {
      bool lvalAt = false;
      bool rvalAt = false;
      bool byRef = false;
      bool arrRef = false;
      const char *sep = ", AccessFlags::";
      bool isArrayType = type && type->is(Type::KindOfArray);
      bool isStringType = type && type->is(Type::KindOfString);
      bool isRealChainRoot = isChainRoot() && hasCPPCseTemp();

      TypePtr t;
      bool hasCseStore = isRealChainRoot && GetCseTempInfo(
          ar,
          static_pointer_cast<Expression>(shared_from_this()),
          t);

      if (hasContext(UnsetContext)) {
        // do nothing
      } else if (hasContext(InvokeArgument) && cg.callInfoTop() != -1) {
        ASSERT(!isRealChainRoot); // TODO: handle this case
        cg_printf(".argvalAt(cit%d->isRef(%d), ", cg.callInfoTop(), m_argNum);
      } else if (m_context & (LValue|RefValue|DeepReference)) {
        // if we see an array access element in LValue context, the
        // type inference pass will never infer its type to be a string
        ASSERT(!isStringType);
        if (isRealChainRoot && !isArrayType) {
          // chain roots for non array types (variants) should call
          // lvalRef()
          cg_printf(".lvalRef(");
        } else {
          cg_printf(".lvalAt(");
        }
        lvalAt = true;
      } else {
        byRef =
          ((m_context & AccessContext) || isRealChainRoot) && !isStringType;
        arrRef = byRef && isArrayType;
        cg_printf(".rval%s%s(",
                  arrRef || !byRef ? "At" : "", byRef ? "Ref" : "");
        rvalAt = true;
      }
      m_offset->outputCPP(cg, ar);
      if (!isStringType) {
        if (rvalAt) {
          if (byRef && !arrRef) {
            string tmp;
            if (hasCseStore) {
              tmp = string(Option::CseTempStoragePrefix) + m_cppCseTemp;
            } else {
              tmp = cg.getReferenceTemp();
            }
            cg_printf(", %s", tmp.empty() ? "Variant()" : tmp.c_str());
          }
          if (!hasContext(ExistContext)) {
            cg_printf(", AccessFlags::Error"); // raise undefined index error
            sep = "_";
          }
        } else if (lvalAt) {
          if (hasCseStore && !isArrayType) {
            cg_printf(", %s%s",
                Option::CseTempStoragePrefix, m_cppCseTemp.c_str());
          }
          if (hasContext(AccessContext)) {
            // Dont copy the array if the element is an object, or
            // is referenced.
            // This is safe in AccessContext (the parent is an ArrayElement,
            // or an ObjectProperty) because applying [] to an object will
            // either invoke OffsetGet, or fatal, and modifications to a
            // referenced element would be reflected in all copies
            // of the array anyway.
            cg_printf(", AccessFlags::CheckExist");
            sep = "_";
          }
        }
        ScalarExpressionPtr sc =
          dynamic_pointer_cast<ScalarExpression>(m_offset);
        if (!hasContext(UnsetContext) && sc && sc->isLiteralString()) {
          String s(sc->getLiteralString());
          int64 n;
          if (!s.get()->isStrictlyInteger(n)) {
            if (lvalAt || rvalAt) {
              cg_printf("%sKey", sep);
            } else {
              cg_printf(", true"); // skip toKey() at run time
            }
          }
        }
      }
      cg_printf(")");
    } else {
      cg_printf(".lvalAt()");
    }
  }
}