예제 #1
0
/// RunProgramRemotelyWithTimeout - This function runs the given program
/// remotely using the given remote client and the sys::Program::ExecuteAndWait.
/// Returns the remote program exit code or reports a remote client error if it
/// fails. Remote client is required to return 255 if it failed or program exit
/// code otherwise.
/// @see sys::Program::ExecuteAndWait
static int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath,
                                         const char **Args,
                                         const sys::Path &StdInFile,
                                         const sys::Path &StdOutFile,
                                         const sys::Path &StdErrFile,
                                         unsigned NumSeconds = 0,
                                         unsigned MemoryLimit = 0) {
  const sys::Path* redirects[3];
  redirects[0] = &StdInFile;
  redirects[1] = &StdOutFile;
  redirects[2] = &StdErrFile;

#if 0 // For debug purposes
  {
    errs() << "RUN:";
    for (unsigned i = 0; Args[i]; ++i)
      errs() << " " << Args[i];
    errs() << "\n";
  }
#endif

  // Run the program remotely with the remote client
  int ReturnCode = sys::Program::ExecuteAndWait(RemoteClientPath, Args,
                                 0, redirects, NumSeconds, MemoryLimit);

  // Has the remote client fail?
  if (255 == ReturnCode) {
    std::ostringstream OS;
    OS << "\nError running remote client:\n ";
    for (const char **Arg = Args; *Arg; ++Arg)
      OS << " " << *Arg;
    OS << "\n";

    // The error message is in the output file, let's print it out from there.
    std::ifstream ErrorFile(StdOutFile.c_str());
    if (ErrorFile) {
      std::copy(std::istreambuf_iterator<char>(ErrorFile),
                std::istreambuf_iterator<char>(),
                std::ostreambuf_iterator<char>(OS));
      ErrorFile.close();
    }

    errs() << OS.str();
  }

  return ReturnCode;
}
예제 #2
0
bool LTOCodeGenerator::assemble(const std::string& asmPath, 
                                const std::string& objPath, std::string& errMsg)
{
    // find compiler driver
    const sys::Path gcc = sys::Program::FindProgramByName("gcc");
    if ( gcc.isEmpty() ) {
        errMsg = "can't locate gcc";
        return true;
    }

    // build argument list
    std::vector<const char*> args;
    std::string targetTriple = _linker.getModule()->getTargetTriple();
    args.push_back(gcc.c_str());
    if ( targetTriple.find("darwin") != targetTriple.size() ) {
        if (strncmp(targetTriple.c_str(), "i686-apple-", 11) == 0) {
            args.push_back("-arch");
            args.push_back("i386");
        }
        else if (strncmp(targetTriple.c_str(), "x86_64-apple-", 13) == 0) {
            args.push_back("-arch");
            args.push_back("x86_64");
        }
        else if (strncmp(targetTriple.c_str(), "powerpc-apple-", 14) == 0) {
            args.push_back("-arch");
            args.push_back("ppc");
        }
        else if (strncmp(targetTriple.c_str(), "powerpc64-apple-", 16) == 0) {
            args.push_back("-arch");
            args.push_back("ppc64");
        }
    }
    args.push_back("-c");
    args.push_back("-x");
    args.push_back("assembler");
    args.push_back("-o");
    args.push_back(objPath.c_str());
    args.push_back(asmPath.c_str());
    args.push_back(0);

    // invoke assembler
    if ( sys::Program::ExecuteAndWait(gcc, &args[0], 0, 0, 0, 0, &errMsg) ) {
        errMsg = "error in assembly";    
        return true;
    }
    return false; // success
}
예제 #3
0
파일: Linker.cpp 프로젝트: 32bitmicro/llvm
// LoadObject - Read in and parse the bitcode file named by FN and return the
// module it contains (wrapped in an auto_ptr), or auto_ptr<Module>() and set
// Error if an error occurs.
std::auto_ptr<Module>
Linker::LoadObject(const sys::Path &FN) {
  std::string ParseErrorMessage;
  Module *Result = 0;

  OwningPtr<MemoryBuffer> Buffer;
  if (error_code ec = MemoryBuffer::getFileOrSTDIN(FN.c_str(), Buffer))
    ParseErrorMessage = "Error reading file '" + FN.str() + "'" + ": "
                      + ec.message();
  else
    Result = ParseBitcodeFile(Buffer.get(), Context, &ParseErrorMessage);

  if (Result)
    return std::auto_ptr<Module>(Result);
  Error = "Bitcode file '" + FN.str() + "' could not be loaded";
  if (ParseErrorMessage.size())
    Error += ": " + ParseErrorMessage;
  return std::auto_ptr<Module>();
}
/// GenerateAssembly - generates a native assembly language source file from the
/// specified bytecode file.
///
/// Inputs:
///  InputFilename  - The name of the input bytecode file.
///  OutputFilename - The name of the file to generate.
///  llc            - The pathname to use for LLC.
///  envp           - The environment to use when running LLC.
///
/// Return non-zero value on error.
///
static int GenerateAssembly(const std::string &OutputFilename,
                            const std::string &InputFilename,
                            const sys::Path &llc,
                            std::string &ErrMsg ) {
  // Run LLC to convert the bytecode file into assembly code.
  std::vector<const char*> args;
  args.push_back(llc.c_str());
  args.push_back("-f");
  args.push_back("-o");
  args.push_back(OutputFilename.c_str());
  args.push_back(InputFilename.c_str());
  args.push_back(0);

  if (Verbose) {
    cout << "Generating Assembly With: \n";
    PrintCommand(args);
  }

  return sys::Program::ExecuteAndWait(llc, &args[0], 0, 0, 0, 0, &ErrMsg);
}
예제 #5
0
/// GenerateCFile - generates a C source file from the specified bitcode file.
static int GenerateCFile(const std::string &OutputFile,
                         const std::string &InputFile,
                         const sys::Path &llc,
                         std::string& ErrMsg) {
  // Run LLC to convert the bitcode file into C.
  std::vector<const char*> args;
  args.push_back(llc.c_str());
  args.push_back("-march=c");
  args.push_back("-o");
  args.push_back(OutputFile.c_str());
  args.push_back(InputFile.c_str());
  args.push_back(0);

  if (Verbose) {
    errs() << "Generating C Source With: \n";
    PrintCommand(args);
  }

  return sys::Program::ExecuteAndWait(llc, &args[0], 0, 0, 0, 0, &ErrMsg);
}
예제 #6
0
// Get just the externally visible defined symbols from the bitcode
bool llvm::GetBitcodeSymbols(const sys::Path& fName,
                             LLVMContext& Context,
                             std::vector<std::string>& symbols,
                             std::string* ErrMsg) {
  OwningPtr<MemoryBuffer> Buffer;
  if (error_code ec = MemoryBuffer::getFileOrSTDIN(fName.c_str(), Buffer)) {
    if (ErrMsg) *ErrMsg = "Could not open file '" + fName.str() + "'" + ": "
                        + ec.message();
    return true;
  }

  Module *M = ParseBitcodeFile(Buffer.get(), Context, ErrMsg);
  if (!M)
    return true;

  // Get the symbols
  getSymbols(M, symbols);

  // Done with the module.
  delete M;
  return true;
}
예제 #7
0
/// GenerateAssembly - generates a native assembly language source file from the
/// specified bitcode file.
///
/// Inputs:
///  InputFilename  - The name of the input bitcode file.
///  OutputFilename - The name of the file to generate.
///  llc            - The pathname to use for LLC.
///  envp           - The environment to use when running LLC.
///
/// Return non-zero value on error.
///
static int GenerateAssembly(const std::string &OutputFilename,
                            const std::string &InputFilename,
                            const sys::Path &llc,
                            std::string &ErrMsg ) {
  // Run LLC to convert the bitcode file into assembly code.
  std::vector<const char*> args;
  args.push_back(llc.c_str());
  // We will use GCC to assemble the program so set the assembly syntax to AT&T,
  // regardless of what the target in the bitcode file is.
  args.push_back("-x86-asm-syntax=att");
  args.push_back("-o");
  args.push_back(OutputFilename.c_str());
  args.push_back(InputFilename.c_str());
  args.push_back(0);

  if (Verbose) {
    errs() << "Generating Assembly With: \n";
    PrintCommand(args);
  }

  return sys::Program::ExecuteAndWait(llc, &args[0], 0, 0, 0, 0, &ErrMsg);
}
void llvm::DisplayGraph(const sys::Path &Filename, bool wait,
                        GraphProgram::Name program) {
  std::string ErrMsg;
#if HAVE_GRAPHVIZ
  sys::Path Graphviz(LLVM_PATH_GRAPHVIZ);

  std::vector<const char*> args;
  args.push_back(Graphviz.c_str());
  args.push_back(Filename.c_str());
  args.push_back(0);
  
  errs() << "Running 'Graphviz' program... ";
  if (sys::Program::ExecuteAndWait(Graphviz, &args[0],0,0,0,0,&ErrMsg))
    errs() << "Error viewing graph " << Filename.str() << ": " << ErrMsg
           << "\n";
  else
    Filename.eraseFromDisk();

#elif (HAVE_GV && (HAVE_DOT || HAVE_FDP || HAVE_NEATO || \
                   HAVE_TWOPI || HAVE_CIRCO))
  sys::Path PSFilename = Filename;
  PSFilename.appendSuffix("ps");

  sys::Path prog;

  // Set default grapher
