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