Esempio n. 1
0
int analyzeTarget(const ProgramOptions &po, AnalysisResultPtr ar) {
  int ret = 0;

  if (!po.noTypeInference) {
    Option::GenerateInferredTypes = true;
  }
  if (Option::GenerateInferredTypes) {
    Timer timer(Timer::WallTime, "inferring types");
    ar->inferTypes();
  }
  return ret;
}
Esempio n. 2
0
bool BuiltinSymbols::Load(AnalysisResultPtr ar, bool extOnly /* = false */) {
    if (Loaded) return true;
    Loaded = true;

    // load extension functions first, so system/classes may call them
    ParseExtFunctions(ar, ExtensionFunctions, false);
    AnalysisResultPtr ar2 = AnalysisResultPtr(new AnalysisResult());
    s_variables = VariableTablePtr(new VariableTable(*ar2.get()));
    s_constants = ConstantTablePtr(new ConstantTable(*ar2.get()));

    // parse all PHP files under system/classes
    if (!extOnly) {
        ar = AnalysisResultPtr(new AnalysisResult());
        ar->loadBuiltinFunctions();
        string slib = systemlib_path();
        if (slib.empty()) {
            for (const char **cls = SystemClasses; *cls; cls++) {
                string phpBaseName = "/system/classes/";
                phpBaseName += *cls;
                phpBaseName += ".php";
                Parse(ar, phpBaseName, Option::GetSystemRoot() + phpBaseName);
            }
        } else {
            Parse(ar, slib, slib);
        }
        ar->analyzeProgram(true);
        ar->inferTypes();
        const StringToFileScopePtrMap &files = ar->getAllFiles();
        for (StringToFileScopePtrMap::const_iterator iterFile = files.begin();
                iterFile != files.end(); iterFile++) {
            const StringToClassScopePtrVecMap &classes =
                iterFile->second->getClasses();
            for (StringToClassScopePtrVecMap::const_iterator iter = classes.begin();
                    iter != classes.end(); ++iter) {
                assert(iter->second.size() == 1);
                iter->second[0]->setSystem();
                assert(!s_classes[iter->first]);
                s_classes[iter->first] = iter->second[0];
            }
        }
    } else {
        NoSuperGlobals = true;
    }

    // load extension constants, classes and dynamics
    ParseExtConsts(ar, ExtensionConsts, false);
    ParseExtClasses(ar, ExtensionClasses, false);
    for (unsigned int i = 0; i < Option::SepExtensions.size(); i++) {
        Option::SepExtensionOptions &options = Option::SepExtensions[i];
        string soname = options.soname;
        if (soname.empty()) {
            soname = string("lib") + options.name + ".so";
        }
        if (!options.lib_path.empty()) {
            soname = options.lib_path + "/" + soname;
        }
        if (!LoadSepExtensionSymbols(ar, options.name, soname)) {
            return false;
        }
    }

    if (!extOnly) {
        Array constants = ClassInfo::GetSystemConstants();
        LocationPtr loc(new Location);
        for (ArrayIter it = constants.begin(); it; ++it) {
            CVarRef key = it.first();
            if (!key.isString()) continue;
            std::string name = key.toCStrRef().data();
            if (s_constants->getSymbol(name)) continue;
            if (name == "true" || name == "false" || name == "null") continue;
            CVarRef value = it.secondRef();
            if (!value.isInitialized() || value.isObject()) continue;
            ExpressionPtr e = Expression::MakeScalarExpression(ar2, ar2, loc, value);
            TypePtr t =
                value.isNull()    ? Type::Null    :
                value.isBoolean() ? Type::Boolean :
                value.isInteger() ? Type::Int64   :
                value.isDouble()  ? Type::Double  :
                value.isArray()   ? Type::Array   : Type::Variant;

            s_constants->add(key.toCStrRef().data(), t, e, ar2, e);
        }
        s_variables = ar2->getVariables();
        for (int i = 0, n = NumGlobalNames(); i < n; ++i) {
            s_variables->add(GlobalNames[i], Type::Variant, false, ar,
                             ConstructPtr(), ModifierExpressionPtr());
        }
    }
    s_constants->setDynamic(ar, "SID", true);

    return true;
}
bool BuiltinSymbols::Load(AnalysisResultPtr ar, bool extOnly /* = false */) {
  if (Loaded) return true;
  Loaded = true;

  // Build function scopes for some of the runtime helper functions
  // declared in "runtime/base/builtin_functions.h"
  const char **helper = HelperFunctions;
  while (*helper) {
    FunctionScopePtr f = ParseHelperFunction(ar, helper);
    ASSERT(!s_helperFunctions[f->getName()]);
    s_helperFunctions[f->getName()] = f;
  }

  // load extension functions first, so system/classes may call them
  ParseExtFunctions(ar, ExtensionFunctions, false);
  AnalysisResultPtr ar2;

  // parse all PHP files under system/classes
  if (!extOnly) {
    ar = AnalysisResultPtr(new AnalysisResult());
    ar->loadBuiltinFunctions();
    for (const char **cls = SystemClasses; *cls; cls++) {
      string phpBaseName = "/system/classes/";
      phpBaseName += *cls;
      phpBaseName += ".php";
      string phpFileName = Option::GetSystemRoot() + phpBaseName;
      const char *baseName = s_strings.add(phpBaseName.c_str());
      const char *fileName = s_strings.add(phpFileName.c_str());
      try {
        Scanner scanner(fileName, Option::ScannerType);
        Compiler::Parser parser(scanner, baseName, ar);
        if (!parser.parse()) {
          Logger::Error("Unable to parse file %s: %s", fileName,
                        parser.getMessage().c_str());
          ASSERT(false);
        }
      } catch (FileOpenException &e) {
        Logger::Error("%s", e.getMessage().c_str());
      }
    }
    ar->analyzeProgram(true);
    ar->inferTypes();
    const StringToFileScopePtrMap &files = ar->getAllFiles();
    for (StringToFileScopePtrMap::const_iterator iterFile = files.begin();
         iterFile != files.end(); iterFile++) {
      const StringToClassScopePtrVecMap &classes =
        iterFile->second->getClasses();
      for (StringToClassScopePtrVecMap::const_iterator iter = classes.begin();
           iter != classes.end(); ++iter) {
        ASSERT(iter->second.size() == 1);
        iter->second[0]->setSystem();
        ASSERT(!s_classes[iter->first]);
        s_classes[iter->first] = iter->second[0];
      }
    }

    // parse globals/variables.php and globals/constants.php
    NoSuperGlobals = true;
    s_variables = LoadGlobalSymbols("symbols.php")->getVariables();
    ar2 = LoadGlobalSymbols("constants.php");
    const FileScopePtrVec &fileScopes = ar2->getAllFilesVector();
    if (!fileScopes.empty()) {
      s_constants = fileScopes[0]->getConstants();
    } else {
      Logger::Error("Couldn't load constants.php");
      return false;
    }
    NoSuperGlobals = false;
  } else {
    ar2 = AnalysisResultPtr(new AnalysisResult());
    s_variables = VariableTablePtr(new VariableTable(*ar2.get()));
    s_constants = ConstantTablePtr(new ConstantTable(*ar2.get()));
    NoSuperGlobals = true;
  }
  s_constants->setDynamic(ar, "SID", true);

  // load extension constants, classes and dynamics
  ParseExtConsts(ar, ExtensionConsts, false);
  ParseExtClasses(ar, ExtensionClasses, false);
  for (unsigned int i = 0; i < Option::SepExtensions.size(); i++) {
    Option::SepExtensionOptions &options = Option::SepExtensions[i];
    string soname = options.soname;
    if (soname.empty()) {
      soname = string("lib") + options.name + ".so";
    }
    if (!options.lib_path.empty()) {
      soname = options.lib_path + "/" + soname;
    }
    if (!LoadSepExtensionSymbols(ar, options.name, soname)) {
      return false;
    }
  }

  return true;
}
Esempio n. 4
0
bool BuiltinSymbols::Load(AnalysisResultPtr ar, bool extOnly /* = false */) {
  if (Loaded) return true;
  Loaded = true;

  if (g_context.isNull()) init_thread_locals();
  ClassInfo::Load();

  // load extension functions first, so system/classes may call them
  ImportExtFunctions(ar, s_functions, ClassInfo::GetSystem());
  AnalysisResultPtr ar2 = AnalysisResultPtr(new AnalysisResult());
  s_variables = VariableTablePtr(new VariableTable(*ar2.get()));
  s_constants = ConstantTablePtr(new ConstantTable(*ar2.get()));

  // parse all PHP files under system/classes
  if (!extOnly) {
    ar = AnalysisResultPtr(new AnalysisResult());
    ar->loadBuiltinFunctions();
    string slib = get_systemlib();

    Scanner scanner(slib.c_str(), slib.size(),
                    Option::ScannerType, "systemlib.php");
    Compiler::Parser parser(scanner, "systemlib.php", ar);
    if (!parser.parse()) {
      Logger::Error("Unable to parse systemlib.php: %s",
                    parser.getMessage().c_str());
      assert(false);
    }

    ar->analyzeProgram(true);
    ar->inferTypes();
    const StringToFileScopePtrMap &files = ar->getAllFiles();
    for (StringToFileScopePtrMap::const_iterator iterFile = files.begin();
         iterFile != files.end(); iterFile++) {
      const StringToClassScopePtrVecMap &classes =
        iterFile->second->getClasses();
      for (StringToClassScopePtrVecMap::const_iterator iter = classes.begin();
           iter != classes.end(); ++iter) {
        assert(iter->second.size() == 1);
        iter->second[0]->setSystem();
        assert(!s_classes[iter->first]);
        s_classes[iter->first] = iter->second[0];
      }
    }
  } else {
    NoSuperGlobals = true;
  }

  // load extension constants, classes and dynamics
  ImportExtConstants(ar, s_constants, ClassInfo::GetSystem());
  ImportExtClasses(ar);

  if (!extOnly) {
    Array constants = ClassInfo::GetSystemConstants();
    LocationPtr loc(new Location);
    for (ArrayIter it = constants.begin(); it; ++it) {
      CVarRef key = it.first();
      if (!key.isString()) continue;
      std::string name = key.toCStrRef().data();
      if (s_constants->getSymbol(name)) continue;
      if (name == "true" || name == "false" || name == "null") continue;
      CVarRef value = it.secondRef();
      if (!value.isInitialized() || value.isObject()) continue;
      ExpressionPtr e = Expression::MakeScalarExpression(ar2, ar2, loc, value);
      TypePtr t =
        value.isNull()    ? Type::Null    :
        value.isBoolean() ? Type::Boolean :
        value.isInteger() ? Type::Int64   :
        value.isDouble()  ? Type::Double  :
        value.isArray()   ? Type::Array   : Type::Variant;

      s_constants->add(key.toCStrRef().data(), t, e, ar2, e);
    }
    s_variables = ar2->getVariables();
    for (int i = 0, n = NumGlobalNames(); i < n; ++i) {
      s_variables->add(GlobalNames[i], Type::Variant, false, ar,
                       ConstructPtr(), ModifierExpressionPtr());
    }
  }
  s_constants->setDynamic(ar, "SID", true);

  return true;
}
Esempio n. 5
0
int cppTarget(const ProgramOptions &po, AnalysisResultPtr ar,
              bool allowSys /* = true */) {
  int ret = 0;
  int clusterCount = po.clusterCount;
  // format
  CodeGenerator::Output format = CodeGenerator::InvalidOutput;
  if (po.format == "file") {
    clusterCount = 0;
    format = CodeGenerator::FileCPP;
  } else if (po.format == "cluster") {
    format = CodeGenerator::ClusterCPP;
  } else if (po.format == "sys" && allowSys) {
    clusterCount = 0;
    format = CodeGenerator::SystemCPP;
    ar->setSystem();
  } else if (po.format == "exe" || po.format == "lib") {
    format = CodeGenerator::ClusterCPP;
  }

  if (format == CodeGenerator::InvalidOutput) {
    Logger::Error("Unknown format for CPP target: %s", po.format.c_str());
    return 1;
  }

  if (!po.noTypeInference) {
    Option::GenerateInferredTypes = true;
  }
  if (Option::PreOptimization) {
    Timer timer(Timer::WallTime, "pre-optimizing");
    ar->preOptimize();
  }


  if (!Option::RTTIOutputFile.empty()) {
    if (!po.rttiDirectory.empty()) {
      Option::UseRTTIProfileData = true;
      ar->cloneRTTIFuncs(po.rttiDirectory.c_str());
    } else {
      Option::GenRTTIProfileData = true;
    }
  }

  if (Option::GenerateInferredTypes) {
    Timer timer(Timer::WallTime, "inferring types");
    ar->inferTypes();
  }
  if (Option::PostOptimization) {
    Timer timer(Timer::WallTime, "post-optimizing");
    ar->postOptimize();
  }
  ar->analyzeProgramFinal();
  //MethodSlot::genMethodSlot(ar);

  {
    Timer timer(Timer::WallTime, "creating CPP files");
    if (po.syncDir.empty()) {
      ar->setOutputPath(po.outputDir);
      ar->outputAllCPP(format, clusterCount, NULL);
    } else {
      ar->setOutputPath(po.syncDir);
      ar->outputAllCPP(format, clusterCount, &po.outputDir);
      Util::syncdir(po.outputDir, po.syncDir);
      boost::filesystem::remove_all(po.syncDir);
    }
  }

  return ret;
}
Esempio n. 6
0
int phpTarget(const ProgramOptions &po, AnalysisResultPtr ar) {
  int ret = 0;

  // format
  int formatCount = 0;
  if (po.format.find("pickled") != string::npos) {
    Option::GeneratePickledPHP = true;
    formatCount++;
  }
  if (po.format.find("inlined") != string::npos) {
    Option::GenerateInlinedPHP = true;
    formatCount++;
  }
  if (po.format.find("trimmed") != string::npos) {
    Option::GenerateTrimmedPHP = true;
    formatCount++;
  }
  if (po.format.find("typeinfo") != string::npos) {
    Option::GenerateInferredTypes = true;
  }
  if (formatCount == 0) {
    Logger::Error("Unknown format for PHP target: %s", po.format.c_str());
    return 1;
  }

  // analyze
  if (Option::GenerateInferredTypes || Option::ConvertSuperGlobals) {
    Logger::Info("inferring types...");
    ar->inferTypes();
  }

  // generate
  ar->setOutputPath(po.outputDir);
  if (Option::GeneratePickledPHP) {
    Logger::Info("creating pickled PHP files...");
    string outputDir = po.outputDir;
    if (formatCount > 1) outputDir += "/pickled";
    mkdir(outputDir.c_str(), 0777);
    ar->outputAllPHP(CodeGenerator::PickledPHP);
  }
  if (Option::GenerateInlinedPHP) {
    Logger::Info("creating inlined PHP files...");
    string outputDir = po.outputDir;
    if (formatCount > 1) outputDir += "/inlined";
    mkdir(outputDir.c_str(), 0777);
    if (!ar->outputAllPHP(CodeGenerator::InlinedPHP)) {
      ret = -1;
    }
  }
  if (Option::GenerateTrimmedPHP) {
    Logger::Info("creating trimmed PHP files...");
    string outputDir = po.outputDir;
    if (formatCount > 1) outputDir += "/trimmed";
    mkdir(outputDir.c_str(), 0777);
    if (!ar->outputAllPHP(CodeGenerator::TrimmedPHP)) {
      ret = -1;
    }
  }

  return ret;
}