summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmake/Modules/FindClang.cmake1
m---------grextras0
-rw-r--r--lib/CMakeLists.txt28
-rw-r--r--lib/jit_factory.cpp212
4 files changed, 165 insertions, 76 deletions
diff --git a/cmake/Modules/FindClang.cmake b/cmake/Modules/FindClang.cmake
index cbce0af..1b8be4a 100644
--- a/cmake/Modules/FindClang.cmake
+++ b/cmake/Modules/FindClang.cmake
@@ -18,6 +18,7 @@ ENDMACRO(FIND_AND_ADD_CLANG_LIB)
# Clang shared library provides just the limited C interface, so it
# can not be used. We look for the static libraries.
+FIND_AND_ADD_CLANG_LIB(clangSerialization)
FIND_AND_ADD_CLANG_LIB(clangFrontend)
FIND_AND_ADD_CLANG_LIB(clangDriver)
FIND_AND_ADD_CLANG_LIB(clangCodeGen)
diff --git a/grextras b/grextras
-Subproject 3aa900e4908d82d222806a3a7d17faf94505d86
+Subproject 02e23f149fda731a5049f6df40a7a6eaff882f1
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 2d61b91..f8aaebc 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -107,26 +107,34 @@ endif()
########################################################################
# Setup factory compiler
########################################################################
+
+#step 1) call into the LLVM find package
find_program(LLVM_CONFIG_EXECUTABLE llvm-config DOC "llvm-config executable")
if(LLVM_CONFIG_EXECUTABLE)
find_package(LLVM)
endif()
-if(LLVM_FOUND)
- find_program(CLANG_EXECUTABLE clang DOC "clang executable")
- set(CLANG_FOUND ${CLANG_EXECUTABLE})
-else()
- message(WARNING "LLVM library not found - optional for factory compiler")
-endif()
-if(NOT CLANG_FOUND)
- message(WARNING "Clang executable not found - optional for factory compiler")
-endif()
-if(CLANG_FOUND)
+#step 2) setup LLVM if found and find Clang
+if(LLVM_FOUND)
+ add_definitions(-DHAVE_LLVM)
add_definitions(${LLVM_CFLAGS})
link_directories(${LLVM_LIBRARY_DIRS})
include_directories(${LLVM_INCLUDE_DIRS})
list(APPEND GRAS_LIBRARIES ${LLVM_MODULE_LIBS})
list(APPEND GRAS_LIBRARIES ${LLVM_LDFLAGS})
+ find_package(Clang)
+endif()
+
+#step 3) setup Clang if found
+if(CLANG_FOUND)
+ add_definitions(-DHAVE_CLANG)
+ include_directories(${CLANG_INCLUDE_DIRS})
+ list(APPEND GRAS_LIBRARIES ${CLANG_LIBS})
+endif()
+
+#step 4) find clang executable as backup (found llvm but not clang dev)
+find_program(CLANG_EXECUTABLE clang DOC "clang executable")
+if(CLANG_EXECUTABLE)
SET_SOURCE_FILES_PROPERTIES(
${CMAKE_CURRENT_SOURCE_DIR}/jit_factory.cpp
PROPERTIES COMPILE_DEFINITIONS "CLANG_EXECUTABLE=${CLANG_EXECUTABLE}"
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