Exemplo n.º 1
0
static std::unique_ptr<llvm::Module>
getModuleFromSource(llvm::opt::ArgStringList CFlags,
		    StringRef Path, IntrusiveRefCntPtr<vfs::FileSystem> VFS)
{
	CompilerInstance Clang;
	Clang.createDiagnostics();

	Clang.setVirtualFileSystem(&*VFS);

#if CLANG_VERSION_MAJOR < 4
	IntrusiveRefCntPtr<CompilerInvocation> CI =
		createCompilerInvocation(std::move(CFlags), Path,
					 Clang.getDiagnostics());
	Clang.setInvocation(&*CI);
#else
	std::shared_ptr<CompilerInvocation> CI(
		createCompilerInvocation(std::move(CFlags), Path,
					 Clang.getDiagnostics()));
	Clang.setInvocation(CI);
#endif

	std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx));
	if (!Clang.ExecuteAction(*Act))
		return std::unique_ptr<llvm::Module>(nullptr);

	return Act->takeModule();
}
Exemplo n.º 2
0
vector<uint8_t> ClangCompilerBackend<T>::compileEBPFObject(const string _code) {
    // Send code trough pipe to stdin
    int codeInPipe[2];
    pipe2(codeInPipe, O_NONBLOCK);
    write(codeInPipe[1], (void *) _code.c_str(), _code.length());
    close(codeInPipe[1]); // We need to close the pipe to send an EOF
    int stdinCopy = dup(STDIN_FILENO);
    dup2(codeInPipe[0], STDIN_FILENO);

    // Prepare reception of code trought stdou
    int codeOutPipe[2];
    pipe(codeOutPipe);
    int stdoutCopy = dup(STDOUT_FILENO);
    dup2(codeOutPipe[1], STDOUT_FILENO);

    // Initialize various LLVM/Clang components
    InitializeAllTargetMCs();   
    InitializeAllAsmPrinters();
    InitializeAllTargets();

    // Prepare compilation arguments
    vector<const char *> args;
    args.push_back("--target=bpf"); // Target is bpf assembly
    args.push_back("-xc"); // Code is in c language
    args.push_back("-"); // Read code from stdiargs.push_back("-strip-debug"); // Strip symbols

    // Initialize CompilerInvocation
    CompilerInvocation *CI = createInvocationFromCommandLine(makeArrayRef(args) , NULL);

    // Create CompilerInstance
    CompilerInstance Clang;
    Clang.setInvocation(CI);

    // Initialize CompilerInstace
    Clang.createDiagnostics();

    // Create and execute action
    CodeGenAction *compilerAction; 
    compilerAction = new EmitObjAction();
    Clang.ExecuteAction(*compilerAction);

    // Get compiled object
    close(codeInPipe[0]);
    vector<uint8_t> objBuffer(2048);
    int bytesRead = read(codeOutPipe[0], objBuffer.data(), objBuffer.size()); 
    objBuffer.resize(bytesRead);

    // Cleanup
    dup2(stdinCopy, STDIN_FILENO);
    dup2(stdoutCopy, STDOUT_FILENO);

    return objBuffer;
}
Exemplo n.º 3
0
int
main (int argc, char* argv[])
{
  // Process our own command line options and remove them from the arguments
  // before letting the compiler invocation process the arguments.
  Arguments arguments;
  handleCommandLineOptions(argc, argv, arguments);

  CompilerInstance compiler;

  // Create diagnostics so errors while processing command line arguments can
  // be reported.
  compiler.createDiagnostics(argc, argv);

  CompilerInvocation::CreateFromArgs(
      compiler.getInvocation(),
      &arguments[0],
      &arguments[0] + arguments.size(),
      compiler.getDiagnostics());

  if (!handleFrontEndOptions(compiler.getFrontendOpts())) {
    return EXIT_FAILURE;
  }

  compiler.getInvocation().setLangDefaults(IK_CXX);

  if (compiler.getHeaderSearchOpts().UseBuiltinIncludes
   && compiler.getHeaderSearchOpts().ResourceDir.empty())
  {
    compiler.getHeaderSearchOpts().ResourceDir =
        CompilerInvocation::GetResourcesPath(
            argv[0], reinterpret_cast<void*>(showHelp));
  }

  if (compiler.getLangOpts().MicrosoftMode) {
    // TODO: Kludge to allow clang to parse Microsoft headers.
    // Visual C++ does name resolution at template instantiation, but clang does
    // name resolution at template definition.  A Microsoft header defines a
    // template referencing _invalid_parameter_noinfo but is not declared at
    // that point. It is declared later in the <xutility> header file.
  }

  UnnecessaryIncludeFinderAction action;
  compiler.ExecuteAction(action);
  bool foundUnnecessary = action.reportUnnecessaryIncludes(
      compiler.getSourceManager());

  llvm_shutdown();
  return foundUnnecessary ? EXIT_FAILURE : exitStatus;
}
Exemplo n.º 4
0
LLVMResult* ClangCodeContainer::produceModule(Tree signals, const string& filename)
{
    // Compile DSP and generate C code
    fCompiler->compileMultiSignal(signals);
    fContainer->produceClass();
    
#if defined(LLVM_34) || defined(LLVM_35) || defined(LLVM_36) || defined(LLVM_37) || defined(LLVM_38) || defined(LLVM_39) || defined(LLVM_40)
    // Compile it with 'clang'
    IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
    TextDiagnosticPrinter* DiagClient = new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts);
    
    IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
    DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);
    Driver TheDriver("", llvm::sys::getProcessTriple(), "a.out", Diags);
    TheDriver.setTitle("clang interpreter");
    
    int argc = 2;
    const char* argv[argc + 1];
    argv[0] = "clang";
    argv[1] = getTempName();
    argv[argc] = 0;  // NULL terminated argv
    SmallVector<const char*, 16> Args(argv, argv + argc);
    Args.push_back("-fsyntax-only");
    //Args.push_back("-O3");
    Args.push_back("-ffast-math");
      
    list<string>::iterator it;
    for (it = gGlobal->gImportDirList.begin(); it != gGlobal->gImportDirList.end(); it++) {
        string path = "-I" + (*it);
        Args.push_back(strdup(path.c_str()));
    }
    
    OwningPtr<Compilation> C(TheDriver.BuildCompilation(Args));
    if (!C) {
        return NULL;
    }

    const driver::JobList &Jobs = C->getJobs();
    if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) {
        SmallString<256> Msg;
        llvm::raw_svector_ostream OS(Msg);
        Jobs.Print(OS, "; ", true);
        Diags.Report(diag::err_fe_expected_compiler_job) << OS.str();
        return NULL;
    }

    const driver::Command* Cmd = cast<driver::Command>(*Jobs.begin());
    if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
        Diags.Report(diag::err_fe_expected_clang_command);
        return NULL;
    }

    // Initialize a compiler invocation object from the clang (-cc1) arguments.
    const driver::ArgStringList &CCArgs = Cmd->getArguments();
    OwningPtr<CompilerInvocation> CI(new CompilerInvocation);
    CompilerInvocation::CreateFromArgs(*CI, const_cast<const char**>(CCArgs.data()),
                                            const_cast<const char**>(CCArgs.data()) + CCArgs.size(), Diags);

    // Create a compiler instance to handle the actual work.
    CompilerInstance Clang;
    Clang.setInvocation(CI.take());

    // Create the compilers actual diagnostics engine.
    Clang.createDiagnostics();
    if (!Clang.hasDiagnostics()) {
        return NULL;
    }
    
    CompilerInvocation::setLangDefaults(Clang.getLangOpts(), IK_CXX, LangStandard::lang_unspecified);

    // Create and execute the frontend to generate an LLVM bitcode module.
    OwningPtr<CodeGenAction> Act(new EmitLLVMOnlyAction());
    if (!Clang.ExecuteAction(*Act)) {
        return NULL;
    }

    // Get the compiled LLVM module
    if (llvm::Module* Module = Act->takeModule()) {
        LLVMResult* result = static_cast<LLVMResult*>(calloc(1, sizeof(LLVMResult)));
        result->fModule = Module;
        result->fContext = Act->takeLLVMContext();
        
        // Link LLVM modules defined in 'ffunction'
        set<string> S;
        set<string>::iterator f;
        char error_msg[512];
        
        collectLibrary(S);
        if (S.size() > 0) {
            for (f = S.begin(); f != S.end(); f++) {
                string module_name = unquote(*f);
                if (endWith(module_name, ".bc") || endWith(module_name, ".ll")) {
                    Module* module = loadModule(module_name, result->fContext);
                    if (module) {
                        bool res = linkModules(result->fModule, module, error_msg);
                        if (!res) printf("Link LLVM modules %s\n", error_msg);
                    }
                }
            }
        }
        
        // Possibly link with additional LLVM modules
        char error[256];
        if (!linkAllModules(result->fContext, result->fModule, error)) {
            stringstream llvm_error;
            llvm_error << "ERROR : " << error << endl;
            throw faustexception(llvm_error.str());
        }
        
        // Keep source files pathnames
        result->fPathnameList = gGlobal->gReader.listSrcFiles();
        
        // Possibly output file
        if (filename != "") {
            std::string err;
            raw_fd_ostream out(filename.c_str(), err, sysfs_binary_flag);
            WriteBitcodeToFile(result->fModule, out);
        }
        
        return result;
    } else {
        return NULL;
    }