#if HAVE_CIRCO
  prog = sys::Path(LLVM_PATH_CIRCO);
#endif
#if HAVE_TWOPI
  prog = sys::Path(LLVM_PATH_TWOPI);
#endif
#if HAVE_NEATO
  prog = sys::Path(LLVM_PATH_NEATO);
#endif
#if HAVE_FDP
  prog = sys::Path(LLVM_PATH_FDP);
#endif
#if HAVE_DOT
  prog = sys::Path(LLVM_PATH_DOT);
#endif

  // Find which program the user wants
#if HAVE_DOT
  if (program == GraphProgram::DOT)
    prog = sys::Path(LLVM_PATH_DOT);
#endif
#if (HAVE_FDP)
  if (program == GraphProgram::FDP)
    prog = sys::Path(LLVM_PATH_FDP);
#endif
#if (HAVE_NEATO)
  if (program == GraphProgram::NEATO)
    prog = sys::Path(LLVM_PATH_NEATO);
#endif
#if (HAVE_TWOPI)
  if (program == GraphProgram::TWOPI)
    prog = sys::Path(LLVM_PATH_TWOPI);
#endif
#if (HAVE_CIRCO)
  if (program == GraphProgram::CIRCO)
    prog = sys::Path(LLVM_PATH_CIRCO);
