pax_global_header00006660000000000000000000000064144156530530014520gustar00rootroot0000000000000052 comment=1adc46ef38aeba1585b3587b95b6af692a12e4f4 opencl-clang-16.0.0/000077500000000000000000000000001441565305300141465ustar00rootroot00000000000000opencl-clang-16.0.0/.github/000077500000000000000000000000001441565305300155065ustar00rootroot00000000000000opencl-clang-16.0.0/.github/actions/000077500000000000000000000000001441565305300171465ustar00rootroot00000000000000opencl-clang-16.0.0/.github/actions/build-opencl-clang/000077500000000000000000000000001441565305300226055ustar00rootroot00000000000000opencl-clang-16.0.0/.github/actions/build-opencl-clang/action.yml000066400000000000000000000037101441565305300246060ustar00rootroot00000000000000# ===--- # Main opencl-clang building script # ===--- name: Build opencl-clang inputs: ref_llvm: description: 'LLVM ref to build with' required: true ref_translator: description: 'SPIRV-LLVM-Translator ref to build with' required: true ref_opencl-clang: description: 'opencl-clang ref to build with' required: true build_type: description: 'Build type to pass to CMake' required: false default: Release runs: using: 'composite' steps: # Setup git credentials to make applying patches possible - run: | git config --global user.email "action@intel.com" git config --global user.name "Action Bot" shell: bash - name: Checkout LLVM uses: actions/checkout@v3 with: repository: llvm/llvm-project path: llvm-project ref: ${{ inputs.ref_llvm }} - name: Checkout SPIRV-LLVM-Translator uses: actions/checkout@v3 with: repository: KhronosGroup/SPIRV-LLVM-Translator path: llvm-project/SPIRV-LLVM-Translator ref: ${{ inputs.ref_translator }} - name: Checkout opencl-clang uses: actions/checkout@v3 with: path: llvm-project/opencl-clang ref: ${{ inputs.ref_opencl-clang }} - name: Configure shell: bash run: | mkdir build && cd build cmake ${{ github.workspace }}/llvm-project/llvm \ -DLLVM_ENABLE_PROJECTS="clang" \ -DLLVM_EXTERNAL_PROJECTS="llvm-spirv;opencl-clang" \ -DLLVM_EXTERNAL_LLVM_SPIRV_SOURCE_DIR=${{ github.workspace }}/llvm-project/SPIRV-LLVM-Translator \ -DLLVM_EXTERNAL_OPENCL_CLANG_SOURCE_DIR=${{ github.workspace }}/llvm-project/opencl-clang \ -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} \ -DLLVM_TARGETS_TO_BUILD="X86" \ -G "Unix Makefiles" - name: Build shell: bash run: | cd build make opencl-clang -j8 opencl-clang-16.0.0/.github/workflows/000077500000000000000000000000001441565305300175435ustar00rootroot00000000000000opencl-clang-16.0.0/.github/workflows/on-push-verification.yml000066400000000000000000000046111441565305300243410ustar00rootroot00000000000000# ===--- # Running on push & pull_request. # This workflow parses the destination branch # to choose correct dependencies revisions # ===--- name: On push & pull-request verification run-name: '${{ github.event_name }}: ${{ github.base_ref }} ${{ github.ref_name }}' # github.base_ref null for 'on: push' on: push: branches: - main - ocl-open-* pull_request: branches: - main - ocl-open-* types: - opened - reopened - synchronize # commit pushed to the PR - ready_for_review # moved from draft state jobs: verify_default_branch: name: Verify for `main` branch # ref_name for 'on: push' # base_ref for 'on: pull_request' if: ${{ (github.event_name == 'push' && github.ref_name == 'main') || (github.event_name == 'pull_request' && github.base_ref == 'main') }} runs-on: ubuntu-22.04 steps: - name: Checkout opencl-clang sources for action files uses: actions/checkout@v3 - name: Run build-opencl-clang action uses: ./.github/actions/build-opencl-clang with: ref_llvm: main ref_translator: main ref_opencl-clang: ${{ github.ref }} verify_release_branch: name: Verify for `ocl-open-*` release branch # ref_name for 'on: push' # base_ref for 'on: pull_request' if: ${{ github.ref_name != 'main' && github.base_ref != 'main' }} runs-on: ubuntu-22.04 steps: - name: Checkout opencl-clang sources for action files uses: actions/checkout@v3 # This step will fail when the branch naming scheme 'ocl-open-XXX' changes! - name: Parse LLVM version from branch name id: check-llvm-version run: | BRANCH="${{ github.base_ref }}" # on: pull_request, otherwise null BRANCH=${BRANCH:-${{ github.ref_name }}} # on: push LLVM_VERSION_LONG=$(echo $BRANCH | grep -oP '\d+') # Eg. 150 for LLVM 15 LLVM_VERSION_SHORT=${LLVM_VERSION_LONG::-1} # Eg. 15 for LLVM 15 echo "llvm_version=$LLVM_VERSION_SHORT" >> $GITHUB_OUTPUT - name: Run build-opencl-clang action uses: ./.github/actions/build-opencl-clang with: ref_llvm: release/${{ steps.check-llvm-version.outputs.llvm_version }}.x ref_translator: llvm_release_${{ steps.check-llvm-version.outputs.llvm_version }}0 ref_opencl-clang: ${{ github.ref }} opencl-clang-16.0.0/.travis.yml000066400000000000000000000024021441565305300162550ustar00rootroot00000000000000language: cpp os: - linux # Use Ubuntu 18.04 LTS (Bionic) as the Linux testing environment. dist: bionic git: depth: 1 branches: only: - master env: global: - LLVM_VERSION=12 matrix: - BUILD_TYPE=Release - BUILD_TYPE=Debug before_install: - curl -L "https://apt.llvm.org/llvm-snapshot.gpg.key" | sudo apt-key add - - echo "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main" | sudo tee -a ${TRAVIS_ROOT}/etc/apt/sources.list - sudo apt-get update - sudo apt-get -yq --no-install-suggests --no-install-recommends install llvm-${LLVM_VERSION}-dev llvm-${LLVM_VERSION}-tools libclang-${LLVM_VERSION}-dev libclang-cpp${LLVM_VERSION}-dev install: - wget https://github.com/KhronosGroup/SPIRV-LLVM-Translator/releases/download/dev-build/SPIRV-LLVM-Translator-dev-build-linux-Release.zip -O /tmp/SPIRV-LLVM-Translator-dev-build-linux-${BUILD_TYPE}.zip - unzip /tmp/SPIRV-LLVM-Translator-dev-build-linux-${BUILD_TYPE}.zip -d spirv-llvm-translator compiler: - gcc - clang script: - mkdir build && cd build - cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DLLVM_NO_DEAD_STRIP=ON -DLLVMSPIRV_INCLUDED_IN_LLVM=OFF -DSPIRV_TRANSLATOR_DIR=./spirv-llvm-translator -DCMAKE_INSTALL_PREFIX=./install .. - make install opencl-clang-16.0.0/CMakeLists.txt000066400000000000000000000316541441565305300167170ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.13.4) if(NOT DEFINED BASE_LLVM_VERSION) set(BASE_LLVM_VERSION 16.0.0) endif(NOT DEFINED BASE_LLVM_VERSION) set(OPENCL_CLANG_VERSION ${BASE_LLVM_VERSION}.0) if(NOT DEFINED OPENCL_CLANG_BUILD_EXTERNAL) # check if we build inside llvm or not if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) set(OPENCL_CLANG_BUILD_EXTERNAL YES) endif(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) endif(NOT DEFINED OPENCL_CLANG_BUILD_EXTERNAL) if(OPENCL_CLANG_BUILD_EXTERNAL) project(OPENCL_CLANG VERSION ${OPENCL_CLANG_VERSION} LANGUAGES CXX C ) endif() # Do not omit TARGET_OBJECTS expression from the SOURCES target # property # `cmake --help-policy CMP0051` for details. cmake_policy(SET CMP0051 NEW) cmake_policy(SET CMP0057 NEW) cmake_policy(SET CMP0022 NEW) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") include(CMakeFunctions) if(LLVM_USE_HOST_TOOLS AND OPENCL_CLANG_BUILD_EXTERNAL) include(CrossCompile) llvm_create_cross_target(${PROJECT_NAME} NATIVE "" Release) endif() if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) set(USE_PREBUILT_LLVM ON) add_definitions(-DUSE_PREBUILT_LLVM) if(NOT PREFERRED_LLVM_VERSION) set(PREFERRED_LLVM_VERSION "16.0.0") endif(NOT PREFERRED_LLVM_VERSION) message(STATUS "[OPENCL-CLANG] Looking for LLVM version ${PREFERRED_LLVM_VERSION}") find_package(LLVM ${PREFERRED_LLVM_VERSION} REQUIRED) message(STATUS "[OPENCL-CLANG] Using LLVMConfig.cmake in: ${LLVM_DIR}") message(STATUS "[OPENCL-CLANG] Found LLVM ${LLVM_PACKAGE_VERSION}") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${LLVM_CMAKE_DIR}) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) option(LLVMSPIRV_INCLUDED_IN_LLVM "Set to ON if libLLVMSPIRVLib is linked into libLLVM" ON) if(LLVMSPIRV_INCLUDED_IN_LLVM) message(STATUS "[OPENCL-CLANG] Assuming that libLLVMSPIRVLib is linked into libLLVM") else(LLVMSPIRV_INCLUDED_IN_LLVM) message(STATUS "[OPENCL-CLANG] Assuming that libLLVMSPIRVLib is NOT linked into libLLVM") if(NOT SPIRV_TRANSLATOR_DIR) message(FATAL_ERROR "[OPENCL-CLANG] SPIRV_TRANSLATOR_DIR is required") endif(NOT SPIRV_TRANSLATOR_DIR) endif(LLVMSPIRV_INCLUDED_IN_LLVM) else(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) set(USE_PREBUILT_LLVM OFF) find_package(Git REQUIRED) endif(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) include(AddLLVM) include(TableGen) if (NOT WIN32) add_subdirectory( linux_linker bin) endif() use_rtti(FALSE) use_eh(TRUE) if (CMAKE_SIZEOF_VOID_P EQUAL 4) set(ADDR 32) else () set(ADDR 64) endif (CMAKE_SIZEOF_VOID_P EQUAL 4) # set windows binary suffix if (WIN32) set (BUILD_PLATFORM ${ADDR}) else (WIN32) set (BUILD_PLATFORM "") endif (WIN32) # set that name of the main output file as a target name if (NOT DEFINED OPENCL_CLANG_LIBRARY_NAME) set(OPENCL_CLANG_LIBRARY_NAME "opencl-clang") endif() set(TARGET_NAME ${OPENCL_CLANG_LIBRARY_NAME}${BUILD_PLATFORM} ) # PCH_EXTENSION can override PCH extension map in options_compile.cpp. # Example: "cl_khr_3d_image_writes,cl_khr_depth_images" set(PCH_EXTENSION "" CACHE STRING "Comma-separated list of OpenCL extensions") if (NOT "${PCH_EXTENSION}" STREQUAL "") add_definitions(-DPCH_EXTENSION="${PCH_EXTENSION}") endif() if(NOT USE_PREBUILT_LLVM) if(NOT LLVM_EXTERNAL_CLANG_SOURCE_DIR) set(CLANG_SOURCE_DIR ${LLVM_SOURCE_DIR}/tools/clang) elseif(EXISTS "${LLVM_EXTERNAL_CLANG_SOURCE_DIR}/CMakeLists.txt") set(CLANG_SOURCE_DIR "${LLVM_EXTERNAL_CLANG_SOURCE_DIR}") endif() if(EXISTS ${CLANG_SOURCE_DIR}) message(STATUS "[OPENCL-CLANG] Using Clang source code direcotry: ${CLANG_SOURCE_DIR}") else() message(FATAL_ERROR "[OPENCL-CLANG] Can't find Clang source code directory!\n" "If you are using LLVM monorepo:\n" " 1. Clean CMake cache: `rm CMakeCache.txt`\n" " 2. Enable Clang project with `-DLLVM_ENABLE_PROJECTS=\"clang\"` option\n" "If Clang is used as a separate repository (not monorepo), it should " "be checked out at `llvm/tools/clang`." ) endif() if(NOT LLVM_EXTERNAL_LLVM_SPIRV_SOURCE_DIR) set(SPIRV_SOURCE_DIR ${LLVM_SOURCE_DIR}/projects/llvm-spirv) elseif(EXISTS "${LLVM_EXTERNAL_LLVM_SPIRV_SOURCE_DIR}/CMakeLists.txt") set(SPIRV_SOURCE_DIR ${LLVM_EXTERNAL_LLVM_SPIRV_SOURCE_DIR}) endif() if(EXISTS ${SPIRV_SOURCE_DIR}) message(STATUS "[OPENCL-CLANG] Using SPIRV-LLVM-Translator source code directory: ${SPIRV_SOURCE_DIR}") else() message(FATAL_ERROR "[OPENCL-CLANG] Can't find SPIRV-LLVM-Translator source code dir!\n" "If you are using LLVM monorepo, SPIRV-LLVM-Translator should be checked out " "at '/llvm-spirv' and it should be enabled as an external LLVM " "project using the following 2 options:\n" " -DLLVM_EXTERNAL_PROJECTS=\"opencl-clang;llvm-spirv\"\n" " -DLLVM_EXTERNAL_LLVM_SPIRV_SOURCE_DIR=\"/llvm-spirv\"\n" "If you are not using LLVM monorepo, SPIRV-LLVM-Translator should be checked " "out at `llvm/projects/llvm-spirv`" ) endif() set(CLANG_BASE_REVISION release/16.x) set(SPIRV_BASE_REVISION llvm_release_160) set(TARGET_BRANCH "ocl-open-160") apply_patches(${CLANG_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/patches/clang ${CLANG_BASE_REVISION} ${TARGET_BRANCH}) apply_patches(${SPIRV_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/patches/spirv ${SPIRV_BASE_REVISION} ${TARGET_BRANCH}) endif(NOT USE_PREBUILT_LLVM) # # TblGen the options include file # set (COMPILE_OPTIONS_TD opencl_clang_options.td) set (COMPILE_OPTIONS_INC opencl_clang_options.inc) find_program(LLVM_TABLEGEN_EXE "llvm-tblgen" ${LLVM_TOOLS_BINARY_DIR}) set(LLVM_TARGET_DEFINITIONS ${COMPILE_OPTIONS_TD}) if(USE_PREBUILT_LLVM) set(TABLEGEN_ADDITIONAL -I ${LLVM_INCLUDE_DIRS}) else(USE_PREBUILT_LLVM) set(TABLEGEN_ADDITIONAL "") endif(USE_PREBUILT_LLVM) tablegen(LLVM ${COMPILE_OPTIONS_INC} -gen-opt-parser-defs ${TABLEGEN_ADDITIONAL}) add_public_tablegen_target(CClangCompileOptions) # # Source code # set(TARGET_INCLUDE_FILES opencl_clang.h options.h binary_result.h pch_mgr.h ${COMPILE_OPTIONS_TD} ${COMPILE_OPTIONS_INC} ) set(TARGET_SOURCE_FILES opencl_clang.cpp options.cpp pch_mgr.cpp options_compile.cpp ) # # Resources # set( PRODUCT_VER_MAJOR 2 ) set( PRODUCT_VER_MINOR 0 ) set (LLVM_VER_MAJOR ${LLVM_VERSION_MAJOR} ) set (LLVM_VER_MINOR ${LLVM_VERSION_MINOR} ) add_definitions( -D__STDC_LIMIT_MACROS ) add_definitions( -D__STDC_CONSTANT_MACROS ) add_definitions( -DOPENCL_CLANG_EXPORTS ) # # Include directories # if(NOT USE_PREBUILT_LLVM) set(CLANG_BINARY_DIR ${LLVM_BINARY_DIR}/tools/clang/) include_directories( ${CLANG_BINARY_DIR}/include # for tablegened includes ${CLANG_SOURCE_DIR}/include # for basic headers ${SPIRV_SOURCE_DIR}/include) # for SPIRV headers endif(NOT USE_PREBUILT_LLVM) if(USE_PREBUILT_LLVM AND NOT LLVMSPIRV_INCLUDED_IN_LLVM) include_directories(${SPIRV_TRANSLATOR_DIR}/include) link_directories(${SPIRV_TRANSLATOR_DIR}/lib${LLVM_LIBDIR_SUFFIX}) endif(USE_PREBUILT_LLVM AND NOT LLVMSPIRV_INCLUDED_IN_LLVM) include_directories( AFTER ${LLVM_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} ) link_directories( ${LLVM_LIBRARY_DIRS} ) set(OPENCL_CLANG_LINK_LIBS ${CMAKE_DL_LIBS}) if(NOT LLVMSPIRVLib IN_LIST LLVM_AVAILABLE_LIBS OR (USE_PREBUILT_LLVM AND LLVM_LINK_LLVM_DYLIB)) # SPIRV-LLVM-Translator is not included into LLVM as a component. # So, we need to list it here explicitly as an external library list(APPEND OPENCL_CLANG_LINK_LIBS LLVMSPIRVLib) endif() add_subdirectory(cl_headers) set(LLVM_REQUIRES_EH ON) if(USE_PREBUILT_LLVM OR CLANG_LINK_CLANG_DYLIB) list(APPEND OPENCL_CLANG_LINK_LIBS clang-cpp) else() list(APPEND OPENCL_CLANG_LINK_LIBS # The list of clang libraries is taken from clang makefile # (build/tools/clang/tools/driver/CMakeFiles/clang.dir/link.txt) # All duplicate libraries are there on purpose clangBasic clangCodeGen clangDriver clangFrontend clangFrontendTool clangCodeGen clangRewriteFrontend clangARCMigrate clangStaticAnalyzerFrontend clangStaticAnalyzerCheckers clangStaticAnalyzerCore clangCrossTU clangIndex clangFrontend clangDriver clangParse clangSerialization clangSema clangAnalysis clangEdit clangFormat clangToolingInclusions clangToolingCore clangRewrite clangASTMatchers clangAST clangLex clangBasic ) endif() add_library(${TARGET_NAME} SHARED ${TARGET_INCLUDE_FILES} ${TARGET_SOURCE_FILES} $ ) # Same CRT compile option are reqiured to avoid link errors on Windows. # MD and MDd are choosed by default for release and debug build in LLVM. # If users set MT or MTd flags, they also need to add the flags for # opencl-clang sources using a custom macro set_msvc_crt_flags. if(COMMAND set_msvc_crt_flags) set_msvc_crt_flags(${TARGET_NAME}) endif() add_dependencies(${TARGET_NAME} CClangCompileOptions) if (WIN32) # Enable compiler generation of Control Flow Guard security checks. target_compile_options(${TARGET_NAME} PUBLIC "/guard:cf") set_property(TARGET ${TARGET_NAME} APPEND_STRING PROPERTY LINK_FLAGS "/DYNAMICBASE /GUARD:CF") elseif(UNIX) set_property(TARGET ${TARGET_NAME} APPEND_STRING PROPERTY COMPILE_DEFINITIONS LIBOPENCL_CLANG_NAME="$") set_property(TARGET ${TARGET_NAME} APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--no-undefined") endif(WIN32) # Enable new IN_LIST operator. cmake_policy(SET CMP0057 NEW) set(OTHER_LIBRARIES) if ("NVPTX" IN_LIST LLVM_TARGETS_TO_BUILD) list(APPEND OTHER_LIBRARIES LLVMNVPTXCodeGen LLVMNVPTXDesc LLVMNVPTXInfo) endif() if ("AMDGPU" IN_LIST LLVM_TARGETS_TO_BUILD) list(APPEND OTHER_LIBRARIES LLVMAMDGPUCodeGen LLVMAMDGPUAsmParser LLVMAMDGPUDesc LLVMAMDGPUInfo) endif() target_link_libraries( ${TARGET_NAME} LINK_PRIVATE ${OPENCL_CLANG_LINK_LIBS} LLVMX86CodeGen LLVMX86AsmParser LLVMX86Desc LLVMX86Info LLVMX86Disassembler LLVMAnalysis LLVMCodeGen LLVMCore LLVMipo LLVMInstCombine LLVMInstrumentation LLVMMC LLVMMCParser LLVMObjCARCOpts LLVMOption LLVMScalarOpts LLVMSupport LLVMTransformUtils LLVMVectorize LLVMAsmPrinter LLVMSelectionDAG LLVMMCDisassembler LLVMProfileData LLVMObject LLVMBitWriter LLVMIRReader LLVMAsmParser LLVMTarget LLVMBitReader ${OTHER_LIBRARIES} ) install(FILES opencl_clang.h DESTINATION include/cclang COMPONENT ${TARGET_NAME}) # # Stripped PDB files # if (WIN32) get_target_property(RT_OUTPUT_DIRECTORY ${TARGET_NAME} RUNTIME_OUTPUT_DIRECTORY) file(TO_NATIVE_PATH ${RT_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/${TARGET_NAME}_stripped.pdb PDB_NAME) if (${MSVC_VERSION} EQUAL 1500) # Visual Studio 2008 set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS "${LINK_FLAGS} /PDBSTRIPPED:${PDB_NAME}") else (${MSVC_VERSION} EQUAL 1500) # Visual Studio 2010 (assumed if not Visual Studio 2008) # This is a fix due to a bug in CMake, Does not add the flag /DEBUG to the linker flags in Release mode. # The /DEBUG flag is required in order to create stripped pdbs. set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS_DEBUG "${LINK_FLAGS_DEBUG} /PDBSTRIPPED:${PDB_NAME}") set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS_RELEASE "${LINK_FLAGS_RELEASE} /DEBUG /PDBSTRIPPED:${PDB_NAME}") endif (${MSVC_VERSION} EQUAL 1500) if (INSTALL_PDBS) install(FILES ${RT_OUTPUT_DIRECTORY}/\${BUILD_TYPE}/${TARGET_NAME}.pdb DESTINATION bin) endif(INSTALL_PDBS) install(FILES ${RT_OUTPUT_DIRECTORY}/\${BUILD_TYPE}/${TARGET_NAME}_stripped.pdb DESTINATION bin) else (WIN32) SET_LINUX_EXPORTS_FILE( ${TARGET_NAME} opencl_clang.map ) endif(WIN32) opencl-clang-16.0.0/LICENSE000066400000000000000000000061711441565305300151600ustar00rootroot00000000000000============================================================================== LLVM Release License ============================================================================== University of Illinois/NCSA Open Source License Copyright (c) 2003-2018 University of Illinois at Urbana-Champaign. All rights reserved. Developed by: LLVM Team University of Illinois at Urbana-Champaign http://llvm.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. * Neither the names of the LLVM Team, University of Illinois at Urbana-Champaign, nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. ============================================================================== Copyrights and Licenses for Third Party Software Distributed with LLVM: ============================================================================== The LLVM software contains code written by third parties. Such software will have its own individual LICENSE.TXT file in the directory in which it appears. This file will describe the copyrights, license, and restrictions which apply to that code. The disclaimer of warranty in the University of Illinois Open Source License applies to all code in the LLVM Distribution, and nothing in any of the other licenses gives permission to use the names of the LLVM Team or the University of Illinois to endorse or promote products derived from this Software. The following pieces of software have additional or alternate copyrights, licenses, and/or restrictions: Program Directory ------- --------- Google Test llvm/utils/unittest/googletest OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex} pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT} ARM contributions llvm/lib/Target/ARM/LICENSE.TXT md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h opencl-clang-16.0.0/README.md000066400000000000000000000103021441565305300154210ustar00rootroot00000000000000[![Build Status](https://travis-ci.com/intel/opencl-clang.svg?branch=master)](https://travis-ci.com/intel/opencl-clang) opencl-clang is a thin wrapper library around clang. The library has OpenCL-oriented API and is capable to compile OpenCL C kernels to SPIR-V modules. ## Build Source code in this repo can be built in different manners: * in-tree as an LLVM project * out-of-tree using pre-built LLVM ### In-tree build Before the build all dependencies must be downloaded and laid out as follows: ``` |-- llvm |-- clang |-- SPIRV-LLVM-Translator `-- opencl-clang ``` This can be done using the following commands: ```bash cd git clone https://github.com/llvm/llvm-project.git . -b release/16.x git clone https://github.com/KhronosGroup/SPIRV-LLVM-Translator.git -b llvm_release_160 git clone https://github.com/intel/opencl-clang.git -b ocl-open-160 ``` Then we need to create a build directory and run the build: ```bash export OCL_CLANG_WS= cd $OCL_CLANG_WS mkdir build && cd build cmake -DLLVM_TARGETS_TO_BUILD="X86" -DLLVM_ENABLE_PROJECTS="clang" \ -DLLVM_EXTERNAL_PROJECTS="llvm-spirv;opencl-clang" \ -DLLVM_EXTERNAL_LLVM_SPIRV_SOURCE_DIR="$OCL_CLANG_WS/SPIRV-LLVM-Translator" \ -DLLVM_EXTERNAL_OPENCL_CLANG_SOURCE_DIR="$OCL_CLANG_WS/opencl-clang" \ -DCMAKE_BUILD_TYPE=Release $OCL_CLANG_WS/llvm make opencl-clang -j`nproc` ``` For sanity check of the build please run `make check-clang` and `make check-llvm-spirv` ### Out-of-tree build To build opencl-clang as a standalone project, you need to obtain pre-built LLVM and SPIR-V Translator libraries. **Note:** currently this kind of build is supported on Linux only. If opencl-clang is used as part of another CMake project, you will need to define `OPENCL_CLANG_BUILD_EXTERNAL`. Integration with pre-built LLVM is done using standard `find_package` way as documented in [Embedding LLVM in your project](https://llvm.org/docs/CMake.html#embedding-llvm-in-your-project). Commands to checkout sources and build: ```bash cd git clone https://github.com/intel/opencl-clang.git -b ocl-open-160 mkdir build && cd build cmake ../opencl-clang make all -j`nproc` ``` #### Configuration options ##### Preferred LLVM version By default, openclc-clang's cmake script is searching for LLVM 16.0.0. You can override target version of LLVM by using the `PREFERRED_LLVM_VERSION` cmake option: Example: ```bash cmake -DPREFERRED_LLVM_VERSION="16.0.0" ../opencl-clang ``` ##### Custom LLVM installation If LLVM is installed somewhere in custom (non-system directories) location, you could point to it using the `LLVM_DIR` cmake option. **Note**: You need to specify the path to a directory containing the `LLVMConfig.cmake` file. This file is available in two different locations. * `/lib/cmake/llvm/LLVMConfig.cmake` where `` is the install prefix of an installed version of LLVM. On Linux this is typically `/usr/lib/cmake/llvm/LLVMConfig.cmake`. * `/lib/cmake/llvm/LLVMConfig.cmake` where `` is the root of the LLVM build tree. **Note: this is only available when building LLVM with CMake.** Example: ```bash cmake -DLLVM_DIR=/path/to/installed/llvm/lib/cmake/llvm ../opencl-clang ``` ##### Location of SPIR-V Translator library By default, opencl-clang's cmake script assumes that SPIR-V Translator library is built as part of LLVM, installed in the same place and libLLVMSPIRVLib is linked into libLLVM. If that is not true for you, you can override this: firstly, you need to set `LLVMSPIRV_INCLUDED_IN_LLVM` cmake option to `OFF`. Then you need to specify directory where SPIR-V Translator is installed by using `SPIRV_TRANSLATOR_DIR` cmake option. Example: ```bash cmake -DLLVMSPIRV_INCLUDED_IN_LLVM=OFF -DSPIRV_TRANSLATOR_DIR=/path/to/installed/spirv/translator ../opencl-clang ``` There is a known issue (linker crash) for this kind of build on Ubuntu 16.04 Xenial. In this case the following cmake option should fix it: ``` -DLLVM_NO_DEAD_STRIP=ON ``` Installation directory of SPIR-V Translator is expected to contain the following files: ``` |-- include | `-- LLVMSPIRVLib | `-- LLVMSPIRVLib.h `-- lib64 `-- libLLVMSPIRVLib.so ``` opencl-clang-16.0.0/binary_result.h000066400000000000000000000044551441565305300172110ustar00rootroot00000000000000/*****************************************************************************\ Copyright (c) Intel Corporation (2009-2017). INTEL MAKES NO WARRANTY OF ANY KIND REGARDING THE CODE. THIS CODE IS LICENSED ON AN "AS IS" BASIS AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, INSTALLATION, TRAINING OR OTHER SERVICES. INTEL DOES NOT PROVIDE ANY UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY WARRANTY OF MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR ANY PARTICULAR PURPOSE, OR ANY OTHER WARRANTY. Intel disclaims all liability, including liability for infringement of any proprietary rights, relating to use of the code. No license, express or implied, by estoppel or otherwise, to any intellectual property rights is granted herein. \file binary_result.h \*****************************************************************************/ #pragma once #include "opencl_clang.h" #include "llvm/ADT/SmallVector.h" #include // The following #define is taken from // https://github.com/KhronosGroup/OpenCL-Headers/blob/master/CL/cl.h #define CL_SUCCESS 0 class OCLFEBinaryResult : public Intel::OpenCL::ClangFE::IOCLFEBinaryResult { // IOCLFEBinaryResult public: size_t GetIRSize() const override { return m_IRBuffer.size(); } const void *GetIR() const override { return m_IRBuffer.data(); } const char *GetIRName() const override { return m_IRName.c_str(); } Intel::OpenCL::ClangFE::IR_TYPE GetIRType() const override { return m_type; } const char *GetErrorLog() const override { return m_log.c_str(); } void Release() override { delete this; } // OCLFEBinaryResult public: OCLFEBinaryResult() : m_type(Intel::OpenCL::ClangFE::IR_TYPE_UNKNOWN), m_result(CL_SUCCESS) {} llvm::SmallVectorImpl &getIRBufferRef() { return m_IRBuffer; } std::string &getLogRef() { return m_log; } void setLog(const std::string &log) { m_log = log; } void setIRName(const std::string &name) { m_IRName = name; } void setIRType(Intel::OpenCL::ClangFE::IR_TYPE type) { m_type = type; } void setResult(int result) { m_result = result; } int getResult(void) const { return m_result; } private: llvm::SmallVector m_IRBuffer; std::string m_log; std::string m_IRName; Intel::OpenCL::ClangFE::IR_TYPE m_type; int m_result; }; opencl-clang-16.0.0/cl_headers/000077500000000000000000000000001441565305300162375ustar00rootroot00000000000000opencl-clang-16.0.0/cl_headers/CMakeLists.txt000066400000000000000000000155611441565305300210070ustar00rootroot00000000000000set(CL_HEADERS_LIB cl_headers) set(CLANG_COMMAND $ ) if(LLVM_USE_HOST_TOOLS AND NOT OPENCL_CLANG_BUILD_EXTERNAL) build_native_tool(clang CLANG_COMMAND) endif() set(LINUX_RESOURCE_LINKER_COMMAND linux_resource_linker) function(copy_file SRC DST) add_custom_command( OUTPUT ${DST} MAIN_DEPENDENCY ${SRC} COMMAND ${CMAKE_COMMAND} -E copy "${SRC}" "${DST}" COMMENT "Copying '${SRC}' to ${DST}" ) endfunction(copy_file) if(USE_PREBUILT_LLVM) set(OPENCL_HEADERS_DIR "${LLVM_LIBRARY_DIRS}/clang/${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}/include/") else(USE_PREBUILT_LLVM) set(OPENCL_HEADERS_DIR "${CLANG_SOURCE_DIR}/lib/Headers") endif(USE_PREBUILT_LLVM) copy_file(${OPENCL_HEADERS_DIR}/opencl-c.h opencl-c.h) copy_file(${OPENCL_HEADERS_DIR}/opencl-c-base.h opencl-c-base.h) copy_file(${CMAKE_CURRENT_SOURCE_DIR}/module.modulemap module.modulemap) add_custom_target ( opencl.headers.target DEPENDS module.modulemap opencl-c.h opencl-c-base.h ) function(create_pcm DST MODULE HEADER OPTS DEPS) add_custom_command ( OUTPUT ${DST} MAIN_DEPENDENCY ${MODMAP} DEPENDS ${HEADER} ${DEPS} ${CLANG_COMMAND} COMMAND ${CLANG_COMMAND} -cc1 -x cl -I. -O0 ${OPTS} -fmodules -fmodule-name=${MODULE} -fmodule-map-file-home-is-cwd -emit-module "module.modulemap" -fno-validate-pch -o ${DST} VERBATIM COMMENT "Generating ${DST}" ) endfunction(create_pcm) set(CL12 "-cl-std=CL1.2") set(CL20 "-cl-std=CL2.0") set(CL30 "-cl-std=CL3.0") # Add OpenCL C 3.0 Optional features set(OPTS30 "-cl-ext=+__opencl_c_3d_image_writes,+__opencl_c_atomic_order_acq_rel,+__opencl_c_atomic_order_seq_cst,+__opencl_c_atomic_scope_device,+__opencl_c_atomic_scope_all_devices,+__opencl_c_device_enqueue,+__opencl_c_generic_address_space,+__opencl_c_images,+__opencl_c_int64,+__opencl_c_pipes,+__opencl_c_program_scope_global_variables,+__opencl_c_read_write_images,+__opencl_c_subgroups,+__opencl_c_work_group_collective_functions") set(OPTS30_FP64 "-D__opencl_c_fp64=1") set(SPIR_TRIPLE "-triple;spir-unknown-unknown") set(SPIR64_TRIPLE "-triple;spir64-unknown-unknown") if (BUILD_X64) set(HOST_TRIPLE "${SPIR64_TRIPLE}") else() set(HOST_TRIPLE "${SPIR_TRIPLE}") endif() set(OPTS -cl-ext=+all,-cl_khr_fp64,-__opencl_c_fp64) create_pcm(opencl-c-12-spir.pcm cl12spir opencl-c-base.h "${SPIR_TRIPLE};${CL12};${OPTS}" "${DEPS}") create_pcm(opencl-c-20-spir.pcm cl20spir opencl-c-base.h "${SPIR_TRIPLE};${CL20};${OPTS}" "${DEPS}") create_pcm(opencl-c-30-spir.pcm cl30spir opencl-c-base.h "${SPIR_TRIPLE};${CL30};${OPTS};${OPTS30}" "${DEPS}") create_pcm(opencl-c-12-spir64.pcm cl12spir64 opencl-c-base.h "${SPIR64_TRIPLE};${CL12};${OPTS}" "${DEPS}") create_pcm(opencl-c-20-spir64.pcm cl20spir64 opencl-c-base.h "${SPIR64_TRIPLE};${CL20};${OPTS}" "${DEPS}") create_pcm(opencl-c-30-spir64.pcm cl30spir64 opencl-c-base.h "${SPIR64_TRIPLE};${CL30};${OPTS};${OPTS30}" "${DEPS}") set(OPTS -cl-ext=+all) create_pcm(opencl-c-12-spir-fp64.pcm cl12spirfp64 opencl-c-base.h "${SPIR_TRIPLE};${CL12};${OPTS}" "${DEPS}") create_pcm(opencl-c-20-spir-fp64.pcm cl20spirfp64 opencl-c-base.h "${SPIR_TRIPLE};${CL20};${OPTS}" "${DEPS}") create_pcm(opencl-c-30-spir-fp64.pcm cl30spirfp64 opencl-c-base.h "${SPIR_TRIPLE};${CL30};${OPTS};${OPTS30};${OPTS30_FP64}" "${DEPS}") create_pcm(opencl-c-12-spir64-fp64.pcm cl12spir64fp64 opencl-c-base.h "${SPIR64_TRIPLE};${CL12};${OPTS}" "${DEPS}") create_pcm(opencl-c-20-spir64-fp64.pcm cl20spir64fp64 opencl-c-base.h "${SPIR64_TRIPLE};${CL20};${OPTS}" "${DEPS}") create_pcm(opencl-c-30-spir64-fp64.pcm cl30spir64fp64 opencl-c-base.h "${SPIR64_TRIPLE};${CL30};${OPTS};${OPTS30};${OPTS30_FP64}" "${DEPS}") add_custom_target ( opencl.pcm.target DEPENDS opencl.headers.target opencl-c-12-spir.pcm opencl-c-20-spir.pcm opencl-c-30-spir.pcm opencl-c-12-spir64.pcm opencl-c-20-spir64.pcm opencl-c-30-spir64.pcm opencl-c-12-spir-fp64.pcm opencl-c-20-spir-fp64.pcm opencl-c-30-spir-fp64.pcm opencl-c-12-spir64-fp64.pcm opencl-c-20-spir64-fp64.pcm opencl-c-30-spir64-fp64.pcm ) function(pack_to_obj SRC DST TAG) add_custom_command ( OUTPUT ${DST} DEPENDS ${SRC} ${LINUX_RESOURCE_LINKER_COMMAND} COMMAND ${LINUX_RESOURCE_LINKER_COMMAND} "${SRC}" "${DST}" "${TAG}" COMMENT "Packing ${SRC}" ) endfunction(pack_to_obj) if(WIN32) list(APPEND CL_HEADERS_SRC OpenCL.rc) else() pack_to_obj(opencl-c.h opencl-c.h.cpp "PCM_OPENCL_C_H") pack_to_obj(opencl-c-base.h opencl-c-base.h.cpp "PCM_OPENCL_C_BASE_H") list(APPEND CL_HEADERS_SRC opencl-c.h.cpp opencl-c-base.h.cpp opencl-c-12-spir.mod.cpp opencl-c-20-spir.mod.cpp opencl-c-30-spir.mod.cpp opencl-c-12-spir64.mod.cpp opencl-c-20-spir64.mod.cpp opencl-c-30-spir64.mod.cpp opencl-c-12-spir-fp64.mod.cpp opencl-c-20-spir-fp64.mod.cpp opencl-c-30-spir-fp64.mod.cpp opencl-c-12-spir64-fp64.mod.cpp opencl-c-20-spir64-fp64.mod.cpp opencl-c-30-spir64-fp64.mod.cpp module.modulemap.cpp ) # note the .pcm -> .mod extension change # this is a workaround for CMake bug that caused # dependency cycle in generated build rules pack_to_obj(opencl-c-12-spir.pcm opencl-c-12-spir.mod.cpp "PCM_OPENCL_C_12_SPIR_PCM") pack_to_obj(opencl-c-20-spir.pcm opencl-c-20-spir.mod.cpp "PCM_OPENCL_C_20_SPIR_PCM") pack_to_obj(opencl-c-30-spir.pcm opencl-c-30-spir.mod.cpp "PCM_OPENCL_C_30_SPIR_PCM") pack_to_obj(opencl-c-12-spir64.pcm opencl-c-12-spir64.mod.cpp "PCM_OPENCL_C_12_SPIR64_PCM") pack_to_obj(opencl-c-20-spir64.pcm opencl-c-20-spir64.mod.cpp "PCM_OPENCL_C_20_SPIR64_PCM") pack_to_obj(opencl-c-30-spir64.pcm opencl-c-30-spir64.mod.cpp "PCM_OPENCL_C_30_SPIR64_PCM") pack_to_obj(opencl-c-12-spir-fp64.pcm opencl-c-12-spir-fp64.mod.cpp "PCM_OPENCL_C_12_SPIR_FP64_PCM") pack_to_obj(opencl-c-20-spir-fp64.pcm opencl-c-20-spir-fp64.mod.cpp "PCM_OPENCL_C_20_SPIR_FP64_PCM") pack_to_obj(opencl-c-30-spir-fp64.pcm opencl-c-30-spir-fp64.mod.cpp "PCM_OPENCL_C_30_SPIR_FP64_PCM") pack_to_obj(opencl-c-12-spir64-fp64.pcm opencl-c-12-spir64-fp64.mod.cpp "PCM_OPENCL_C_12_SPIR64_FP64_PCM") pack_to_obj(opencl-c-20-spir64-fp64.pcm opencl-c-20-spir64-fp64.mod.cpp "PCM_OPENCL_C_20_SPIR64_FP64_PCM") pack_to_obj(opencl-c-30-spir64-fp64.pcm opencl-c-30-spir64-fp64.mod.cpp "PCM_OPENCL_C_30_SPIR64_FP64_PCM") pack_to_obj(module.modulemap module.modulemap.cpp "PCM_OPENCL_C_MODULE_MAP") endif() add_library(${CL_HEADERS_LIB} OBJECT ${CL_HEADERS_SRC} ) add_dependencies(${CL_HEADERS_LIB} opencl.pcm.target) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/opencl-c.h ${CMAKE_CURRENT_BINARY_DIR}/opencl-c-base.h ${CMAKE_CURRENT_BINARY_DIR}/module.modulemap DESTINATION include/cclang ) opencl-clang-16.0.0/cl_headers/OpenCL.rc000066400000000000000000000021331441565305300177040ustar00rootroot00000000000000// Microsoft Visual C++ generated resource script. // #include "resource.h" 1 TEXTINCLUDE BEGIN "resource.h\0" END // // Module with OpenCL C declarations with corresponding headers // OPENCL_C_H PCM "opencl-c.h" OPENCL_C_BASE_H PCM "opencl-c-base.h" OPENCL_C_12_SPIR_PCM PCM "opencl-c-12-spir.pcm" OPENCL_C_20_SPIR_PCM PCM "opencl-c-20-spir.pcm" OPENCL_C_30_SPIR_PCM PCM "opencl-c-30-spir.pcm" OPENCL_C_12_SPIR64_PCM PCM "opencl-c-12-spir64.pcm" OPENCL_C_20_SPIR64_PCM PCM "opencl-c-20-spir64.pcm" OPENCL_C_30_SPIR64_PCM PCM "opencl-c-30-spir64.pcm" OPENCL_C_12_SPIR_FP64_PCM PCM "opencl-c-12-spir-fp64.pcm" OPENCL_C_20_SPIR_FP64_PCM PCM "opencl-c-20-spir-fp64.pcm" OPENCL_C_30_SPIR_FP64_PCM PCM "opencl-c-30-spir-fp64.pcm" OPENCL_C_12_SPIR64_FP64_PCM PCM "opencl-c-12-spir64-fp64.pcm" OPENCL_C_20_SPIR64_FP64_PCM PCM "opencl-c-20-spir64-fp64.pcm" OPENCL_C_30_SPIR64_FP64_PCM PCM "opencl-c-30-spir64-fp64.pcm" OPENCL_C_MODULE_MAP PCM "module.modulemap" opencl-clang-16.0.0/cl_headers/module.modulemap000066400000000000000000000017441441565305300214370ustar00rootroot00000000000000module cl12spir { header "opencl-c.h" header "opencl-c-base.h" export * } module cl20spir { header "opencl-c.h" header "opencl-c-base.h" export * } module cl30spir { header "opencl-c.h" header "opencl-c-base.h" export * } module cl12spir64 { header "opencl-c.h" header "opencl-c-base.h" export * } module cl20spir64 { header "opencl-c.h" header "opencl-c-base.h" export * } module cl30spir64 { header "opencl-c.h" header "opencl-c-base.h" export * } module cl12spirfp64 { header "opencl-c.h" header "opencl-c-base.h" export * } module cl20spirfp64 { header "opencl-c.h" header "opencl-c-base.h" export * } module cl30spirfp64 { header "opencl-c.h" header "opencl-c-base.h" export * } module cl12spir64fp64 { header "opencl-c.h" header "opencl-c-base.h" export * } module cl20spir64fp64 { header "opencl-c.h" header "opencl-c-base.h" export * } module cl30spir64fp64 { header "opencl-c.h" header "opencl-c-base.h" export * } opencl-clang-16.0.0/cl_headers/resource.h000066400000000000000000000036061441565305300202440ustar00rootroot00000000000000/*****************************************************************************\ Copyright (c) Intel Corporation (2009-2017). INTEL MAKES NO WARRANTY OF ANY KIND REGARDING THE CODE. THIS CODE IS LICENSED ON AN "AS IS" BASIS AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, INSTALLATION, TRAINING OR OTHER SERVICES. INTEL DOES NOT PROVIDE ANY UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY WARRANTY OF MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR ANY PARTICULAR PURPOSE, OR ANY OTHER WARRANTY. Intel disclaims all liability, including liability for infringement of any proprietary rights, relating to use of the code. No license, express or implied, by estoppel or otherwise, to any intellectual property rights is granted herein. \file resource.h \*****************************************************************************/ #ifndef __RESOURCE__ #define __RESOURCE__ #define OPENCL_C_H "OPENCL_C_H" #define OPENCL_C_BASE_H "OPENCL_C_BASE_H" #define OPENCL_C_12_SPIR_PCM "OPENCL_C_12_SPIR_PCM" #define OPENCL_C_20_SPIR_PCM "OPENCL_C_20_SPIR_PCM" #define OPENCL_C_30_SPIR_PCM "OPENCL_C_30_SPIR_PCM" #define OPENCL_C_12_SPIR64_PCM "OPENCL_C_12_SPIR64_PCM" #define OPENCL_C_20_SPIR64_PCM "OPENCL_C_20_SPIR64_PCM" #define OPENCL_C_30_SPIR64_PCM "OPENCL_C_30_SPIR64_PCM" #define OPENCL_C_12_SPIR_FP64_PCM "OPENCL_C_12_SPIR_FP64_PCM" #define OPENCL_C_20_SPIR_FP64_PCM "OPENCL_C_20_SPIR_FP64_PCM" #define OPENCL_C_30_SPIR_FP64_PCM "OPENCL_C_30_SPIR_FP64_PCM" #define OPENCL_C_12_SPIR64_FP64_PCM "OPENCL_C_12_SPIR64_FP64_PCM" #define OPENCL_C_20_SPIR64_FP64_PCM "OPENCL_C_20_SPIR64_FP64_PCM" #define OPENCL_C_30_SPIR64_FP64_PCM "OPENCL_C_30_SPIR64_FP64_PCM" #define OPENCL_C_MODULE_MAP "OPENCL_C_MODULE_MAP" #endif /* __RESOURCE__ */ opencl-clang-16.0.0/cmake/000077500000000000000000000000001441565305300152265ustar00rootroot00000000000000opencl-clang-16.0.0/cmake/modules/000077500000000000000000000000001441565305300166765ustar00rootroot00000000000000opencl-clang-16.0.0/cmake/modules/CMakeFunctions.cmake000066400000000000000000000153031441565305300225530ustar00rootroot00000000000000# # Set compiler RTTI options according to the given flag # macro(use_rtti val) if (MSVC) if( ${val} ) llvm_replace_compiler_option(CMAKE_CXX_FLAGS "/GR-" "/GR") else() llvm_replace_compiler_option(CMAKE_CXX_FLAGS "/GR" "/GR-" ) endif() else () # G++ or clang or icx if( ${val} ) llvm_replace_compiler_option(CMAKE_CXX_FLAGS "-fno-rtti" "-frtti") else() llvm_replace_compiler_option(CMAKE_CXX_FLAGS "-frtti" "-fno-rtti" ) endif() endif() set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE ) endmacro(use_rtti) # # Set compiler Exception Handling options according to the given flag # macro(use_eh val) if (MSVC) if( ${val} ) llvm_replace_compiler_option(CMAKE_CXX_FLAGS "/EHs-c-" "/EHsc" ) add_definitions( /D_HAS_EXCEPTIONS=1 ) else() llvm_replace_compiler_option(CMAKE_CXX_FLAGS "/EHsc" "/EHs-c-") add_definitions( /D_HAS_EXCEPTIONS=0 ) endif() else () # G++ or clang or icx if( ${val} ) remove_definitions( -fno-exceptions ) else() add_definitions( -fno-exceptions ) endif() endif() endmacro(use_eh) # Reads hash-commit from backported patch # This function assumes that each of files starts with (for example): # From 1a400928bf8fc86fa0f062524c25d0985c94ac6f Mon Sep 17 00:00:00 2001 function(get_backport_patch_hash patch_path patch_hash) file(READ ${patch_path} first_line LIMIT 40 OFFSET 5) string(STRIP ${first_line} first_line_strip) set(patch_hash ${first_line_strip} PARENT_SCOPE) endfunction() # Checks if the the patch is present in current local branch function(is_backport_patch_present patch_path repo_dir patch_in_branch) get_backport_patch_hash(${patch_path} patch_hash) message(STATUS "[OPENCL-CLANG] Checking if patch ${patch_hash} is present in repository") execute_process( COMMAND ${GIT_EXECUTABLE} merge-base --is-ancestor ${patch_hash} HEAD WORKING_DIRECTORY ${repo_dir} RESULT_VARIABLE patch_not_in_branches OUTPUT_QUIET ERROR_QUIET ) if(patch_not_in_branches) set(patch_in_branch False PARENT_SCOPE) # The patch is not present in local branch else() set(patch_in_branch True PARENT_SCOPE) # The patch is not present in local branch endif() endfunction() # Validates if given SHA1/tag/branch name exists in local repo function(is_valid_revision repo_dir revision return_val) message(STATUS "[OPENCL-CLANG] Validating ${revision} in repository") # Check if we have under revision existing branch/tag/SHA1 in this repo execute_process( COMMAND ${GIT_EXECUTABLE} log -1 ${revision} WORKING_DIRECTORY ${repo_dir} RESULT_VARIABLE output_var ERROR_QUIET OUTPUT_QUIET ) if(${output_var} EQUAL 0) set(${return_val} True PARENT_SCOPE) # this tag/branch/sha1 exists in repo else() set(${return_val} False PARENT_SCOPE) # this tag/branch/sha1 not exists in repo endif() endfunction() # # Creates `target_branch` starting at the `base_revision` in the `repo_dir`. # Then all patches from the `patches_dir` are committed to the `target_branch`. # Does nothing if the `target_branch` is already checked out in the `repo_dir`. # function(apply_patches repo_dir patches_dir base_revision target_branch) file(GLOB patches ${patches_dir}/*.patch) if(NOT patches) message(STATUS "[OPENCL-CLANG] No patches in ${patches_dir}") return() endif() message(STATUS "[OPENCL-CLANG] Patching repository ${repo_dir}") # Check if the target branch already exists execute_process( COMMAND ${GIT_EXECUTABLE} rev-parse --verify --no-revs -q ${target_branch} WORKING_DIRECTORY ${repo_dir} RESULT_VARIABLE patches_needed ERROR_QUIET OUTPUT_QUIET ) if(patches_needed) # The target branch doesn't exist list(SORT patches) is_valid_revision(${repo_dir} ${base_revision} exists_base_rev) if(NOT ${exists_base_rev}) execute_process( # take SHA1 from HEAD COMMAND ${GIT_EXECUTABLE} rev-parse HEAD WORKING_DIRECTORY ${repo_dir} OUTPUT_VARIABLE repo_head OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) message(STATUS "[OPENCL-CLANG] ref ${base_revision} not exists in repository, using current HEAD:${repo_head}") set(base_revision ${repo_head}) endif() execute_process( # Create the target branch COMMAND ${GIT_EXECUTABLE} checkout -b ${target_branch} ${base_revision} WORKING_DIRECTORY ${repo_dir} RESULT_VARIABLE ret_check_out ERROR_STRIP_TRAILING_WHITESPACE ERROR_VARIABLE checkout_log OUTPUT_QUIET ) message(STATUS "[OPENCL-CLANG] ${checkout_log} which starts from ref : ${base_revision}") foreach(patch ${patches}) is_backport_patch_present(${patch} ${repo_dir} patch_in_branch) if(${patch_in_branch}) message(STATUS "[OPENCL-CLANG] Patch ${patch} is already in local branch - ignore patching") else() execute_process( # Apply the patch COMMAND ${GIT_EXECUTABLE} am --3way --ignore-whitespace ${patch} WORKING_DIRECTORY ${repo_dir} OUTPUT_VARIABLE patching_log ERROR_QUIET ) message(STATUS "[OPENCL-CLANG] Not present - ${patching_log}") endif() endforeach(patch) else() # The target branch already exists execute_process( # Check it out COMMAND ${GIT_EXECUTABLE} checkout ${target_branch} WORKING_DIRECTORY ${repo_dir} ERROR_QUIET OUTPUT_QUIET ) endif() endfunction() # Usage # SET_LINUX_EXPORTS_FILE( TARGET FILE_NAME ) # This function provides special linkage options for OCL Back-End. These options # prevents exposure of function symbols externally (except functions which are # explicitly listed in version script) function ( SET_LINUX_EXPORTS_FILE TARGET FILE_NAME ) if(NOT WIN32) get_target_property( SOURCE_FILES ${TARGET_NAME} SOURCES ) list( GET SOURCE_FILES 0 FIRST_SOURCE ) set_source_files_properties( ${FIRST_SOURCE} PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${FILE_NAME} ) set_property( TARGET ${TARGET_NAME} APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-Bsymbolic -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/${FILE_NAME}" ) endif(NOT WIN32) endfunction ( SET_LINUX_EXPORTS_FILE ) opencl-clang-16.0.0/linux_linker/000077500000000000000000000000001441565305300166515ustar00rootroot00000000000000opencl-clang-16.0.0/linux_linker/CMakeLists.txt000066400000000000000000000007351441565305300214160ustar00rootroot00000000000000add_executable(linux_resource_linker linux_resource_linker.cpp) if(LLVM_USE_HOST_TOOLS) build_native_tool(linux_resource_linker LINUX_RESOURCE_LINKER_COMMAND) add_custom_target(linux_resource_linker-host DEPENDS ${LINUX_RESOURCE_LINKER_COMMAND} ) add_dependencies(linux_resource_linker linux_resource_linker-host) else() set(LINUX_RESOURCE_LINKER_COMMAND linux_resource_linker) endif() set(LINUX_RESOURCE_LINKER_COMMAND ${LINUX_RESOURCE_LINKER_COMMAND} PARENT_SCOPE) opencl-clang-16.0.0/linux_linker/linux_resource_linker.cpp000066400000000000000000000041641441565305300237740ustar00rootroot00000000000000/*****************************************************************************\ Copyright (c) Intel Corporation (2009-2017). INTEL MAKES NO WARRANTY OF ANY KIND REGARDING THE CODE. THIS CODE IS LICENSED ON AN "AS IS" BASIS AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, INSTALLATION, TRAINING OR OTHER SERVICES. INTEL DOES NOT PROVIDE ANY UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY WARRANTY OF MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR ANY PARTICULAR PURPOSE, OR ANY OTHER WARRANTY. Intel disclaims all liability, including liability for infringement of any proprietary rights, relating to use of the code. No license, express or implied, by estoppel or otherwise, to any intellectual property rights is granted herein. \file linux_resource_linker.cpp \*****************************************************************************/ #include #include int main(int argc, char **argv) { FILE *input; FILE *output; if (!argv[1] || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help") || !argv[2] || !argv[3]) { printf("Usage: bif_linker [input file] [output file] [symbol base name]\n"); return 0; } input = fopen(argv[1], "rb"); if (!input) { printf("Unable to open input file for reading (%s)\n", argv[1]); return 1; } output = fopen(argv[2], "wb"); if (!output) { printf("Unable to open output file for writing (%s)\n", argv[2]); return 1; } fprintf(output, "// This file is auto generated by bo_linker, DO NOT EDIT\n\n"); fprintf(output, "unsigned char __attribute__((visibility(\"default\"))) %s[] =\n{\n ", argv[3]); int count = 0; int is_eol; unsigned char data; while(fread(&data, 1, 1, input)) { is_eol = count ? !(count % 20) : 0; fprintf(output, "%s0x%.2x, ", is_eol? "\n ":"", data); count++; } fprintf(output, "0x00\n};\n\n"); fprintf(output, "unsigned int __attribute__((visibility(\"default\"))) %s_size = %d;\n\n", argv[3], count); fclose(input); fclose(output); } opencl-clang-16.0.0/opencl_clang.cpp000066400000000000000000000311421441565305300172770ustar00rootroot00000000000000/*****************************************************************************\ Copyright (c) Intel Corporation (2009-2017). INTEL MAKES NO WARRANTY OF ANY KIND REGARDING THE CODE. THIS CODE IS LICENSED ON AN "AS IS" BASIS AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, INSTALLATION, TRAINING OR OTHER SERVICES. INTEL DOES NOT PROVIDE ANY UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY WARRANTY OF MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR ANY PARTICULAR PURPOSE, OR ANY OTHER WARRANTY. Intel disclaims all liability, including liability for infringement of any proprietary rights, relating to use of the code. No license, express or implied, by estoppel or otherwise, to any intellectual property rights is granted herein. \file opencl_clang.cpp \*****************************************************************************/ #include "opencl_clang.h" #include "pch_mgr.h" #include "cl_headers/resource.h" #include "binary_result.h" #include "options.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Twine.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Module.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" #include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/Linker/Linker.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Path.h" #include "llvm/Support/Threading.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Mutex.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticIDs.h" #include "clang/Basic/DiagnosticOptions.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/FrontendTool/Utils.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Serialization/ModuleManager.h" #ifdef USE_PREBUILT_LLVM #include "LLVMSPIRVLib/LLVMSPIRVLib.h" #else // USE_PREBUILT_LLVM #include "LLVMSPIRVLib.h" #endif // USE_PREBUILT_LLVM // The following #defines are used as return value of Compile() API and defined // in https://github.com/KhronosGroup/OpenCL-Headers/blob/master/CL/cl.h #define CL_SUCCESS 0 #define CL_COMPILE_PROGRAM_FAILURE -15 #define CL_OUT_OF_HOST_MEMORY -6 #include "assert.h" #include #include #ifdef _WIN32 #include #endif #if defined _DEBUG #include #include #include #include #endif using namespace Intel::OpenCL::ClangFE; static volatile bool lazyCCInit = true; // the flag must be 'volatile' to prevent caching in a CPU register static llvm::sys::Mutex lazyCCInitMutex; static llvm::ManagedStatic > compileMutex; void CommonClangTerminate() { llvm::llvm_shutdown(); } // This function mustn't be invoked from a static object constructor, // from a DllMain function (Windows specific), or from a function // w\ __attribute__ ((constructor)) (Linux specific). void CommonClangInitialize() { if (lazyCCInit) { llvm::sys::ScopedLock lock(lazyCCInitMutex); if (lazyCCInit) { // CommonClangTerminate calls llvm_shutdown to deallocate resources used // by LLVM libraries. llvm_shutdown uses static mutex to make it safe for // multi-threaded envirounment and LLVM libraries user is expected call // llvm_shutdown before static object are destroyed, so we use atexit to // satisfy this requirement. atexit(CommonClangTerminate); llvm::InitializeAllTargets(); llvm::InitializeAllAsmPrinters(); llvm::InitializeAllAsmParsers(); llvm::InitializeAllTargetMCs(); lazyCCInit = false; } } } static bool GetHeaders(std::vector &Result) { struct { const char *ID; const char *Name; } Headers[] = {{OPENCL_C_H, "opencl-c.h"}, {OPENCL_C_BASE_H, "opencl-c-base.h"}, {OPENCL_C_12_SPIR_PCM, "opencl-c-12-spir.pcm"}, {OPENCL_C_20_SPIR_PCM, "opencl-c-20-spir.pcm"}, {OPENCL_C_30_SPIR_PCM, "opencl-c-30-spir.pcm"}, {OPENCL_C_12_SPIR64_PCM, "opencl-c-12-spir64.pcm"}, {OPENCL_C_20_SPIR64_PCM, "opencl-c-20-spir64.pcm"}, {OPENCL_C_30_SPIR64_PCM, "opencl-c-30-spir64.pcm"}, {OPENCL_C_12_SPIR_FP64_PCM, "opencl-c-12-spir-fp64.pcm"}, {OPENCL_C_20_SPIR_FP64_PCM, "opencl-c-20-spir-fp64.pcm"}, {OPENCL_C_30_SPIR_FP64_PCM, "opencl-c-30-spir-fp64.pcm"}, {OPENCL_C_12_SPIR64_FP64_PCM, "opencl-c-12-spir64-fp64.pcm"}, {OPENCL_C_20_SPIR64_FP64_PCM, "opencl-c-20-spir64-fp64.pcm"}, {OPENCL_C_30_SPIR64_FP64_PCM, "opencl-c-30-spir64-fp64.pcm"}, {OPENCL_C_MODULE_MAP, "module.modulemap"}}; Result.clear(); Result.reserve(sizeof(Headers) / sizeof(*Headers)); ResourceManager &RM = ResourceManager::instance(); for (auto Header : Headers) { Resource R = RM.get_resource(Header.Name, Header.ID, "PCM", true); if (!R) { assert(false && "Resource not found"); return false; } Result.push_back(R); } return true; } static void PrintCompileOptions(const char *pszOptions, const char *pszOptionsEx, const char *pszOpenCLVer, const char * pszSource) { #ifdef _DEBUG static int ID = 0; if (!getenv("CCLANG_OPTIONS_DIR")) return; std::string OptionsDir = getenv("CCLANG_OPTIONS_DIR"); std::stringstream logPath; logPath << OptionsDir << "/log_" << std::this_thread::get_id() << "_" << ID << ".txt"; std::cout << logPath.str() << std::endl; // Creating log file std::ofstream logFile(logPath.str(), std::ios::out); if (!logFile.is_open()) { std::cout << "[ERROR] Can't create log file" << std::endl; return; } logFile << "pszOptions=" << pszOptions << std::endl; logFile << "pszOptionsEx=" << pszOptionsEx << std::endl; logFile << "pszOpenCLVer=" << pszOpenCLVer << std::endl; logFile << pszSource; ++ID; logFile.close(); #endif } class SmallVectorBuffer : public std::streambuf { // All memory management is delegated to llvm::SmallVectorImpl llvm::SmallVectorImpl &OS; // Since we don't touch any pointer in streambuf(pbase, pptr, epptr) this is // the only method we need to override. virtual std::streamsize xsputn(const char *s, std::streamsize n) override { OS.append(s, s + n); return n; } public: SmallVectorBuffer() = delete; SmallVectorBuffer(const SmallVectorBuffer&) = delete; SmallVectorBuffer &operator=(const SmallVectorBuffer&) = delete; SmallVectorBuffer(llvm::SmallVectorImpl &O) : OS(O) {} }; extern "C" CC_DLL_EXPORT int Compile(const char *pszProgramSource, const char **pInputHeaders, unsigned int uiNumInputHeaders, const char **pInputHeadersNames, const char *pPCHBuffer, size_t uiPCHBufferSize, const char *pszOptions, const char *pszOptionsEx, const char *pszOpenCLVer, IOCLFEBinaryResult **pBinaryResult) { // Capturing cclang compile options PrintCompileOptions(pszOptions, pszOptionsEx, pszOpenCLVer, pszProgramSource); // Lazy initialization CommonClangInitialize(); try { std::unique_ptr pResult(new OCLFEBinaryResult()); // Create the clang compiler std::unique_ptr compiler( new clang::CompilerInstance()); CompileOptionsParser optionsParser(pszOpenCLVer); // Prepare error log llvm::raw_string_ostream err_ostream(pResult->getLogRef()); { llvm::sys::SmartScopedLock compileGuard {*compileMutex}; // Parse options optionsParser.processOptions(pszOptions, pszOptionsEx); // Prepare our diagnostic client. llvm::IntrusiveRefCntPtr DiagID( new clang::DiagnosticIDs()); llvm::IntrusiveRefCntPtr DiagOpts( new clang::DiagnosticOptions()); DiagOpts->ShowPresumedLoc = true; clang::TextDiagnosticPrinter *DiagsPrinter = new clang::TextDiagnosticPrinter(err_ostream, &*DiagOpts); llvm::IntrusiveRefCntPtr Diags( new clang::DiagnosticsEngine(DiagID, &*DiagOpts, DiagsPrinter)); // Prepare output buffer std::unique_ptr ir_ostream(new llvm::raw_svector_ostream(pResult->getIRBufferRef())); // Set buffers // CompilerInstance takes ownership over output stream compiler->setOutputStream(std::move(ir_ostream)); compiler->setDiagnostics(&*Diags); llvm::IntrusiveRefCntPtr OverlayFS( new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem())); llvm::IntrusiveRefCntPtr MemFS( new llvm::vfs::InMemoryFileSystem); OverlayFS->pushOverlay(MemFS); compiler->createFileManager(std::move(OverlayFS)); compiler->createSourceManager(compiler->getFileManager()); // Create compiler invocation from user args before trickering with it clang::CompilerInvocation::CreateFromArgs(compiler->getInvocation(), optionsParser.args(), *Diags); // Configure our handling of diagnostics. ProcessWarningOptions(*Diags, compiler->getDiagnosticOpts()); // Map memory buffers to a virtual file system MemFS->addFile( optionsParser.getSourceName(), (time_t)0, llvm::MemoryBuffer::getMemBuffer( llvm::StringRef(pszProgramSource), optionsParser.getSourceName())); // Input header with OpenCL defines. std::vector vHeaderWithDefs; if (!GetHeaders(vHeaderWithDefs)) { return CL_COMPILE_PROGRAM_FAILURE; } for (const auto &Header:vHeaderWithDefs) { auto Buf = llvm::MemoryBuffer::getMemBuffer( llvm::StringRef(Header.m_data, Header.m_size), Header.m_name); MemFS->addFile(Header.m_name,(time_t)0, std::move(Buf)); } // Input Headers for (unsigned int i = 0; i < uiNumInputHeaders; ++i) { auto Header = llvm::MemoryBuffer::getMemBuffer( pInputHeaders[i], pInputHeadersNames[i]); MemFS->addFile(pInputHeadersNames[i], (time_t)0, std::move(Header)); } } // Execute the frontend actions. bool success = false; try { success = clang::ExecuteCompilerInvocation(compiler.get()); } catch (const std::exception &) { } pResult->setIRType(IR_TYPE_COMPILED_OBJECT); pResult->setIRName(optionsParser.getSourceName()); // Our error handler depends on the Diagnostics object, which we're // potentially about to delete. Uninstall the handler now so that any // later errors use the default handling behavior instead. // (currently commented out since setting the llvm error handling in // multi-threaded environment is unsupported) // llvm::remove_fatal_error_handler(); err_ostream.flush(); if (success && optionsParser.hasEmitSPIRV()) { // Translate LLVM IR to SPIR-V. llvm::StringRef LLVM_IR(static_cast(pResult->GetIR()), pResult->GetIRSize()); std::unique_ptr MB = llvm::MemoryBuffer::getMemBuffer(LLVM_IR, pResult->GetIRName(), false); llvm::LLVMContext Context; auto E = llvm::getOwningLazyBitcodeModule(std::move(MB), Context, /*ShouldLazyLoadMetadata=*/true); llvm::logAllUnhandledErrors(E.takeError(), err_ostream, "error: "); std::unique_ptr M = std::move(*E); if (M->materializeAll()) { if (pBinaryResult) { *pBinaryResult = nullptr; } assert(false && "Failed to read just compiled LLVM IR!"); return CL_COMPILE_PROGRAM_FAILURE; } pResult->getIRBufferRef().clear(); SmallVectorBuffer StreamBuf(pResult->getIRBufferRef()); std::ostream OS(&StreamBuf); std::string Err; SPIRV::TranslatorOpts SPIRVOpts; SPIRVOpts.enableAllExtensions(); if (!optionsParser.hasOptDisable()) { SPIRVOpts.setMemToRegEnabled(true); } SPIRVOpts.setPreserveOCLKernelArgTypeMetadataThroughString(true); success = llvm::writeSpirv(M.get(), SPIRVOpts, OS, Err); err_ostream << Err.c_str(); err_ostream.flush(); } { llvm::sys::SmartScopedLock compileGuard {*compileMutex}; if (pBinaryResult) { *pBinaryResult = pResult.release(); } } return success ? CL_SUCCESS : CL_COMPILE_PROGRAM_FAILURE; } catch (std::bad_alloc &) { if (pBinaryResult) { *pBinaryResult = NULL; } return CL_OUT_OF_HOST_MEMORY; } } opencl-clang-16.0.0/opencl_clang.h000066400000000000000000000107521441565305300167500ustar00rootroot00000000000000/*****************************************************************************\ Copyright (c) Intel Corporation (2009-2017). INTEL MAKES NO WARRANTY OF ANY KIND REGARDING THE CODE. THIS CODE IS LICENSED ON AN "AS IS" BASIS AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, INSTALLATION, TRAINING OR OTHER SERVICES. INTEL DOES NOT PROVIDE ANY UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY WARRANTY OF MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR ANY PARTICULAR PURPOSE, OR ANY OTHER WARRANTY. Intel disclaims all liability, including liability for infringement of any proprietary rights, relating to use of the code. No license, express or implied, by estoppel or otherwise, to any intellectual property rights is granted herein. \file opencl_clang.h \*****************************************************************************/ #pragma once #include "assert.h" #include "cstddef" // size_t #if defined(_WIN32) #if defined(OPENCL_CLANG_EXPORTS) #define CC_DLL_EXPORT _declspec(dllexport) #else #define CC_DLL_EXPORT _declspec(dllimport) #endif #else #define CC_DLL_EXPORT #endif namespace Intel { namespace OpenCL { namespace ClangFE { // // Type of the binary returned after compilation and/or link // enum IR_TYPE { IR_TYPE_UNKNOWN, IR_TYPE_EXECUTABLE, IR_TYPE_LIBRARY, IR_TYPE_COMPILED_OBJECT }; // // Compilation results interface // Returned by Compile method // struct IOCLFEBinaryResult { // Returns the size in bytes of the IR buffer virtual size_t GetIRSize() const = 0; // Returns the pointer to the IR buffer or NULL if no IR buffer is present virtual const void *GetIR() const = 0; // Returns the name of the program virtual const char *GetIRName() const = 0; // Returns the type of the resulted binary virtual IR_TYPE GetIRType() const = 0; // Returns the pointer to the compilation log string or NULL if not log was // created virtual const char *GetErrorLog() const = 0; // Releases the result object virtual void Release() = 0; protected: virtual ~IOCLFEBinaryResult() {} }; } } } // // Verifies the given OpenCL application supplied compilation options // Params: // pszOptions - compilation options string // pszUnknownOptions - optional outbound pointer to the space separated // unrecognized options // uiUnknownOptionsSize - size of the pszUnknownOptions buffer // Returns: // true if the options verification was successful, false otherwise // extern "C" CC_DLL_EXPORT bool CheckCompileOptions( // A string for compile options const char *pszOptions, // buffer to get the list of unknown options char *pszUnknownOptions, // size of the buffer for unknown options size_t uiUnknownOptionsSize); // // Compiles the given OpenCL program to the LLVM IR // Params: // pProgramSource - OpenCL source program to compile // pInputHeaders - array of the header buffers // uiNumInputHeader - size of the pInputHeaders array // pszInputHeadersNames - array of the headers names // pPCHBuffer - optional pointer to the pch buffer // uiPCHBufferSize - size of the pch buffer // pszOptions - OpenCL application supplied options // pszOptionsEx - optional extra options string usually supplied by runtime // pszOpenCLVer - OpenCL version supported by the device, also defines // __OPENCL_VERSION__ macro - "120" for OpenCL 1.2, "200" for OpenCL 2.0, ... // pBinaryResult - optional outbound pointer to the compilation results // Returns: // Compilation Result as int: 0 - success, error otherwise. // extern "C" CC_DLL_EXPORT int Compile( // A pointer to main program's source (null terminated string) const char *pszProgramSource, // array of additional input headers to be passed in memory (each null // terminated) const char **pInputHeaders, // the number of input headers in pInputHeaders unsigned int uiNumInputHeaders, // array of input headers names corresponding to pInputHeaders const char **pInputHeadersNames, // optional pointer to the pch buffer const char *pPCHBuffer, // size of the pch buffer size_t uiPCHBufferSize, // OpenCL application supplied options const char *pszOptions, // optional extra options string usually supplied by runtime const char *pszOptionsEx, // OpenCL version string - "120" for OpenCL 1.2, "200" for OpenCL 2.0, ... const char *pszOpenCLVer, // optional outbound pointer to the compilation results Intel::OpenCL::ClangFE::IOCLFEBinaryResult **pBinaryResult); opencl-clang-16.0.0/opencl_clang.map000066400000000000000000000011341441565305300172700ustar00rootroot00000000000000{ global: extern "C" { CheckCompileOptions; CheckLinkOptions; Compile; Link; GetKernelArgInfo; PCM_OPENCL_C_H*; PCM_OPENCL_C_BASE_H*; PCM_OPENCL_C_12_SPIR_PCM*; PCM_OPENCL_C_20_SPIR_PCM*; PCM_OPENCL_C_30_SPIR_PCM*; PCM_OPENCL_C_12_SPIR64_PCM*; PCM_OPENCL_C_20_SPIR64_PCM*; PCM_OPENCL_C_30_SPIR64_PCM*; PCM_OPENCL_C_12_SPIR_FP64_PCM*; PCM_OPENCL_C_20_SPIR_FP64_PCM*; PCM_OPENCL_C_30_SPIR_FP64_PCM*; PCM_OPENCL_C_12_SPIR64_FP64_PCM*; PCM_OPENCL_C_20_SPIR64_FP64_PCM*; PCM_OPENCL_C_30_SPIR64_FP64_PCM*; PCM_OPENCL_C_MODULE_MAP*; }; local: *; }; opencl-clang-16.0.0/opencl_clang_options.td000066400000000000000000000043741441565305300207060ustar00rootroot00000000000000//===----------------------------------------------------------------------===// // // This file defines the options accepted by opencl_clang. // //===----------------------------------------------------------------------===// // Include the common option parsing interfaces. include "llvm/Option/OptParser.td" //===----------------------------------------------------------------------===// // OpenCL Options //===----------------------------------------------------------------------===// def g_Flag : Flag<["-"], "g">, HelpText<"Generate source level debug information">; def gline_tables_only_Flag : Flag<["-"], "gline-tables-only">; def profiling : Flag<["-"], "profiling">, HelpText<"Allow profiling">; def w : Flag<["-"], "w">, HelpText<"Suppress all warnings">; def D : JoinedOrSeparate<["-"], "D">; def I : JoinedOrSeparate<["-"], "I">, Flags<[RenderJoined]>, HelpText<"Add directory to include search path">; def s : Separate<["-"], "s">; def Werror : Flag<["-"], "Werror">; def cl_single_precision_constant : Flag<["-"], "cl-single-precision-constant">; def cl_denorms_are_zero : Flag<["-"], "cl-denorms-are-zero">; def cl_fp32_correctly_rounded_divide_sqrt : Flag<["-"], "cl-fp32-correctly-rounded-divide-sqrt">; def cl_opt_disable : Flag<["-"], "cl-opt-disable">; def cl_mad_enable : Flag<["-"], "cl-mad-enable">; def cl_no_signed_zeros : Flag<["-"], "cl-no-signed-zeros">; def cl_unsafe_math_optimizations: Flag<["-"], "cl-unsafe-math-optimizations">; def cl_finite_math_only: Flag<["-"], "cl-finite-math-only">; def cl_fast_relaxed_math: Flag<["-"], "cl-fast-relaxed-math">; def cl_kernel_arg_info: Flag<["-"], "cl-kernel-arg-info">; def cl_std_CL1_1: Flag<["-"], "cl-std=CL1.1">; def cl_std_CL1_2: Flag<["-"], "cl-std=CL1.2">; def cl_std_CL2_0: Flag<["-"], "cl-std=CL2.0">; def cl_std_CL3_0: Flag<["-"], "cl-std=CL3.0">; def cl_uniform_work_group_size: Flag<["-"], "cl-uniform-work-group-size">; def cl_no_subgroup_ifp: Flag<["-"], "cl-no-subgroup-ifp">; def triple : Separate<["-"], "triple">, HelpText<"Specify target triple (e.g. i686-apple-darwin9)">; def target_triple : Separate<["-"], "target-triple">, HelpText<"Specify target triple for spir">; def spir_std_1_0: Flag<["-"], "spir-std=1.0">; def spir_std_1_2: Flag<["-"], "spir-std=1.2">; def x : Separate<["-"], "x">; opencl-clang-16.0.0/options.cpp000066400000000000000000000071671441565305300163600ustar00rootroot00000000000000/*****************************************************************************\ Copyright (c) Intel Corporation (2009-2017). INTEL MAKES NO WARRANTY OF ANY KIND REGARDING THE CODE. THIS CODE IS LICENSED ON AN "AS IS" BASIS AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, INSTALLATION, TRAINING OR OTHER SERVICES. INTEL DOES NOT PROVIDE ANY UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY WARRANTY OF MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR ANY PARTICULAR PURPOSE, OR ANY OTHER WARRANTY. Intel disclaims all liability, including liability for infringement of any proprietary rights, relating to use of the code. No license, express or implied, by estoppel or otherwise, to any intellectual property rights is granted herein. \file options.cpp \*****************************************************************************/ #include "options.h" #include "llvm/Option/Arg.h" #include "clang/Driver/Options.h" #include #include using namespace llvm::opt; OpenCLArgList::OpenCLArgList(const char *pszOptions) { std::back_insert_iterator it( std::back_inserter(m_synthesizedStrings)); quoted_tokenize(it, pszOptions, " \t", '"', '\\'); // need to be careful about the reallocation that could happen in // m_synthesizedStrings upon push_back for (ArgsVector::const_iterator it = m_synthesizedStrings.begin(), end = m_synthesizedStrings.end(); it != end; ++it) { m_argStrings.push_back(it->c_str()); } m_uiOriginalArgsCount = m_argStrings.size(); } unsigned OpenCLArgList::MakeIndex(llvm::StringRef str) const { unsigned index = m_argStrings.size(); // Tuck away so we have a reliable const char *. m_synthesizedStrings.push_back(std::string(str)); m_argStrings.push_back(m_synthesizedStrings.back().c_str()); return index; } unsigned OpenCLArgList::MakeIndex(llvm::StringRef str0, llvm::StringRef str1) const { unsigned index0 = MakeIndex(str0); unsigned index1 = MakeIndex(str1); assert(index0 + 1 == index1 && "Unexpected non-consecutive indices!"); (void)index1; return index0; } const char *OpenCLArgList::MakeArgStringRef(llvm::StringRef str) const { return getArgString(MakeIndex(str)); } std::string OpenCLArgList::getFilteredArgs(int id) const { std::stringstream ss; for (const auto &I : filtered(id)) { ss << I->getAsString(*this) << ' '; } return ss.str(); } OpenCLArgList *OpenCLOptTable::ParseArgs(const char *szOptions, unsigned &missingArgIndex, unsigned &missingArgCount) const { std::unique_ptr pArgs(new OpenCLArgList(szOptions)); // FIXME: Handle '@' args (or at least error on them). missingArgIndex = missingArgCount = 0; unsigned index = 0, argsCount = pArgs->getNumInputArgStrings(); while (index < argsCount) { // Ignore empty arguments (other things may still take them as arguments). if (pArgs->getArgString(index)[0] == '\0') { ++index; continue; } unsigned prev = index; std::unique_ptr pArg = ParseOneArg(*pArgs, index); assert(index > prev && "Parser failed to consume argument."); // Check for missing argument error. if (!pArg) { assert(index >= argsCount && "Unexpected parser error."); assert(index - prev - 1 && "No missing arguments!"); missingArgIndex = prev; missingArgCount = index - prev - 1; break; } pArgs->append(pArg.get()); m_synthesizedArgs.emplace_back(std::move(pArg)); } return pArgs.release(); } opencl-clang-16.0.0/options.h000066400000000000000000000171531441565305300160210ustar00rootroot00000000000000/*****************************************************************************\ Copyright (c) Intel Corporation (2009-2017). INTEL MAKES NO WARRANTY OF ANY KIND REGARDING THE CODE. THIS CODE IS LICENSED ON AN "AS IS" BASIS AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, INSTALLATION, TRAINING OR OTHER SERVICES. INTEL DOES NOT PROVIDE ANY UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY WARRANTY OF MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR ANY PARTICULAR PURPOSE, OR ANY OTHER WARRANTY. Intel disclaims all liability, including liability for infringement of any proprietary rights, relating to use of the code. No license, express or implied, by estoppel or otherwise, to any intellectual property rights is granted herein. \file opencl_clang.h \brief Defines the common structures for both compile and link options parsing \*****************************************************************************/ #ifndef OPENCL_CLANG_OPTIONS_H #define OPENCL_CLANG_OPTIONS_H #include "llvm/Option/Arg.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" #include "clang/Basic/OpenCLOptions.h" #include enum COMPILE_OPT_ID { OPT_COMPILE_INVALID = 0, // This is not an option ID. #define PREFIX(NAME, VALUE) #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ HELPTEXT, METAVAR, VALUES) \ OPT_COMPILE_##ID, #include "opencl_clang_options.inc" OPT_COMPILE_LAST_OPTION #undef OPTION #undef PREFIX }; typedef std::list ArgsVector; // // Extend the ArgList to allow the argument parsing from single string. // // Originally llvm::opt::ArgList allowed only parsing or array of options // string. // class OpenCLArgList : public llvm::opt::ArgList { public: OpenCLArgList(const char *pszOptions); const char *getArgString(unsigned index) const override { return m_argStrings[index]; } unsigned getNumInputArgStrings() const override { return m_uiOriginalArgsCount; } std::string getFilteredArgs(int id) const; public: /// MakeIndex - Get an index for the given string(s). unsigned MakeIndex(llvm::StringRef str) const; unsigned MakeIndex(llvm::StringRef str0, llvm::StringRef str1) const; const char *MakeArgStringRef(llvm::StringRef str) const override; virtual ~OpenCLArgList() {} private: /// List of argument strings used by the contained Args. /// /// This is mutable since we treat the ArgList as being the list /// of Args, and allow routines to add new strings (to have a /// convenient place to store the memory) via MakeIndex. mutable llvm::opt::ArgStringList m_argStrings; /// Strings for synthesized arguments. /// /// This is mutable since we treat the ArgList as being the list /// of Args, and allow routines to add new strings (to have a /// convenient place to store the memory) via MakeIndex. mutable std::list m_synthesizedStrings; /// The number of original input argument strings. unsigned m_uiOriginalArgsCount; }; // // OpenCL specific OptTable // class OpenCLOptTable : public llvm::opt::GenericOptTable { public: OpenCLOptTable(llvm::ArrayRef pOptionInfos) : llvm::opt::GenericOptTable(pOptionInfos) {} OpenCLArgList *ParseArgs(const char *szOptions, unsigned &missingArgIndex, unsigned &missingArgCount) const; private: /// Synthesized arguments - owned to avoid memory leaks. mutable std::vector> m_synthesizedArgs; }; // OpenCL OptTable for compile options class OpenCLCompileOptTable : public OpenCLOptTable { public: OpenCLCompileOptTable(); }; // OpenCL OptTable for link options class OpenCLLinkOptTable : public OpenCLOptTable { public: OpenCLLinkOptTable(); }; /// // Options filter that validates the opencl used options // class EffectiveOptionsFilter { public: EffectiveOptionsFilter(const char *pszOpenCLVer) : m_opencl_ver(pszOpenCLVer) { assert(pszOpenCLVer != NULL); } std::string processOptions(const OpenCLArgList &args, const char *pszOptionsEx, ArgsVector &effectiveArgs); private: std::string m_opencl_ver; static int s_progID; }; /// // Options parser for the Compile function // class CompileOptionsParser { public: CompileOptionsParser(const char *pszOpenCLVersion) : m_commonFilter(pszOpenCLVersion), m_emitSPIRV(false), m_optDisable(false) {} // // Validates and prepares the effective options to pass to clang upon // compilation // void processOptions(const char *pszOptions, const char *pszOptionsEx); // // Just validates the user supplied OpenCL compile options // bool checkOptions(const char *pszOptions, char *pszUnknownOptions, size_t uiUnknownOptionsSize); // // Returns the calculated source name for the input source // std::string getSourceName() const { return m_sourceName; } const char *const *beginArgs() const { return m_effectiveArgsRaw.data(); } const char *const *endArgs() const { return beginArgs() + m_effectiveArgsRaw.size(); } llvm::ArrayRef args() { return m_effectiveArgsRaw; } std::string getEffectiveOptionsAsString() const; bool hasEmitSPIRV() const { return m_emitSPIRV; } bool hasOptDisable() const { return m_optDisable; } private: OpenCLCompileOptTable m_optTbl; EffectiveOptionsFilter m_commonFilter; ArgsVector m_effectiveArgs; llvm::SmallVector m_effectiveArgsRaw; std::string m_sourceName; bool m_emitSPIRV; bool m_optDisable; }; // Tokenize a string into tokens separated by any char in 'delims'. // Support quoting to allow some tokens to contain delimiters, with possible // escape characters to support quotes inside quotes. // To disable quoting or escaping, set relevant chars to '\x00'. // Unescaped quotes are dropped. template void quoted_tokenize(OutIt dest, llvm::StringRef str, llvm::StringRef delims, char quote, char escape) { llvm::StringRef::size_type ptr = str.find_first_not_of(delims); llvm::StringRef::size_type end = str.size(); if (ptr == llvm::StringRef::npos) return; // pArg state machine, with the following state vars: // // ptr - points to the current char in the string // is_escaped - is the current char escaped (i.e. was the // previous char = escape, inside a quote) // in_quote - are we in a quote now (i.e. a quote character // appeared without a matching closing quote) // tok - accumulates the current token. once an unquoted // delimiter or end of string is encountered, tok // is added to the return vector and re-initialized // bool is_escaped = false; bool in_quote = false; std::string tok; while (ptr < end) { char c = str[ptr]; if (c == escape) { tok += c; is_escaped = is_escaped ? false : true; } else if (c == quote) { if (is_escaped) { tok += c; is_escaped = false; } else { in_quote = in_quote ? false : true; } } else if (delims.find(c) != llvm::StringRef::npos) { is_escaped = false; if (in_quote) { tok += c; } else { *(dest++) = tok; tok.clear(); ptr = str.find_first_not_of(delims, ptr); if (ptr != llvm::StringRef::npos) { continue; } else { break; } } } else { is_escaped = false; tok += c; } ++ptr; } if (!tok.empty()) { *(dest++) = tok; } } #endif opencl-clang-16.0.0/options_compile.cpp000066400000000000000000000413221441565305300200570ustar00rootroot00000000000000/*****************************************************************************\ Copyright (c) Intel Corporation (2009-2017). INTEL MAKES NO WARRANTY OF ANY KIND REGARDING THE CODE. THIS CODE IS LICENSED ON AN "AS IS" BASIS AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, INSTALLATION, TRAINING OR OTHER SERVICES. INTEL DOES NOT PROVIDE ANY UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY WARRANTY OF MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR ANY PARTICULAR PURPOSE, OR ANY OTHER WARRANTY. Intel disclaims all liability, including liability for infringement of any proprietary rights, relating to use of the code. No license, express or implied, by estoppel or otherwise, to any intellectual property rights is granted herein. \file options_compile.cpp \*****************************************************************************/ #include "opencl_clang.h" #include "options.h" #include "clang/Driver/Options.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Mutex.h" #include #include #include #define PREFIX(NAME, VALUE) \ static constexpr llvm::StringLiteral NAME##_init[] = VALUE; \ static constexpr llvm::ArrayRef NAME( \ NAME##_init, std::size(NAME##_init) - 1); #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ HELPTEXT, METAVAR, VALUES) #include "opencl_clang_options.inc" #undef OPTION #undef PREFIX using namespace llvm::opt; static llvm::ManagedStatic > compileOptionsMutex; static constexpr OptTable::Info ClangOptionsInfoTable[] = { #define PREFIX(NAME, VALUE) #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ HELPTEXT, METAVAR, VALUES) \ { \ PREFIX, NAME, HELPTEXT, METAVAR, OPT_COMPILE_##ID, \ llvm::opt::Option::KIND##Class, PARAM, FLAGS, OPT_COMPILE_##GROUP, \ OPT_COMPILE_##ALIAS, ALIASARGS, VALUES \ } \ , #include "opencl_clang_options.inc" }; OpenCLCompileOptTable::OpenCLCompileOptTable() : OpenCLOptTable(ClangOptionsInfoTable) {} int EffectiveOptionsFilter::s_progID = 1; /// // Options filter that validates the opencl used options // std::string EffectiveOptionsFilter::processOptions(const OpenCLArgList &args, const char *pszOptionsEx, ArgsVector &effectiveArgs) { // Reset args int iCLStdSet = 0; bool fp64Enabled = false; std::string szTriple; std::string sourceName(llvm::Twine(s_progID++).str()); for (OpenCLArgList::const_iterator it = args.begin(), ie = args.end(); it != ie; ++it) { switch ((*it)->getOption().getID()) { case OPT_COMPILE_w: case OPT_COMPILE_D: case OPT_COMPILE_I: case OPT_COMPILE_Werror: case OPT_COMPILE_cl_single_precision_constant: case OPT_COMPILE_cl_fp32_correctly_rounded_divide_sqrt: case OPT_COMPILE_cl_opt_disable: case OPT_COMPILE_cl_mad_enable: case OPT_COMPILE_cl_no_signed_zeros: case OPT_COMPILE_cl_unsafe_math_optimizations: effectiveArgs.push_back((*it)->getAsString(args)); break; case OPT_COMPILE_cl_denorms_are_zero: effectiveArgs.push_back("-fdenormal-fp-math=preserve-sign"); break; case OPT_COMPILE_s: { std::string newSourceName = (*it)->getValue(); if (!newSourceName.empty()) { sourceName = newSourceName; // Normalize path to contain forward slashes replace(sourceName.begin(), sourceName.end(), '\\', '/'); #ifdef _WIN32 // On Windows only, normalize the file name to lower case, since // LLVM saves buffer names in a case-sensitive manner, while // other Windows tools don't. // std::transform(sourceName.begin(), sourceName.end(), sourceName.begin(), ::tolower); #endif } effectiveArgs.push_back("-main-file-name"); effectiveArgs.push_back(sourceName.substr(sourceName.rfind('/') + 1)); break; } case OPT_COMPILE_cl_finite_math_only: effectiveArgs.push_back((*it)->getAsString(args)); effectiveArgs.push_back("-D"); effectiveArgs.push_back("__FINITE_MATH_ONLY__=1"); break; case OPT_COMPILE_cl_fast_relaxed_math: effectiveArgs.push_back((*it)->getAsString(args)); effectiveArgs.push_back("-D"); effectiveArgs.push_back("__FAST_RELAXED_MATH__=1"); break; case OPT_COMPILE_cl_std_CL1_1: iCLStdSet = 110; effectiveArgs.push_back((*it)->getAsString(args)); break; case OPT_COMPILE_cl_std_CL1_2: iCLStdSet = 120; effectiveArgs.push_back((*it)->getAsString(args)); break; case OPT_COMPILE_cl_std_CL2_0: iCLStdSet = 200; effectiveArgs.push_back((*it)->getAsString(args)); break; case OPT_COMPILE_cl_std_CL3_0: iCLStdSet = 300; effectiveArgs.push_back((*it)->getAsString(args)); break; case OPT_COMPILE_triple: szTriple = (*it)->getValue(); break; case OPT_COMPILE_cl_uniform_work_group_size: case OPT_COMPILE_cl_no_subgroup_ifp: case OPT_COMPILE_target_triple: case OPT_COMPILE_spir_std_1_0: case OPT_COMPILE_spir_std_1_2: // ignore for now case OPT_COMPILE_cl_kernel_arg_info: // For SPIR, we always create kernel // arg info, so ignoring it here break; case OPT_COMPILE_x: // ensure that the value is spir assert((*it)->getValue() == std::string("spir")); // TODO: move the validation of the value to the check section of the // option processing to be reported as an unknown option break; // Just ignore the unknown options ( they will be listed in the unknown // list inside the ArgsList anyway) // The below assert is usable for manual debugging only // default: // assert(false && "some unknown argument"); case OPT_COMPILE_profiling: case OPT_COMPILE_gline_tables_only_Flag: effectiveArgs.push_back("-debug-info-kind=line-tables-only"); effectiveArgs.push_back("-dwarf-version=4"); break; case OPT_COMPILE_g_Flag: effectiveArgs.push_back("-debug-info-kind=limited"); effectiveArgs.push_back("-dwarf-version=4"); #ifdef _WIN32 // Do not use column information on Windows. effectiveArgs.push_back("-gno-column-info"); #endif break; } } if (!iCLStdSet) { effectiveArgs.push_back("-cl-std=CL1.2"); iCLStdSet = 120; } effectiveArgs.push_back("-D"); effectiveArgs.push_back("__OPENCL_VERSION__=" + m_opencl_ver); effectiveArgs.push_back("-x"); effectiveArgs.push_back("cl"); effectiveArgs.push_back("-cl-kernel-arg-info"); effectiveArgs.push_back("-fno-validate-pch"); effectiveArgs.push_back("-fno-caret-diagnostics"); if (std::find_if(effectiveArgs.begin(), effectiveArgs.end(), [](const ArgsVector::value_type& a) { return a == "-S" || a.find("-emit") == 0; }) == effectiveArgs.end()) { effectiveArgs.push_back("-emit-llvm-bc"); } effectiveArgs.push_back("-triple"); if (szTriple.empty()) { #if defined(_M_X64) || defined(__LP64__) szTriple = "spir64-unknown-unknown"; #else szTriple = "spir-unknown-unknown"; #endif } effectiveArgs.push_back(szTriple); effectiveArgs.push_back("-include"); effectiveArgs.push_back("opencl-c.h"); // Don't optimize in the frontend // clang defaults to -O0, and in that mode, does not produce IR that is // intended to be optimized (e.g. produces 'optnone' attribute), so we are // using '-disable-llvm-passes' to get out the unoptimized IR. effectiveArgs.push_back("-disable-llvm-passes"); // Specifying the option makes clang emit function body for functions // marked with inline keyword. effectiveArgs.push_back("-fgnu89-inline"); // Do not support all extensions by default. Support for a particular // extension should be enabled by passing a '-cl-ext' option in pszOptionsEx. effectiveArgs.push_back("-cl-ext=-all"); // OpenCL v2.0 s6.9.u - Implicit function declaration is not supported. // Behavior of clang is changed and now there is only warning about // implicit function declarations. To be more user friendly and avoid // unexpected indirect function calls in BE, let's force this warning to // error. effectiveArgs.push_back("-Werror=implicit-function-declaration"); // add the extended options verbatim std::back_insert_iterator it(std::back_inserter(effectiveArgs)); quoted_tokenize(it, pszOptionsEx, " \t", '"', '\x00'); for (auto it = effectiveArgs.begin(), end = effectiveArgs.end(); it != end; ++it) { if (it->compare("-Dcl_khr_fp64") == 0 || it->compare("-D cl_khr_fp64=1") == 0) fp64Enabled = true; else if (it->compare("-U cl_khr_fp64") == 0) fp64Enabled = false; // Find last position that enables or disables cl_khr_fp64 else if (it->find("cl_khr_fp64") != std::string::npos) { auto NegFp64 = it->rfind("-cl_khr_fp64"); auto PosFp64 = it->rfind("+cl_khr_fp64"); if(NegFp64 != std::string::npos && PosFp64 != std::string::npos) fp64Enabled = PosFp64 > NegFp64; else if(NegFp64 != std::string::npos) fp64Enabled = false; else fp64Enabled = true; } } #ifdef PCH_EXTENSION std::map extMap; llvm::SmallVector extVec; llvm::SplitString(PCH_EXTENSION, extVec, ","); for(auto ext : extVec) extMap.insert({ext.str(), true}); #else std::map extMap{ {"cl_khr_3d_image_writes", true}, {"cl_khr_depth_images", true}, {"cl_khr_fp16", true}, #ifdef _WIN32 // cl_khr_gl_msaa_sharing is only supported on Windows [NEO]. {"cl_khr_gl_msaa_sharing", true}, #endif {"cl_khr_global_int32_base_atomics", true}, {"cl_khr_global_int32_extended_atomics", true}, {"cl_khr_int64_base_atomics", true}, {"cl_khr_int64_extended_atomics", true}, {"cl_khr_local_int32_base_atomics", true}, {"cl_khr_local_int32_extended_atomics", true}, {"cl_khr_mipmap_image", true}, {"cl_khr_mipmap_image_writes", true}, {"cl_khr_subgroups", true}, {"cl_intel_device_side_avc_motion_estimation", true}, {"cl_intel_planar_yuv", true}, {"cl_intel_subgroups", true}, {"cl_intel_subgroups_short", true}}; #endif auto parseClExt = [&](const std::string &clExtStr) { llvm::StringRef clExtRef(clExtStr); clExtRef.consume_front("-cl-ext="); llvm::SmallVector parsedExt; clExtRef.split(parsedExt, ','); for (auto ext : parsedExt) { char sign = ext.front(); bool enabled = sign != '-'; llvm::StringRef extName = ext; if (sign == '+' || sign == '-') extName = extName.drop_front(); if (extName == "all") { for (auto &p : extMap) p.second = enabled; continue; } auto it = extMap.find(extName.str()); if (it != extMap.end()) it->second = enabled; } }; std::for_each(effectiveArgs.begin(), effectiveArgs.end(), [&](const ArgsVector::value_type &a) { if (a.find("-cl-ext=") == 0) parseClExt(a); }); // extension is enabled in PCH but disabled or not specifed in options => // disable pch bool useModules = !std::any_of(extMap.begin(), extMap.end(), [](const auto &p) { return p.second == false; }); if (useModules) { effectiveArgs.push_back("-fmodules"); if (!fp64Enabled) { if (szTriple.find("spir64") != szTriple.npos) { if (iCLStdSet <= 120) effectiveArgs.push_back("-fmodule-file=opencl-c-12-spir64.pcm"); else if (iCLStdSet == 200) effectiveArgs.push_back("-fmodule-file=opencl-c-20-spir64.pcm"); else if (iCLStdSet == 300) effectiveArgs.push_back("-fmodule-file=opencl-c-30-spir64.pcm"); } else if (szTriple.find("spir") != szTriple.npos) { if (iCLStdSet <= 120) effectiveArgs.push_back("-fmodule-file=opencl-c-12-spir.pcm"); else if (iCLStdSet == 200) effectiveArgs.push_back("-fmodule-file=opencl-c-20-spir.pcm"); else if (iCLStdSet == 300) effectiveArgs.push_back("-fmodule-file=opencl-c-30-spir.pcm"); } } else { if (szTriple.find("spir64") != szTriple.npos) { if (iCLStdSet <= 120) effectiveArgs.push_back("-fmodule-file=opencl-c-12-spir64-fp64.pcm"); else if (iCLStdSet == 200) effectiveArgs.push_back("-fmodule-file=opencl-c-20-spir64-fp64.pcm"); else if (iCLStdSet == 300) effectiveArgs.push_back("-fmodule-file=opencl-c-30-spir64-fp64.pcm"); } else if (szTriple.find("spir") != szTriple.npos) { if (iCLStdSet <= 120) effectiveArgs.push_back("-fmodule-file=opencl-c-12-spir-fp64.pcm"); else if (iCLStdSet == 200) effectiveArgs.push_back("-fmodule-file=opencl-c-20-spir-fp64.pcm"); else if (iCLStdSet == 300) effectiveArgs.push_back("-fmodule-file=opencl-c-30-spir-fp64.pcm"); } } } // add source name to options as an input file assert(!sourceName.empty() && "Empty source name."); effectiveArgs.push_back(sourceName); return sourceName; } void CompileOptionsParser::processOptions(const char *pszOptions, const char *pszOptionsEx) { // parse options unsigned missingArgIndex, missingArgCount; std::unique_ptr pArgs( m_optTbl.ParseArgs(pszOptions, missingArgIndex, missingArgCount)); // post process logic m_sourceName = m_commonFilter.processOptions(*pArgs, pszOptionsEx, m_effectiveArgs); // build the raw options array for (ArgsVector::iterator it = m_effectiveArgs.begin(), end = m_effectiveArgs.end(); it != end; ++it) { if (it->compare("-cl-opt-disable") == 0) { m_optDisable = true; } else if (it->compare("-emit-spirv") == 0) { m_effectiveArgsRaw.push_back("-emit-llvm-bc"); m_emitSPIRV = true; continue; } m_effectiveArgsRaw.push_back(it->c_str()); } } bool CompileOptionsParser::checkOptions(const char *pszOptions, char *pszUnknownOptions, size_t uiUnknownOptionsSize) { // Parse the arguments. unsigned missingArgIndex, missingArgCount; std::unique_ptr pArgs( m_optTbl.ParseArgs(pszOptions, missingArgIndex, missingArgCount)); // Check for missing argument error. if (missingArgCount) { std::fill_n(pszUnknownOptions, uiUnknownOptionsSize, '\0'); std::string missingArg(pArgs->getArgString(missingArgIndex)); missingArg.copy(pszUnknownOptions, uiUnknownOptionsSize - 1); return false; } std::string unknownOptions = pArgs->getFilteredArgs(OPT_COMPILE_UNKNOWN); if (!unknownOptions.empty()) { std::fill_n(pszUnknownOptions, uiUnknownOptionsSize, '\0'); unknownOptions.copy(pszUnknownOptions, uiUnknownOptionsSize - 1); return false; } // we do not support input options std::string inputOptions = pArgs->getFilteredArgs(OPT_COMPILE_INPUT); if (!inputOptions.empty()) { std::fill_n(pszUnknownOptions, uiUnknownOptionsSize, '\0'); inputOptions.copy(pszUnknownOptions, uiUnknownOptionsSize - 1); return false; } return true; } std::string CompileOptionsParser::getEffectiveOptionsAsString() const { std::stringstream ss; const char *const *it = beginArgs(); const char *const *ie = endArgs(); for (; it != ie; ++it) { ss << *it << " "; } return ss.str(); } extern "C" CC_DLL_EXPORT bool CheckCompileOptions(const char *pszOptions, char *pszUnknownOptions, size_t uiUnknownOptionsSize) { // LLVM doesn't guarantee thread safety, // therefore we serialize execution of LLVM code. llvm::sys::SmartScopedLock compileOptionsGuard {*compileOptionsMutex}; try { CompileOptionsParser optionsParser("200"); return optionsParser.checkOptions(pszOptions, pszUnknownOptions, uiUnknownOptionsSize); } catch (std::bad_alloc &) { if (pszUnknownOptions && uiUnknownOptionsSize > 0) { std::fill_n(pszUnknownOptions, uiUnknownOptionsSize, '\0'); } return false; } } opencl-clang-16.0.0/pch_mgr.cpp000066400000000000000000000162131441565305300162740ustar00rootroot00000000000000/*****************************************************************************\ Copyright (c) Intel Corporation (2009-2017). INTEL MAKES NO WARRANTY OF ANY KIND REGARDING THE CODE. THIS CODE IS LICENSED ON AN "AS IS" BASIS AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, INSTALLATION, TRAINING OR OTHER SERVICES. INTEL DOES NOT PROVIDE ANY UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY WARRANTY OF MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR ANY PARTICULAR PURPOSE, OR ANY OTHER WARRANTY. Intel disclaims all liability, including liability for infringement of any proprietary rights, relating to use of the code. No license, express or implied, by estoppel or otherwise, to any intellectual property rights is granted herein. \file pch_mgr.cpp \*****************************************************************************/ #include "pch_mgr.h" #include "llvm/ADT/Twine.h" #include "llvm/Object/ELF.h" #include #include #include #include #ifdef _WIN32 #include #else #include #include struct auto_dlclose { auto_dlclose(void *module) : m_pModule(module) {} ~auto_dlclose() { if (m_pModule) dlclose(m_pModule); } void *get() { return m_pModule; } bool operator!() { return !m_pModule; } operator bool() { return m_pModule != NULL; } void *release() { void *pTemp = m_pModule; m_pModule = NULL; return pTemp; } private: auto_dlclose(const auto_dlclose &); void *m_pModule; }; #endif ResourceManager ResourceManager::g_instance; void dummy() {} // returns the pointer to the buffer loaded from the resource with the given id Resource ResourceManager::get_resource(const char *name, const char *id, const char *type, bool requireNullTerminate) { llvm::sys::ScopedLock mutexGuard(m_lock); auto res = m_buffers.find(id); if (res == m_buffers.end()) { // lazy load the resource if not found in the cache if (!load_resource(id, type, requireNullTerminate)) { return Resource(); } } res = m_buffers.find(id); assert(res != m_buffers.end()); const char *data = res->second.first; size_t size = res->second.second; return Resource(data, size, name); } const char *ResourceManager::get_file(const char *path, bool binary, bool requireNullTerminate, size_t &out_size) { llvm::sys::ScopedLock mutexGuard(m_lock); std::string key(path); if (m_buffers.find(key) == m_buffers.end()) { // lazy load the resource if not found in the cache load_file(path, binary, requireNullTerminate); } assert(m_buffers.find(key) != m_buffers.end()); out_size = m_buffers[key].second; return m_buffers[key].first; } const char* ResourceManager::realloc_buffer(const char *id, const char* buf, size_t size, bool requireNullTerminate) { std::vector &buffer = m_allocations[id]; size_t alloc_size = requireNullTerminate ? size + 1 : size; buffer.resize(alloc_size); buffer.assign(buf, buf + size); // The data in the buffer will be eventually passed to llvm::MemoryBufferMem // ctor via argument of StringRef type. The Length of this StringRef will be // = the 'size' argument of this function. There is an assert in // llvm::MemoryBuffer::init checking that element *past the end* of the memory // range passed via the ctor is '\0'. So we add it here. buffer.push_back('\0'); return &buffer[0]; } #ifdef _WIN32 bool ResourceManager::GetResourceWin32(const char *id, const char *pszType, const char *&res, size_t &size) { HMODULE hMod = NULL; // Get the handle to the current module GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR)dummy, &hMod); if (!hMod) { return false; } std::string ResName = ("\"" + llvm::Twine(id) + "\"").str(); // Locate the resource HRSRC hRes = FindResourceA(hMod, ResName.c_str(), pszType); if (!hRes) { return false; } // Load the resource HGLOBAL hBytes = LoadResource(hMod, hRes); if (!hBytes) { return false; } // Get the base address to the resource. This call doesn't really lock it res = (const char*) LockResource(hBytes); if (!res) { return false; } // Get the buffer size size = SizeofResource(hMod, hRes); if (!size) { return false; } return true; } #else // WIN32 /** * GetResourceUnix loads resource from shared library `lib`. * * If `relocate` argument is `false`, returned resource is only valid if: * 1) library `lib` is loaded into memory before use of this function * 2) resource will be used only while library is still loaded * * If relocate is `true`, resource will be memcpy'ed into an internal buffer, * i.e. no resource will be valid as long as the ResourceManager is alive. */ bool ResourceManager::GetResourceUnix(const char *id, const char *pszType, const char *lib, bool relocate, const char *&res, size_t &size) { void *handle = dlopen(lib, RTLD_NOW); if (!handle) { return false; } auto_dlclose module(handle); std::string name = (pszType + llvm::Twine("_") + llvm::Twine(id)).str(); std::string size_name = (name.c_str() + llvm::Twine("_size")).str(); const void *size_ptr = dlsym(module.get(), size_name.c_str()); if (!size_ptr) { return false; } size = *(const uint32_t *)size_ptr; res = (const char *)dlsym(module.get(), name.c_str()); if (!res) { return false; } return true; } #endif // WIN32 bool ResourceManager::load_resource(const char *id, const char *pszType, bool requireNullTerminate) { // this function is called under lock assert(m_buffers.find(id) == m_buffers.end()); const char *res = nullptr; size_t size = 0; #ifdef WIN32 bool ok = GetResourceWin32(id, pszType, res, size); #else bool ok = GetResourceUnix(id, pszType, LIBOPENCL_CLANG_NAME, false, res, size); #endif if (!ok) { return false; } if (requireNullTerminate && res[size] != '\0') { // reallocate the buffer to ensure the null termination res = realloc_buffer(id, res, size, requireNullTerminate); } m_buffers[id] = std::pair(res, size); return true; } // cache the content of the file to the internal buffers void ResourceManager::load_file(const char *path, bool binary, bool requireNullTerminate) { std::string key(path); std::ifstream fs(path, binary ? std::ios::binary : std::ios::in); std::vector &buffer = m_allocations[key]; buffer.assign(std::istreambuf_iterator(fs), std::istreambuf_iterator()); if (requireNullTerminate && buffer.size() > 0 && buffer.back() != '\0') { buffer.push_back('\0'); } m_buffers[key] = std::pair(buffer.data(), buffer.size()); } opencl-clang-16.0.0/pch_mgr.h000066400000000000000000000056351441565305300157470ustar00rootroot00000000000000/*****************************************************************************\ Copyright (c) Intel Corporation (2009-2017). INTEL MAKES NO WARRANTY OF ANY KIND REGARDING THE CODE. THIS CODE IS LICENSED ON AN "AS IS" BASIS AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, INSTALLATION, TRAINING OR OTHER SERVICES. INTEL DOES NOT PROVIDE ANY UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY WARRANTY OF MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR ANY PARTICULAR PURPOSE, OR ANY OTHER WARRANTY. Intel disclaims all liability, including liability for infringement of any proprietary rights, relating to use of the code. No license, express or implied, by estoppel or otherwise, to any intellectual property rights is granted herein. \file pch_mgr.h \*****************************************************************************/ #include "llvm/Support/Mutex.h" #include #include #include #include #include struct Resource { const char* m_data; size_t m_size; std::string m_name; Resource() { m_data = nullptr; m_size = 0; m_name = ""; } Resource(const char* data, size_t size, const std::string& name): m_data(data), m_size(size), m_name(name) {} bool operator!() { return m_data == nullptr; } }; // Singleton class for resource management // Its main purpose is to cache the buffers loaded from the resources // but it could be easely extended to support file based buffers as well class ResourceManager { public: static ResourceManager &instance() { return g_instance; } Resource get_resource(const char *name, const char *id, const char *type, bool requireNullTerminate); const char *get_file(const char *path, bool binary, bool requireNullTerminate, size_t &out_size); private: ResourceManager() {} bool load_resource(const char *id, const char *pszType, bool requireNullTerminate); void load_file(const char *path, bool binary, bool requireNullTerminate); const char* realloc_buffer(const char *id, const char* buf, size_t size, bool requireNullTerminate); #ifdef _WIN32 bool GetResourceWin32(const char *id, const char *pszType, const char *&res, size_t &size); #else bool GetResourceUnix(const char *id, const char *pszType, const char *lib, bool relocate, const char *&res, size_t &size); #endif private: static ResourceManager g_instance; llvm::sys::Mutex m_lock; // map that caches the pointers to the loaded buffers and their sizes // those buffers could be either the pointer to the loaded // resource or to the cached buffers (stored in the m_allocations var below) std::map> m_buffers; std::map> m_allocations; };