diff options
author | Yang Rong <rong.r.yang@intel.com> | 2013-05-23 13:48:46 +0800 |
---|---|---|
committer | Zhigang Gong <zhigang.gong@linux.intel.com> | 2013-05-23 13:51:20 +0800 |
commit | 34ed7dbf95eae804655869828e4544366cc4b54b (patch) | |
tree | 116ed06bd73f3ae9d43ce6487231d17a91538690 | |
parent | 5fb4ca0755d62ba62e30f17511b1314ade5c017d (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.cmake | 27 | ||||
-rw-r--r-- | backend/src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | 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 <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 |