#endif

  std::vector<const char*> args;
  args.push_back(prog.c_str());
  args.push_back("-Tps");
  args.push_back("-Nfontname=Courier");
  args.push_back("-Gsize=7.5,10");
  args.push_back(Filename.c_str());
  args.push_back("-o");
  args.push_back(PSFilename.c_str());
  args.push_back(0);
  
  errs() << "Running '" << prog.str() << "' program... ";

  if (sys::Program::ExecuteAndWait(prog, &args[0], 0, 0, 0, 0, &ErrMsg)) {
     errs() << "Error viewing graph " << Filename.str() << ": '"
            << ErrMsg << "\n";
  } else {
    errs() << " done. \n";

    sys::Path gv(LLVM_PATH_GV);
    args.clear();
    args.push_back(gv.c_str());
    args.push_back(PSFilename.c_str());
    args.push_back("--spartan");
    args.push_back(0);
    
    ErrMsg.clear();
    if (wait) {
       if (sys::Program::ExecuteAndWait(gv, &args[0],0,0,0,0,&ErrMsg))
          errs() << "Error viewing graph: " << ErrMsg << "\n";
       Filename.eraseFromDisk();
       PSFilename.eraseFromDisk();
    }
    else {
       sys::Program::ExecuteNoWait(gv, &args[0],0,0,0,&ErrMsg);
       errs() << "Remember to erase graph files: " << Filename.str() << " "
              << PSFilename.str() << "\n";
    }
  }
