diff options
Diffstat (limited to 'backend/src')
-rw-r--r-- | backend/src/CMakeLists.txt | 135 | ||||
-rw-r--r-- | backend/src/GBEConfig.h.in | 5 | ||||
-rw-r--r-- | backend/src/backend/program.cpp | 276 | ||||
-rw-r--r-- | backend/src/libocl/CMakeLists.txt | 209 | ||||
-rw-r--r-- | backend/src/libocl/include/ocl.h | 23 | ||||
-rw-r--r-- | backend/src/llvm/llvm_to_gen.cpp | 70 |
6 files changed, 371 insertions, 347 deletions
diff --git a/backend/src/CMakeLists.txt b/backend/src/CMakeLists.txt index 85b5e21e..1df87324 100644 --- a/backend/src/CMakeLists.txt +++ b/backend/src/CMakeLists.txt @@ -1,95 +1,25 @@ -set (ocl_vector_spec_file ${GBE_SOURCE_DIR}/src/builtin_vector_proto.def) -set (ocl_vector_file ${GBE_SOURCE_DIR}/src/ocl_vector.h) -set (ocl_as_file ${GBE_SOURCE_DIR}/src/ocl_as.h) -set (ocl_convert_file ${GBE_SOURCE_DIR}/src/ocl_convert.h) -set (ocl_stdlib_tmpl_file ${GBE_SOURCE_DIR}/src/ocl_stdlib.tmpl.h) -set (ocl_common_header_file ${GBE_SOURCE_DIR}/src/ocl_common_defines.h) -set (ocl_blob_file ${CMAKE_CURRENT_BINARY_DIR}${BEIGNET_INSTALL_DIR}ocl_stdlib.h) -set (ocl_blob_cpp_file ${GBE_SOURCE_DIR}/src/ocl_stdlib_str.cpp) -set (ocl_gen_blob_cmd ${GBE_SOURCE_DIR}/src/update_blob_ocl_header.py) -set (ocl_gen_vector_cmd ${GBE_SOURCE_DIR}/src/gen_builtin_vector.py) - -set (string_header "\\\"string\\\"") -add_custom_command( - OUTPUT ${ocl_blob_cpp_file} - COMMAND rm -rf ${ocl_blob_cpp_file} - COMMAND echo "\\\#include ${string_header}" >> ${ocl_blob_cpp_file} - COMMAND echo "namespace gbe {" >> ${ocl_blob_cpp_file} - COMMAND echo "std::string ocl_stdlib_str = " >> ${ocl_blob_cpp_file} - # Yeah!!! welcome to back slash hell - COMMAND cat ${ocl_blob_file} |sed 's/\\\\/\\\\\\\\/g' | sed 's/\\\"/\\\\\\\"/g' | awk '{ printf \(\"\\"%s\\\\n\\"\\n\", $$0\) }' >> ${ocl_blob_cpp_file} - COMMAND echo "\;" >> ${ocl_blob_cpp_file} - COMMAND echo "}" >> ${ocl_blob_cpp_file} - COMMAND echo "" >> ${ocl_blob_cpp_file} - DEPENDS ${ocl_blob_file}) - -set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "ocl_vector.h;${ocl_blob_file}") - -add_custom_command( - OUTPUT ${ocl_vector_file} - COMMAND ${PYTHON_EXECUTABLE} ${ocl_gen_vector_cmd} ${ocl_vector_spec_file} ${ocl_vector_file} - DEPENDS ${ocl_gen_vector_cmd} ${ocl_vector_spec_file} - ) - -add_custom_command( - OUTPUT ${ocl_blob_file} - COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/${BEIGNET_INSTALL_DIR} - COMMAND ${PYTHON_EXECUTABLE} ${ocl_gen_blob_cmd} ${ocl_stdlib_tmpl_file} ${ocl_blob_file} - DEPENDS ${ocl_gen_blob_cmd} ${ocl_stdlib_tmpl_file} ${ocl_common_header_file} ${ocl_vector_file} ${ocl_as_file} ${ocl_convert_file} - ) - -set (pch_object ${ocl_blob_file}.pch) -set (local_pch_object ${ocl_blob_file}.local.pch) -# generate pch object -if (LLVM_VERSION_NODOT VERSION_GREATER 32) - set (clang_cmd -cc1 -x cl -triple spir -ffp-contract=off -cl-kernel-arg-info) -else (LLVM_VERSION_NODOT VERSION_GREATER 32) - if (LLVM_VERSION_NODOT VERSION_GREATER 31) - set (clang_cmd -cc1 -x cl -triple nvptx -ffp-contract=off) - else (LLVM_VERSION_NODOT VERSION_GREATER 31) - set (clang_cmd -cc1 -x cl -triple ptx32) - endif (LLVM_VERSION_NODOT VERSION_GREATER 31) -endif (LLVM_VERSION_NODOT VERSION_GREATER 32) -set (clang_cmd ${clang_cmd} -fno-builtin -DGEN7_SAMPLER_CLAMP_BORDER_WORKAROUND) +set (OCL_BITCODE_BIN "${BEIGNET_INSTALL_DIR}beignet.bc:${CMAKE_CURRENT_BINARY_DIR}/libocl/lib/beignet.bc") +set (OCL_HEADER_DIR "${CMAKE_INSTALL_PREFIX}/include/CL/ocl/:${CMAKE_CURRENT_BINARY_DIR}/libocl/include/") +set (OCL_PCH_OBJECT "${BEIGNET_INSTALL_DIR}beignet.pch:${CMAKE_CURRENT_BINARY_DIR}/libocl/lib/beignet.pch") +set (GBE_OBJECT_DIR "${BEIGNET_INSTALL_DIR}/libgbe.so") +set (INTERP_OBJECT_DIR "${BEIGNET_INSTALL_DIR}/libgbeinterp.so") -add_custom_command( - OUTPUT ${pch_object} - COMMAND rm -f ${pch_object} - COMMAND ${LLVM_INSTALL_DIR}clang ${clang_cmd} --relocatable-pch -emit-pch -isysroot ${CMAKE_CURRENT_BINARY_DIR} ${ocl_blob_file} -o ${pch_object} - COMMAND ${LLVM_INSTALL_DIR}clang ${clang_cmd} -emit-pch ${ocl_blob_file} -o ${local_pch_object} - DEPENDS ${ocl_blob_file} - ) +set (LOCAL_GBE_OBJECT_DIR "${CMAKE_CURRENT_BINARY_DIR}/libgbe.so" PARENT_SCOPE) +set (LOCAL_OCL_BITCODE_BIN "${CMAKE_CURRENT_BINARY_DIR}/libocl/lib/beignet.bc" PARENT_SCOPE) +set (LOCAL_OCL_HEADER_DIR "${CMAKE_CURRENT_BINARY_DIR}/libocl/include/" PARENT_SCOPE) +set (LOCAL_OCL_PCH_OBJECT "${CMAKE_CURRENT_BINARY_DIR}/libocl/lib/beignet.pch" PARENT_SCOPE) +set (LOCAL_INTERP_OBJECT_DIR "${CMAKE_CURRENT_BINARY_DIR}/libgbeinterp.so" PARENT_SCOPE) -add_custom_target(pch_object - DEPENDS ${pch_object}) +configure_file ( + "GBEConfig.h.in" + "GBEConfig.h" +) -macro(ll_add_library ll_lib ll_sources) - foreach (ll ${${ll_sources}}) - add_custom_command( - OUTPUT ${ll}.bc - COMMAND rm -f ${ll}.bc - COMMAND ${LLVM_INSTALL_DIR}llvm-as -o ${ll}.bc ${GBE_SOURCE_DIR}/src/${ll} - DEPENDS ${ll} - ) - set (ll_objects ${ll_objects} ${ll}.bc) - endforeach (ll ${ll_sources}) - add_custom_command( - OUTPUT ${ll_lib} - COMMAND ${LLVM_INSTALL_DIR}llvm-link -o ${ll_lib} ${ll_objects} - DEPENDS ${ll_objects} - ) - add_custom_target(${ll_lib} - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ll_lib}) -endmacro(ll_add_library) +add_subdirectory(libocl) +add_dependencies(beignet_bitcode libocl) -if (GBE_USE_BLOB) - set (GBE_SRC - blob.cpp - backend/gen/gen_mesa_disasm.c) -else (GBE_USE_BLOB) - set (GBE_SRC +set (GBE_SRC ${ocl_blob_file} - ocl_stdlib_str.cpp # this file is auto-generated. sys/vector.hpp sys/hash_map.hpp sys/map.hpp @@ -143,6 +73,7 @@ else (GBE_USE_BLOB) backend/program.cpp backend/program.hpp backend/program.h + llvm/llvm_bitcode_link.cpp llvm/llvm_gen_backend.cpp llvm/llvm_passes.cpp llvm/llvm_scalarize.cpp @@ -176,19 +107,13 @@ else (GBE_USE_BLOB) backend/gen75_encoder.cpp ) -endif (GBE_USE_BLOB) include_directories (.) link_directories (${LLVM_LIBRARY_DIRS} ${DRM_LIBDIR}) include_directories(${LLVM_INCLUDE_DIRS}) add_library (gbe SHARED ${GBE_SRC}) -# for pre compiled module library. -set (pcm_lib "beignet.bc") -set (pcm_sources ocl_barrier.ll ocl_memset.ll ocl_memcpy.ll) -ll_add_library (${pcm_lib} pcm_sources) -ADD_DEPENDENCIES (gbe pch_object ${pcm_lib}) target_link_libraries( gbe ${DRM_INTEL_LIBRARIES} @@ -201,6 +126,8 @@ target_link_libraries( add_library(gbeinterp SHARED gbe_bin_interpreter.cpp) +add_dependencies(gbe beignet_bitcode) + if (LLVM_VERSION_NODOT VERSION_EQUAL 34) find_library(TERMINFO NAMES tinfo ncurses) if (${TERMINFO} STREQUAL TERMINFO-NOTFOUND) @@ -217,22 +144,6 @@ TARGET_LINK_LIBRARIES(gbe_bin_generater gbe) install (TARGETS gbe LIBRARY DESTINATION ${BEIGNET_INSTALL_DIR}) install (TARGETS gbeinterp LIBRARY DESTINATION ${BEIGNET_INSTALL_DIR}) -#install (FILES backend/program.h DESTINATION include/gen) -install (FILES ${ocl_blob_file} DESTINATION ${BEIGNET_INSTALL_DIR}) -install (FILES ${pch_object} DESTINATION ${BEIGNET_INSTALL_DIR}) -install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${pcm_lib} DESTINATION ${BEIGNET_INSTALL_DIR}) -# When build beignet itself, we need to export the local precompiled header file and precompiled module -# file to libcl and utests. -set (LOCAL_PCH_OBJECT_DIR "${local_pch_object}:${BEIGNET_INSTALL_DIR}/ocl_stdlib.h.pch" PARENT_SCOPE) -set (LOCAL_PCM_OBJECT_DIR "${CMAKE_CURRENT_BINARY_DIR}/${pcm_lib}:${BEIGNET_INSTALL_DIR}/${pcm_lib}" PARENT_SCOPE) -set (LOCAL_GBE_OBJECT_DIR "${CMAKE_CURRENT_BINARY_DIR}/libgbe.so" PARENT_SCOPE) -set (LOCAL_INTERP_OBJECT_DIR "${CMAKE_CURRENT_BINARY_DIR}/libgbeinterp.so" PARENT_SCOPE) - -set (PCH_OBJECT_DIR "${BEIGNET_INSTALL_DIR}/ocl_stdlib.h.pch") -set (PCM_OBJECT_DIR "${BEIGNET_INSTALL_DIR}/${pcm_lib}") -set (GBE_OBJECT_DIR "${BEIGNET_INSTALL_DIR}/libgbe.so") -set (INTERP_OBJECT_DIR "${BEIGNET_INSTALL_DIR}/libgbeinterp.so") -configure_file ( - "GBEConfig.h.in" - "GBEConfig.h" -) +install (FILES ${CMAKE_CURRENT_BINARY_DIR}/libocl/lib/beignet.bc DESTINATION ${BEIGNET_INSTALL_DIR}) +install (FILES ${CMAKE_CURRENT_BINARY_DIR}/libocl/lib/beignet.pch DESTINATION ${BEIGNET_INSTALL_DIR}) +install (DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/libocl/include/ DESTINATION ${CMAKE_INSTALL_PREFIX}/include/CL/ocl/ PATTERN *.h) diff --git a/backend/src/GBEConfig.h.in b/backend/src/GBEConfig.h.in index f5c69c68..b5bec14a 100644 --- a/backend/src/GBEConfig.h.in +++ b/backend/src/GBEConfig.h.in @@ -1,7 +1,8 @@ // the configured options and settings for LIBGBE #define LIBGBE_VERSION_MAJOR @LIBGBE_VERSION_MAJOR@ #define LIBGBE_VERSION_MINOR @LIBGBE_VERSION_MINOR@ -#define PCH_OBJECT_DIR "@PCH_OBJECT_DIR@" -#define PCM_OBJECT_DIR "@PCM_OBJECT_DIR@" #define GBE_OBJECT_DIR "@GBE_OBJECT_DIR@" #define INTERP_OBJECT_DIR "@INTERP_OBJECT_DIR@" +#define OCL_BITCODE_BIN "@OCL_BITCODE_BIN@" +#define OCL_HEADER_DIR "@OCL_HEADER_DIR@" +#define OCL_PCH_OBJECT "@OCL_PCH_OBJECT@" diff --git a/backend/src/backend/program.cpp b/backend/src/backend/program.cpp index 20471f94..ac651d51 100644 --- a/backend/src/backend/program.cpp +++ b/backend/src/backend/program.cpp @@ -491,38 +491,6 @@ namespace gbe { /*********************** End of Program class member function *************************/ -#define REDEF_MATH_FUNC(x) "#ifdef "#x"\n#undef "#x"\n#endif\n#define "#x" __gen_ocl_internal_fastpath_"#x"\n" - std::string ocl_mathfunc_fastpath_str = - REDEF_MATH_FUNC(acosh) - REDEF_MATH_FUNC(asinh) - REDEF_MATH_FUNC(atanh) - REDEF_MATH_FUNC(cbrt) - REDEF_MATH_FUNC(cos) - REDEF_MATH_FUNC(cosh) - REDEF_MATH_FUNC(cospi) - REDEF_MATH_FUNC(exp) - REDEF_MATH_FUNC(exp10) - REDEF_MATH_FUNC(expm1) - REDEF_MATH_FUNC(fmod) - REDEF_MATH_FUNC(hypot) - REDEF_MATH_FUNC(ilogb) - REDEF_MATH_FUNC(ldexp) - REDEF_MATH_FUNC(log) - REDEF_MATH_FUNC(log2) - REDEF_MATH_FUNC(log10) - REDEF_MATH_FUNC(log1p) - REDEF_MATH_FUNC(logb) - REDEF_MATH_FUNC(remainder) - REDEF_MATH_FUNC(rootn) - REDEF_MATH_FUNC(sin) - REDEF_MATH_FUNC(sincos) - REDEF_MATH_FUNC(sinh) - REDEF_MATH_FUNC(sinpi) - REDEF_MATH_FUNC(tan) - REDEF_MATH_FUNC(tanh) - "\n" - ; - static void programDelete(gbe_program gbeProgram) { gbe::Program *program = (gbe::Program*)(gbeProgram); GBE_SAFE_DELETE(program); @@ -535,38 +503,21 @@ namespace gbe { #ifdef GBE_COMPILER_AVAILABLE BVAR(OCL_OUTPUT_BUILD_LOG, false); - SVAR(OCL_PCH_PATH, PCH_OBJECT_DIR); - SVAR(OCL_PCM_PATH, PCM_OBJECT_DIR); - static bool buildModuleFromSource(const char* input, llvm::Module** out_module, llvm::LLVMContext* llvm_ctx, std::string options, - size_t stringSize, char *err, size_t *errSize) { + static bool buildModuleFromSource(const char* input, llvm::Module** out_module, llvm::LLVMContext* llvm_ctx, + std::vector<std::string>& options, size_t stringSize, char *err, + size_t *errSize) { // Arguments to pass to the clang frontend vector<const char *> args; bool bFastMath = false; - vector<std::string> useless; //hold substrings to avoid c_str free - size_t start = 0, end = 0; - /* FIXME - clang unsupport options: - -cl-denorms-are-zero, -cl-strict-aliasing - -cl-no-signed-zeros, -cl-fp32-correctly-rounded-divide-sqrt - all support options, refer to clang/include/clang/Driver/Options.inc - */ - //Handle -cl-opt-disable in llvmToGen, skip here - const std::string unsupportedOptions("-cl-denorms-are-zero, -cl-strict-aliasing, -cl-opt-disable," - "-cl-no-signed-zeros, -cl-fp32-correctly-rounded-divide-sqrt"); - while (end != std::string::npos) { - end = options.find(' ', start); - std::string str = options.substr(start, end - start); - start = end + 1; - if(str.size() == 0) - continue; - if(str == "-cl-fast-relaxed-math") bFastMath = true; - if(unsupportedOptions.find(str) != std::string::npos) - continue; - useless.push_back(str); - args.push_back(str.c_str()); + for (auto &s : options) { + args.push_back(s.c_str()); } + + args.push_back("-cl-kernel-arg-info"); + args.push_back("-Dcl_khr_fp64"); + args.push_back("-mllvm"); args.push_back("-inline-threshold=200000"); #ifdef GEN7_SAMPLER_CLAMP_BORDER_WORKAROUND @@ -590,28 +541,21 @@ namespace gbe { #endif /* LLVM_VERSION_MINOR <= 2 */ args.push_back(input); + args.push_back("-ffp-contract=off"); + // The compiler invocation needs a DiagnosticsEngine so it can report problems std::string ErrorString; llvm::raw_string_ostream ErrorInfo(ErrorString); llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts = new clang::DiagnosticOptions(); DiagOpts->ShowCarets = false; DiagOpts->ShowPresumedLoc = true; -#if LLVM_VERSION_MINOR <= 1 - args.push_back("-triple"); - args.push_back("ptx32"); - - clang::TextDiagnosticPrinter *DiagClient = - new clang::TextDiagnosticPrinter(ErrorInfo, *DiagOpts) - llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(new clang::DiagnosticIDs()); - clang::DiagnosticsEngine Diags(DiagID, DiagClient); -#else - args.push_back("-ffp-contract=off"); + clang::TextDiagnosticPrinter *DiagClient = new clang::TextDiagnosticPrinter(ErrorInfo, &*DiagOpts); llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(new clang::DiagnosticIDs()); clang::DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient); -#endif /* LLVM_VERSION_MINOR <= 1 */ + // Create the compiler invocation std::unique_ptr<clang::CompilerInvocation> CI(new clang::CompilerInvocation); clang::CompilerInvocation::CreateFromArgs(*CI, @@ -623,11 +567,7 @@ namespace gbe { clang::CompilerInstance Clang; Clang.setInvocation(CI.release()); // Get ready to report problems -#if LLVM_VERSION_MINOR <= 2 - Clang.createDiagnostics(args.size(), &args[0]); -#else Clang.createDiagnostics(DiagClient, false); -#endif /* LLVM_VERSION_MINOR <= 2 */ Clang.getDiagnosticOpts().ShowCarets = false; if (!Clang.hasDiagnostics()) @@ -636,10 +576,7 @@ namespace gbe { // Set Language clang::LangOptions & lang_opts = Clang.getLangOpts(); lang_opts.OpenCL = 1; - - clang::PreprocessorOptions& prep_opt = Clang.getPreprocessorOpts(); - prep_opt.DisablePCHValidation = 1; - + //llvm flags need command line parsing to take effect if (!Clang.getFrontendOpts().LLVMArgs.empty()) { unsigned NumArgs = Clang.getFrontendOpts().LLVMArgs.size(); @@ -652,32 +589,17 @@ namespace gbe { llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args); delete [] Args; } - + // Create an action and make the compiler instance carry it out std::unique_ptr<clang::CodeGenAction> Act(new clang::EmitLLVMOnlyAction(llvm_ctx)); - - std::string dirs = OCL_PCM_PATH; - std::string pcmFileName; - std::istringstream idirs(dirs); - bool findPcm = false; - - while (getline(idirs, pcmFileName, ':')) { - if(access(pcmFileName.c_str(), R_OK) == 0) { - findPcm |= true; - break; - } - } - - GBE_ASSERT(findPcm && "Could not find pre compiled module library.\n"); - - Clang.getCodeGenOpts().LinkBitcodeFile = pcmFileName; + auto retVal = Clang.ExecuteAction(*Act); if (err != NULL) { GBE_ASSERT(errSize != NULL); *errSize = ErrorString.copy(err, stringSize - 1, 0); } - + if (err == NULL || OCL_OUTPUT_BUILD_LOG) { // flush the error messages to the errs() if there is no // error string buffer. @@ -693,137 +615,70 @@ namespace gbe { return true; } - extern std::string ocl_stdlib_str; - BVAR(OCL_USE_PCH, true); + SVAR(OCL_HEADER_FILE_DIR, OCL_HEADER_DIR); + static void processSourceAndOption(const char *source, const char *options, const char *temp_header_path, - std::string& clOpt, + std::vector<std::string>& clOpt, std::string& clName, int& optLevel) { - char clStr[] = "/tmp/XXXXXX.cl"; - int clFd = mkstemps(clStr, 3); - clName = std::string(clStr); - - FILE *clFile = fdopen(clFd, "w"); - FATAL_IF(clFile == NULL, "Failed to open temporary file"); - - bool usePCH = OCL_USE_PCH; - bool findPCH = false; - - /* Because our header file is so big, we want to avoid recompile the header from - scratch. We use the PCH support of Clang to save the huge compiling time. - We just use the most general build opt to build the PCH header file, so if - user pass new build options here, the PCH can not pass the Clang's compitable - validating. Clang will do three kinds of compatible check: Language Option, - Target Option and Preprocessing Option. Other kinds of options such as the - CodeGen options will not affect the AST result, so no need to check. - - According to OpenCL 1.1's spec, the CL build options: - -D name=definition - If the definition is not used in our header, it is compitable - - -cl-single-precision-constant - -cl-denorms-are-zero - -cl-std= - Language options, really affect. - - -cl-opt-disable - -cl-mad-enable - -cl-no-signed-zeros - -cl-unsafe-math-optimizations - -cl-finite-math-only - -cl-fast-relaxed-math - CodeGen options, not affect - - -Werror - -w - Our header should not block the compiling because of warning. - - So we just disable the PCH validation of Clang and do the judgement by ourself. */ - - /* We always add -cl-kernel-arg-info to the options. This option just generate the arg - information for the backend, no other side effect and does not have performance issue. */ - if (!options || !strstr(const_cast<char *>(options), "-cl-kernel-arg-info")) - clOpt += "-cl-kernel-arg-info "; + size_t start = 0, end = 0; - if (options) { - char *p; - /* FIXME: Though we can disable the pch valid check, and load pch successfully, - but these language opts and pre-defined macro will still generate the diag msg - to the diag engine of the Clang and cause the Clang to report error. - We filter them all here to avoid these. */ - const char * incompatible_opts[] = { - "-cl-single-precision-constant", -// "-cl-denorms-are-zero", - "-cl-fast-relaxed-math", - "-cl-std=", - }; - const char * incompatible_defs[] = { - "GET_FLOAT_WORD", - "__NV_CL_C_VERSION", - "GEN7_SAMPLER_CLAMP_BORDER_WORKAROUND" - }; - - for (unsigned int i = 0; i < sizeof(incompatible_opts)/sizeof(char *); i++ ) { - p = strstr(const_cast<char *>(options), incompatible_opts[i]); - if (p) { - usePCH = false; - break; - } - } + std::string hdirs = OCL_HEADER_FILE_DIR; + std::istringstream hidirs(hdirs); + std::string headerFilePath; + bool findOcl = false; - if (usePCH) { - for (unsigned int i = 0; i < sizeof(incompatible_defs)/sizeof(char *); i++ ) { - p = strstr(const_cast<char *>(options), incompatible_defs[i]); - if (p) { - usePCH = false; - break; - } - } + while (getline(hidirs, headerFilePath, ':')) { + std::string oclDotHName = headerFilePath + "/ocl.h"; + if(access(oclDotHName.c_str(), R_OK) == 0) { + findOcl = true; + break; } - - p = strstr(const_cast<char *>(options), "-cl-opt-disable"); - if (p) - optLevel = 0; - - clOpt += options; } + assert(findOcl); + std::string includePath = "-I" + headerFilePath; + clOpt.push_back(includePath); - std::string dirs = OCL_PCH_PATH; - std::istringstream idirs(dirs); - std::string pchFileName; - - while (getline(idirs, pchFileName, ':')) { - if(access(pchFileName.c_str(), R_OK) == 0) { - findPCH = true; - break; + if (options) { + char *str = (char *)malloc(sizeof(char) * (strlen(options) + 1)); + memcpy(str, options, strlen(options) + 1); + std::string optionStr(str); + const std::string unsupportedOptions("-cl-denorms-are-zero, -cl-strict-aliasing, -cl-opt-disable," + "-cl-no-signed-zeros, -cl-fp32-correctly-rounded-divide-sqrt"); + while (end != std::string::npos) { + end = optionStr.find(' ', start); + std::string str = optionStr.substr(start, end - start); + start = end + 1; + if(str.size() == 0) + continue; + + if(unsupportedOptions.find(str) != std::string::npos) + continue; + + clOpt.push_back(str); } + free(str); } - if (usePCH && findPCH) { - clOpt += " -include-pch "; - clOpt += pchFileName; - clOpt += " "; - } else - fwrite(ocl_stdlib_str.c_str(), strlen(ocl_stdlib_str.c_str()), 1, clFile); - //for clCompilerProgram usage. if(temp_header_path){ - clOpt += " -I "; - clOpt += temp_header_path; - clOpt += " "; + clOpt.push_back("-I"); + clOpt.push_back(temp_header_path); } - if (!OCL_STRICT_CONFORMANCE) { - fwrite(ocl_mathfunc_fastpath_str.c_str(), strlen(ocl_mathfunc_fastpath_str.c_str()), 1, clFile); - } + char clStr[] = "/tmp/XXXXXX.cl"; + int clFd = mkstemps(clStr, 3); + clName = std::string(clStr); + + FILE *clFile = fdopen(clFd, "w"); + FATAL_IF(clFile == NULL, "Failed to open temporary file"); - // reset the file number in case we have inserted something into the kernel - std::string resetFileNum = "#line 1\n"; - fwrite(resetFileNum.c_str(), strlen(resetFileNum.c_str()), 1, clFile); + clOpt.push_back("-include"); + clOpt.push_back("ocl.h"); // Write the source to the cl file fwrite(source, strlen(source), 1, clFile); @@ -838,7 +693,7 @@ namespace gbe { size_t *errSize) { int optLevel = 1; - std::string clOpt; + std::vector<std::string> clOpt; std::string clName; processSourceAndOption(source, options, NULL, clOpt, clName, optLevel); @@ -846,12 +701,11 @@ namespace gbe { // will delete the module and act in GenProgram::CleanLlvmResource(). llvm::Module * out_module; llvm::LLVMContext* llvm_ctx = new llvm::LLVMContext; - static std::mutex llvm_mutex; if (!llvm::llvm_is_multithreaded()) llvm_mutex.lock(); - if (buildModuleFromSource(clName.c_str(), &out_module, llvm_ctx, clOpt.c_str(), + if (buildModuleFromSource(clName.c_str(), &out_module, llvm_ctx, clOpt, stringSize, err, errSize)) { // Now build the program from llvm size_t clangErrSize = 0; @@ -890,7 +744,7 @@ namespace gbe { size_t *errSize) { int optLevel = 1; - std::string clOpt; + std::vector<std::string> clOpt; std::string clName; processSourceAndOption(source, options, temp_header_path, clOpt, clName, optLevel); @@ -900,7 +754,7 @@ namespace gbe { //for some functions, so we use global context now, need switch to new context later. llvm::Module * out_module; llvm::LLVMContext* llvm_ctx = &llvm::getGlobalContext(); - if (buildModuleFromSource(clName.c_str(), &out_module, llvm_ctx, clOpt.c_str(), + if (buildModuleFromSource(clName.c_str(), &out_module, llvm_ctx, clOpt, stringSize, err, errSize)) { // Now build the program from llvm if (err != NULL) { diff --git a/backend/src/libocl/CMakeLists.txt b/backend/src/libocl/CMakeLists.txt new file mode 100644 index 00000000..d4e3a536 --- /dev/null +++ b/backend/src/libocl/CMakeLists.txt @@ -0,0 +1,209 @@ +PROJECT(LIBOCL) + +SET (OCL_HEADER_FILES ${LIBOCL_BINARY_DIR}/include/ocl_defines.h) +SET (OCL_SOURCE_FILES "") + +ADD_CUSTOM_COMMAND(OUTPUT ${LIBOCL_BINARY_DIR}/include/ocl_defines.h + COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/include/ + # COMMAND echo "cat ${LIBOCL_SOURCE_DIR}/tmpl/ocl_defines.tmpl.h \\> ${LIBOCL_BINARY_DIR}/include/ocl_defines.h" + COMMAND cat ${LIBOCL_SOURCE_DIR}/tmpl/ocl_defines.tmpl.h > ${LIBOCL_BINARY_DIR}/include/ocl_defines.h + # COMMAND echo "cat ${LIBOCL_SOURCE_DIR}/../ocl_common_defines.h \\>\\> ${LIBOCL_BINARY_DIR}/include/ocl_defines.h" + COMMAND cat ${LIBOCL_SOURCE_DIR}/../ocl_common_defines.h >> ${LIBOCL_BINARY_DIR}/include/ocl_defines.h + DEPENDS ${LIBOCL_SOURCE_DIR}/tmpl/ocl_defines.tmpl.h ${LIBOCL_SOURCE_DIR}/../ocl_common_defines.h + COMMENT "Generate the header: ${LIBOCL_BINARY_DIR}/include/ocl_defines.h" + ) + +#other module just copy. +MACRO(COPY_THE_HEADER _mod) + # Use the python script to generate the header files. + STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_BINARY_DIR}/include/\\1.h" output_name ${_mod}) + STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_SOURCE_DIR}/include/\\1.h" orgin_name ${_mod}) + SET(OCL_HEADER_FILES ${OCL_HEADER_FILES} ${output_name}) + IF(orgin_name STREQUAL output_name) + ELSE(orgin_name STREQUAL output_name) + ADD_CUSTOM_COMMAND(OUTPUT ${output_name} + COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/include/ + #COMMAND echo "cp ${orgin_name} ${output_name}" + COMMAND cp ${orgin_name} ${output_name} + DEPENDS ${orgin_name} + COMMENT "Copy the header: ${output_name}" + ) + ENDIF(orgin_name STREQUAL output_name) +ENDMACRO(COPY_THE_HEADER) +MACRO(COPY_THE_SOURCE _mod) + # Use the python script to generate the header files. + STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_BINARY_DIR}/src/\\1.cl" output_name ${_mod}) + STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_SOURCE_DIR}/src/\\1.cl" orgin_name ${_mod}) + SET(OCL_SOURCE_FILES ${OCL_SOURCE_FILES} ${output_name}) + IF(orgin_name STREQUAL output_name) + ELSE(orgin_name STREQUAL output_name) + ADD_CUSTOM_COMMAND(OUTPUT ${output_name} + COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/src/ + #COMMAND echo "cp ${orgin_name} ${output_name}" + COMMAND cp ${orgin_name} ${output_name} + DEPENDS ${orgin_name} + COMMENT "Copy the source: ${output_name}" + ) + ENDIF(orgin_name STREQUAL output_name) +ENDMACRO(COPY_THE_SOURCE) + +SET (OCL_COPY_HEADERS ocl ocl_types ocl_float ocl_printf) +FOREACH(M ${OCL_COPY_HEADERS}) + COPY_THE_HEADER(${M}) +ENDFOREACH(M) + +SET (OCL_COPY_MODULES ocl_workitem ocl_atom ocl_async ocl_sync ocl_misc ocl_vload ocl_geometric ocl_image) +FOREACH(M ${OCL_COPY_MODULES}) + COPY_THE_HEADER(${M}) + COPY_THE_SOURCE(${M}) +ENDFOREACH(M) + + +MACRO(GENERATE_HEADER_PY _mod) + STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_BINARY_DIR}/include/\\1.h" output_name ${_mod}) + STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_SOURCE_DIR}/tmpl/\\1.tmpl.h" tmpl_name ${_mod}) + STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_SOURCE_DIR}/script/\\1.def" def_name ${_mod}) + SET(OCL_HEADER_FILES ${OCL_HEADER_FILES} ${output_name}) + ADD_CUSTOM_COMMAND(OUTPUT ${output_name} + COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/include/ + #COMMAND echo "cat ${tmpl_name} \\> ${output_name}" + COMMAND cat ${tmpl_name} > ${output_name} + #COMMAND echo "${LIBOCL_SOURCE_DIR}/script/gen_vector.py ${def_name} ${output_name} 1" + COMMAND ${LIBOCL_SOURCE_DIR}/script/gen_vector.py ${def_name} ${output_name} 1 + #COMMAND echo "echo \\#endif \\>\\> ${output_name}" + COMMAND echo "\\#endif" >> ${output_name} + DEPENDS ${tmpl_name} + COMMENT "Generate the header by python: ${output_name}" + ) +ENDMACRO(GENERATE_HEADER_PY) +MACRO(GENERATE_SOURCE_PY _mod) + STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_BINARY_DIR}/src/\\1.cl" output_name ${_mod}) + STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_SOURCE_DIR}/tmpl/\\1.tmpl.cl" tmpl_name ${_mod}) + STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_SOURCE_DIR}/script/\\1.def" def_name ${_mod}) + SET(OCL_SOURCE_FILES ${OCL_SOURCE_FILES} ${output_name}) + ADD_CUSTOM_COMMAND(OUTPUT ${output_name} + COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/src/ + COMMAND cat ${tmpl_name} > ${output_name} + COMMAND ${LIBOCL_SOURCE_DIR}/script/gen_vector.py ${def_name} ${output_name} 0 + DEPENDS ${tmpl_name} + COMMENT "Generate the source by python: ${output_name}" + ) +ENDMACRO(GENERATE_SOURCE_PY) + +SET (OCL_PY_GENERATED_MODULES ocl_common ocl_relational ocl_integer ocl_math) +FOREACH(M ${OCL_PY_GENERATED_MODULES}) + GENERATE_HEADER_PY(${M}) + GENERATE_SOURCE_PY(${M}) +ENDFOREACH(M) + + +MACRO(GENERATE_HEADER_BASH _mod) + # Use the python script to generate the header files. + STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_BINARY_DIR}/include/\\1.h" output_name ${_mod}) + STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_SOURCE_DIR}/script/\\1.sh" sh_name ${_mod}) + SET(OCL_HEADER_FILES ${OCL_HEADER_FILES} ${output_name}) + ADD_CUSTOM_COMMAND(OUTPUT ${output_name} + COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/include/ + COMMAND ${sh_name} -p > ${output_name} + DEPENDS ${sh_name} + COMMENT "Generate the header by script: ${output_name}" + ) +ENDMACRO(GENERATE_HEADER_BASH) +MACRO(GENERATE_SOURCE_BASH _mod) + # Use the python script to generate the header files. + STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_BINARY_DIR}/src/\\1.cl" output_name ${_mod}) + STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_SOURCE_DIR}/script/\\1.sh" def_name ${_mod}) + SET(OCL_SOURCE_FILES ${OCL_SOURCE_FILES} ${output_name}) + ADD_CUSTOM_COMMAND(OUTPUT ${output_name} + COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/src/ + COMMAND ${sh_name} > ${output_name} + DEPENDS ${sh_name} + COMMENT "Generate the source by script: ${output_name}" + ) +ENDMACRO(GENERATE_SOURCE_BASH) + +SET (OCL_BASH_GENERATED_MODULES ocl_as ocl_convert) +FOREACH(M ${OCL_BASH_GENERATED_MODULES}) + GENERATE_HEADER_BASH(${M}) + GENERATE_SOURCE_BASH(${M}) +ENDFOREACH(M) + + +SET (CLANG_OCL_FLAGS -fno-builtin -Dcl_khr_fp64 -ffp-contract=off -cl-kernel-arg-info -DGEN7_SAMPLER_CLAMP_BORDER_WORKAROUND) + +MACRO(ADD_CL_TO_BC_TARGET _file) + # CMake seems can not add pattern rule, use MACRO to replace. + STRING(REGEX REPLACE "${LIBOCL_BINARY_DIR}/src/\(o.*\)\\.cl" "${LIBOCL_BINARY_DIR}/lib/\\1.bc" output_name ${_file}) + ADD_CUSTOM_COMMAND(OUTPUT ${output_name} + COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/lib/ + #COMMAND echo ${LLVM_INSTALL_DIR}clang -cc1 ${CLANG_OCL_FLAGS} -I ${LIBOCL_BINARY_DIR}/include/ -emit-llvm-bc -triple spir -o ${output_name} -x cl ${_file} + COMMAND ${LLVM_INSTALL_DIR}clang -cc1 ${CLANG_OCL_FLAGS} -I ${LIBOCL_BINARY_DIR}/include/ -emit-llvm-bc -triple spir -o ${output_name} -x cl ${_file} + DEPENDS ${_file} ${OCL_HEADER_FILES} + COMMENT "Compiling ${_file}" + ) +ENDMACRO(ADD_CL_TO_BC_TARGET) + + +FOREACH(f ${OCL_SOURCE_FILES}) + ADD_CL_TO_BC_TARGET(${f}) +ENDFOREACH(f) + +FOREACH(f ${OCL_SOURCE_FILES}) + STRING(REGEX REPLACE "${LIBOCL_BINARY_DIR}/src/\(o.*\)\\.cl" "${LIBOCL_BINARY_DIR}/lib/\\1.bc" bc_name ${f}) + SET(OCL_BC_FILES ${OCL_BC_FILES} ${bc_name}) +ENDFOREACH(f) + + +# handle the ll files +MACRO(COPY_THE_LL _mod) + # Use the python script to generate the header files. + STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_BINARY_DIR}/src/\\1.ll" output_name ${_mod}) + STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_SOURCE_DIR}/src/\\1.ll" orgin_name ${_mod}) + IF(orgin_name STREQUAL output_name) + ELSE(orgin_name STREQUAL output_name) + ADD_CUSTOM_COMMAND(OUTPUT ${output_name} + COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/src/ + #COMMAND echo "cp ${orgin_name} ${output_name}" + COMMAND cp ${orgin_name} ${output_name} + DEPENDS ${orgin_name} + COMMENT "Copy the LL file: ${output_name}" + ) + ENDIF(orgin_name STREQUAL output_name) +ENDMACRO(COPY_THE_LL) +MACRO(ADD_LL_TO_BC_TARGET M) + STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_BINARY_DIR}/lib/\\1.bc" output_name ${M}) + STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_BINARY_DIR}/src/\\1.ll" srcll_name ${M}) + ADD_CUSTOM_COMMAND(OUTPUT ${output_name} + COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/lib/ + #COMMAND echo ${LLVM_INSTALL_DIR}llvm-as -o ${output_name} ${srcll_name} + COMMAND ${LLVM_INSTALL_DIR}llvm-as -o ${output_name} ${srcll_name} + DEPENDS ${srcll_name} + COMMENT "Compiling ${srcll_name}" + ) +ENDMACRO(ADD_LL_TO_BC_TARGET) + +SET (OCL_LL_MODULES ocl_barrier ocl_memcpy ocl_memset) +FOREACH(f ${OCL_LL_MODULES}) + COPY_THE_LL(${f}) + ADD_LL_TO_BC_TARGET(${f}) + STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_BINARY_DIR}/lib/\\1.bc" bc_name ${f}) + SET(OCL_BC_FILES ${OCL_BC_FILES} ${bc_name}) +ENDFOREACH(f) + + +ADD_CUSTOM_COMMAND(OUTPUT ${LIBOCL_BINARY_DIR}/lib/beignet.bc + COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/lib/ + #COMMAND echo llvm-link -o ${LIBOCL_BINARY_DIR}/lib/beignet.bc ${OCL_BC_FILES} + COMMAND ${LLVM_INSTALL_DIR}llvm-link -o ${LIBOCL_BINARY_DIR}/lib/beignet.bc ${OCL_BC_FILES} + DEPENDS ${OCL_BC_FILES} + COMMENT "Generate the bitcode file: ${LIBOCL_BINARY_DIR}/lib/beignet.bc" + ) + +ADD_CUSTOM_COMMAND(OUTPUT ${LIBOCL_BINARY_DIR}/lib/beignet.pch + COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/lib/ + COMMAND ${LLVM_INSTALL_DIR}clang -cc1 ${CLANG_OCL_FLAGS} -triple spir -I ${LIBOCL_BINARY_DIR}/include/ -emit-pch -x cl ${LIBOCL_BINARY_DIR}/include/ocl.h -o ${LIBOCL_BINARY_DIR}/lib/beignet.pch + DEPENDS ${OCL_HEADER_FILES} + COMMENT "Generate the pch file: ${LIBOCL_BINARY_DIR}/lib/beignet.pch" + ) + +add_custom_target(beignet_bitcode ALL DEPENDS ${LIBOCL_BINARY_DIR}/lib/beignet.bc ${LIBOCL_BINARY_DIR}/lib/beignet.pch) diff --git a/backend/src/libocl/include/ocl.h b/backend/src/libocl/include/ocl.h new file mode 100644 index 00000000..a7d03e69 --- /dev/null +++ b/backend/src/libocl/include/ocl.h @@ -0,0 +1,23 @@ +#ifndef __OCL_H__ +#define __OCL_H__ + +#include "ocl_defines.h" +#include "ocl_types.h" +#include "ocl_as.h" +#include "ocl_async.h" +#include "ocl_atom.h" +#include "ocl_common.h" +#include "ocl_convert.h" +#include "ocl_float.h" +#include "ocl_geometric.h" +#include "ocl_image.h" +#include "ocl_integer.h" +#include "ocl_math.h" +#include "ocl_misc.h" +#include "ocl_printf.h" +#include "ocl_relational.h" +#include "ocl_sync.h" +#include "ocl_vload.h" +#include "ocl_workitem.h" + +#endif diff --git a/backend/src/llvm/llvm_to_gen.cpp b/backend/src/llvm/llvm_to_gen.cpp index beb36c01..8e49cbb9 100644 --- a/backend/src/llvm/llvm_to_gen.cpp +++ b/backend/src/llvm/llvm_to_gen.cpp @@ -72,10 +72,8 @@ namespace gbe { - BVAR(OCL_OUTPUT_LLVM, false); BVAR(OCL_OUTPUT_CFG, false); BVAR(OCL_OUTPUT_CFG_ONLY, false); - BVAR(OCL_OUTPUT_LLVM_BEFORE_EXTRA_PASS, false); using namespace llvm; void runFuntionPass(Module &mod, TargetLibraryInfo *libraryInfo) @@ -177,29 +175,68 @@ namespace gbe MPM.run(mod); } + +#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5 +#define OUTPUT_BITCODE(STAGE, MOD) do { \ + llvm::PassManager passes__; \ + if (OCL_OUTPUT_LLVM_##STAGE) { \ + passes__.add(createPrintModulePass(*o)); \ + passes__.run(MOD); \ + } \ + }while(0) +#else +#define OUTPUT_BITCODE(STAGE, MOD) do { \ + llvm::PassManager passes__; \ + if (OCL_OUTPUT_LLVM_##STAGE) { \ + passes__.add(createPrintModulePass(&*o)); \ + passes__.run(MOD); \ + } \ + }while(0) +#endif + + BVAR(OCL_OUTPUT_LLVM_BEFORE_LINK, false); + BVAR(OCL_OUTPUT_LLVM_AFTER_LINK, false); + BVAR(OCL_OUTPUT_LLVM_AFTER_GEN, false); + bool llvmToGen(ir::Unit &unit, const char *fileName,const void* module, int optLevel) { std::string errInfo; std::unique_ptr<llvm::raw_fd_ostream> o = NULL; - if (OCL_OUTPUT_LLVM_BEFORE_EXTRA_PASS || OCL_OUTPUT_LLVM) + if (OCL_OUTPUT_LLVM_BEFORE_LINK || OCL_OUTPUT_LLVM_AFTER_LINK || OCL_OUTPUT_LLVM_AFTER_GEN) o = std::unique_ptr<llvm::raw_fd_ostream>(new llvm::raw_fd_ostream(fileno(stdout), false)); // Get the module from its file llvm::SMDiagnostic Err; - std::unique_ptr<Module> M; - if(fileName){ - // only when module is null, Get the global LLVM context + Module* cl_mod = NULL; + if (module) { + cl_mod = reinterpret_cast<Module*>(const_cast<void*>(module)); + } else if (fileName){ llvm::LLVMContext& c = llvm::getGlobalContext(); - M.reset(ParseIRFile(fileName, Err, c)); - if (M.get() == 0) return false; + cl_mod = ParseIRFile(fileName, Err, c); } - Module &mod = (module!=NULL)?*(llvm::Module*)module:*M.get(); + + if (!cl_mod) return false; + + OUTPUT_BITCODE(BEFORE_LINK, (*cl_mod)); + + std::unique_ptr<Module> M; + + /* Before do any thing, we first filter in all CL functions in bitcode. */ + M.reset(runBitCodeLinker(cl_mod)); + if (!module) + delete cl_mod; + if (M.get() == 0) + return false; + + Module &mod = *M.get(); Triple TargetTriple(mod.getTargetTriple()); TargetLibraryInfo *libraryInfo = new TargetLibraryInfo(TargetTriple); libraryInfo->disableAllFunctions(); + OUTPUT_BITCODE(AFTER_LINK, mod); + runFuntionPass(mod, libraryInfo); runModulePass(mod, libraryInfo, optLevel); @@ -210,12 +247,6 @@ namespace gbe passes.add(new DataLayout(&mod)); #endif // Print the code before further optimizations - if (OCL_OUTPUT_LLVM_BEFORE_EXTRA_PASS) -#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5 - passes.add(createPrintModulePass(*o)); -#else - passes.add(createPrintModulePass(&*o)); -#endif passes.add(createIntrinsicLoweringPass()); passes.add(createFunctionInliningPass(200000)); passes.add(createScalarReplAggregatesPass()); // Break up allocas @@ -237,15 +268,10 @@ namespace gbe if(OCL_OUTPUT_CFG_ONLY) passes.add(createCFGOnlyPrinterPass()); passes.add(createGenPass(unit)); + passes.run(mod); // Print the code extra optimization passes - if (OCL_OUTPUT_LLVM) -#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5 - passes.add(createPrintModulePass(*o)); -#else - passes.add(createPrintModulePass(&*o)); -#endif - passes.run(mod); + OUTPUT_BITCODE(AFTER_GEN, mod); const ir::Unit::FunctionSet& fs = unit.getFunctionSet(); ir::Unit::FunctionSet::const_iterator iter = fs.begin(); |