pax_global_header00006660000000000000000000000064150115264620014514gustar00rootroot0000000000000052 comment=24c2c66279e3cf01544f727bf726e2e294f299b3 opencl-clang-20.1.0/000077500000000000000000000000001501152646200141365ustar00rootroot00000000000000opencl-clang-20.1.0/.github/000077500000000000000000000000001501152646200154765ustar00rootroot00000000000000opencl-clang-20.1.0/.github/actions/000077500000000000000000000000001501152646200171365ustar00rootroot00000000000000opencl-clang-20.1.0/.github/actions/build-opencl-clang/000077500000000000000000000000001501152646200225755ustar00rootroot00000000000000opencl-clang-20.1.0/.github/actions/build-opencl-clang/action.yml000066400000000000000000000037101501152646200245760ustar00rootroot00000000000000# ===--- # 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-20.1.0/.github/dependabot.yml000066400000000000000000000002421501152646200203240ustar00rootroot00000000000000# Set update schedule for GitHub Actions version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "monthly" opencl-clang-20.1.0/.github/workflows/000077500000000000000000000000001501152646200175335ustar00rootroot00000000000000opencl-clang-20.1.0/.github/workflows/codeql.yml000066400000000000000000000065111501152646200215300ustar00rootroot00000000000000name: "CodeQL" on: push: branches: [ "ocl-open-200" ] pull_request: branches: [ "ocl-open-200" ] permissions: contents: read env: LLVM_VERSION: 20 LLVM_VERSION_MINOR: 1 jobs: analyze: name: Analyze runs-on: ubuntu-latest permissions: # required for all workflows security-events: write # required to fetch internal or private CodeQL packs packages: read strategy: fail-fast: false matrix: include: - language: c-cpp build-mode: manual steps: - name: Install llvm and its dependencies run: | curl -L "https://apt.llvm.org/llvm-snapshot.gpg.key" | sudo apt-key add - curl -L "https://packages.lunarg.com/lunarg-signing-key-pub.asc" | sudo apt-key add - echo "deb https://apt.llvm.org/jammy/ llvm-toolchain-jammy-20 main" | sudo tee -a /etc/apt/sources.list echo "deb https://packages.lunarg.com/vulkan jammy main" | sudo tee -a /etc/apt/sources.list sudo apt-get update sudo apt-get -yq --no-install-suggests --no-install-recommends install \ clang-${{ env.LLVM_VERSION }} \ clang-tools-${{ env.LLVM_VERSION }} \ llvm-${{ env.LLVM_VERSION }}-dev \ libllvmlibc-${{ env.LLVM_VERSION }}-dev \ libclang-${{ env.LLVM_VERSION }}-dev \ libclang-cpp${{ env.LLVM_VERSION }}-dev \ libpolly-${{ env.LLVM_VERSION }}-dev \ libzstd-dev \ libedit-dev \ mlir-${{ env.LLVM_VERSION }}-tools - name: Checkout opencl-clang sources for action files uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: ref: ${{ github.ref }} - name: Checkout SPIRV-LLVM-Translator sources uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: repository: KhronosGroup/SPIRV-LLVM-Translator path: SPIRV-LLVM-Translator ref: llvm_release_200 - name: Build SPIRV-LLVM-Translator run: | builddir=${{ github.workspace }}/SPIRV-LLVM-Translator/build cmake -B "$builddir" \ ${{ github.workspace }}/SPIRV-LLVM-Translator \ -DLLVM_INCLUDE_TESTS=OFF \ -DCMAKE_INSTALL_PREFIX="$builddir"/install \ -DCMAKE_BUILD_TYPE=Release cmake --build "$builddir" -j $(nproc) cmake --install "$builddir" echo "spirv-translator-dir=${builddir}/install" >> $GITHUB_ENV - name: Initialize CodeQL uses: github/codeql-action/init@f079b8493333aace61c81488f8bd40919487bd9f # v3.25.7 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} - name: Build opencl-clang run: | mkdir build && cd build cmake ${{ github.workspace }} \ -DPREFERRED_LLVM_VERSION="${{ env.LLVM_VERSION }}.${{ env.LLVM_VERSION_MINOR }}" \ -DLLVMSPIRV_INCLUDED_IN_LLVM=OFF \ -DSPIRV_TRANSLATOR_DIR=${{ env.spirv-translator-dir }} \ -DCMAKE_BUILD_TYPE=Release cmake --build . -j $(nproc) - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@f079b8493333aace61c81488f8bd40919487bd9f # v3.25.7 with: category: "/language:${{matrix.language}}" opencl-clang-20.1.0/.github/workflows/on-demand-verification.yml000066400000000000000000000023561501152646200246060ustar00rootroot00000000000000# ===--- # To be run manually by maintainers # ===--- name: On demand verification run-name: 'On demand by ${{ github.actor }}' permissions: contents: read on: workflow_dispatch: inputs: ref_llvm: description: 'LLVM ref to build with' required: true default: main ref_translator: description: 'SPIRV-LLVM-Translator ref to build with' required: true default: main ref_opencl-clang: description: 'opencl-clang ref to build with' required: true default: main build_type: description: 'Build type to pass to CMake' required: true default: Release type: choice options: - Release - Debug - RelWithDebInfo jobs: verify_on_demand: runs-on: ubuntu-22.04 steps: - name: Checkout opencl-clang sources for action files availabilty uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - name: Run build-opencl-clang action uses: ./.github/actions/build-opencl-clang with: ref_llvm: ${{ inputs.ref_llvm }} ref_translator: ${{ inputs.ref_translator }} ref_opencl-clang: ${{ inputs.ref_opencl-clang }} opencl-clang-20.1.0/.github/workflows/on-push-verification-in-tree.yml000066400000000000000000000020611501152646200256670ustar00rootroot00000000000000# ===--- # Running on push & pull_request. # This workflow parses the destination branch # to choose correct dependencies revisions # ===--- name: In-tree build run-name: '${{ github.event_name }}: ${{ github.base_ref }} ${{ github.ref_name }}' # github.base_ref null for 'on: push' permissions: contents: read on: push: branches: - ocl-open-200 pull_request: branches: - ocl-open-200 types: - opened - reopened - synchronize # commit pushed to the PR - ready_for_review # moved from draft state jobs: verify_default_branch: name: Linux # ref_name for 'on: push' # base_ref for 'on: pull_request' runs-on: ubuntu-22.04 steps: - name: Checkout opencl-clang sources for action files uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - name: Run build-opencl-clang action uses: ./.github/actions/build-opencl-clang with: ref_llvm: main ref_translator: main ref_opencl-clang: ${{ github.ref }} opencl-clang-20.1.0/.github/workflows/on-push-verification-out-of-tree.yml000066400000000000000000000060621501152646200264770ustar00rootroot00000000000000# ===--- # Running on push & pull_request. # ===--- name: Out-of-tree build run-name: '${{ github.event_name }}: ${{ github.base_ref }} ${{ github.ref_name }}' # github.base_ref null for 'on: push' permissions: contents: read env: LLVM_VERSION: 20 LLVM_VERSION_MINOR: 1 on: push: branches: - ocl-open-200 pull_request: branches: - ocl-open-200 types: - opened - reopened - synchronize # commit pushed to the PR - ready_for_review # moved from draft state jobs: verify_default_branch: name: linux # ref_name for 'on: push' # base_ref for 'on: pull_request' runs-on: ubuntu-22.04 steps: - name: Install llvm and its dependencies run: | curl -L "https://apt.llvm.org/llvm-snapshot.gpg.key" | sudo apt-key add - curl -L "https://packages.lunarg.com/lunarg-signing-key-pub.asc" | sudo apt-key add - echo "deb https://apt.llvm.org/jammy/ llvm-toolchain-jammy-20 main" | sudo tee -a /etc/apt/sources.list echo "deb https://packages.lunarg.com/vulkan jammy main" | sudo tee -a /etc/apt/sources.list sudo apt-get update sudo apt-get -yq --no-install-suggests --no-install-recommends install \ clang-${{ env.LLVM_VERSION }} \ clang-tools-${{ env.LLVM_VERSION }} \ llvm-${{ env.LLVM_VERSION }}-dev \ libllvmlibc-${{ env.LLVM_VERSION }}-dev \ libclang-${{ env.LLVM_VERSION }}-dev \ libclang-cpp${{ env.LLVM_VERSION }}-dev \ libpolly-${{ env.LLVM_VERSION }}-dev \ libzstd-dev \ libedit-dev \ mlir-${{ env.LLVM_VERSION }}-tools - name: Checkout SPIRV-LLVM-Translator sources uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: repository: KhronosGroup/SPIRV-LLVM-Translator path: SPIRV-LLVM-Translator ref: llvm_release_200 - name: Build SPIRV-LLVM-Translator run: | builddir=${{ github.workspace }}/SPIRV-LLVM-Translator/build cmake -B "$builddir" \ ${{ github.workspace }}/SPIRV-LLVM-Translator \ -DLLVM_INCLUDE_TESTS=OFF \ -DCMAKE_INSTALL_PREFIX="$builddir"/install \ -DCMAKE_BUILD_TYPE=Release cmake --build "$builddir" -j $(nproc) cmake --install "$builddir" echo "spirv-translator-dir=${builddir}/install" >> $GITHUB_ENV - name: Checkout opencl-clang sources uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: path: opencl-clang ref: ${{ github.ref }} - name: Build opencl-clang run: | mkdir build && cd build cmake ${{ github.workspace }}/opencl-clang \ -DPREFERRED_LLVM_VERSION="${{ env.LLVM_VERSION }}.${{ env.LLVM_VERSION_MINOR }}" \ -DLLVMSPIRV_INCLUDED_IN_LLVM=OFF \ -DSPIRV_TRANSLATOR_DIR=${{ env.spirv-translator-dir }} \ -DCMAKE_BUILD_TYPE=Release cmake --build . -j $(nproc) opencl-clang-20.1.0/.github/workflows/patch-release.yml000066400000000000000000000115151501152646200227760ustar00rootroot00000000000000name: Generate patch releases permissions: contents: read on: workflow_dispatch: schedule: # First day of every month - cron: '0 0 1 * *' jobs: setup: runs-on: ubuntu-latest outputs: latest_branch: ${{steps.latest_branch.outputs.latest_branch}} branches_json: ${{steps.release_branches.outputs.branches_json}} steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Get latest llvm_release branch id: latest_branch run: | git branch -r \ | grep 'ocl-open-' \ | sed -E 's/.*\/ocl-open-([0-9]+)/\1/' \ | sort -n -r \ | head -1 \ | xargs printf "latest_branch=ocl-open-%s" \ >> $GITHUB_OUTPUT - name: Get branch list id: release_branches run: | git branch -r \ | grep "origin/ocl-open-" \ | sed -E 's/\ *origin\/([^\ ]*)/\"\1\"/' \ | paste -sd',' \ | xargs -0 -d"\n" printf 'branches_json={"branch":[%s]}' \ >> $GITHUB_OUTPUT release: permissions: # required by softprops/action-gh-release to create a release contents: write runs-on: ubuntu-latest needs: setup strategy: matrix: ${{fromJson(needs.setup.outputs.branches_json)}} steps: - name: Checkout uses: actions/checkout@v4 with: ref: ${{ matrix.branch }} fetch-depth: 0 - name: Get commits info id: versions run: | export LATEST_VERSION=\ "$(git describe --tags --abbrev=0 --match 'v*')" export LLVM_VERSION=$(echo $LATEST_VERSION \ | sed -E 's/v([0-9]+\.[0-9]+)\.([0-9]+).*/\1/') export PATCH=$(echo $LATEST_VERSION \ | sed -E 's/(v[0-9]+\.[0-9]+)\.([0-9]+).*/\2/') echo "llvm_version=$LLVM_VERSION" >> $GITHUB_OUTPUT echo "patch=$PATCH" >> $GITHUB_OUTPUT echo "latest_version=${LATEST_VERSION}" >> $GITHUB_OUTPUT echo "release_version=${LLVM_VERSION}.$((${PATCH}+1))" \ >> $GITHUB_OUTPUT git rev-list ${LATEST_VERSION}..HEAD --count \ | xargs printf "commits_since_last_release=%d\n" >> $GITHUB_OUTPUT git rev-parse HEAD | xargs printf "last_commit=%s\n" >> $GITHUB_OUTPUT - name: Get SPIRV-LLVM-Translator and llvm-project latest tags id: llvm-spirv-versions run: | export SPIRV_PATCH=\ $(git ls-remote --tags \ "https://github.com/KhronosGroup/SPIRV-LLVM-Translator" \ "refs/tags/v${{ steps.versions.outputs.llvm_version }}.[0-9]" \ "refs/tags/v${{ steps.versions.outputs.llvm_version }}.[0-9][0-9]" \ | awk '{print $2}' \ | sed -E 's/refs\/tags\/v${{ steps.versions.outputs.llvm_version }}.([0-9]+)/\1/' \ | sort -n \ | tail -1) echo "spirv_patch=${SPIRV_PATCH}" >> $GITHUB_OUTPUT export LLVM_PATCH=\ $(git ls-remote --tags \ "https://github.com/llvm/llvm-project" \ "refs/tags/llvmorg-${{ steps.versions.outputs.llvm_version }}.[0-9]" \ "refs/tags/llvmorg-${{ steps.versions.outputs.llvm_version }}.[0-9][0-9]" \ | awk '{print $2}' \ | sed -E 's/refs\/tags\/llvmorg-${{ steps.versions.outputs.llvm_version }}.([0-9]+)/\1/' \ | sort -n \ | tail -1) echo "llvm_patch=${LLVM_PATCH}" >> $GITHUB_OUTPUT - name: Release uses: softprops/action-gh-release@v2 if: ${{ steps.versions.outputs.commits_since_last_release != 0 }} with: # Setting tag to have format: # %latest llvm version%.%latest patch + 1% tag_name: v${{ steps.versions.outputs.release_version }} # We have to set this so tag is set on the branch we are releasing target_commitish: ${{ steps.versions.outputs.last_commit }} # We don't want to mark patch releases latest unless it is latest # major version make_latest: >- ${{ needs.setup.outputs.latest_branch == matrix.branch }} name: > opencl-clang linked against LLVM v${{ steps.versions.outputs.llvm_version }} libraries # TODO: update body: "This release is linked against LLVM \ v${{ steps.versions.outputs.llvm_version }}.${{ steps.llvm-spirv-versions.outputs.llvm_patch }} \ and SPIR-V LLVM translator \ v${{ steps.versions.outputs.llvm_version }}.${{ steps.llvm-spirv-versions.outputs.spirv_patch }}. \ Full Changelog: ${{ github.server_url }}/\ ${{ github.repository }}/compare/\ ${{ steps.versions.outputs.latest_version }}...\ v${{ steps.versions.outputs.release_version }}" opencl-clang-20.1.0/.github/workflows/scheduled-verification.yml000066400000000000000000000025601501152646200247010ustar00rootroot00000000000000# ===--- # Workflow run for regular SPIRV-LLVM-Translator and LLVM compatibility check # ===--- name: Scheduled verification run-name: Scheduled verification permissions: contents: read on: schedule: # Run Sunday & Wednesday at 00:00 - cron: 0 0 * * 0,3 jobs: verify-default-branches: name: Verify `main` branch runs-on: ubuntu-22.04 steps: - name: Checkout opencl-clang sources for action files availabilty uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - name: Run build-opencl-clang action uses: ./.github/actions/build-opencl-clang with: ref_llvm: main ref_translator: main ref_opencl-clang: main verify-release-branches: name: Verify `ocl-open-${{ matrix.llvm_version }}` release branch strategy: matrix: llvm_version: [ 14, 15, 16, 17, 18, 19 ] runs-on: ubuntu-22.04 steps: - name: Checkout opencl-clang sources for action files availabilty uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - name: Run build-opencl-clang action uses: ./.github/actions/build-opencl-clang with: ref_llvm: release/${{ matrix.llvm_version }}.x ref_translator: llvm_release_${{ matrix.llvm_version }}0 ref_opencl-clang: ocl-open-${{ matrix.llvm_version }}0 opencl-clang-20.1.0/.travis.yml000066400000000000000000000024021501152646200162450ustar00rootroot00000000000000language: 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-20.1.0/CMakeLists.txt000066400000000000000000000272661501152646200167130ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.13.4) if(NOT DEFINED BASE_LLVM_VERSION) set(BASE_LLVM_VERSION 20.1) 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 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(CMAKE_CROSSCOMPILING 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 "20.1") 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 17) 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) elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) set(ADDR 64) else () # CMAKE_SIZEOF_VOID_P might not be set on windows x86 in in-tree build message(WARNING "[OPENCL-CLANG] CMAKE_SIZEOF_VOID_P is not set") if (WIN32 AND LLVM_BUILD_32_BITS) set(ADDR 32) endif() 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} ) # OPENCL_CLANG_PCH_EXTENSION can override PCH extension map in options_compile.cpp. # Example: "cl_khr_3d_image_writes,cl_khr_depth_images" set(OPENCL_CLANG_PCH_EXTENSION "" CACHE STRING "Comma-separated list of OpenCL extensions") if (NOT "${OPENCL_CLANG_PCH_EXTENSION}" STREQUAL "") add_definitions(-DPCH_EXTENSION="${OPENCL_CLANG_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/20.x) set(SPIRV_BASE_REVISION llvm_release_200) set(TARGET_BRANCH "ocl-open-200") 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 clangBasic clangFrontend clangFrontendTool clangSerialization ) endif() if(USE_PREBUILT_LLVM AND UNIX) # llvm_map_components_to_libnames(... all) returns empty string if llvm is # pre-built locally in either static or shared type in Ubuntu 22.04 container. find_program(LLVM_CONFIG_EXE NAMES llvm-config-${PREFERRED_LLVM_VERSION} llvm-config PATHS ${LLVM_BINARY_DIR} ${LLVM_BINARY_DIR}/bin) if(NOT LLVM_CONFIG_EXE) message(FATAL_ERROR "[OPENCL-CLANG] llvm-config is not found") endif() execute_process(COMMAND ${LLVM_CONFIG_EXE} --libs all OUTPUT_VARIABLE ALL_LIBS) string(REGEX REPLACE "( |\r|\n|-l)+" ";" ALL_LLVM_LIBS ${ALL_LIBS}) set(ALL_LLVM_LIBS "LLVMSPIRVLib${ALL_LLVM_LIBS}") else() llvm_map_components_to_libnames(ALL_LLVM_LIBS all) endif() set(OPENCL_CLANG_EXCLUDE_LIBS_FROM_ALL "" CACHE STRING "Space-separated list of LLVM libraries to exclude from all") if (NOT "${OPENCL_CLANG_EXCLUDE_LIBS_FROM_ALL}" STREQUAL "") list(REMOVE_ITEM ALL_LLVM_LIBS ${OPENCL_CLANG_EXCLUDE_LIBS_FROM_ALL}) endif() list(APPEND OPENCL_CLANG_LINK_LIBS ${ALL_LLVM_LIBS}) add_llvm_library(${TARGET_NAME} SHARED ${TARGET_INCLUDE_FILES} ${TARGET_SOURCE_FILES} $ DEPENDS CClangCompileOptions LINK_LIBS ${OPENCL_CLANG_LINK_LIBS} ) 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 PROPERTY LINK_OPTIONS "LINKER:/DYNAMICBASE" "LINKER:/GUARD:CF") elseif(UNIX) set_property(TARGET ${TARGET_NAME} APPEND_STRING PROPERTY COMPILE_DEFINITIONS LIBOPENCL_CLANG_NAME="$") # Sanitizers do not support this flag, disable this when under sanitizer build if(NOT LLVM_USE_SANITIZER) set_property(TARGET ${TARGET_NAME} APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--no-undefined") endif() endif(WIN32) 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_property(TARGET ${TARGET_NAME} APPEND PROPERTY LINK_OPTIONS "LINKER:/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_property(TARGET ${TARGET_NAME} APPEND PROPERTY LINK_OPTIONS $<$:LINKER:/DEBUG> "$<$:LINKER:/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-20.1.0/LICENSE000066400000000000000000000354451501152646200151560ustar00rootroot00000000000000============================================================================== The LLVM Project is under the Apache License v2.0 with LLVM Exceptions: ============================================================================== Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ---- LLVM Exceptions to the Apache 2.0 License ---- As an exception, if, as a result of your compiling your source code, portions of this Software are embedded into an Object form of such source code, you may redistribute such embedded portions in such Object form without complying with the conditions of Sections 4(a), 4(b) and 4(d) of the License. In addition, if you combine or link compiled forms of this Software with software that is licensed under the GPLv2 ("Combined Software") and if a court of competent jurisdiction determines that the patent provision (Section 3), the indemnity provision (Section 9) or other Section of the License conflicts with the conditions of the GPLv2, you may retroactively and prospectively choose to deem waived or otherwise exclude such Section(s) of the License, but only in their entirety and only with respect to the Combined Software. ============================================================================== Software from third parties included in the LLVM Project: ============================================================================== The LLVM Project contains third party software which is under different license terms. All such code will be identified clearly using at least one of two mechanisms: 1) It will be in a separate directory tree with its own `LICENSE.txt` or `LICENSE` file at the top containing the specific license and restrictions which apply to that software, or 2) It will contain specific license and restriction terms at the top of every file. ============================================================================== Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy): ============================================================================== University of Illinois/NCSA Open Source License Copyright (c) 2003-2019 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. opencl-clang-20.1.0/README.md000066400000000000000000000111731501152646200154200ustar00rootroot00000000000000[![Scheduled verification](https://github.com/intel/opencl-clang/actions/workflows/scheduled-verification.yml/badge.svg)](https://github.com/intel/opencl-clang/actions/workflows/scheduled-verification.yml) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/9059/badge)](https://www.bestpractices.dev/projects/9059) 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/20.x git clone https://github.com/KhronosGroup/SPIRV-LLVM-Translator.git -b llvm_release_200 git clone https://github.com/intel/opencl-clang.git -b ocl-open-200 ``` 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-200 mkdir build && cd build cmake ../opencl-clang make all -j`nproc` ``` #### Configuration options ##### Preferred LLVM version By default, opencl-clang's cmake script is searching for LLVM 20.1. You can override target version of LLVM by using the `PREFERRED_LLVM_VERSION` cmake option: Example: ```bash cmake -DPREFERRED_LLVM_VERSION="20.1" ../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 ``` ## Contribution Please submit a pull request to contribute. Please follow [LLVM coding standards](https://llvm.org/docs/CodingStandards.html) ## Report a problem Please submit an [issue](https://github.com/intel/opencl-clang/issues) opencl-clang-20.1.0/SECURITY.md000066400000000000000000000006251501152646200157320ustar00rootroot00000000000000# Security Policy Intel is committed to rapidly addressing security vulnerabilities affecting our customers and providing clear guidance on the solution, impact, severity and mitigation. ## Reporting a Vulnerability Please report any security vulnerabilities in this project utilizing the guidelines [here](https://www.intel.com/content/www/us/en/security-center/vulnerability-handling-guidelines.html). opencl-clang-20.1.0/binary_result.h000066400000000000000000000044551501152646200172010ustar00rootroot00000000000000/*****************************************************************************\ 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-20.1.0/cl_headers/000077500000000000000000000000001501152646200162275ustar00rootroot00000000000000opencl-clang-20.1.0/cl_headers/CMakeLists.txt000066400000000000000000000166071501152646200210010ustar00rootroot00000000000000set(CL_HEADERS_LIB cl_headers) if(USE_PREBUILT_LLVM) find_program(CLANG_COMMAND clang PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH) else() set(CLANG_COMMAND $) endif() if(CMAKE_CROSSCOMPILING 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) if(EXISTS "${LLVM_LIBRARY_DIRS}/clang/${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}/") set(OPENCL_HEADERS_DIR "${LLVM_LIBRARY_DIRS}/clang/${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}/include/") elseif(EXISTS "${LLVM_LIBRARY_DIRS}/clang/${LLVM_VERSION_MAJOR}/") set(OPENCL_HEADERS_DIR "${LLVM_LIBRARY_DIRS}/clang/${LLVM_VERSION_MAJOR}/include/") else() message(FATAL_ERROR "[OPENCL-CLANG] Couldn't find prebuilt LLVM include directory.") endif() 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-20.1.0/cl_headers/OpenCL.rc000066400000000000000000000021331501152646200176740ustar00rootroot00000000000000// 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-20.1.0/cl_headers/module.modulemap000066400000000000000000000017441501152646200214270ustar00rootroot00000000000000module 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-20.1.0/cl_headers/resource.h000066400000000000000000000036061501152646200202340ustar00rootroot00000000000000/*****************************************************************************\ 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-20.1.0/cmake/000077500000000000000000000000001501152646200152165ustar00rootroot00000000000000opencl-clang-20.1.0/cmake/modules/000077500000000000000000000000001501152646200166665ustar00rootroot00000000000000opencl-clang-20.1.0/cmake/modules/CMakeFunctions.cmake000066400000000000000000000155101501152646200225430ustar00rootroot00000000000000# # 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() 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 ) 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 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 OUTPUT_QUIET ) if(patches_needed EQUAL 128) message(STATUS "[OPENCL-CLANG][Warning] ${repo_dir} is not a git repository, therefore, local patches are not applied") return() endif() if(patches_needed EQUAL 1) # 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 ) 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 ) message(STATUS "[OPENCL-CLANG] Not present - ${patching_log}") endif() endforeach(patch) elsef(patches_needed EQUAL 0) # The target branch already exists execute_process( # Check it out COMMAND ${GIT_EXECUTABLE} checkout ${target_branch} WORKING_DIRECTORY ${repo_dir} OUTPUT_QUIET ) endif() if (ret_check_out OR ret_apply_patch) message(FATAL_ERROR "[OPENCL-CLANG] Failed to apply patch!") 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-20.1.0/linux_linker/000077500000000000000000000000001501152646200166415ustar00rootroot00000000000000opencl-clang-20.1.0/linux_linker/CMakeLists.txt000066400000000000000000000007351501152646200214060ustar00rootroot00000000000000add_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-20.1.0/linux_linker/linux_resource_linker.cpp000066400000000000000000000041641501152646200237640ustar00rootroot00000000000000/*****************************************************************************\ 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-20.1.0/opencl_clang.cpp000066400000000000000000000303761501152646200172770ustar00rootroot00000000000000/*****************************************************************************\ 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/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/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" #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; llvm::ManagedStatic> compileMutex; void OpenCLClangTerminate() { 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 OpenCLClangInitialize() { // OpenCLClangTerminate 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. llvm::once_flag OnceFlag; llvm::call_once(OnceFlag, []() { atexit(OpenCLClangTerminate); }); } 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 OpenCLClangInitialize(); try { #ifdef _WIN32 llvm::sys::SmartScopedLock compileGuard{*compileMutex}; #endif 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()); { #ifndef _WIN32 llvm::sys::SmartScopedLock compileGuard{*compileMutex}; #endif // 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(), compiler->getFileManager().getVirtualFileSystem()); // 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(); } { #ifndef _WIN32 llvm::sys::SmartScopedLock compileGuard{*compileMutex}; #endif 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-20.1.0/opencl_clang.h000066400000000000000000000107521501152646200167400ustar00rootroot00000000000000/*****************************************************************************\ 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-20.1.0/opencl_clang.map000066400000000000000000000011341501152646200172600ustar00rootroot00000000000000{ 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-20.1.0/opencl_clang_options.td000066400000000000000000000047611501152646200206760ustar00rootroot00000000000000//===----------------------------------------------------------------------===// // // 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 coverage: Flag<["-"], "coverage">, HelpText<"Enable source level coverage analysis">; 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_std_CLCxx: Flag<["-"], "cl-std=CLC++">; def cl_std_CLCxx1_0: Flag<["-"], "cl-std=CLC++1.0">; def cl_std_CLCxx2021: Flag<["-"], "cl-std=CLC++2021">; 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-20.1.0/options.cpp000066400000000000000000000071671501152646200163500ustar00rootroot00000000000000/*****************************************************************************\ 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-20.1.0/options.h000066400000000000000000000176631501152646200160170ustar00rootroot00000000000000/*****************************************************************************\ 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, \ VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, \ VALUES) \ OPT_COMPILE_##ID, #include "opencl_clang_options.inc" OPT_COMPILE_LAST_OPTION #undef OPTION #undef PREFIX }; #define OPTTABLE_STR_TABLE_CODE #include "opencl_clang_options.inc" #undef OPTTABLE_STR_TABLE_CODE #define OPTTABLE_PREFIXES_TABLE_CODE #include "opencl_clang_options.inc" #undef OPTTABLE_PREFIXES_TABLE_CODE 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(OptionStrTable, OptionPrefixesTable, 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-20.1.0/options_compile.cpp000066400000000000000000000445731501152646200200620ustar00rootroot00000000000000/*****************************************************************************\ 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/SmallSet.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 using namespace llvm::opt; extern llvm::ManagedStatic> compileMutex; static constexpr OptTable::Info ClangOptionsInfoTable[] = { #define PREFIX(NAME, VALUE) #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \ VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, \ VALUES) \ {PREFIX, \ NAME, \ HELPTEXT, \ HELPTEXTSFORVARIANTS, \ METAVAR, \ OPT_COMPILE_##ID, \ llvm::opt::Option::KIND##Class, \ PARAM, \ FLAGS, \ VISIBILITY, \ 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 isCpp = false; 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_uniform_work_group_size: 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_cl_std_CLCxx: case OPT_COMPILE_cl_std_CLCxx1_0: iCLStdSet = 200; isCpp = true; effectiveArgs.push_back((*it)->getAsString(args)); break; case OPT_COMPILE_cl_std_CLCxx2021: iCLStdSet = 300; isCpp = true; effectiveArgs.push_back((*it)->getAsString(args)); break; case OPT_COMPILE_triple: szTriple = (*it)->getValue(); break; 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_coverage: 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. if (!isCpp) { 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); bool hasPrefix = clExtRef.consume_front("-cl-ext="); assert(hasPrefix && "clExtRef doesn't start with \"-cl-ext\" prefix"); (void)hasPrefix; 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; } }; llvm::SmallSet parsedOclCFeatures; std::for_each(effectiveArgs.begin(), effectiveArgs.end(), [&](const ArgsVector::value_type &a) { if (a.find("-cl-ext=") == 0) parseClExt(a); else if (a.find("-D__opencl_c_") == 0) parsedOclCFeatures.insert(a); }); // "opencl-c-base.h" unconditionally enables a list of so-called "optional // core" language features. We need to undef those that aren't explicitly // defined within the compilation command (which would suggest that the // target platform supports the corresponding feature). const char* optionalCoreOclCFeaturesList[] = { "__opencl_c_work_group_collective_functions", "__opencl_c_atomic_order_seq_cst", "__opencl_c_atomic_scope_device", "__opencl_c_atomic_scope_all_devices", "__opencl_c_read_write_images" }; for (std::string OclCFeature : optionalCoreOclCFeaturesList) { if (!parsedOclCFeatures.contains(std::string("-D") + OclCFeature)) effectiveArgs.push_back(std::string("-D__undef_") + OclCFeature); } // 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{*compileMutex}; 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-20.1.0/pch_mgr.cpp000066400000000000000000000161561501152646200162720ustar00rootroot00000000000000/*****************************************************************************\ 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 #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-20.1.0/pch_mgr.h000066400000000000000000000056351501152646200157370ustar00rootroot00000000000000/*****************************************************************************\ 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; };