#elif HAVE_DOTTY
  sys::Path dotty(LLVM_PATH_DOTTY);

  std::vector<const char*> args;
  args.push_back(dotty.c_str());
  args.push_back(Filename.c_str());
  args.push_back(0);
  
  errs() << "Running 'dotty' program... ";
  if (sys::Program::ExecuteAndWait(dotty, &args[0],0,0,0,0,&ErrMsg)) {
     errs() << "Error viewing graph " << Filename.str() << ": "
            << ErrMsg << "\n";
  } else {
#ifdef __MINGW32__ // Dotty spawns another app and doesn't wait until it returns
    return;
#endif
    Filename.eraseFromDisk();
  }
#endif
}
void llvm::DisplayGraph(const sys::Path &Filename) {
  std::string ErrMsg;
#if HAVE_GRAPHVIZ
  sys::Path Graphviz(LLVM_PATH_GRAPHVIZ);

  std::vector<const char*> args;
  args.push_back(Graphviz.c_str());
  args.push_back(Filename.c_str());
  args.push_back(0);
  
  cerr << "Running 'Graphviz' program... " << std::flush;
  if (sys::Program::ExecuteAndWait(Graphviz, &args[0],0,0,0,0,&ErrMsg)) {
    cerr << "Error viewing graph: " << ErrMsg << "\n";
  }
#elif (HAVE_GV && HAVE_DOT)
  sys::Path PSFilename = Filename;
  PSFilename.appendSuffix("ps");
  
  sys::Path dot(LLVM_PATH_DOT);

  std::vector<const char*> args;
  args.push_back(dot.c_str());
  args.push_back("-Tps");
  args.push_back("-Nfontname=Courier");
  args.push_back("-Gsize=7.5,10");
  args.push_back(Filename.c_str());
  args.push_back("-o");
  args.push_back(PSFilename.c_str());
  args.push_back(0);
  
  cerr << "Running 'dot' program... " << std::flush;
  if (sys::Program::ExecuteAndWait(dot, &args[0],0,0,0,0,&ErrMsg)) {
    cerr << "Error viewing graph: '" << ErrMsg << "\n";
  } else {
    cerr << " done. \n";

    sys::Path gv(LLVM_PATH_GV);
    args.clear();
    args.push_back(gv.c_str());
    args.push_back(PSFilename.c_str());
    args.push_back(0);
    
    ErrMsg.clear();
    if (sys::Program::ExecuteAndWait(gv, &args[0],0,0,0,0,&ErrMsg)) {
      cerr << "Error viewing graph: " << ErrMsg << "\n";
    }
  }
  PSFilename.eraseFromDisk();
#elif HAVE_DOTTY
  sys::Path dotty(LLVM_PATH_DOTTY);

  std::vector<const char*> args;
  args.push_back(dotty.c_str());
  args.push_back(Filename.c_str());
  args.push_back(0);
  
  cerr << "Running 'dotty' program... " << std::flush;
  if (sys::Program::ExecuteAndWait(dotty, &args[0],0,0,0,0,&ErrMsg)) {
    cerr << "Error viewing graph: " << ErrMsg << "\n";
  } else {
#ifdef __MINGW32__ // Dotty spawns another app and doesn't wait until it returns
    return;
#endif
  }
#endif
  
  Filename.eraseFromDisk();
}
예제 #10
0
파일: lto.cpp 프로젝트: marnen/rubinius
///Link all modules together and optimize them using IPO. Generate
/// native object file using OutputFilename
/// Return appropriate LTOStatus.
enum LTOStatus
LTO::optimizeModules(const std::string &OutputFilename,
                     std::vector<const char *> &exportList,
                     std::string &targetTriple,
                     bool saveTemps, const char *FinalOutputFilename)
{
  if (modules.empty())
    return LTO_NO_WORK;

  std::ios::openmode io_mode = 
    std::ios::out | std::ios::trunc | std::ios::binary; 
  std::string *errMsg = NULL;
  Module *bigOne = modules[0];
  Linker theLinker("LinkTimeOptimizer", bigOne, false);
  for (unsigned i = 1, e = modules.size(); i != e; ++i)
    if (theLinker.LinkModules(bigOne, modules[i], errMsg))
      return LTO_MODULE_MERGE_FAILURE;
  //  all modules have been handed off to the linker.
  modules.clear();

  sys::Path FinalOutputPath(FinalOutputFilename);
  FinalOutputPath.eraseSuffix();

  switch(CGModel) {
  case LTO_CGM_Dynamic:
    Target->setRelocationModel(Reloc::PIC_);
    break;
  case LTO_CGM_DynamicNoPIC:
    Target->setRelocationModel(Reloc::DynamicNoPIC);
    break;
  case LTO_CGM_Static:
    Target->setRelocationModel(Reloc::Static);
    break;
  }

  if (saveTemps) {
    std::string tempFileName(FinalOutputPath.c_str());
    tempFileName += "0.bc";
    std::ofstream Out(tempFileName.c_str(), io_mode);
    WriteBitcodeToFile(bigOne, Out);
  }

  // Strip leading underscore because it was added to match names
  // seen by linker.
  for (unsigned i = 0, e = exportList.size(); i != e; ++i) {
    const char *name = exportList[i];
    NameToSymbolMap::iterator itr = allSymbols.find(name);
    if (itr != allSymbols.end())
      exportList[i] = allSymbols[name]->getName();
  }


  std::string ErrMsg;
  sys::Path TempDir = sys::Path::GetTemporaryDirectory(&ErrMsg);
  if (TempDir.isEmpty()) {
    cerr << "lto: " << ErrMsg << "\n";
    return LTO_WRITE_FAILURE;
  }
  sys::Path tmpAsmFilePath(TempDir);
  if (!tmpAsmFilePath.appendComponent("lto")) {
    cerr << "lto: " << ErrMsg << "\n";
    TempDir.eraseFromDisk(true);
    return LTO_WRITE_FAILURE;
  }
  if (tmpAsmFilePath.createTemporaryFileOnDisk(true, &ErrMsg)) {
    cerr << "lto: " << ErrMsg << "\n";
    TempDir.eraseFromDisk(true);
    return LTO_WRITE_FAILURE;
  }
  sys::RemoveFileOnSignal(tmpAsmFilePath);

  std::ofstream asmFile(tmpAsmFilePath.c_str(), io_mode);
  if (!asmFile.is_open() || asmFile.bad()) {
    if (tmpAsmFilePath.exists()) {
      tmpAsmFilePath.eraseFromDisk();
      TempDir.eraseFromDisk(true);
    }
    return LTO_WRITE_FAILURE;
  }

  enum LTOStatus status = optimize(bigOne, asmFile, exportList);
  asmFile.close();
  if (status != LTO_OPT_SUCCESS) {
    tmpAsmFilePath.eraseFromDisk();
    TempDir.eraseFromDisk(true);
    return status;
  }

  if (saveTemps) {
    std::string tempFileName(FinalOutputPath.c_str());
    tempFileName += "1.bc";
    std::ofstream Out(tempFileName.c_str(), io_mode);
    WriteBitcodeToFile(bigOne, Out);
  }

  targetTriple = bigOne->getTargetTriple();

  // Run GCC to assemble and link the program into native code.
  //
  // Note:
  //  We can't just assemble and link the file with the system assembler
  //  and linker because we don't know where to put the _start symbol.
  //  GCC mysteriously knows how to do it.
  const sys::Path gcc = sys::Program::FindProgramByName("gcc");
  if (gcc.isEmpty()) {
    tmpAsmFilePath.eraseFromDisk();
    TempDir.eraseFromDisk(true);
    return LTO_ASM_FAILURE;
  }

  std::vector<const char*> args;
  args.push_back(gcc.c_str());
  if (strncmp(targetTriple.c_str(), "i686-apple-", 11) == 0) {
    args.push_back("-arch");
    args.push_back("i386");
  }
  if (strncmp(targetTriple.c_str(), "x86_64-apple-", 13) == 0) {
    args.push_back("-arch");
    args.push_back("x86_64");
  }
  if (strncmp(targetTriple.c_str(), "powerpc-apple-", 14) == 0) {
    args.push_back("-arch");
    args.push_back("ppc");
  }
  if (strncmp(targetTriple.c_str(), "powerpc64-apple-", 16) == 0) {
    args.push_back("-arch");
    args.push_back("ppc64");
  }
  args.push_back("-c");
  args.push_back("-x");
  args.push_back("assembler");
  args.push_back("-o");
  args.push_back(OutputFilename.c_str());
  args.push_back(tmpAsmFilePath.c_str());
  args.push_back(0);

  if (sys::Program::ExecuteAndWait(gcc, &args[0], 0, 0, 0, 0, &ErrMsg)) {
    cerr << "lto: " << ErrMsg << "\n";
    return LTO_ASM_FAILURE;
  }

  tmpAsmFilePath.eraseFromDisk();
  TempDir.eraseFromDisk(true);

  return LTO_OPT_SUCCESS;
}
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;
}
/// GenerateNative - generates a native object file from the
/// specified bytecode file.
///
/// Inputs:
///  InputFilename   - The name of the input bytecode file.
///  OutputFilename  - The name of the file to generate.
///  NativeLinkItems - The native libraries, files, code with which to link
///  LibPaths        - The list of directories in which to find libraries.
///  gcc             - The pathname to use for GGC.
///  envp            - A copy of the process's current environment.
///
/// Outputs:
///  None.
///
/// Returns non-zero value on error.
///
static int GenerateNative(const std::string &OutputFilename,
                          const std::string &InputFilename,
                          const Linker::ItemList &LinkItems,
                          const sys::Path &gcc, char ** const envp,
                          std::string& ErrMsg) {
  // Remove these environment variables from the environment of the
  // programs that we will execute.  It appears that GCC sets these
  // environment variables so that the programs it uses can configure
  // themselves identically.
  //
  // However, when we invoke GCC below, we want it to use its normal
  // configuration.  Hence, we must sanitize its environment.
  char ** clean_env = CopyEnv(envp);
  if (clean_env == NULL)
    return 1;
  RemoveEnv("LIBRARY_PATH", clean_env);
  RemoveEnv("COLLECT_GCC_OPTIONS", clean_env);
  RemoveEnv("GCC_EXEC_PREFIX", clean_env);
  RemoveEnv("COMPILER_PATH", clean_env);
  RemoveEnv("COLLECT_GCC", clean_env);


  // Run GCC to assemble and link the program into native code.
  //
  // Note:
  //  We can't just assemble and link the file with the system assembler
  //  and linker because we don't know where to put the _start symbol.
  //  GCC mysteriously knows how to do it.
  std::vector<const char*> args;
  args.push_back(gcc.c_str());
  args.push_back("-fno-strict-aliasing");
  args.push_back("-O3");
  args.push_back("-o");
  args.push_back(OutputFilename.c_str());
  args.push_back(InputFilename.c_str());

  // Add in the library paths
  for (unsigned index = 0; index < LibPaths.size(); index++) {
    args.push_back("-L");
    args.push_back(LibPaths[index].c_str());
  }

  // Add the requested options
  for (unsigned index = 0; index < XLinker.size(); index++) {
    args.push_back(XLinker[index].c_str());
    args.push_back(Libraries[index].c_str());
  }

  // Add in the libraries to link.
  for (unsigned index = 0; index < LinkItems.size(); index++)
    if (LinkItems[index].first != "crtend") {
      if (LinkItems[index].second) {
        std::string lib_name = "-l" + LinkItems[index].first;
        args.push_back(lib_name.c_str());
      } else
        args.push_back(LinkItems[index].first.c_str());
    }

  args.push_back(0);

  if (Verbose) {
    cout << "Generating Native Executable With:\n";
    PrintCommand(args);
  }

  // Run the compiler to assembly and link together the program.
  int R = sys::Program::ExecuteAndWait(
    gcc, &args[0], (const char**)clean_env, 0, 0, 0, &ErrMsg);
  delete [] clean_env;
  return R;
}
예제 #13
0
void llvm::DisplayGraph(const sys::Path &Filename, bool wait,
                        GraphProgram::Name program) {
  wait &= !ViewBackground;
  std::string ErrMsg;
#if HAVE_GRAPHVIZ
  sys::Path Graphviz(LLVM_PATH_GRAPHVIZ);

  std::vector<const char*> args;
  args.push_back(Graphviz.c_str());
  args.push_back(Filename.c_str());
  args.push_back(0);

  errs() << "Running 'Graphviz' program... ";
  if (!ExecGraphViewer(Graphviz, args, Filename, wait, ErrMsg))
    return;

#elif HAVE_XDOT_PY
  std::vector<const char*> args;
  args.push_back(LLVM_PATH_XDOT_PY);
  args.push_back(Filename.c_str());

  switch (program) {
  case GraphProgram::DOT:   args.push_back("-f"); args.push_back("dot"); break;
  case GraphProgram::FDP:   args.push_back("-f"); args.push_back("fdp"); break;
  case GraphProgram::NEATO: args.push_back("-f"); args.push_back("neato");break;
  case GraphProgram::TWOPI: args.push_back("-f"); args.push_back("twopi");break;
  case GraphProgram::CIRCO: args.push_back("-f"); args.push_back("circo");break;
  }

  args.push_back(0);

  errs() << "Running 'xdot.py' program... ";
  if (!ExecGraphViewer(sys::Path(LLVM_PATH_XDOT_PY), args, Filename, wait, ErrMsg))
    return;

#elif (HAVE_GV && (HAVE_DOT || HAVE_FDP || HAVE_NEATO || \
                   HAVE_TWOPI || HAVE_CIRCO))
  sys::Path PSFilename = Filename;
  PSFilename.appendSuffix("ps");

  sys::Path prog;

  // Set default grapher
