summaryrefslogtreecommitdiff
path: root/lib/jit_factory.cpp
diff options
context:
space:
mode:
authorJosh Blum2013-08-05 00:59:07 -0700
committerJosh Blum2013-08-05 00:59:07 -0700
commitcb68dc4b2de256176e5ed224767241b033e2ede9 (patch)
treef54b52f4922234ab4365c6ccd0b69282828a4468 /lib/jit_factory.cpp
parent21bb17612dec27213805321fb656788ec423453f (diff)
downloadsandhi-cb68dc4b2de256176e5ed224767241b033e2ede9.tar.gz
sandhi-cb68dc4b2de256176e5ed224767241b033e2ede9.tar.bz2
sandhi-cb68dc4b2de256176e5ed224767241b033e2ede9.zip
gras: work on using clang api - but commented out
The last thing missing is that the API use case doesnt automatically have default C++ include paths.
Diffstat (limited to 'lib/jit_factory.cpp')
-rw-r--r--lib/jit_factory.cpp212
1 files changed, 146 insertions, 66 deletions
diff --git a/lib/jit_factory.cpp b/lib/jit_factory.cpp
index 882ee05..e7362cc 100644
--- a/lib/jit_factory.cpp
+++ b/lib/jit_factory.cpp
@@ -1,10 +1,29 @@
// Copyright (C) by Josh Blum. See LICENSE.txt for licensing information.
#include <gras/factory.hpp>
+#include <boost/foreach.hpp>
+#include <boost/format.hpp>
+#include <boost/thread/mutex.hpp>
#include <stdexcept>
+#include <iostream>
+#include <cstdio>
+#include <fstream>
+#include <map>
-#ifdef CLANG_EXECUTABLE
+//defined in module loader
+std::string get_gras_runtime_include_path(void);
+#ifdef HAVE_CLANG
+#include <clang/CodeGen/CodeGenAction.h>
+#include <clang/Frontend/CompilerInstance.h>
+#include <clang/Frontend/CompilerInvocation.h>
+#include <clang/Frontend/TextDiagnosticPrinter.h>
+#include <clang/Driver/Compilation.h>
+#include <clang/Driver/Driver.h>
+#include <clang/Driver/ArgList.h>
+#endif //HAVE_CLANG
+
+#ifdef HAVE_LLVM
#include <llvm/LLVMContext.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Bitcode/ReaderWriter.h>
@@ -12,36 +31,69 @@
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/ExecutionEngine/JIT.h>
#include <llvm/Support/system_error.h>
+#include <llvm/Support/Host.h>
+#include <llvm/Support/Program.h>
#include <llvm/Module.h>
+#endif //HAVE_LLVM
-#include <boost/foreach.hpp>
-#include <boost/format.hpp>
-#include <boost/thread/mutex.hpp>
-#include <stdexcept>
-#include <iostream>
-#include <cstdio>
-#include <fstream>
-#include <map>
+/***********************************************************************
+ * Storage for execution engines
+ **********************************************************************/
+#ifdef HAVE_LLVM
+struct ExecutionEngineMonitor
+{
+ ExecutionEngineMonitor(void)
+ {
+ boost::mutex::scoped_lock l(mutex);
+ }
-//defined in module loader
-std::string get_gras_runtime_include_path(void);
+ ~ExecutionEngineMonitor(void)
+ {
+ boost::mutex::scoped_lock l(mutex);
+ for (size_t i = 0; i < ees.size(); i++)
+ {
+ ees[i]->runStaticConstructorsDestructors(true);
+ ees[i].reset();
+ }
+ ees.clear();
+ }
+
+ void add(boost::shared_ptr<llvm::ExecutionEngine> ee)
+ {
+ boost::mutex::scoped_lock l(mutex);
+ ee->runStaticConstructorsDestructors(false);
+ ees.push_back(ee);
+ }
+
+ llvm::LLVMContext &get_context(void)
+ {
+ return context;
+ }
+
+ boost::mutex mutex;
+ llvm::LLVMContext context;
+ std::vector<boost::shared_ptr<llvm::ExecutionEngine> > ees;
+};
+
+static ExecutionEngineMonitor &get_eemon(void)
+{
+ static ExecutionEngineMonitor eemon;
+ return eemon;
+}
+#endif //HAVE_LLVM
/***********************************************************************
- * Helper function to call a clang compliation
+ * Helper function to call a clang compliation -- execs clang
**********************************************************************/
-static std::string call_clang(const std::string &source, const std::vector<std::string> &flags)
+#ifdef CLANG_EXECUTABLE
+static llvm::Module *call_clang_exe(const std::string &source_file, const std::vector<std::string> &flags)
{
+ std::cout << "GRAS compiler: compile source into bitcode..." << std::endl;
+
//make up bitcode file path
char bitcode_file[L_tmpnam];
std::tmpnam(bitcode_file);
- //write source to tmp file
- char source_file[L_tmpnam];
- std::tmpnam(source_file);
- std::ofstream source_fstream(source_file);
- source_fstream << source;
- source_fstream.close();
-
//begin command setup
std::vector<std::string> cmd;
cmd.push_back(BOOST_STRINGIZE(CLANG_EXECUTABLE));
@@ -63,9 +115,6 @@ static std::string call_clang(const std::string &source, const std::vector<std::
cmd.push_back(flag.c_str());
}
- //root include path
- cmd.push_back("-I"+get_gras_runtime_include_path());
-
//format command string
std::string command;
BOOST_FOREACH(const std::string &c, cmd)
@@ -81,84 +130,115 @@ static std::string call_clang(const std::string &source, const std::vector<std::
//readback bitcode for result
std::ifstream bitcode_fstream(bitcode_file);
- return std::string((std::istreambuf_iterator<char>(bitcode_fstream)), std::istreambuf_iterator<char>());
+ const std::string bitcode((std::istreambuf_iterator<char>(bitcode_fstream)), std::istreambuf_iterator<char>());
+
+ //create a memory buffer from the bitcode
+ boost::shared_ptr<llvm::MemoryBuffer> buffer(llvm::MemoryBuffer::getMemBuffer(bitcode));
+
+ //parse the bitcode into a module
+ std::string error;
+ llvm::Module *module = llvm::ParseBitcodeFile(buffer.get(), get_eemon().get_context(), &error);
+ if (not error.empty()) throw std::runtime_error("GRAS compiler: ParseBitcodeFile " + error);
+ return module;
}
+#endif //CLANG_EXECUTABLE
/***********************************************************************
- * Storage for execution engines
+ * Helper function to call a clang compliation -- uses clang API
**********************************************************************/
-struct ExecutionEngineMonitor
+/*
+#ifdef HAVE_CLANG
+static llvm::Module *call_clang_api(const std::string &source_file, const std::vector<std::string> &flags)
{
- ExecutionEngineMonitor(void)
- {
- boost::mutex::scoped_lock l(mutex);
- }
+ //begin command setup
+ std::vector<const char *> args;
- ~ExecutionEngineMonitor(void)
- {
- boost::mutex::scoped_lock l(mutex);
- for (size_t i = 0; i < ees.size(); i++)
- {
- ees[i]->runStaticConstructorsDestructors(true);
- ees[i].reset();
- }
- ees.clear();
- }
+ //inject source
+ args.push_back("-c");
+ args.push_back("-x");
+ args.push_back("c++");
+ args.push_back(source_file.c_str());
- void add(boost::shared_ptr<llvm::ExecutionEngine> ee)
+ //inject args...
+ BOOST_FOREACH(const std::string &flag, flags)
{
- boost::mutex::scoped_lock l(mutex);
- ee->runStaticConstructorsDestructors(false);
- ees.push_back(ee);
+ args.push_back(flag.c_str());
}
- llvm::LLVMContext &get_context(void)
+ //http://fdiv.net/2012/08/15/compiling-code-clang-api
+
+ // The compiler invocation needs a DiagnosticsEngine so it can report problems
+ clang::DiagnosticOptions *DiagOpts = new clang::DiagnosticOptions();
+ clang::TextDiagnosticPrinter *DiagClient = new clang::TextDiagnosticPrinter(llvm::errs(), DiagOpts);
+ llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(new clang::DiagnosticIDs());
+ clang::DiagnosticsEngine Diags(DiagID, DiagOpts, DiagClient);
+
+ // Create the compiler invocation
+ clang::LangOptions LangOpts;
+ llvm::OwningPtr<clang::CompilerInvocation> CI(new clang::CompilerInvocation());
+ //CI->setLangDefaults(LangOpts, clang::IK_CXX, clang::LangStandard::lang_gnucxx98);
+ clang::CompilerInvocation::CreateFromArgs(*CI, &args[0], &args[0] + args.size(), Diags);
+
+ // Print the argument list
+ std::cout << "clang ";
+ BOOST_FOREACH(const char *arg, args)
{
- return context;
+ std::cout << arg << " ";
}
+ std::cout << std::endl;
- boost::mutex mutex;
- llvm::LLVMContext context;
- std::vector<boost::shared_ptr<llvm::ExecutionEngine> > ees;
-};
+ // Create the compiler instance
+ clang::CompilerInstance Clang;
+ Clang.setInvocation(CI.take());
-static ExecutionEngineMonitor &get_eemon(void)
-{
- static ExecutionEngineMonitor eemon;
- return eemon;
+ // Get ready to report problems
+ Clang.createDiagnostics(args.size(), &args[0]);
+ if (not Clang.hasDiagnostics()) throw std::runtime_error("ClangBlock::createDiagnostics");
+
+ // Create an action and make the compiler instance carry it out
+ clang::CodeGenAction *Act = new clang::EmitLLVMOnlyAction();
+ if (not Clang.ExecuteAction(*Act)) throw std::runtime_error("ClangBlock::EmitLLVMOnlyAction");
+
+ return Act->takeModule();
}
+#endif //HAVE_CLANG
+*/
/***********************************************************************
* factory compile implementation
**********************************************************************/
-void gras::jit_factory(const std::string &source, const std::vector<std::string> &flags)
+#ifdef HAVE_LLVM
+void gras::jit_factory(const std::string &source, const std::vector<std::string> &flags_)
{
- std::cout << "GRAS compiler: compile source into bitcode..." << std::endl;
- const std::string bitcode = call_clang(source, flags);
+ //write source to tmp file
+ char source_file[L_tmpnam];
+ std::tmpnam(source_file);
+ std::ofstream source_fstream(source_file);
+ source_fstream << source;
+ source_fstream.close();
llvm::InitializeNativeTarget();
llvm::llvm_start_multithreaded();
- std::string error;
- //create a memory buffer from the bitcode
- boost::shared_ptr<llvm::MemoryBuffer> buffer(llvm::MemoryBuffer::getMemBuffer(bitcode));
-
- //parse the bitcode into a module
- llvm::Module *module = llvm::ParseBitcodeFile(buffer.get(), get_eemon().get_context(), &error);
- if (not error.empty()) throw std::runtime_error("GRAS compiler: ParseBitcodeFile " + error);
+ //use clang to compile source into bitcode
+ std::cout << "GRAS compiler: compile source into bitcode..." << std::endl;
+ std::vector<std::string> flags = flags_;
+ flags.push_back("-I"+get_gras_runtime_include_path()); //add root include path
+ llvm::Module *module = call_clang_exe(source_file, flags);
//create execution engine
+ std::string error;
boost::shared_ptr<llvm::ExecutionEngine> ee(llvm::ExecutionEngine::create(module, false, &error));
if (not error.empty()) throw std::runtime_error("GRAS compiler: ExecutionEngine " + error);
std::cout << "GRAS compiler: execute static constructors..." << std::endl;
get_eemon().add(ee);
}
-#else //CLANG_EXECUTABLE
+#else //HAVE_LLVM
void Factory::compile(const std::string &, const std::vector<std::string> &)
{
throw std::runtime_error("GRAS compiler not built with Clang support!");
}
-#endif //CLANG_EXECUTABLE
+#endif //HAVE_LLVM