#else
    return NULL;
#endif
}
Exemplo n.º 5
0
int main(int argc, const char **argv, char * const *envp) {
  void *MainAddr = (void*) (intptr_t) GetExecutablePath;
  llvm::sys::Path Path = GetExecutablePath(argv[0]);
  TextDiagnosticPrinter *DiagClient =
    new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions());

  llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
  Diagnostic Diags(DiagID, DiagClient);
  Driver TheDriver(Path.str(), llvm::sys::getHostTriple(),
                   "a.out", /*IsProduction=*/false, /*CXXIsProduction=*/false,
                   Diags);
  TheDriver.setTitle("clang interpreter");

  // FIXME: This is a hack to try to force the driver to do something we can
  // recognize. We need to extend the driver library to support this use model
  // (basically, exactly one input, and the operation mode is hard wired).
  llvm::SmallVector<const char *, 16> Args(argv, argv + argc);
  Args.push_back("-fsyntax-only");
  llvm::OwningPtr<Compilation> C(TheDriver.BuildCompilation(Args));
  if (!C)
    return 0;

  // FIXME: This is copied from ASTUnit.cpp; simplify and eliminate.

  // We expect to get back exactly one command job, if we didn't something
  // failed. Extract that job from the compilation.
  const driver::JobList &Jobs = C->getJobs();
  if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) {
    llvm::SmallString<256> Msg;
    llvm::raw_svector_ostream OS(Msg);
    C->PrintJob(OS, C->getJobs(), "; ", true);
    Diags.Report(diag::err_fe_expected_compiler_job) << OS.str();
    return 1;
  }

  const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
  if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
    Diags.Report(diag::err_fe_expected_clang_command);
    return 1;
  }

  // Initialize a compiler invocation object from the clang (-cc1) arguments.
  const driver::ArgStringList &CCArgs = Cmd->getArguments();
  llvm::OwningPtr<CompilerInvocation> CI(new CompilerInvocation);
  CompilerInvocation::CreateFromArgs(*CI,
                                     const_cast<const char **>(CCArgs.data()),
                                     const_cast<const char **>(CCArgs.data()) +
                                       CCArgs.size(),
                                     Diags);

  // Show the invocation, with -v.
  if (CI->getHeaderSearchOpts().Verbose) {
    llvm::errs() << "clang invocation:\n";
    C->PrintJob(llvm::errs(), C->getJobs(), "\n", true);
    llvm::errs() << "\n";
  }

  // FIXME: This is copied from cc1_main.cpp; simplify and eliminate.

  // Create a compiler instance to handle the actual work.
  CompilerInstance Clang;
  Clang.setInvocation(CI.take());

  // Create the compilers actual diagnostics engine.
  Clang.createDiagnostics(int(CCArgs.size()),const_cast<char**>(CCArgs.data()));
  if (!Clang.hasDiagnostics())
    return 1;

  // Infer the builtin include path if unspecified.
  if (Clang.getHeaderSearchOpts().UseBuiltinIncludes &&
      Clang.getHeaderSearchOpts().ResourceDir.empty())
    Clang.getHeaderSearchOpts().ResourceDir =
      CompilerInvocation::GetResourcesPath(argv[0], MainAddr);

  // Create and execute the frontend to generate an LLVM bitcode module.
  llvm::OwningPtr<CodeGenAction> Act(new EmitLLVMOnlyAction());
  if (!Clang.ExecuteAction(*Act))
    return 1;

  int Res = 255;
  if (llvm::Module *Module = Act->takeModule())
    Res = Execute(Module, envp);

  // Shutdown.

  llvm::llvm_shutdown();

  return Res;
}
Exemplo n.º 6
0
void ModelInjector::onBodySynthesis(const NamedDecl *D) {

  // FIXME: what about overloads? Declarations can be used as keys but what
  // about file name index? Mangled names may not be suitable for that either.
  if (Bodies.count(D->getName()) != 0)
    return;

  SourceManager &SM = CI.getSourceManager();
  FileID mainFileID = SM.getMainFileID();

  AnalyzerOptionsRef analyzerOpts = CI.getAnalyzerOpts();
  llvm::StringRef modelPath = analyzerOpts->Config["model-path"];

  llvm::SmallString<128> fileName;

  if (!modelPath.empty())
    fileName =
        llvm::StringRef(modelPath.str() + "/" + D->getName().str() + ".model");
  else
    fileName = llvm::StringRef(D->getName().str() + ".model");

  if (!llvm::sys::fs::exists(fileName.str())) {
    Bodies[D->getName()] = nullptr;
    return;
  }

  IntrusiveRefCntPtr<CompilerInvocation> Invocation(
      new CompilerInvocation(CI.getInvocation()));

  FrontendOptions &FrontendOpts = Invocation->getFrontendOpts();
  InputKind IK = IK_CXX; // FIXME
  FrontendOpts.Inputs.clear();
  FrontendOpts.Inputs.push_back(FrontendInputFile(fileName, IK));
  FrontendOpts.DisableFree = true;

  Invocation->getDiagnosticOpts().VerifyDiagnostics = 0;

  // Modules are parsed by a separate CompilerInstance, so this code mimics that
  // behavior for models
  CompilerInstance Instance;
  Instance.setInvocation(&*Invocation);
  Instance.createDiagnostics(
      new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()),
      /*ShouldOwnClient=*/true);

  Instance.getDiagnostics().setSourceManager(&SM);

  Instance.setVirtualFileSystem(&CI.getVirtualFileSystem());

  // The instance wants to take ownership, however DisableFree frontend option
  // is set to true to avoid double free issues
  Instance.setFileManager(&CI.getFileManager());
  Instance.setSourceManager(&SM);
  Instance.setPreprocessor(&CI.getPreprocessor());
  Instance.setASTContext(&CI.getASTContext());

  Instance.getPreprocessor().InitializeForModelFile();

  ParseModelFileAction parseModelFile(Bodies);

  const unsigned ThreadStackSize = 8 << 20;
  llvm::CrashRecoveryContext CRC;

  CRC.RunSafelyOnThread([&]() { Instance.ExecuteAction(parseModelFile); },
                        ThreadStackSize);

  Instance.getPreprocessor().FinalizeForModelFile();

  Instance.resetAndLeakSourceManager();
  Instance.resetAndLeakFileManager();
  Instance.resetAndLeakPreprocessor();

  // The preprocessor enters to the main file id when parsing is started, so
  // the main file id is changed to the model file during parsing and it needs
  // to be reseted to the former main file id after parsing of the model file
  // is done.
  SM.setMainFileID(mainFileID);
}
int cc1_main(const char **ArgBegin, const char **ArgEnd,
             const char *Argv0, void *MainAddr) {
  CompilerInstance Clang;

  Clang.setLLVMContext(new llvm::LLVMContext);

  // Run clang -cc1 test.
  if (ArgBegin != ArgEnd && llvm::StringRef(ArgBegin[0]) == "-cc1test") {
    TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions());
    Diagnostic Diags(&DiagClient);
    return cc1_test(Diags, ArgBegin + 1, ArgEnd);
  }

  // Initialize targets first, so that --version shows registered targets.
  llvm::InitializeAllTargets();
  llvm::InitializeAllAsmPrinters();

  // Buffer diagnostics from argument parsing so that we can output them using a
  // well formed diagnostic object.
  TextDiagnosticBuffer DiagsBuffer;
  Diagnostic Diags(&DiagsBuffer);
  CompilerInvocation::CreateFromArgs(Clang.getInvocation(), ArgBegin, ArgEnd,
                                     Diags);

  // Infer the builtin include path if unspecified.
  if (Clang.getHeaderSearchOpts().UseBuiltinIncludes &&
      Clang.getHeaderSearchOpts().ResourceDir.empty())
    Clang.getHeaderSearchOpts().ResourceDir =
      CompilerInvocation::GetResourcesPath(Argv0, MainAddr);

  // Honor -help.
  if (Clang.getFrontendOpts().ShowHelp) {
    llvm::OwningPtr<driver::OptTable> Opts(driver::createCC1OptTable());
    Opts->PrintHelp(llvm::outs(), "clang -cc1",
                    "LLVM 'Clang' Compiler: http://clang.llvm.org");
    return 0;
  }

  // Honor -version.
  //
  // FIXME: Use a better -version message?
  if (Clang.getFrontendOpts().ShowVersion) {
    llvm::cl::PrintVersionMessage();
    return 0;
  }

  // Create the actual diagnostics engine.
  Clang.createDiagnostics(ArgEnd - ArgBegin, const_cast<char**>(ArgBegin));
  if (!Clang.hasDiagnostics())
    return 1;

  // Set an error handler, so that any LLVM backend diagnostics go through our
  // error handler.
  llvm::llvm_install_error_handler(LLVMErrorHandler,
                                   static_cast<void*>(&Clang.getDiagnostics()));

  DiagsBuffer.FlushDiagnostics(Clang.getDiagnostics());

  // Load any requested plugins.
  for (unsigned i = 0,
         e = Clang.getFrontendOpts().Plugins.size(); i != e; ++i) {
    const std::string &Path = Clang.getFrontendOpts().Plugins[i];
    std::string Error;
    if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error))
      Diags.Report(diag::err_fe_unable_to_load_plugin) << Path << Error;
  }

  // If there were errors in processing arguments, don't do anything else.
  bool Success = false;
  if (!Clang.getDiagnostics().getNumErrors()) {
    // Create and execute the frontend action.
    llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang));
    if (Act)
      Success = Clang.ExecuteAction(*Act);
  }

  // Managed static deconstruction. Useful for making things like
  // -time-passes usable.
  llvm::llvm_shutdown();

  return !Success;
}
Exemplo n.º 8
0
extern "C"  void* getFunctionPointer(const char *filename, const char *function)
{
  raw_string_ostream sstream(error);
  error.clear();
  // if no execution engine is present, create new one
  if (!EE)
  {
    llvm::InitializeNativeTarget();
    llvm::InitializeNativeTargetAsmPrinter();
    Ctx.reset(new llvm::LLVMContext());

    llvm::sys::Path Path = GetExecutablePath("clang");
    IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
    TextDiagnosticPrinter *DiagClient =
      new TextDiagnosticPrinter(sstream, &*DiagOpts);

    IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
    DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);
    Driver TheDriver(Path.str(), llvm::sys::getProcessTriple(), "a.out", Diags);
    TheDriver.setTitle("clang interpreter");

    // FIXME: This is a hack to try to force the driver to do something we can
    // recognize. We need to extend the driver library to support this use model
    // (basically, exactly one input, and the operation mode is hard wired).
    SmallVector<const char *, 16> Args(0);
    // argv[0] = clang - emulate program name
    Args.push_back("clang");
    // argv[1] = file to compile
    Args.push_back(filename);
    Args.push_back("-fsyntax-only");
    OwningPtr<Compilation> C(TheDriver.BuildCompilation(Args));
    if (!C)
    {
      sstream << "Can't create Compilation object (TheDriver.BuildCompilation())\n";
      return NULL;
    }

    // FIXME: This is copied from ASTUnit.cpp; simplify and eliminate.

    // We expect to get back exactly one command job, if we didn't something
    // failed. Extract that job from the compilation.
    const driver::JobList &Jobs = C->getJobs();
    if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) {
      SmallString<256> Msg;
      llvm::raw_svector_ostream OS(Msg);
      sstream << "Wrong number of compiler jobs (see details below)\n";
      C->PrintJob(OS, C->getJobs(), "; ", true);
      Diags.Report(diag::err_fe_expected_compiler_job) << OS.str();
      return NULL;
    }

    const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
    if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
      sstream << "No clang job (see details below)\n";
      Diags.Report(diag::err_fe_expected_clang_command);
      return NULL;
    }

    // Initialize a compiler invocation object from the clang (-cc1) arguments.
    const driver::ArgStringList &CCArgs = Cmd->getArguments();
    OwningPtr<CompilerInvocation> CI(new CompilerInvocation);
    CompilerInvocation::CreateFromArgs(*CI,
                                       const_cast<const char **>(CCArgs.data()),
                                       const_cast<const char **>(CCArgs.data()) +
                                         CCArgs.size(),
                                       Diags);

    // FIXME: This is copied from cc1_main.cpp; simplify and eliminate.

    // Create a compiler instance to handle the actual work.
    CompilerInstance Clang;
    Clang.setInvocation(CI.take());

    // Create the compilers actual diagnostics engine.
    Clang.createDiagnostics();
    if (!Clang.hasDiagnostics())
    {
      sstream << "Can't create diagnostics engine\n";
      return NULL;
    }

    // Create and execute the frontend to generate an LLVM bitcode module.
    OwningPtr<CodeGenAction> Act(new EmitLLVMOnlyAction(Ctx.get()));
    if (!Clang.ExecuteAction(*Act))
    {
      sstream <<  "Can't execute frontend action (parsing source, converting to LLVM IR)\n";
      return NULL;
    }

    if (llvm::Module *Module = Act->takeModule())
    {
      // now let's create MSCJIT instance
      LLVMLinkInMCJIT();
      std::string Error;
      EE.reset(createMCJIT (Module, Error));
      if (!EE) {
        sstream <<  "Unable to make execution engine: " << Error;
        return NULL;
      }
      // compile module, apply memory permissions
      EE->finalizeObject();
      // retrieve requested function
      Function* F = Module->getFunction(function);
      if (!F) {
        sstream << "Function " << function << " couldn't be found in module\n";
        return NULL;
      }

      return EE->getPointerToFunction(F);
    }
  }


  // Execution engine already created
  if (EE)
  {
    // just find damn function
    Function* F = EE->FindFunctionNamed(function);
    if (!F) {
      sstream << "Function " << function << " couldn't be found in module\n";
      return NULL;
    }

    return EE->getPointerToFunction(F);
  }

  sstream << "Unknown error (may be no execution engine is present)\n";
  return NULL;
}
Exemplo n.º 9
0
std::unique_ptr<llvm::Module> ModelCompiler::compileModel(const char* filename)
{
    void *MainAddr = (void*) (intptr_t) GetExecutablePath;
    std::string Path = GetExecutablePath(mExecutable.c_str());
    DiagnosticOptions diagOpts;
    /*TextDiagnosticPrinter *DiagClient = */new TextDiagnosticPrinter(llvm::errs(), &diagOpts
                                                                     );

    llvm::IntrusiveRefCntPtr < DiagnosticIDs > DiagID(new DiagnosticIDs());
    DiagnosticsEngine Diags(DiagID, &diagOpts);

    // Use ELF on windows for now.
    std::string TripleStr = llvm::sys::getProcessTriple();
    llvm::Triple T(TripleStr);
    if (T.isOSBinFormatCOFF())
        T.setObjectFormat(llvm::Triple::ELF);
    std::cerr << "**&& triple string: " << T.str() << " &&**" << std::endl;
    Driver TheDriver(Path, T.str(), Diags);
//xx    Driver TheDriver(Path, llvm::sys::getHostTriple(), "a.out", /*IsProduction=*/
//xx            false, Diags);
    TheDriver.setTitle("csim clang compiler");

    llvm::SmallVector<const char *, 16> Args;//(argv, argv + argc);
    std::cout << "executable = '" << mExecutable.c_str() << "'" << std::endl;
    std::cout << "filename = '" << filename << "'" << std::endl;
    Args.push_back(mExecutable.c_str());
    Args.push_back("-fsyntax-only");
    Args.push_back("-x");
    Args.push_back("c");
    if (mDebug) Args.push_back("-g");
    else Args.push_back("-O3");
    if (mVerbose) Args.push_back("-v");
    Args.push_back(filename);
    std::unique_ptr < Compilation > C(TheDriver.BuildCompilation(Args));
    if (!C)
        return 0;

    // We expect to get back exactly one command job, if we didn't something
    // failed. Extract that job from the compilation.
    const driver::JobList &Jobs = C->getJobs();
    if (Jobs.size() != 1 || !isa < driver::Command > (*Jobs.begin()))
    {
        llvm::SmallString < 256 > Msg;
        llvm::raw_svector_ostream OS(Msg);
        C->getJobs().Print(OS, ";", true);
        //C->PrintJob(OS, C->getJobs(), "; ", true);
        Diags.Report(diag::err_fe_expected_compiler_job) << OS.str();
        return 0;
    }

    const driver::Command &Cmd = cast < driver::Command > (*Jobs.begin());
    if (llvm::StringRef(Cmd.getCreator().getName()) != "clang")
    {
        Diags.Report(diag::err_fe_expected_clang_command);
        return 0;
    }

    // Initialize a compiler invocation object from the clang (-cc1) arguments.
    const driver::ArgStringList &CCArgs = Cmd.getArguments();
    std::unique_ptr < CompilerInvocation > CI(new CompilerInvocation);
    CompilerInvocation::CreateFromArgs(*CI,
                                       const_cast<const char **>(CCArgs.data()),
                                       const_cast<const char **>(CCArgs.data()) + CCArgs.size(), Diags);

    // Show the invocation, with -v.
    if (CI->getHeaderSearchOpts().Verbose)
    {
        llvm::errs() << "clang invocation:\n";
        C->getJobs().Print(llvm::errs(), "\n", true);
        //C->PrintJob(llvm::errs(), C->getJobs(), "\n", true);
        llvm::errs() << "\n";
    }

    // Create a compiler instance to handle the actual work.
    CompilerInstance Clang;
    Clang.setInvocation(CI.release());

    // Create the compilers actual diagnostics engine.
    //Clang.createDiagnostics(int(CCArgs.size()), const_cast<char**>(CCArgs.data()));
    Clang.createDiagnostics();
    if (!Clang.hasDiagnostics())
        return 0;

    // Infer the builtin include path if unspecified.
    if (Clang.getHeaderSearchOpts().UseBuiltinIncludes
            && Clang.getHeaderSearchOpts().ResourceDir.empty())
        Clang.getHeaderSearchOpts().ResourceDir =
            CompilerInvocation::GetResourcesPath(mExecutable.c_str(), MainAddr);

#if 0 // Not needed as long as generated CellML code doesn't #include anything...
    // Need to add the clang system path, is there a way to get this? Need to include in executable?
    Clang.getHeaderSearchOpts().AddPath("/data/std-libs/llvm-opt/lib/clang/3.1/include/",
                                        clang::frontend::System, /*IsUserSupplied*/false, /*IsFramework*/false,
                                        /*IgnoreSysRoot*/false);
#endif

    // Create and execute the frontend to generate an LLVM bitcode module.
    CodeGenAction* Act(new EmitLLVMOnlyAction()); // <== FIXME: memory leak??
    if (!Clang.ExecuteAction(*Act))
        return 0;

    return Act->takeModule();
}
Exemplo n.º 10
0
int ModelCompiler::Compile(const char* executable, const char* filename, bool verbose)
{
    void *MainAddr = (void*) (intptr_t) GetExecutablePath;
    std::string Path = GetExecutablePath(executable);
    TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter(llvm::errs(),
            DiagnosticOptions());

    llvm::IntrusiveRefCntPtr < DiagnosticIDs > DiagID(new DiagnosticIDs());
    DiagnosticsEngine Diags(DiagID, DiagClient);
    Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), "a.out", /*IsProduction=*/
                     false, Diags);
    TheDriver.setTitle("clang compiler");

    // FIXME: This is a hack to try to force the driver to do something we can
    // recognize. We need to extend the driver library to support this use model
    // (basically, exactly one input, and the operation mode is hard wired).
    llvm::SmallVector<const char *, 16> Args;//(argv, argv + argc);
    Args.push_back(executable);
    Args.push_back("-fsyntax-only");
    if (verbose) Args.push_back("-v");
    Args.push_back(filename);
    llvm::OwningPtr < Compilation > C(TheDriver.BuildCompilation(Args));
    if (!C)
        return 0;

    // FIXME: This is copied from ASTUnit.cpp; simplify and eliminate.

    // We expect to get back exactly one command job, if we didn't something
    // failed. Extract that job from the compilation.
    const driver::JobList &Jobs = C->getJobs();
    if (Jobs.size() != 1 || !isa < driver::Command > (*Jobs.begin()))
    {
        llvm::SmallString < 256 > Msg;
        llvm::raw_svector_ostream OS(Msg);
        C->PrintJob(OS, C->getJobs(), "; ", true);
        Diags.Report(diag::err_fe_expected_compiler_job) << OS.str();
        return 1;
    }

    const driver::Command *Cmd = cast < driver::Command > (*Jobs.begin());
    if (llvm::StringRef(Cmd->getCreator().getName()) != "clang")
    {
        Diags.Report(diag::err_fe_expected_clang_command);
        return 1;
    }

    // Initialize a compiler invocation object from the clang (-cc1) arguments.
    const driver::ArgStringList &CCArgs = Cmd->getArguments();
    llvm::OwningPtr < CompilerInvocation > CI(new CompilerInvocation);
    CompilerInvocation::CreateFromArgs(*CI,
                                       const_cast<const char **>(CCArgs.data()),
                                       const_cast<const char **>(CCArgs.data()) + CCArgs.size(), Diags);

    // Show the invocation, with -v.
    if (CI->getHeaderSearchOpts().Verbose)
    {
        llvm::errs() << "clang invocation:\n";
        C->PrintJob(llvm::errs(), C->getJobs(), "\n", true);
        llvm::errs() << "\n";
    }

    // FIXME: This is copied from cc1_main.cpp; simplify and eliminate.

    // Create a compiler instance to handle the actual work.
    CompilerInstance Clang;
    Clang.setInvocation(CI.take());

    // Create the compilers actual diagnostics engine.
    Clang.createDiagnostics(int(CCArgs.size()),
                            const_cast<char**>(CCArgs.data()));
    if (!Clang.hasDiagnostics())
        return 1;

    // Infer the builtin include path if unspecified.
    if (Clang.getHeaderSearchOpts().UseBuiltinIncludes
            && Clang.getHeaderSearchOpts().ResourceDir.empty())
        Clang.getHeaderSearchOpts().ResourceDir =
            CompilerInvocation::GetResourcesPath(executable, MainAddr);

#if 0 // Not needed as long as generated CellML code doesn't #include anything...
    // Need to add the clang system path, is there a way to get this? Need to include in executable?
    Clang.getHeaderSearchOpts().AddPath("/data/std-libs/llvm-opt/lib/clang/3.1/include/",
                                        clang::frontend::System, /*IsUserSupplied*/false, /*IsFramework*/false,
                                        /*IgnoreSysRoot*/false);
#endif

    // Create and execute the frontend to generate an LLVM bitcode module.
    llvm::OwningPtr < CodeGenAction > Act(new EmitLLVMOnlyAction());
    if (!Clang.ExecuteAction(*Act))
        return 1;

    int Res = 255;
    if (llvm::Module *Module = Act->takeModule())
        Res = this->Integrate(Module);

    // Shutdown.

    llvm::llvm_shutdown();

    //std::cout << "The result is: " << Res << std::endl;

    return Res;
}