#if HAVE_CIRCO
  prog = sys::Path(LLVM_PATH_CIRCO);
#endif
#if HAVE_TWOPI
  prog = sys::Path(LLVM_PATH_TWOPI);
#endif
#if HAVE_NEATO
  prog = sys::Path(LLVM_PATH_NEATO);
#endif
#if HAVE_FDP
  prog = sys::Path(LLVM_PATH_FDP);
#endif
#if HAVE_DOT
  prog = sys::Path(LLVM_PATH_DOT);
#endif

  // Find which program the user wants
#if HAVE_DOT
  if (program == GraphProgram::DOT)
    prog = sys::Path(LLVM_PATH_DOT);
#endif
#if (HAVE_FDP)
  if (program == GraphProgram::FDP)
    prog = sys::Path(LLVM_PATH_FDP);
#endif
#if (HAVE_NEATO)
  if (program == GraphProgram::NEATO)
    prog = sys::Path(LLVM_PATH_NEATO);
#endif
#if (HAVE_TWOPI)
  if (program == GraphProgram::TWOPI)
    prog = sys::Path(LLVM_PATH_TWOPI);
#endif
#if (HAVE_CIRCO)
  if (program == GraphProgram::CIRCO)
    prog = sys::Path(LLVM_PATH_CIRCO);
