[Beignet] [PATCH 1/2] Change clang system call to libclang api call.

Yang Rong rong.r.yang at intel.com
Wed May 22 22:48:46 PDT 2013


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 at intel.com>
---
 CMake/FindLLVM.cmake            |   27 +++++++++-
 backend/src/CMakeLists.txt      |    1 +
 backend/src/backend/program.cpp |  103 +++++++++++++++++++++++++++++++--------
 3 files changed, 110 insertions(+), 21 deletions(-)

diff --git a/CMake/FindLLVM.cmake b/CMake/FindLLVM.cmake
index c06b8a4..b320639 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 183517a..a0fe198 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 c46c681..6816a13 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
-- 
1.7.9.5



More information about the Beignet mailing list