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(); }
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; }
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; }
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 }
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; }
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; }
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; }
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(); }
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; }