#endif

  std::vector<const char*> args;
  args.push_back(prog.c_str());
  args.push_back("-Tps");
  args.push_back("-Nfontname=Courier");
  args.push_back("-Gsize=7.5,10");
  args.push_back(Filename.c_str());
  args.push_back("-o");
  args.push_back(PSFilename.c_str());
  args.push_back(0);

  errs() << "Running '" << prog.str() << "' program... ";

  if (!ExecGraphViewer(prog, args, Filename, wait, ErrMsg))
    return;

  sys::Path gv(LLVM_PATH_GV);
  args.clear();
  args.push_back(gv.c_str());
  args.push_back(PSFilename.c_str());
  args.push_back("--spartan");
  args.push_back(0);

  ErrMsg.clear();
  if (!ExecGraphViewer(gv, args, PSFilename, wait, ErrMsg))
    return;

#elif HAVE_DOTTY
  sys::Path dotty(LLVM_PATH_DOTTY);

  std::vector<const char*> args;
  args.push_back(dotty.c_str());
  args.push_back(Filename.c_str());
  args.push_back(0);

// Dotty spawns another app and doesn't wait until it returns
#if defined (__MINGW32__) || defined (_WINDOWS)
  wait = false;
#endif
  errs() << "Running 'dotty' program... ";
  if (!ExecGraphViewer(dotty, args, Filename, wait, ErrMsg))
    return;
