Exemplo n.º 1
0
void FunctionScope::RecordFunctionInfo(std::string fname,
                                       FunctionScopePtr func) {
    VariableTablePtr variables = func->getVariables();
    if (Option::WholeProgram) {
        Lock lock(s_refParamInfoLock);
        FunctionInfoPtr &info = s_refParamInfo[fname];
        if (!info) {
            info = std::make_shared<FunctionInfo>();
        }
        if (func->isStatic()) {
            info->setMaybeStatic();
        }
        if (func->isRefReturn()) {
            info->setMaybeRefReturn();
        }
        if (func->isReferenceVariableArgument()) {
            info->setRefVarArg(func->getMaxParamCount());
        }
        for (int i = 0; i < func->getMaxParamCount(); i++) {
            if (func->isRefParam(i)) info->setRefParam(i);
        }
    }
    auto limit = func->getDeclParamCount();
    for (int i = 0; i < limit; i++) {
        variables->addParam(func->getParamName(i),
                            AnalysisResultPtr(), ConstructPtr());
    }
}
Exemplo n.º 2
0
void FunctionScope::RecordRefParamInfo(string fname, FunctionScopePtr func) {
  RefParamInfoPtr info = s_refParamInfo[fname];
  if (!info) {
    info = RefParamInfoPtr(new RefParamInfo());
    s_refParamInfo[fname] = info;
  }
  if (func->isReferenceVariableArgument()) {
    info->setRefVarArg(func->getMaxParamCount());
  }
  for (int i = 0; i < func->getMaxParamCount(); i++) {
    if (func->isRefParam(i)) info->setRefParam(i);
  }
}
Exemplo n.º 3
0
void FunctionCall::markRefParams(FunctionScopePtr func,
                                 const std::string &name,
                                 bool canInvokeFewArgs) {
  ExpressionList &params = *m_params;
  if (func) {
    int mpc = func->getMaxParamCount();
    for (int i = params.getCount(); i--; ) {
      ExpressionPtr p = params[i];
      if (i < mpc ? func->isRefParam(i) :
          func->isReferenceVariableArgument()) {
        p->setContext(Expression::RefValue);
      }
    }
  } else if (!m_name.empty()) {
    FunctionScope::RefParamInfoPtr info =
      FunctionScope::GetRefParamInfo(m_name);
    if (info) {
      for (int i = params.getCount(); i--; ) {
        if (info->isRefParam(i)) {
          m_params->markParam(i, canInvokeFewArgs);
        }
      }
    }
    // If we cannot find information of the so-named function, it might not
    // exist, or it might go through __call(), either of which cannot have
    // reference parameters.
  } else {
    for (int i = params.getCount(); i--; ) {
      m_params->markParam(i, canInvokeFewArgs);
    }
  }
}
Exemplo n.º 4
0
void FunctionCall::markRefParams(FunctionScopePtr func,
                                 const std::string &fooBarName) {
  ExpressionList &params = *m_params;
  if (func) {
    int mpc = func->getMaxParamCount();
    for (int i = params.getCount(); i--; ) {
      ExpressionPtr p = params[i];
      if (i < mpc ? func->isRefParam(i) :
          func->isReferenceVariableArgument()) {
        p->setContext(Expression::RefValue);
      } else if (i < mpc && p->hasContext(RefParameter)) {
        Symbol *sym = func->getVariables()->addSymbol(func->getParamName(i));
        sym->setLvalParam();
        sym->setCallTimeRef();
      }
    }
  } else if (Option::WholeProgram && !m_origName.empty()) {
    FunctionScope::FunctionInfoPtr info =
      FunctionScope::GetFunctionInfo(m_origName);
    if (info) {
      for (int i = params.getCount(); i--; ) {
        if (info->isRefParam(i)) {
          m_params->markParam(i);
        }
      }
    }
    // If we cannot find information of the so-named function, it might not
    // exist, or it might go through __call(), either of which cannot have
    // reference parameters.
  } else {
    for (int i = params.getCount(); i--; ) {
      m_params->markParam(i);
    }
  }
}
Exemplo n.º 5
0
void FunctionScope::RecordRefParamInfo(string fname, FunctionScopePtr func) {
  RefParamInfoPtr info = s_refParamInfo[fname];
  if (!info) {
    info = RefParamInfoPtr(new RefParamInfo());
    s_refParamInfo[fname] = info;
  }
  if (func->isReferenceVariableArgument()) {
    info->setRefVarArg(func->getMaxParamCount());
  }
  VariableTablePtr variables = func->getVariables();
  for (int i = 0; i < func->getMaxParamCount(); i++) {
    if (func->isRefParam(i)) info->setRefParam(i);
    variables->addParam(func->getParamName(i),
                        TypePtr(), AnalysisResultPtr(), ConstructPtr());
  }
}
Exemplo n.º 6
0
void MethodStatement::outputSwigFFIStub(CodeGenerator &cg,
                                        AnalysisResultPtr ar) {
  FunctionScopePtr funcScope = m_funcScope.lock();
  bool varArgs = funcScope->isVariableArgument();
  bool ret = funcScope->getReturnType();
  string fname = funcScope->getId();
  string originalName = funcScope->getOriginalName();
  int ac = funcScope->getMaxParamCount();

  if (cg.getContext() == CodeGenerator::SwigFFIImpl) {
    printSource(cg);
  }

  cg.printf("Variant *%s(HphpSession *s", originalName.c_str());
  ostringstream args;
  bool first = true;
  for (int i = 0; i < ac; i++) {
    cg.printf(", Variant *a%d", i);
    if (first) first = false;
    else args << ", ";
    args << "a" << i;
  }
  if (varArgs) {
    cg.printf(", Variant *va");
    if (!first) args << ", ";
    args << "va";
  }

  if (cg.getContext() == CodeGenerator::SwigFFIDecl) {
    cg.printf(");\n\n");
    return;
  }

  cg.indentBegin(") {\n");
  if (ret) {
    cg.printf("void *result;\n");
    cg.printf("int kind = ");
    cg.printf("%s%s(&result", Option::FFIFnPrefix, fname.c_str());
    if (ac > 0 || varArgs) cg.printf(", ");
  } else {
    cg.printf("%s%s(", Option::FFIFnPrefix, fname.c_str());
  }
  cg.printf("%s);\n", args.str().c_str());
  cg.printf("Variant *ret = ");
  if (ret) {
    cg.printf("hphpBuildVariant(kind, result);\n");
    cg.printf("s->addVariant(ret);\n");
  } else {
    cg.printf("hphpBuildVariant(0, 0);\n");
    cg.printf("s->addVariant(ret);\n");
  }
  cg.printf("return ret;\n");
  cg.indentEnd("}\n\n");
}
Exemplo n.º 7
0
void ClassStatement::outputJavaFFICPPCreator(CodeGenerator &cg,
                                             AnalysisResultPtr ar,
                                             FunctionScopePtr cons) {
  ClassScopePtr cls = m_classScope.lock();
  string packageName = Option::JavaFFIRootPackage;
  int ac = cons ? cons->getMaxParamCount() : 0;
  bool varArgs = cons && cons->isVariableArgument();
  const char *clsName = getOriginalName().c_str();

  string mangledName = "Java_" + packageName + "_" + clsName + "_create";
  Util::replaceAll(mangledName, ".", "_");

  cg.printf("JNIEXPORT jlong JNICALL\n");
  cg.printf("%s(JNIEnv *env, jclass cls", mangledName.c_str());

  ostringstream args;
  bool first = true;
  if (varArgs) {
    args << ac << " + (((Variant *)va)->isNull() ? 0"
               << " : ((Variant *)va)->getArrayData()->size())";
    first = false;
  }
  for (int i = 0; i < ac; i++) {
    if (first) first = false;
    else {
      args << ", ";
    }
    cg.printf(", jlong a%d", i);
    args << "*(Variant *)a" << i;
  }
  if (varArgs) {
    if (!first) {
      args << ", ";
    }
    cg.printf(", jlong va");
    args << "((Variant *)va)->toArray()";
  }

  if (cg.getContext() == CodeGenerator::JavaFFICppDecl) {
    // java_stubs.h
    cg.printf(");\n\n");
    return;
  }

  cg.indentBegin(") {\n");
  cg.printf("ObjectData *obj = ");
  cg.printf("(NEW(%s%s)())->create(%s);\n",
            Option::ClassPrefix, cls->getId().c_str(), args.str().c_str());
  cg.printf("obj->incRefCount();\n");
  cg.printf("return (jlong)(NEW(Variant)(obj));\n");
  cg.indentEnd("}\n\n");
}
void ObjectMethodExpression::analyzeProgram(AnalysisResultPtr ar) {
  m_params->analyzeProgram(ar);
  m_object->analyzeProgram(ar);
  m_nameExp->analyzeProgram(ar);

  if (ar->getPhase() == AnalysisResult::AnalyzeAll) {
    FunctionScopePtr func = m_funcScope;
    if (!func && m_object->isThis() && !m_name.empty()) {
      ClassScopePtr cls = ar->getClassScope();
      if (cls) {
        m_classScope = cls;
        m_funcScope = func = cls->findFunction(ar, m_name, true, true);
        if (!func) {
          cls->addMissingMethod(m_name);
        }
      }
    }

    ExpressionList &params = *m_params;
    if (func) {
      int mpc = func->getMaxParamCount();
      for (int i = params.getCount(); i--; ) {
        ExpressionPtr p = params[i];
        if (i < mpc ? func->isRefParam(i) :
            func->isReferenceVariableArgument()) {
          p->setContext(Expression::RefValue);
        }
      }
    } else if (!m_name.empty()) {
      FunctionScope::RefParamInfoPtr info =
        FunctionScope::GetRefParamInfo(m_name);
      if (info) {
        for (int i = params.getCount(); i--; ) {
          if (info->isRefParam(i)) {
            m_params->markParam(i, canInvokeFewArgs());
          }
        }
      }
      // If we cannot find information of the so-named function, it might not
      // exist, or it might go through __call(), either of which cannot have
      // reference parameters.
    } else {
      for (int i = params.getCount(); i--; ) {
        m_params->markParam(i, canInvokeFewArgs());
      }
    }
  }
}
Exemplo n.º 9
0
void ClassStatement::outputJavaFFIConstructor(CodeGenerator &cg,
                                              AnalysisResultPtr ar,
                                              FunctionScopePtr cons) {
  int ac = cons ? cons->getMaxParamCount() : 0;
  bool varArgs = cons && cons->isVariableArgument();

  // generates the constructor
  cg_printf("public %s(", getOriginalName().c_str());
  ostringstream args;
  ostringstream params;
  bool first = true;
  for (int i = 0; i < ac; i++) {
    if (first) {
      first = false;
    }
    else {
      cg_printf(", ");
      args << ", ";
      params << ", ";
    }
    cg_printf("HphpVariant a%d", i);
    args << "a" << i << ".getVariantPtr()";
    params << "long a" << i;
  }
  if (varArgs) {
    if (!first) {
      cg_printf(", ");
      args << ", ";
      params << ", ";
    }
    cg_printf("HphpVariant va");
    args << "va.getVariantPtr()";
    params << "long va";
  }
  cg_indentBegin(") {\n");
  cg_printf("this(create(%s));\n", args.str().c_str());
  cg_indentEnd("}\n\n");

  // generates the native method stub for creating the object
  cg_printf("private static native long create(%s);\n\n",
            params.str().c_str());
}
Exemplo n.º 10
0
/**
 * Generates the Java stub method for a PHP toplevel function.
 *
 * @author qixin
 */
