/// HSAILTargetMachine ctor -
///
HSAILTargetMachine::HSAILTargetMachine(const Target &T, StringRef TT,
    StringRef CPU, StringRef FS,const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM,CodeGenOpt::Level OL, bool is64bitTarget )
:
  LLVMTargetMachine(T, TT, CPU, FS,Options, RM, CM,OL),
  Subtarget(TT, CPU, FS, is64bitTarget),
  //  DLInfo(Subtarget.getDataLayout()),
  FrameLowering(TargetFrameLowering::StackGrowsUp,
      Subtarget.getStackAlignment(), 0),
  //  InstrInfo(*this),
  //  TLInfo(*this), 
  IntrinsicInfo(this)
 {
     if (FileType == CGFT_AssemblyFile) {
       if (FileType.getNumOccurrences() == 0) {
         // LLVM's default is CGFT_AssemblyFile. HSAIL default is binary BRIG,
         // thus we need to change output to CGFT_AssemblyFile, unless text
         // assembly was explicitly requested by the command line switch.
         HSAILFileType = FileType = CGFT_ObjectFile;
       }
     }

     setAsmVerbosityDefault(true);

     // disable use of the .loc directive, because only by 
     // setting this to false does DwarfDebug generate the .debug_line
     // section
     //
     setMCUseLoc(false);

}
CompilationDatabase *autoDetectCompilations(std::string &ErrorMessage) {
  // Auto-detect a compilation database from BuildPath.
  if (BuildPath.getNumOccurrences() > 0)
    return CompilationDatabase::autoDetectFromDirectory(BuildPath,
                                                        ErrorMessage);
  // Try to auto-detect a compilation database from the first source.
  if (!SourcePaths.empty()) {
    if (CompilationDatabase *Compilations =
            CompilationDatabase::autoDetectFromSource(SourcePaths[0],
                                                      ErrorMessage)) {
      // FIXME: just pass SourcePaths[0] once getCompileCommands supports
      // non-absolute paths.
      SmallString<64> Path(SourcePaths[0]);
      llvm::sys::fs::make_absolute(Path);
      std::vector<CompileCommand> Commands =
          Compilations->getCompileCommands(Path);
      // Ignore a detected compilation database that doesn't contain source0
      // since it is probably an unrelated compilation database.
      if (!Commands.empty())
        return Compilations;
    }
    // Reset ErrorMessage since a fix compilation database will be created if
    // it fails to detect one from source.
    ErrorMessage = "";
    // If no compilation database can be detected from source then we create a
    // fixed compilation database with c++11 support.
    std::string CommandLine[] = { "-std=c++11" };
    return new FixedCompilationDatabase(".", CommandLine);
  }

  ErrorMessage = "Could not determine sources to transform";
  return 0;
}
Пример #3
0
void updateArgIfSet(llvm::cl::opt<T> &argValue, const llvm::Optional<T> &configValue)
{
    if (configValue.hasValue() && argValue.getNumOccurrences() == 0)
    {
        argValue.setValue(configValue.getValue());
    }
}
/// \brief Extract the minimum compiler versions as requested on the command
/// line by the switch \c -for-compilers.
///
/// \param ProgName The name of the program, \c argv[0], used to print errors.
/// \param Error If an error occur while parsing the versions this parameter is
/// set to \c true, otherwise it will be left untouched.
static CompilerVersions handleSupportedCompilers(const char *ProgName,
                                                 bool &Error) {
  if (SupportedCompilers.getNumOccurrences() == 0)
    return CompilerVersions();
  CompilerVersions RequiredVersions;
  llvm::SmallVector<llvm::StringRef, 4> Compilers;

  llvm::StringRef(SupportedCompilers).split(Compilers, ",");

  for (llvm::SmallVectorImpl<llvm::StringRef>::iterator I = Compilers.begin(),
                                                        E = Compilers.end();
       I != E; ++I) {
    llvm::StringRef Compiler, VersionStr;
    std::tie(Compiler, VersionStr) = I->split('-');
    Version *V = llvm::StringSwitch<Version *>(Compiler)
        .Case("clang", &RequiredVersions.Clang)
        .Case("gcc", &RequiredVersions.Gcc).Case("icc", &RequiredVersions.Icc)
        .Case("msvc", &RequiredVersions.Msvc).Default(NULL);

    if (V == NULL) {
      llvm::errs() << ProgName << ": " << Compiler
                   << ": unsupported platform\n";
      Error = true;
      continue;
    }
    if (VersionStr.empty()) {
      llvm::errs() << ProgName << ": " << *I
                   << ": missing version number in platform\n";
      Error = true;
      continue;
    }

    Version Version = Version::getFromString(VersionStr);
    if (Version.isNull()) {
      llvm::errs()
          << ProgName << ": " << *I
          << ": invalid version, please use \"<major>[.<minor>]\" instead of \""
          << VersionStr << "\"\n";
      Error = true;
      continue;
    }
    // support the lowest version given
    if (V->isNull() || Version < *V)
      *V = Version;
  }
  return RequiredVersions;
}
Пример #5
0
static void addMscrtLibs(std::vector<std::string> &args) {
  llvm::StringRef mscrtlibName = mscrtlib;
  if (mscrtlibName.empty()) {
    // default to static release variant
    mscrtlibName =
        staticFlag || staticFlag.getNumOccurrences() == 0 ? "libcmt" : "msvcrt";
  }

  args.push_back(("/DEFAULTLIB:" + mscrtlibName).str());

  const bool isStatic = mscrtlibName.startswith_lower("libcmt");
  const bool isDebug =
      mscrtlibName.endswith_lower("d") || mscrtlibName.endswith_lower("d.lib");

  const llvm::StringRef prefix = isStatic ? "lib" : "";
  const llvm::StringRef suffix = isDebug ? "d" : "";

  args.push_back(("/DEFAULTLIB:" + prefix + "vcruntime" + suffix).str());
}
Пример #6
0
int main(int argc, char **argv) {
  INITIALIZE_LLVM(argc, argv);

  llvm::cl::ParseCommandLineOptions(argc, argv, "Swift SIL optimizer\n");

  if (PrintStats)
    llvm::EnableStatistics();

  CompilerInvocation Invocation;

  Invocation.setMainExecutablePath(
      llvm::sys::fs::getMainExecutable(argv[0],
          reinterpret_cast<void *>(&anchorForGetMainExecutable)));

  // Give the context the list of search paths to use for modules.
  Invocation.setImportSearchPaths(ImportPaths);
  std::vector<SearchPathOptions::FrameworkSearchPath> FramePaths;
  for (const auto &path : FrameworkPaths) {
    FramePaths.push_back({path, /*isSystem=*/false});
  }
  Invocation.setFrameworkSearchPaths(FramePaths);
  // Set the SDK path and target if given.
  if (SDKPath.getNumOccurrences() == 0) {
    const char *SDKROOT = getenv("SDKROOT");
    if (SDKROOT)
      SDKPath = SDKROOT;
  }
  if (!SDKPath.empty())
    Invocation.setSDKPath(SDKPath);
  if (!Target.empty())
    Invocation.setTargetTriple(Target);
  if (!ResourceDir.empty())
    Invocation.setRuntimeResourcePath(ResourceDir);
  Invocation.getFrontendOptions().EnableResilience = EnableResilience;
  // Set the module cache path. If not passed in we use the default swift module
  // cache.
  Invocation.getClangImporterOptions().ModuleCachePath = ModuleCachePath;
  Invocation.setParseStdlib();
  Invocation.getLangOptions().DisableAvailabilityChecking = true;
  Invocation.getLangOptions().EnableAccessControl = false;
  Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false;
  Invocation.getLangOptions().EnableObjCInterop =
    llvm::Triple(Target).isOSDarwin();

  Invocation.getLangOptions().ASTVerifierProcessCount =
      ASTVerifierProcessCount;
  Invocation.getLangOptions().ASTVerifierProcessId =
      ASTVerifierProcessId;
  Invocation.getLangOptions().EnableSILOpaqueValues = EnableSILOpaqueValues;

  // Setup the SIL Options.
  SILOptions &SILOpts = Invocation.getSILOptions();
  SILOpts.InlineThreshold = SILInlineThreshold;
  SILOpts.VerifyAll = EnableSILVerifyAll;
  SILOpts.RemoveRuntimeAsserts = RemoveRuntimeAsserts;
  SILOpts.AssertConfig = AssertConfId;
  if (OptimizationGroup != OptGroup::Diagnostics)
    SILOpts.Optimization = SILOptions::SILOptMode::Optimize;
  SILOpts.EnableSILOwnership = EnableSILOwnershipOpt;
  SILOpts.AssumeUnqualifiedOwnershipWhenParsing =
    AssumeUnqualifiedOwnershipWhenParsing;

  switch (EnforceExclusivity) {
  case EnforceExclusivityMode::Unchecked:
    // This option is analogous to the -Ounchecked optimization setting.
    // It will disable dynamic checking but still diagnose statically.
    SILOpts.EnforceExclusivityStatic = true;
    SILOpts.EnforceExclusivityDynamic = false;
    break;
  case EnforceExclusivityMode::Checked:
    SILOpts.EnforceExclusivityStatic = true;
    SILOpts.EnforceExclusivityDynamic = true;
    break;
  case EnforceExclusivityMode::DynamicOnly:
    // This option is intended for staging purposes. The intent is that
    // it will eventually be removed.
    SILOpts.EnforceExclusivityStatic = false;
    SILOpts.EnforceExclusivityDynamic = true;
    break;
  case EnforceExclusivityMode::None:
    // This option is for staging purposes.
    SILOpts.EnforceExclusivityStatic = false;
    SILOpts.EnforceExclusivityDynamic = false;
    break;
  }

  // Load the input file.
  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
    llvm::MemoryBuffer::getFileOrSTDIN(InputFilename);
  if (!FileBufOrErr) {
    fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
    exit(-1);
  }

  // If it looks like we have an AST, set the source file kind to SIL and the
  // name of the module to the file's name.
  Invocation.addInputBuffer(FileBufOrErr.get().get());

  serialization::ExtendedValidationInfo extendedInfo;
  auto result = serialization::validateSerializedAST(
      FileBufOrErr.get()->getBuffer(), &extendedInfo);
  bool HasSerializedAST = result.status == serialization::Status::Valid;

  if (HasSerializedAST) {
    const StringRef Stem = ModuleName.size() ?
                             StringRef(ModuleName) :
                             llvm::sys::path::stem(InputFilename);
    Invocation.setModuleName(Stem);
    Invocation.setInputKind(InputFileKind::IFK_Swift_Library);
  } else {
    const StringRef Name = ModuleName.size() ? StringRef(ModuleName) : "main";
    Invocation.setModuleName(Name);
    Invocation.setInputKind(InputFileKind::IFK_SIL);
  }

  CompilerInstance CI;
  PrintingDiagnosticConsumer PrintDiags;
  CI.addDiagnosticConsumer(&PrintDiags);

  if (!PerformWMO) {
    auto &FrontendOpts = Invocation.getFrontendOptions();
    if (!InputFilename.empty() && InputFilename != "-") {
      FrontendOpts.PrimaryInput = SelectedInput(
          FrontendOpts.InputFilenames.size());
    } else {
      FrontendOpts.PrimaryInput = SelectedInput(
          FrontendOpts.InputBuffers.size(), SelectedInput::InputKind::Buffer);
    }
  }

  if (CI.setup(Invocation))
    return 1;

  CI.performSema();

  // If parsing produced an error, don't run any passes.
  if (CI.getASTContext().hadError())
    return 1;

  // Load the SIL if we have a module. We have to do this after SILParse
  // creating the unfortunate double if statement.
  if (HasSerializedAST) {
    assert(!CI.hasSILModule() &&
           "performSema() should not create a SILModule.");
    CI.setSILModule(SILModule::createEmptyModule(
        CI.getMainModule(), CI.getSILOptions(), PerformWMO));
    std::unique_ptr<SerializedSILLoader> SL = SerializedSILLoader::create(
        CI.getASTContext(), CI.getSILModule(), nullptr);

    if (extendedInfo.isSIB() || DisableSILLinking)
      SL->getAllForModule(CI.getMainModule()->getName(), nullptr);
    else
      SL->getAll();
  }

  // If we're in verify mode, install a custom diagnostic handling for
  // SourceMgr.
  if (VerifyMode)
    enableDiagnosticVerifier(CI.getSourceMgr());

  if (OptimizationGroup == OptGroup::Diagnostics) {
    runSILDiagnosticPasses(*CI.getSILModule());
  } else if (OptimizationGroup == OptGroup::Performance) {
    runSILOptimizationPasses(*CI.getSILModule());
  } else if (OptimizationGroup == OptGroup::Lowering) {
    runSILLoweringPasses(*CI.getSILModule());
  } else {
    auto *SILMod = CI.getSILModule();
    {
      auto T = irgen::createIRGenModule(SILMod, getGlobalLLVMContext());
      runCommandLineSelectedPasses(SILMod, T.second);
      irgen::deleteIRGenModule(T);
    }
  }

  if (EmitSIB) {
    llvm::SmallString<128> OutputFile;
    if (OutputFilename.size()) {
      OutputFile = OutputFilename;
    } else if (ModuleName.size()) {
      OutputFile = ModuleName;
      llvm::sys::path::replace_extension(OutputFile, SIB_EXTENSION);
    } else {
      OutputFile = CI.getMainModule()->getName().str();
      llvm::sys::path::replace_extension(OutputFile, SIB_EXTENSION);
    }

    SerializationOptions serializationOpts;
    serializationOpts.OutputPath = OutputFile.c_str();
    serializationOpts.SerializeAllSIL = true;
    serializationOpts.IsSIB = true;

    serialize(CI.getMainModule(), serializationOpts, CI.getSILModule());
  } else {
    const StringRef OutputFile = OutputFilename.size() ?
                                   StringRef(OutputFilename) : "-";

    if (OutputFile == "-") {
      CI.getSILModule()->print(llvm::outs(), EmitVerboseSIL, CI.getMainModule(),
                               EnableSILSortOutput, !DisableASTDump);
    } else {
      std::error_code EC;
      llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_None);
      if (EC) {
        llvm::errs() << "while opening '" << OutputFile << "': "
                     << EC.message() << '\n';
        return 1;
      }
      CI.getSILModule()->print(OS, EmitVerboseSIL, CI.getMainModule(),
                               EnableSILSortOutput, !DisableASTDump);
    }
  }

  bool HadError = CI.getASTContext().hadError();

  // If we're in -verify mode, we've buffered up all of the generated
  // diagnostics.  Check now to ensure that they meet our expectations.
  if (VerifyMode) {
    HadError = verifyDiagnostics(CI.getSourceMgr(), CI.getInputBufferIDs(),
                                 /*autoApplyFixes*/false,
                                 /*ignoreUnknown*/false);
    DiagnosticEngine &diags = CI.getDiags();
    if (diags.hasFatalErrorOccurred() &&
        !Invocation.getDiagnosticOptions().ShowDiagnosticsAfterFatalError) {
      diags.resetHadAnyError();
      diags.diagnose(SourceLoc(), diag::verify_encountered_fatal);
      HadError = true;
    }
  }

  return HadError;
}
Пример #7
0
int main(int argc, char **argv) {
  INITIALIZE_LLVM(argc, argv);

  llvm::cl::ParseCommandLineOptions(argc, argv, "Swift LLVM IR Generator\n");

  if (PrintStats)
    llvm::EnableStatistics();

  CompilerInvocation Invocation;

  Invocation.setMainExecutablePath(llvm::sys::fs::getMainExecutable(
      argv[0], reinterpret_cast<void *>(&anchorForGetMainExecutable)));

  // Give the context the list of search paths to use for modules.
  Invocation.setImportSearchPaths(ImportPaths);
  Invocation.setFrameworkSearchPaths(FrameworkPaths);
  // Set the SDK path and target if given.
  if (SDKPath.getNumOccurrences() == 0) {
    const char *SDKROOT = getenv("SDKROOT");
    if (SDKROOT)
      SDKPath = SDKROOT;
  }
  if (!SDKPath.empty())
    Invocation.setSDKPath(SDKPath);
  if (!Target.empty())
    Invocation.setTargetTriple(Target);
  if (!ResourceDir.empty())
    Invocation.setRuntimeResourcePath(ResourceDir);
  // Set the module cache path. If not passed in we use the default swift module
  // cache.
  Invocation.getClangImporterOptions().ModuleCachePath = ModuleCachePath;
  Invocation.setParseStdlib();

  // Setup the language options
  auto &LangOpts = Invocation.getLangOptions();
  LangOpts.DisableAvailabilityChecking = true;
  LangOpts.EnableAccessControl = false;
  LangOpts.EnableObjCAttrRequiresFoundation = false;
  LangOpts.EnableObjCInterop = LangOpts.Target.isOSDarwin();

  // Setup the SIL Options.
  SILOptions &SILOpts = Invocation.getSILOptions();
  SILOpts.AssumeUnqualifiedOwnershipWhenParsing =
      AssumeUnqualifiedOwnershipWhenParsing;

  // Setup the IRGen Options.
  IRGenOptions &Opts = Invocation.getIRGenOptions();
  Opts.MainInputFilename = InputFilename;
  Opts.OutputFilenames.push_back(OutputFilename);
  Opts.OutputKind = OutputKind;

  // Load the input file.
  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
      llvm::MemoryBuffer::getFileOrSTDIN(InputFilename);
  if (!FileBufOrErr) {
    fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
    exit(-1);
  }

  // If it looks like we have an AST, set the source file kind to SIL and the
  // name of the module to the file's name.
  Invocation.addInputBuffer(FileBufOrErr.get().get());

  serialization::ExtendedValidationInfo extendedInfo;
  auto result = serialization::validateSerializedAST(
      FileBufOrErr.get()->getBuffer(), &extendedInfo);
  bool HasSerializedAST = result.status == serialization::Status::Valid;

  if (HasSerializedAST) {
    const StringRef Stem = ModuleName.size()
                               ? StringRef(ModuleName)
                               : llvm::sys::path::stem(InputFilename);
    Invocation.setModuleName(Stem);
    Invocation.setInputKind(InputFileKind::IFK_Swift_Library);
  } else {
    const StringRef Name = ModuleName.size() ? StringRef(ModuleName) : "main";
    Invocation.setModuleName(Name);
    Invocation.setInputKind(InputFileKind::IFK_SIL);
  }

  CompilerInstance CI;
  PrintingDiagnosticConsumer PrintDiags;
  CI.addDiagnosticConsumer(&PrintDiags);

  if (!PerformWMO) {
    auto &FrontendOpts = Invocation.getFrontendOptions();
    if (!InputFilename.empty() && InputFilename != "-") {
      FrontendOpts.PrimaryInput =
          SelectedInput(FrontendOpts.InputFilenames.size());
    } else {
      FrontendOpts.PrimaryInput = SelectedInput(
          FrontendOpts.InputBuffers.size(), SelectedInput::InputKind::Buffer);
    }
  }

  if (CI.setup(Invocation))
    return 1;

  CI.performSema();

  // If parsing produced an error, don't run any passes.
  if (CI.getASTContext().hadError())
    return 1;

  // Load the SIL if we have a module. We have to do this after SILParse
  // creating the unfortunate double if statement.
  if (HasSerializedAST) {
    assert(!CI.hasSILModule() &&
           "performSema() should not create a SILModule.");
    CI.setSILModule(SILModule::createEmptyModule(
        CI.getMainModule(), CI.getSILOptions(), PerformWMO));
    std::unique_ptr<SerializedSILLoader> SL = SerializedSILLoader::create(
        CI.getASTContext(), CI.getSILModule(), nullptr);

    if (extendedInfo.isSIB())
      SL->getAllForModule(CI.getMainModule()->getName(), nullptr);
    else
      SL->getAll();
  }

  std::unique_ptr<llvm::Module> Mod = performIRGeneration(
      Opts, CI.getMainModule(), CI.takeSILModule(),
      CI.getMainModule()->getName().str(), getGlobalLLVMContext());
  return CI.getASTContext().hadError();
}
int main(int argc, const char **argv) {
  llvm::sys::PrintStackTraceOnErrorSignal();
  Transforms TransformManager;
  ReplacementHandling ReplacementHandler;

  TransformManager.registerTransforms();

  // Hide all options we don't define ourselves. Move pre-defined 'help',
  // 'help-list', and 'version' to our general category.
  llvm::StringMap<cl::Option*> Options;
  cl::getRegisteredOptions(Options);
  const cl::OptionCategory **CategoryEnd =
      VisibleCategories + llvm::array_lengthof(VisibleCategories);
  for (llvm::StringMap<cl::Option *>::iterator I = Options.begin(),
                                               E = Options.end();
       I != E; ++I) {
    if (I->first() == "help" || I->first() == "version" ||
        I->first() == "help-list")
      I->second->setCategory(GeneralCategory);
    else if (std::find(VisibleCategories, CategoryEnd, I->second->Category) ==
             CategoryEnd)
      I->second->setHiddenFlag(cl::ReallyHidden);
  }
  cl::SetVersionPrinter(&printVersion);

  // Parse options and generate compilations.
  std::unique_ptr<CompilationDatabase> Compilations(
      FixedCompilationDatabase::loadFromCommandLine(argc, argv));
  cl::ParseCommandLineOptions(argc, argv);

  // Populate the ModifiableFiles structure.
  GlobalOptions.ModifiableFiles.readListFromString(IncludePaths, ExcludePaths);
  GlobalOptions.ModifiableFiles.readListFromFile(IncludeFromFile,
                                                 ExcludeFromFile);

  if (!Compilations) {
    std::string ErrorMessage;
    Compilations.reset(autoDetectCompilations(ErrorMessage));
    if (!Compilations) {
      llvm::errs() << llvm::sys::path::filename(argv[0]) << ": " << ErrorMessage
                   << "\n";
      return 1;
    }
  }

  // Populate source files.
  std::vector<std::string> Sources;
  if (!SourcePaths.empty()) {
    // Use only files that are not explicitly excluded.
    std::remove_copy_if(SourcePaths.begin(), SourcePaths.end(),
                        std::back_inserter(Sources),
                        isFileExplicitlyExcludedPredicate);
  } else {
    if (GlobalOptions.ModifiableFiles.isIncludeListEmpty()) {
      llvm::errs() << llvm::sys::path::filename(argv[0])
                   << ": Use -include to indicate which files of "
                   << "the compilatiion database to transform.\n";
      return 1;
    }
    // Use source paths from the compilation database.
    // We only transform files that are explicitly included.
    Sources = Compilations->getAllFiles();
    std::vector<std::string>::iterator E = std::remove_if(
        Sources.begin(), Sources.end(), isFileNotIncludedPredicate);
    Sources.erase(E, Sources.end());
  }

  // check if line ranges are just applyed to single files
  if ( !LineRanges.empty() && Sources.size() > 1 ){
     llvm::errs() << "error: -line can only be used for single file.\n";
     return 1;
  }

  // add the line ranges to the sources 
  if ( !LineRanges.empty() ){
  }

  if (Sources.empty()) {
    llvm::errs() << llvm::sys::path::filename(argv[0])
                 << ": Could not determine sources to transform.\n";
    return 1;
  }

  // Enable timming.
  GlobalOptions.EnableTiming = TimingDirectoryName.getNumOccurrences() > 0;

  bool CmdSwitchError = false;
  CompilerVersions RequiredVersions =
      handleSupportedCompilers(argv[0], CmdSwitchError);
  if (CmdSwitchError)
    return 1;

  TransformManager.createSelectedTransforms(GlobalOptions, RequiredVersions);

  if (TransformManager.begin() == TransformManager.end()) {
    if (SupportedCompilers.empty())
      llvm::errs() << llvm::sys::path::filename(argv[0])
                   << ": no selected transforms\n";
    else
      llvm::errs() << llvm::sys::path::filename(argv[0])
                   << ": no transforms available for specified compilers\n";
    return 1;
  }

  llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts(
      new DiagnosticOptions());
  DiagnosticsEngine Diagnostics(
      llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()),
      DiagOpts.getPtr());

  // FIXME: Make this DiagnosticsEngine available to all Transforms probably via
  // GlobalOptions.

  // If SerializeReplacements is requested, then code reformatting must be
  // turned off and only one transform should be requested.
  if (SerializeOnly &&
      (std::distance(TransformManager.begin(), TransformManager.end()) > 1 ||
       DoFormat)) {
    llvm::errs() << "Serialization of replacements requested for multiple "
                    "transforms.\nChanges from only one transform can be "
                    "serialized.\n";
    return 1;
  }

  // If we're asked to apply changes to files on disk, need to locate
  // clang-apply-replacements.
  if (!SerializeOnly) {
    if (!ReplacementHandler.findClangApplyReplacements(argv[0])) {
      llvm::errs() << "Could not find clang-apply-replacements\n";
      return 1;
    }

    if (DoFormat)
      ReplacementHandler.enableFormatting(FormatStyleOpt, FormatStyleConfig);
  }

  StringRef TempDestinationDir;
  if (SerializeLocation.getNumOccurrences() > 0)
    ReplacementHandler.setDestinationDir(SerializeLocation);
  else
    TempDestinationDir = ReplacementHandler.useTempDestinationDir();

  SourcePerfData PerfData;

  for (Transforms::const_iterator I = TransformManager.begin(),
                                  E = TransformManager.end();
       I != E; ++I) {
    Transform *T = *I;

    if (T->apply(*Compilations, Sources,LineRanges) != 0) {
      // FIXME: Improve ClangTool to not abort if just one file fails.
      return 1;
    }

    if (GlobalOptions.EnableTiming)
      collectSourcePerfData(*T, PerfData);

    if (SummaryMode) {
      llvm::outs() << "Transform: " << T->getName()
                   << " - Accepted: " << T->getAcceptedChanges();
      if (T->getChangesNotMade()) {
        llvm::outs() << " - Rejected: " << T->getRejectedChanges()
                     << " - Deferred: " << T->getDeferredChanges();
      }
      llvm::outs() << "\n";
    }

    if (!ReplacementHandler.serializeReplacements(T->getAllReplacements()))
      return 1;

    if (!SerializeOnly)
      if (!ReplacementHandler.applyReplacements())
        return 1;
  }

  // Let the user know which temporary directory the replacements got written
  // to.
  if (SerializeOnly && !TempDestinationDir.empty())
    llvm::errs() << "Replacements serialized to: " << TempDestinationDir << "\n";

  if (FinalSyntaxCheck) {
    ClangTool SyntaxTool(*Compilations, SourcePaths);
    if (SyntaxTool.run(newFrontendActionFactory<SyntaxOnlyAction>().get()) != 0)
      return 1;
  }

  // Report execution times.
  if (GlobalOptions.EnableTiming && !PerfData.empty()) {
    std::string DirectoryName = TimingDirectoryName;
    // Use default directory name.
    if (DirectoryName.empty())
      DirectoryName = "./migrate_perf";
    writePerfDataJSON(DirectoryName, PerfData);
  }

  return 0;
}
Пример #9
0
int main(int argc, char **argv) {
  INITIALIZE_LLVM(argc, argv);

  llvm::cl::ParseCommandLineOptions(argc, argv, "Swift SIL Extractor\n");

  CompilerInvocation Invocation;

  Invocation.setMainExecutablePath(llvm::sys::fs::getMainExecutable(
      argv[0], reinterpret_cast<void *>(&anchorForGetMainExecutable)));

  // Give the context the list of search paths to use for modules.
  Invocation.setImportSearchPaths(ImportPaths);
  // Set the SDK path and target if given.
  if (SDKPath.getNumOccurrences() == 0) {
    const char *SDKROOT = getenv("SDKROOT");
    if (SDKROOT)
      SDKPath = SDKROOT;
  }
  if (!SDKPath.empty())
    Invocation.setSDKPath(SDKPath);
  if (!Triple.empty())
    Invocation.setTargetTriple(Triple);
  if (!ResourceDir.empty())
    Invocation.setRuntimeResourcePath(ResourceDir);
  Invocation.getClangImporterOptions().ModuleCachePath = ModuleCachePath;
  Invocation.setParseStdlib();
  Invocation.getLangOptions().DisableAvailabilityChecking = true;
  Invocation.getLangOptions().EnableAccessControl = false;
  Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false;

  // Load the input file.
  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
      llvm::MemoryBuffer::getFileOrSTDIN(InputFilename);
  if (!FileBufOrErr) {
    fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
    exit(-1);
  }

  // If it looks like we have an AST, set the source file kind to SIL and the
  // name of the module to the file's name.
  Invocation.addInputBuffer(FileBufOrErr.get().get());

  serialization::ExtendedValidationInfo extendedInfo;
  auto result = serialization::validateSerializedAST(
      FileBufOrErr.get()->getBuffer(), &extendedInfo);
  bool HasSerializedAST = result.status == serialization::Status::Valid;

  if (HasSerializedAST) {
    const StringRef Stem = ModuleName.size()
                               ? StringRef(ModuleName)
                               : llvm::sys::path::stem(InputFilename);
    Invocation.setModuleName(Stem);
    Invocation.setInputKind(InputFileKind::IFK_Swift_Library);
  } else {
    Invocation.setModuleName("main");
    Invocation.setInputKind(InputFileKind::IFK_SIL);
  }

  SILOptions &SILOpts = Invocation.getSILOptions();
  SILOpts.AssumeUnqualifiedOwnershipWhenParsing =
      AssumeUnqualifiedOwnershipWhenParsing;

  CompilerInstance CI;
  PrintingDiagnosticConsumer PrintDiags;
  CI.addDiagnosticConsumer(&PrintDiags);

  if (CI.setup(Invocation))
    return 1;
  CI.performSema();

  // If parsing produced an error, don't run any passes.
  if (CI.getASTContext().hadError())
    return 1;

  // Load the SIL if we have a module. We have to do this after SILParse
  // creating the unfortunate double if statement.
  if (HasSerializedAST) {
    assert(!CI.hasSILModule() &&
           "performSema() should not create a SILModule.");
    CI.setSILModule(
        SILModule::createEmptyModule(CI.getMainModule(), CI.getSILOptions()));
    std::unique_ptr<SerializedSILLoader> SL = SerializedSILLoader::create(
        CI.getASTContext(), CI.getSILModule(), nullptr);

    if (extendedInfo.isSIB())
      SL->getAllForModule(CI.getMainModule()->getName(), nullptr);
    else
      SL->getAll();
  }

  if (CommandLineFunctionNames.empty() && FunctionNameFile.empty())
    return CI.getASTContext().hadError();

  // For efficient usage, we separate our names into two separate sorted
  // lists, one of managled names, and one of unmangled names.
  std::vector<std::string> Names;
  getFunctionNames(Names);

  // First partition our function names into mangled/demangled arrays.
  auto FirstDemangledName = std::partition(
      Names.begin(), Names.end(), [](const std::string &Name) -> bool {
        StringRef NameRef(Name);
        return NameRef.startswith("_T") ||
               NameRef.startswith(MANGLING_PREFIX_STR);
      });

  // Then grab offsets to avoid any issues with iterator invalidation when we
  // sort.
  unsigned NumMangled = std::distance(Names.begin(), FirstDemangledName);
  unsigned NumNames = Names.size();

  // Then sort the two partitioned arrays.
  std::sort(Names.begin(), FirstDemangledName);
  std::sort(FirstDemangledName, Names.end());

  // Finally construct our ArrayRefs into the sorted std::vector for our
  // mangled and demangled names.
  ArrayRef<std::string> MangledNames(&*Names.begin(), NumMangled);
  ArrayRef<std::string> DemangledNames(&*std::next(Names.begin(), NumMangled),
                                       NumNames - NumMangled);

  DEBUG(llvm::errs() << "MangledNames to keep:\n";
        std::for_each(MangledNames.begin(), MangledNames.end(),
                      [](const std::string &str) {
                        llvm::errs() << "    " << str << '\n';
                      }));
  DEBUG(llvm::errs() << "DemangledNames to keep:\n";
        std::for_each(DemangledNames.begin(), DemangledNames.end(),
                      [](const std::string &str) {
                        llvm::errs() << "    " << str << '\n';
                      }));

  removeUnwantedFunctions(CI.getSILModule(), MangledNames, DemangledNames);

  if (EmitSIB) {
    llvm::SmallString<128> OutputFile;
    if (OutputFilename.size()) {
      OutputFile = OutputFilename;
    } else if (ModuleName.size()) {
      OutputFile = ModuleName;
      llvm::sys::path::replace_extension(OutputFile, SIB_EXTENSION);
    } else {
      OutputFile = CI.getMainModule()->getName().str();
      llvm::sys::path::replace_extension(OutputFile, SIB_EXTENSION);
    }

    SerializationOptions serializationOpts;
    serializationOpts.OutputPath = OutputFile.c_str();
    serializationOpts.SerializeAllSIL = true;
    serializationOpts.IsSIB = true;

    serialize(CI.getMainModule(), serializationOpts, CI.getSILModule());
  } else {
    const StringRef OutputFile =
        OutputFilename.size() ? StringRef(OutputFilename) : "-";

    if (OutputFile == "-") {
      CI.getSILModule()->print(llvm::outs(), EmitVerboseSIL, CI.getMainModule(),
                               EnableSILSortOutput, !DisableASTDump);
    } else {
      std::error_code EC;
      llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_None);
      if (EC) {
        llvm::errs() << "while opening '" << OutputFile << "': " << EC.message()
                     << '\n';
        return 1;
      }
      CI.getSILModule()->print(OS, EmitVerboseSIL, CI.getMainModule(),
                               EnableSILSortOutput, !DisableASTDump);
    }
  }
}
Пример #10
0
int main(int argc, const char **argv) {
    llvm::sys::PrintStackTraceOnErrorSignal();
    Transforms TransformManager;
    ReplacementHandling ReplacementHandler;

    TransformManager.registerTransforms();

    // Hide all options we don't define ourselves. Move pre-defined 'help',
    // 'help-list', and 'version' to our general category.
    llvm::StringMap<cl::Option*> Options;
    cl::getRegisteredOptions(Options);
    const cl::OptionCategory **CategoryEnd =
        VisibleCategories + llvm::array_lengthof(VisibleCategories);
    for (llvm::StringMap<cl::Option *>::iterator I = Options.begin(),
            E = Options.end();
            I != E; ++I) {
        if (I->first() == "help" || I->first() == "version" ||
                I->first() == "help-list")
            I->second->setCategory(GeneralCategory);
        else if (std::find(VisibleCategories, CategoryEnd, I->second->Category) ==
                 CategoryEnd)
            I->second->setHiddenFlag(cl::ReallyHidden);
    }
    cl::SetVersionPrinter(&printVersion);

    // Parse options and generate compilations.
    std::unique_ptr<CompilationDatabase> Compilations(
        FixedCompilationDatabase::loadFromCommandLine(argc, argv));
    cl::ParseCommandLineOptions(argc, argv);

    // Populate the ModifiableFiles structure.
    GlobalOptions.ModifiableFiles.readListFromString(IncludePaths, ExcludePaths);
    GlobalOptions.ModifiableFiles.readListFromFile(IncludeFromFile,
            ExcludeFromFile);

    if (!Compilations) {
        std::string ErrorMessage;
        Compilations = autoDetectCompilations(ErrorMessage);
        if (!Compilations) {
            llvm::errs() << llvm::sys::path::filename(argv[0]) << ": " << ErrorMessage
                         << "\n";
            return 1;
        }
    }

    // Populate source files.
    std::vector<std::string> Sources;
    if (!SourcePaths.empty()) {
        // Use only files that are not explicitly excluded.
        std::remove_copy_if(SourcePaths.begin(), SourcePaths.end(),
                            std::back_inserter(Sources),
                            isFileExplicitlyExcludedPredicate);
    } else {
        if (GlobalOptions.ModifiableFiles.isIncludeListEmpty()) {
            llvm::errs() << llvm::sys::path::filename(argv[0])
                         << ": Use -include to indicate which files of "
                         << "the compilatiion database to transform.\n";
            return 1;
        }
        // Use source paths from the compilation database.
        // We only transform files that are explicitly included.
        Sources = Compilations->getAllFiles();
        std::vector<std::string>::iterator E = std::remove_if(
                Sources.begin(), Sources.end(), isFileNotIncludedPredicate);
        Sources.erase(E, Sources.end());
    }



    // check if line ranges are just applyed to single files
    if ( !LineRanges.empty() && Sources.size() > 1 ) {
        llvm::errs() << "error: -line can only be used for single file.\n";
        return 1;
    }

    // add the line ranges to the sources
    if ( !LineRanges.empty() ) {
    }


    std::string filename;
    int line_begin, column_begin;
    int line_end, column_end;

    if ( Target.getNumOccurrences() ) {
        // TODO parse the target data
        std::stringstream sstr(Target);
        char separator;
        sstr >>
             line_begin >> separator >>
             column_begin >> separator >>
             line_end >> separator >>
             column_end >> separator >> filename;

        llvm::errs() << filename << " " << line_begin << "-" <<
                     column_begin << ":" << line_end << "-" << column_end << "\n";

        // store it in the Transform object
    }