#endif
}
예제 #14
0
/// GenerateNative - generates a native object file from the
/// specified bitcode file.
///
/// Inputs:
///  InputFilename   - The name of the input bitcode file.
///  OutputFilename  - The name of the file to generate.
///  NativeLinkItems - The native libraries, files, code with which to link
///  LibPaths        - The list of directories in which to find libraries.
///  FrameworksPaths - The list of directories in which to find frameworks.
///  Frameworks      - The list of frameworks (dynamic libraries)
///  gcc             - The pathname to use for GGC.
///  envp            - A copy of the process's current environment.
///
/// Outputs:
///  None.
///
/// Returns non-zero value on error.
///
static int GenerateNative(const std::string &OutputFilename,
                          const std::string &InputFilename,
                          const Linker::ItemList &LinkItems,
                          const sys::Path &gcc, char ** const envp,
                          std::string& ErrMsg) {
  // Remove these environment variables from the environment of the
  // programs that we will execute.  It appears that GCC sets these
  // environment variables so that the programs it uses can configure
  // themselves identically.
  //
  // However, when we invoke GCC below, we want it to use its normal
  // configuration.  Hence, we must sanitize its environment.
  char ** clean_env = CopyEnv(envp);
  if (clean_env == NULL)
    return 1;
  RemoveEnv("LIBRARY_PATH", clean_env);
  RemoveEnv("COLLECT_GCC_OPTIONS", clean_env);
  RemoveEnv("GCC_EXEC_PREFIX", clean_env);
  RemoveEnv("COMPILER_PATH", clean_env);
  RemoveEnv("COLLECT_GCC", clean_env);


  // Run GCC to assemble and link the program into native code.
  //
  // Note:
  //  We can't just assemble and link the file with the system assembler
  //  and linker because we don't know where to put the _start symbol.
  //  GCC mysteriously knows how to do it.
  std::vector<std::string> args;
  args.push_back(gcc.c_str());
  args.push_back("-fno-strict-aliasing");
  args.push_back("-O3");
  args.push_back("-o");
  args.push_back(OutputFilename);
  args.push_back(InputFilename);

  // Add in the library and framework paths
  for (unsigned index = 0; index < LibPaths.size(); index++) {
    args.push_back("-L" + LibPaths[index]);
  }
  for (unsigned index = 0; index < FrameworkPaths.size(); index++) {
    args.push_back("-F" + FrameworkPaths[index]);
  }

  // Add the requested options
  for (unsigned index = 0; index < XLinker.size(); index++)
    args.push_back(XLinker[index]);

  // Add in the libraries to link.
  for (unsigned index = 0; index < LinkItems.size(); index++)
    if (LinkItems[index].first != "crtend") {
      if (LinkItems[index].second)
        args.push_back("-l" + LinkItems[index].first);
      else
        args.push_back(LinkItems[index].first);
    }

  // Add in frameworks to link.
  for (unsigned index = 0; index < Frameworks.size(); index++) {
    args.push_back("-framework");
    args.push_back(Frameworks[index]);
  }

  // Now that "args" owns all the std::strings for the arguments, call the c_str
  // method to get the underlying string array.  We do this game so that the
  // std::string array is guaranteed to outlive the const char* array.
  std::vector<const char *> Args;
  for (unsigned i = 0, e = args.size(); i != e; ++i)
    Args.push_back(args[i].c_str());
  Args.push_back(0);

  if (Verbose) {
    errs() << "Generating Native Executable With:\n";
    PrintCommand(Args);
  }

  // Run the compiler to assembly and link together the program.
  int R = sys::Program::ExecuteAndWait(
    gcc, &Args[0], const_cast<const char **>(clean_env), 0, 0, 0, &ErrMsg);
  delete [] clean_env;
  return R;
}