From 34ed7dbf95eae804655869828e4544366cc4b54b Mon Sep 17 00:00:00 2001 From: Yang Rong Date: Thu, 23 May 2013 13:48:46 +0800 Subject: 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 Reviewed-by: Zhigang Gong --- 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 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 +#include +#include +#if LLVM_VERSION_MINOR <= 1 +#include +#else +#include +#endif /* LLVM_VERSION_MINOR <= 1 */ +#include +#include +#include +#include +#include +#include +#include +#include + 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 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 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 DiagOpts = new clang::DiagnosticOptions(); + clang::TextDiagnosticPrinter *DiagClient = + new clang::TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); + llvm::IntrusiveRefCntPtr DiagID(new clang::DiagnosticIDs()); + clang::DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient); +#endif /* LLVM_VERSION_MINOR <= 1 */ + + // Create the compiler invocation + llvm::OwningPtr 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 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 -- cgit v1.2.3