summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYang Rong <rong.r.yang@intel.com>2013-05-23 13:48:46 +0800
committerZhigang Gong <zhigang.gong@linux.intel.com>2013-05-23 13:51:20 +0800
commit34ed7dbf95eae804655869828e4544366cc4b54b (patch)
tree116ed06bd73f3ae9d43ce6487231d17a91538690
parent5fb4ca0755d62ba62e30f17511b1314ade5c017d (diff)
Change clang system call to libclang api call.
The original call clang command directly as frontend. The implement is not very flexible. I change to call libclang apis, support both clang 3.1 and clang 3.2. Now still write the intermediate to the file, for code simply. Signed-off-by: Yang Rong <rong.r.yang@intel.com> Reviewed-by: Zhigang Gong <zhigang.gong@linux.intel.com>
-rw-r--r--CMake/FindLLVM.cmake27
-rw-r--r--backend/src/CMakeLists.txt1
-rw-r--r--backend/src/backend/program.cpp103
3 files changed, 110 insertions, 21 deletions
diff --git a/CMake/FindLLVM.cmake b/CMake/FindLLVM.cmake
index c06b8a48..b3206391 100644
--- a/CMake/FindLLVM.cmake
+++ b/CMake/FindLLVM.cmake
@@ -8,7 +8,7 @@
# LLVM_FOUND - True if llvm found.
if (LLVM_INSTALL_DIR)
find_program(LLVM_CONFIG_EXECUTABLE NAMES llvm-config-32 llvm-config-3.2 llvm-config DOC "llvm-config executable" PATHS ${LLVM_INSTALL_DIR} NO_DEFAULT_PATH)
-else (LLVM_INSTALL_DIR)
+else (LLVM_INSTALL_DIR)
find_program(LLVM_CONFIG_EXECUTABLE NAMES llvm-config-32 llvm-config-3.2 llvm-config DOC "llvm-config executable")
endif (LLVM_INSTALL_DIR)
@@ -66,3 +66,28 @@ execute_process(
OUTPUT_VARIABLE LLVM_MODULE_LIBS
OUTPUT_STRIP_TRAILING_WHITESPACE
)
+
+macro(add_one_lib name)
+ FIND_LIBRARY(CLANG_LIB
+ NAMES ${name}
+ PATHS ${LLVM_LIBRARY_DIR} )
+ set(CLANG_LIBRARIES ${CLANG_LIBRARIES} ${CLANG_LIB})
+ unset(CLANG_LIB CACHE)
+endmacro()
+
+#Assume clang lib path same as llvm lib path
+add_one_lib("clangFrontend")
+add_one_lib("clangSerialization")
+add_one_lib("clangDriver")
+add_one_lib("clangCodeGen")
+add_one_lib("clangSema")
+add_one_lib("clangStaticAnalyzerFrontend")
+add_one_lib("clangStaticAnalyzerCheckers")
+add_one_lib("clangStaticAnalyzerCore")
+add_one_lib("clangAnalysis")
+add_one_lib("clangEdit")
+add_one_lib("clangAST")
+add_one_lib("clangParse")
+add_one_lib("clangSema")
+add_one_lib("clangLex")
+add_one_lib("clangBasic")
diff --git a/backend/src/CMakeLists.txt b/backend/src/CMakeLists.txt
index 183517ae..a0fe1982 100644
--- a/backend/src/CMakeLists.txt
+++ b/backend/src/CMakeLists.txt
@@ -116,6 +116,7 @@ target_link_libraries(
${DRM_INTEL_LIBRARY}
${DRM_LIBRARY}
${OPENGL_LIBRARIES}
+ ${CLANG_LIBRARIES}
${LLVM_MODULE_LIBS}
${CMAKE_THREAD_LIBS_INIT}
${CMAKE_DL_LIBS})
diff --git a/backend/src/backend/program.cpp b/backend/src/backend/program.cpp
index c46c681b..6816a134 100644
--- a/backend/src/backend/program.cpp
+++ b/backend/src/backend/program.cpp
@@ -46,6 +46,23 @@
#define LLVM_VERSION_MINOR 0
#endif /* !defined(LLVM_VERSION_MINOR) */
+#include <clang/CodeGen/CodeGenAction.h>
+#include <clang/Frontend/CompilerInstance.h>
+#include <clang/Frontend/CompilerInvocation.h>
+#if LLVM_VERSION_MINOR <= 1
+#include <clang/Frontend/DiagnosticOptions.h>
+#else
+#include <clang/Basic/DiagnosticOptions.h>
+#endif /* LLVM_VERSION_MINOR <= 1 */
+#include <clang/Frontend/TextDiagnosticPrinter.h>
+#include <clang/Basic/TargetInfo.h>
+#include <clang/Basic/TargetOptions.h>
+#include <llvm/ADT/IntrusiveRefCntPtr.h>
+#include <llvm/ADT/OwningPtr.h>
+#include <llvm/Module.h>
+#include <llvm/Bitcode/ReaderWriter.h>
+#include <llvm/Support/raw_ostream.h>
+
namespace gbe {
Kernel::Kernel(const std::string &name) :
@@ -104,6 +121,71 @@ namespace gbe {
GBE_SAFE_DELETE(program);
}
+ static void buildModuleFromSource(const char* input, const char* output) {
+ // Arguments to pass to the clang frontend
+ vector<const char *> args;
+ args.push_back("-emit-llvm");
+ args.push_back("-O3");
+ args.push_back("-triple");
+ args.push_back("nvptx");
+ args.push_back(input);
+
+ // The compiler invocation needs a DiagnosticsEngine so it can report problems
+#if LLVM_VERSION_MINOR <= 1
+ args.push_back("-triple");
+ args.push_back("ptx32");
+
+ clang::TextDiagnosticPrinter *DiagClient =
+ new clang::TextDiagnosticPrinter(llvm::errs(), clang::DiagnosticOptions());
+ llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(new clang::DiagnosticIDs());
+ clang::DiagnosticsEngine Diags(DiagID, DiagClient);
+#else
+ args.push_back("-ffp-contract=off");
+ args.push_back("-triple");
+ args.push_back("nvptx");
+
+ llvm::IntrusiveRefCntPtr<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);
+#endif /* LLVM_VERSION_MINOR <= 1 */
+
+ // Create the compiler invocation
+ llvm::OwningPtr<clang::CompilerInvocation> CI(new clang::CompilerInvocation);
+ clang::CompilerInvocation::CreateFromArgs(*CI,
+ &args[0],
+ &args[0] + args.size(),
+ Diags);
+
+ // Create the compiler instance
+ clang::CompilerInstance Clang;
+ Clang.setInvocation(CI.take());
+ // Get ready to report problems
+ Clang.createDiagnostics(args.size(), &args[0]);
+ if (!Clang.hasDiagnostics())
+ return;
+
+ // Set Language
+ clang::LangOptions & lang_opts = Clang.getLangOpts();
+ lang_opts.OpenCL = 1;
+
+ // Create an action and make the compiler instance carry it out
+ llvm::OwningPtr<clang::CodeGenAction> Act(new clang::EmitLLVMOnlyAction());
+ if (!Clang.ExecuteAction(*Act))
+ return;
+
+ llvm::Module *module = Act->takeModule();
+
+ std::string ErrorInfo;
+ llvm::raw_fd_ostream OS(output, ErrorInfo,llvm::raw_fd_ostream::F_Binary);
+ //still write to temp file for code simply, otherwise need add another function.
+ //because gbe_program_new_from_llvm also be used by cl_program_create_from_llvm, can't be removed
+ //TODO: Pass module to llvmToGen, if use module, should return Act and use OwningPtr out of this funciton
+ llvm::WriteBitcodeToFile(module, OS);
+ OS.close();
+ }
+
extern std::string ocl_stdlib_str;
extern std::string ocl_common_defines_str;
static gbe_program programNewFromSource(const char *source,
@@ -124,26 +206,7 @@ namespace gbe {
fwrite(source, strlen(source), 1, clFile);
fclose(clFile);
- // Now compile the code to llvm using clang
-#if LLVM_VERSION_MINOR <= 1
- std::string compileCmd = "clang -x cl -fno-color-diagnostics -emit-llvm -O3 -ccc-host-triple ptx32 -c ";
-#else
- std::string compileCmd = "clang -ffp-contract=off -emit-llvm -O3 -target nvptx -x cl -c ";
-#endif /* LLVM_VERSION_MINOR <= 1 */
- compileCmd += clName;
- compileCmd += " ";
- if(options)
- compileCmd += options;
- compileCmd += " -o ";
- compileCmd += llName;
-
- // Open a pipe and compile from here. Using Clang API instead is better
- FILE *pipe = popen(compileCmd.c_str(), "r");
- FATAL_IF (pipe == NULL, "Unable to run extern compilation command");
- char msg[256];
- while (fgets(msg, sizeof(msg), pipe))
- std::cout << msg;
- pclose(pipe);
+ buildModuleFromSource(clName.c_str(), llName.c_str());
remove(clName.c_str());
// Now build the program from llvm