bool GenerateModuleAction::ComputeASTConsumerArguments(CompilerInstance &CI,
                                                       StringRef InFile,
                                                       std::string &Sysroot,
                                                       std::string &OutputFile,
                                                       raw_ostream *&OS) {
  // If no output file was provided, figure out where this module would go
  // in the module cache.
  if (CI.getFrontendOpts().OutputFile.empty()) {
    HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
    CI.getFrontendOpts().OutputFile =
        HS.getModuleFileName(CI.getLangOpts().CurrentModule,
                             ModuleMapForUniquing->getName());
  }
  
  // We use createOutputFile here because this is exposed via libclang, and we
  // must disable the RemoveFileOnSignal behavior.
  // We use a temporary to avoid race conditions.
  OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
                           /*RemoveFileOnSignal=*/false, InFile,
                           /*Extension=*/"", /*useTemporary=*/true,
                           /*CreateMissingDirectories=*/true);
  if (!OS)
    return true;
  
  OutputFile = CI.getFrontendOpts().OutputFile;
  return false;
}
   void CreateOutput(CompilerInstance& CI)
   {
      //llvm::errs() << __FUNCTION__ << ":" << CI.getFrontendOpts().OutputFile << "\n";
      if (output_) return;

      std::string errMsg;
      output_ = CI.createOutputFile("", errMsg, true, true, CI.getFrontendOpts().OutputFile, "fanout");
      if (!output_) llvm::errs() << "Failed to create output file:" << errMsg << "\n";
   }