void MethodStatement::outputJavaFFIStub(CodeGenerator &cg,
                                        AnalysisResultPtr ar) {
  FunctionScopePtr funcScope = m_funcScope.lock();
  bool varArgs = funcScope->isVariableArgument();
  bool ret = funcScope->getReturnType();
  bool inClass = !m_className.empty();
  bool isStatic = !inClass || m_modifiers->isStatic();
  string fname = funcScope->getId();
  string originalName = funcScope->getOriginalName();
  if (originalName.length() < fname.length()) {
    // if there are functions of the same name, fname may contain "$$..."
    // in the end
    originalName += fname.substr(originalName.length());
  }

  if (originalName == "clone"     || originalName == "equals"
   || originalName == "finalize"  || originalName == "getClass"
   || originalName == "hashCode"  || originalName == "notify"
   || originalName == "notifyAll" || originalName == "toString"
   || originalName == "wait") {
    // not to clash with Java method names
    originalName = "_" + originalName;
  }

  if (cg.getContext() == CodeGenerator::JavaFFIInterface
   || inClass && m_modifiers->isAbstract()) {
    // skip all the abstract methods, because php overriding is not very
    // compatible with Java
    return;
  }

  if (!inClass) printSource(cg);

  // This Java method extracts the Variant pointer from the HphpVariant
  // argument as a 64-bit integer, and then calls the native version.
  bool exposeNative = false;
  int ac = funcScope->getMaxParamCount();
  if (ac > 0 || varArgs || !isStatic || !ret && inClass
   || cg.getContext() == CodeGenerator::JavaFFIInterface) {
    // make methods always return something, so that they can override
    // each other
    cg.printf("public %s%s %s(",
              (isStatic ? "static " : ""),
              (!ret && !inClass ? "void" : "HphpVariant"),
              originalName.c_str());
    ostringstream args;
    bool first = true;
    if (!isStatic) {
      // instance method has an additional parameter
      args << "this.getVariantPtr()";
    }
    for (int i = 0; i < ac; i++) {
      if (first) {
        first = false;
        if (!isStatic) args << ", ";
      }
      else {
        cg.printf(", ");
        args << ", ";
      }
      cg.printf("HphpVariant a%d", i);
      args << "a" << i << ".getVariantPtr()";
    }
    if (varArgs) {
      if (!first) {
        cg.printf(", ");
        args << ", ";
      }
      else if (!isStatic) {
        args << ", ";
      }
      cg.printf("HphpVariant va");
      args << "va.getVariantPtr()";
    }

    if (cg.getContext() == CodeGenerator::JavaFFIInterface) {
      cg.printf(");\n\n");
      return;
    }

    cg.indentBegin(") {\n");
    cg.printf("%s%s_native(%s);\n", (ret ? "return " : ""),
              originalName.c_str(),
              args.str().c_str());
    if (!ret && inClass) {
      cg.printf("return HphpNull.phpNull();\n");
    }
    cg.indentEnd("}\n\n");
  }
  else {
    exposeNative = true;
  }

  // the native method stub
  cg.printf("%s %snative %s %s%s(",
            (exposeNative ? "public" : "private"),
            (isStatic ? "static " : ""), (ret ? "HphpVariant" : "void"),
            originalName.c_str(),
            (exposeNative ? "" : "_native"));
  bool first = true;
  if (!isStatic) {
    // instance method has an additional parameter
    cg.printf("long targetPtr");
    first = false;
  }
  for (int i = 0; i < ac; i++) {
    if (first) first = false;
    else cg.printf(", ");
    cg.printf("long a%d", i);
  }
  if (varArgs) {
    if (!first) cg.printf(", ");
    cg.printf("long va");
  }
  cg.printf(");\n\n");
}
Exemplo n.º 11
0
void MethodStatement::outputHSFFIStub(CodeGenerator &cg, AnalysisResultPtr ar) {
  if (!m_className.empty()) {
    // Haskell currently doesn't support FFI for class methods.
    return;
  }

  FunctionScopePtr funcScope = m_funcScope.lock();
  bool varArgs = funcScope->isVariableArgument();
  bool ret = funcScope->getReturnType();
  string fname = funcScope->getId().c_str();
  cg.indentBegin("foreign import ccall \"stubs.h %s%s\" %s%s\n",
                 Option::FFIFnPrefix,
                 fname.c_str(),
                 Option::FFIFnPrefix,
                 fname.c_str());
  cg.printf(":: ");
  if (ret) {
    cg.printf("PtrPtr a -> ");
  }
  int ac = funcScope->getMaxParamCount();
  for (int i = 0; i < ac; ++i) {
    cg.printf("HphpVariantPtr -> ");
  }
  if (varArgs) {
    cg.printf("HphpVariantPtr -> ");
  }
  if (ret) {
    cg.printf("IO CInt");
  } else {
    cg.printf("IO ()");
  }
  cg.indentEnd("\n");

  cg.printf("f_%s :: ", fname.c_str());
  bool first = true;
  if (ac > 0) {
    cg.printf("(");
  }
  for (int i = 0; i < ac; ++i) {
    if (first) {
      first = false;
    } else {
      cg.printf(", ");
    }
    cg.printf("VariantAble a%d", i);
  }
  if (ac > 0) {
    cg.printf(") => ");
  }
  for (int i = 0; i < ac; ++i) {
    cg.printf("a%d -> ", i);
  }
  if (varArgs) {
    cg.printf("[Variant] -> ");
  }
  if (ret) {
    cg.printf("IO Variant");
  } else {
    cg.printf("IO ()");
  }
  cg.printf("\n");
  cg.printf("f_%s ", fname.c_str());
  for (int i = 0; i < ac; ++i) {
    cg.printf("v%d ", i);
  }
  if (varArgs) {
    cg.printf("va ");
  }
  cg.indentBegin("=%s\n", ret ? " alloca (\\pres ->" : "");
  for (int i = 0; i < ac; ++i) {
    cg.indentBegin("withExportedVariant (toVariant v%d) (\\p%d ->\n", i, i);
  }
  if (varArgs) {
    cg.indentBegin("withVParamList va (\\pva ->\n");
  }
  cg.indentBegin("do\n");
  cg.printf("%sffi_%s", ret ? "t <- " : "", fname.c_str());
  if (ret) {
    cg.printf(" pres");
  }
  for (int i = 0; i < ac; ++i) {
    cg.printf(" p%d", i);
  }
  if (varArgs) {
    cg.printf(" pva");
  }
  if (ret) {
    cg.printf("\n");
    cg.printf("ppres <- peek pres\n");
    cg.printf("buildVariant (fromIntegral t) ppres");
  }
  cg.indentEnd(""); // end do
  if (varArgs) {
    cg.indentEnd(")"); // end varargs
  }
  for (int i = 0; i < ac; ++i) {
    cg.indentEnd(")"); // end wEV i
  }
  if (ret) {
    cg.indentEnd(")"); // end alloca
  } else {
    cg.indentEnd("");
  }
  cg.printf("\n");
  return;
}
Exemplo n.º 12
0
void MethodStatement::outputCPPFFIStub(CodeGenerator &cg,
                                       AnalysisResultPtr ar) {
  FunctionScopePtr funcScope = m_funcScope.lock();
  bool varArgs = funcScope->isVariableArgument();
  bool ret = funcScope->getReturnType();
  string fname = funcScope->getId();
  bool inClass = !m_className.empty();
  bool isStatic = !inClass || m_modifiers->isStatic();

  if (inClass && m_modifiers->isAbstract()) {
    return;
  }

  if (fname == "__lval" || fname == "__offsetget_lval") {
    return;
  }

  if (ret) {
    cg.printf("int");
  } else {
    cg.printf("void");
  }
  cg.printf(" %s%s%s(", Option::FFIFnPrefix,
            (inClass ? (m_className + "_cls_").c_str() : ""), fname.c_str());
  if (ret) {
    cg.printf("void** res");
  }

  bool first = !ret;

  if (!isStatic) {
    // instance methods need one additional parameter for the target
    if (first) {
      first = false;
    }
    else {
      cg.printf(", ");
    }
    cg.printf("Variant *target");
  }

  int ac = funcScope->getMaxParamCount();
  for (int i = 0; i < ac; ++i) {
    if (first) {
      first = false;
    } else {
      cg.printf(", ");
    }
    cg.printf("Variant *a%d", i);
  }
  if (varArgs) {
    if (!first) {
      cg.printf(", ");
    }
    cg.printf("Variant *va");
  }
  cg.printf(")");
  if (cg.getContext() == CodeGenerator::CppFFIDecl) {
    cg.printf(";\n");
  } else {
    cg.indentBegin(" {\n");
    if (ret) {
      cg.printf("return hphp_ffi_exportVariant(");
    }

    if (!inClass) {
      // simple function call
      cg.printf("%s%s(", Option::FunctionPrefix, fname.c_str());
    }
    else if (isStatic) {
      // static method call
      cg.printf("%s%s::%s%s(", Option::ClassPrefix, m_className.c_str(),
                Option::MethodPrefix, fname.c_str());
    }
    else {
      // instance method call
      cg.printf("dynamic_cast<%s%s *>(target->getObjectData())->",
                Option::ClassPrefix, m_className.c_str());
      cg.printf("%s%s(", Option::MethodPrefix, fname.c_str());
    }

    first = true;
    if (varArgs) {
      cg.printf("%d + (va->isNull() ? 0 : va->getArrayData()->size())", ac);
      first = false;
    }

    for (int i = 0; i < ac; ++i) {
      if (first) {
        first = false;
      } else {
        cg.printf(", ");
      }
      cg.printf("*a%d", i);
    }
    if (varArgs) {
      cg.printf(", va->toArray()");
    }
    if (ret) {
      cg.printf("), res");
    }
    cg.printf(");\n");
    cg.indentEnd("} /* function */\n");
  }
  return;
}
Exemplo n.º 13
0
void MethodStatement::outputJavaFFICPPStub(CodeGenerator &cg,
                                           AnalysisResultPtr ar) {
  // TODO translate PHP namespace once that is supported
  string packageName = Option::JavaFFIRootPackage;

  FunctionScopePtr funcScope = m_funcScope.lock();
  bool varArgs = funcScope->isVariableArgument();
  bool ret = funcScope->getReturnType();
  bool inClass = !m_className.empty();
  bool isStatic = !inClass || m_modifiers->isStatic();
  string fname = funcScope->getId();
  int ac = funcScope->getMaxParamCount();
  bool exposeNative = !(ac > 0 || varArgs || !isStatic || !ret && inClass);

  if (inClass && m_modifiers->isAbstract()) {
    // skip all the abstract methods, because hphp doesn't generate code
    // for them
    return;
  }

  if (fname == "__lval" || fname == "__offsetget_lval") return;

  const char *clsName;
  if (inClass) {
    // uses capitalized original class name
    ClassScopePtr cls = ar->findClass(m_className);
    clsName = cls->getOriginalName();
  }
  else {
    clsName = "HphpMain";
  }
  string mangledName = "Java." + packageName + "." + clsName + "." + fname
    + (exposeNative ? "" : "_native");
  // all the existing "_" are replaced as "_1"
  Util::replaceAll(mangledName, "_", "_1");
  Util::replaceAll(mangledName, ".", "_");

  cg.printf("JNIEXPORT %s JNICALL\n", ret ? "jobject" : "void");
  cg.printf("%s(JNIEnv *env, %s target", mangledName.c_str(),
            (isStatic ? "jclass" : "jobject"));

  ostringstream args;
  bool first = true;
  if (!isStatic) {
    // instance method also gets an additional argument, which is a Variant
    // pointer to the target, encoded in int64
    first = false;
    cg.printf(", jlong targetPtr");
    args << "(Variant *)targetPtr";
  }
  for (int i = 0; i < ac; i++) {
    cg.printf(", jlong a%d", i);
    if (first) first = false;
    else args << ", ";
    args << "(Variant *)a" << i;
  }
  if (varArgs) {
    cg.printf(", jlong va");
    if (!first) args << ", ";
    args << "(Variant *)va";
  }

  if (cg.getContext() == CodeGenerator::JavaFFICppDecl) {
    // java_stubs.h
    cg.printf(");\n\n");
    return;
  }

  cg.indentBegin(") {\n");

  // support static/instance methods
  if (ret) {
    cg.printf("void *result;\n");
    cg.printf("int kind = ");
    cg.printf("%s%s%s(&result",
              Option::FFIFnPrefix,
              (inClass ? (m_className + "_cls_").c_str() : ""), fname.c_str());
    if (!isStatic || ac > 0 || varArgs) cg.printf(", ");
  }
  else {
    cg.printf("%s%s%s(", Option::FFIFnPrefix,
                         (inClass ? (m_className + "_cls_").c_str() : ""),
                         fname.c_str());
  }
  cg.printf("%s);\n", args.str().c_str());
  if (ret) {
    if (!inClass) {
      // HphpMain extends hphp.Hphp.
      cg.printf("jclass hphp = env->GetSuperclass(target);\n");
    }
    else {
      cg.printf("jclass hphp = env->FindClass(\"hphp/Hphp\");\n");
    }
    cg.printf("return exportVariantToJava(env, hphp, result, kind);\n");
  }

  cg.indentEnd("} /* function */\n\n");
}