Beispiel #3
0
std::unique_ptr<llvm::raw_pwrite_stream>
GeneratePCHAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile,
                                    std::string &OutputFile) {
  // We use createOutputFile here because this is exposed via libclang, and we
  // must disable the RemoveFileOnSignal behavior.
  // We use a temporary to avoid race conditions.
  std::unique_ptr<raw_pwrite_stream> OS =
      CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
                          /*RemoveFileOnSignal=*/false, InFile,
                          /*Extension=*/"", /*useTemporary=*/true);
  if (!OS)
    return nullptr;

  OutputFile = CI.getFrontendOpts().OutputFile;
  return OS;
}
std::unique_ptr<raw_pwrite_stream>
GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI,
                                                    StringRef InFile) {
  // If no output file was provided, figure out where this module would go
  // in the module cache.
  if (CI.getFrontendOpts().OutputFile.empty()) {
    HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
    CI.getFrontendOpts().OutputFile =
        HS.getModuleFileName(CI.getLangOpts().CurrentModule,
                             ModuleMapForUniquing->getName(),
                             /*UsePrebuiltPath=*/false);
  }

  // We use createOutputFile here because this is exposed via libclang, and we
  // must disable the RemoveFileOnSignal behavior.
  // We use a temporary to avoid race conditions.
  return CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
                             /*RemoveFileOnSignal=*/false, InFile,
                             /*Extension=*/"", /*useTemporary=*/true,
                             /*CreateMissingDirectories=*/true);
}
Beispiel #5
0
bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
                                                    llvm::StringRef InFile,
                                                    std::string &Sysroot,
                                                    llvm::raw_ostream *&OS,
                                                    bool &Chaining) {
  Sysroot = CI.getHeaderSearchOpts().Sysroot;
  if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) {
    CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot);
    return true;
  }

  // We use createOutputFile here because this is exposed via libclang, and we
  // must disable the RemoveFileOnSignal behavior.
  OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
                           /*RemoveFileOnSignal=*/false, InFile);
  if (!OS)
    return true;

  Chaining = CI.getInvocation().getFrontendOpts().ChainedPCH &&
             !CI.getPreprocessorOpts().ImplicitPCHInclude.empty();
  return false;
}
bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
                                                    StringRef InFile,
                                                    std::string &Sysroot,
                                                    std::string &OutputFile,
                                                    raw_ostream *&OS) {
  Sysroot = CI.getHeaderSearchOpts().Sysroot;
  if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) {
    CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot);
    return true;
  }

  // We use createOutputFile here because this is exposed via libclang, and we
  // must disable the RemoveFileOnSignal behavior.
  // We use a temporary to avoid race conditions.
  OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
                           /*RemoveFileOnSignal=*/false, InFile,
                           /*Extension=*/"", /*useTemporary=*/true);
  if (!OS)
    return true;

  OutputFile = CI.getFrontendOpts().OutputFile;
  return false;
}
static int CompileSubprocess(const char **argv, int argc, 
                             sys::Path &ResourceDir, bool bugreport,
                             bool versionOnly, sys::Path &apiMapPath)
{
  std::vector<char*> llvmArgs;
  char apim[] = "-clam-apimap";
  llvmArgs.push_back((char*)argv[0]);
  llvmArgs.push_back(apim);
  llvmArgs.push_back((char*)apiMapPath.c_str());

  // Split args into cc1 and LLVM args, separator is --
  int cc1_argc;
  for (cc1_argc=1;cc1_argc<argc;cc1_argc++) {
    if (StringRef(argv[cc1_argc]) == "--") {
      for (int i=cc1_argc+1;i<argc;i++) {
        llvmArgs.push_back((char*)argv[i]);
      }
      break;
    }
  }

  // Initialize CompilerInstance from commandline args
  CompilerInstance Clang;
  Clang.setLLVMContext(new llvm::LLVMContext);
  LLVMInitializeClamBCTargetInfo();
  LLVMInitializeClamBCTarget();

  TextDiagnosticBuffer DiagsBuffer;
  Diagnostic Diags(&DiagsBuffer);
  CompilerInvocation::CreateFromArgs(Clang.getInvocation(), argv+1,
                                     argv+cc1_argc, Diags);
  FrontendOptions &FrontendOpts = Clang.getInvocation().getFrontendOpts();
  // Handle --version
  if (FrontendOpts.ShowVersion || versionOnly) {
    printVersion(outs(), true);
    exit(0);
  }

  DiagnosticOptions &DiagOpts = Clang.getInvocation().getDiagnosticOpts();
  DiagOpts.ShowOptionNames = DiagOpts.ShowColors = 1;
  DiagOpts.MessageLength = 80;// we are writing to a file
  DiagOpts.Warnings.push_back("all");
  DiagOpts.Warnings.push_back("no-pointer-sign");

  Clang.createDiagnostics(argc-1, const_cast<char**>(argv+1));
  if (!Clang.hasDiagnostics())
    return 2;

  Clang.getInvocation().getHeaderSearchOpts().ResourceDir = ResourceDir.str();

  // Set default options
  LangOptions &LangOpts = Clang.getInvocation().getLangOpts();
  // This is a freestanding environment, without libc, etc.
  LangOpts.Freestanding = 1;
  HeaderSearchOptions &HeaderSearchOpts =
    Clang.getInvocation().getHeaderSearchOpts();
  HeaderSearchOpts.UseStandardIncludes = 0;
  if (bugreport)
    HeaderSearchOpts.Verbose = 1;

  if (FrontendOpts.ProgramAction != frontend::PrintPreprocessedInput)
    FrontendOpts.ProgramAction = frontend::EmitBC;
  if (bugreport)
    FrontendOpts.ProgramAction = frontend::PrintPreprocessedInput;

  // Don't bother freeing of memory on exit 
  FrontendOpts.DisableFree = 1;

  CodeGenOptions &Opts = Clang.getInvocation().getCodeGenOpts();
  Opts.Inlining = CodeGenOptions::OnlyAlwaysInlining;
  // always generate debug info, so that ClamBC backend can output sourcelevel
  // diagnostics.
  Opts.DebugInfo = true;
  // FIXME: once the verifier can work w/o targetdata, and targetdate opts set
  // DisableLLVMOpts to true!
  // This is needed to avoid target-specific optimizations
  Opts.DisableLLVMOpts = false;

  AnalyzerOptions &AOpts = Clang.getInvocation().getAnalyzerOpts();
  AOpts.AnalysisList.push_back(WarnDeadStores);
  AOpts.AnalysisList.push_back(WarnUninitVals);
  AOpts.AnalysisList.push_back(SecuritySyntacticChecks);
  AOpts.AnalysisList.push_back(WarnSizeofPointer);

  // Set triple
  Clang.getInvocation().getTargetOpts().Triple = "clambc-generic-generic";
  // Set default include
  Clang.getInvocation().getPreprocessorOpts().Includes.push_back("bytecode.h");

  // Set an LLVM error handler.
  llvm::llvm_install_error_handler(LLVMErrorHandler,
                                   static_cast<void*>(&Clang.getDiagnostics()));
  DiagsBuffer.FlushDiagnostics(Clang.getDiagnostics());
  // If there were any errors in processing arguments, exit now.
  if (Clang.getDiagnostics().getNumErrors())
    return 1;

  // Create the target instance.
  //TODO: directly create a clambc target
  Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
                                               Clang.getTargetOpts()));
  if (!Clang.hasTarget())
    return 1;

  // Inform the target of the language options
  Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());

  if (Clang.getHeaderSearchOpts().Verbose) {
    llvm::errs() << "clang -cc1 version " CLANG_VERSION_STRING
                 << " based upon " << PACKAGE_STRING
                 << " hosted on " << llvm::sys::getHostTriple() << "\n";
    // Convert the invocation back to argument strings.
    std::vector<std::string> InvocationArgs;
    Clang.getInvocation().toArgs(InvocationArgs);

    // Dump the converted arguments.
    llvm::SmallVector<const char*, 32> Invocation2Args;
    llvm::errs() << "invocation argv :";
    for (unsigned i = 0, e = InvocationArgs.size(); i != e; ++i) {
      Invocation2Args.push_back(InvocationArgs[i].c_str());
      llvm::errs() << " \"" << InvocationArgs[i] << '"';
    }
    llvm::errs() << "\n";
  }

  std::string Input = FrontendOpts.Inputs[0].second;
  if (Input == "-" && bugreport)
    return 2;
  raw_fd_ostream *fd = 0;
  if (FrontendOpts.ProgramAction == frontend::EmitBC) {
    // replace output file of compiler with a tempfile,
    // and save the final output filename.
    std::string FinalOutput = FrontendOpts.OutputFile;
    if (FinalOutput.empty()) {
      if (Input == "-")
        FinalOutput = "-";
      else {
        sys::Path P(sys::Path(Input).getBasename());
        P.appendSuffix("cbc");
        FinalOutput = P.str();
      }
    }
    llvm::raw_fd_ostream *tmpfd;
    std::string Err2;
    fd = Clang.createOutputFile(FinalOutput, Err2, false);
    if (!fd) {
      Clang.getDiagnostics().Report(clang::diag::err_drv_unable_to_make_temp) << Err2;
      return 1;
    }
    sys::Path P = sys::Path(FinalOutput);
    P.eraseSuffix();
    P.appendSuffix("tmp.bc");
    FrontendOpts.OutputFile = P.str();
    tmpfd = Clang.createOutputFile(P.str(), Err2, true);
    if (!tmpfd) {
      Clang.getDiagnostics().Report(clang::diag::err_drv_unable_to_make_temp) << Err2;
      return 1;
    }
    delete tmpfd;

    sys::RemoveFileOnSignal(sys::Path(FrontendOpts.OutputFile));
  }

  if (!FrontendOpts.Inputs.empty()) {
    char srcp[] = "-clambc-src";
    llvmArgs.push_back(srcp);
    llvmArgs.push_back(strdup(Input.c_str()));
  }

  // Parse LLVM commandline args
  cl::ParseCommandLineOptions(llvmArgs.size(), &llvmArgs[0]);

  std::string re2cpath = getTmpDir();
  if (re2cpath.empty()) {
    llvm::errs()<< "Failed to create temporary file for re2c-out!\n";
    return 2;
  }
  re2cpath += "/clambc-compiler-re2c-out";

  sys::Path TmpRe2C(re2cpath);
  if (!FrontendOpts.Inputs.empty()) {
    char re2c_args[] = "--no-generation-date";
    char re2c_o[] = "-o";
    char name[] = "";
    char *args[6] = {
      name,
      re2c_args,
      re2c_o,
      NULL,
      NULL,
      NULL
    };
    args[4] = strdup(Input.c_str());
    std::string ErrMsg("");
    if (TmpRe2C.createTemporaryFileOnDisk(true, &ErrMsg)) {
      Clang.getDiagnostics().Report(clang::diag::err_drv_unable_to_make_temp) <<
        ErrMsg;
      return 1;
    }
    sys::RemoveFileOnSignal(TmpRe2C);
    args[3] = strdup(TmpRe2C.str().c_str());
    int ret = re2c_main(5, args);
    if (ret) {
      Clang.getDiagnostics().Report(clang::diag::err_drv_command_failed) <<
        "re2c" << ret;
      return 1;
    }
    Input = TmpRe2C.str();
  }

  // Create a file manager object to provide access to and cache the
  // filesystem.
  Clang.createFileManager();

  // Create the source manager.
  Clang.createSourceManager();

  // Create the preprocessor.
  Clang.createPreprocessor();

  llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang));

  if (Act && Act->BeginSourceFile(Clang, Input, false)) {
    Act->Execute();
    Act->EndSourceFile();
  }

  TmpRe2C.eraseFromDisk();// erase tempfile
  int ret = Clang.getDiagnostics().getNumErrors() != 0;
  if (ret)
    return ret;

  if (FrontendOpts.ProgramAction != frontend::EmitBC) {
    // stop processing if not compiling a final .cbc file
    return 0;
  }

  ret = compileInternal(FrontendOpts.OutputFile.c_str(), Opts.OptimizationLevel,
                        Opts.OptimizeSize, argv[0], fd, Clang);
  // Erase temp file, we need to do this here since OutputFile is a tempfile
  // only if action was EmitBC
  sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
  return ret;
}