pax_global_header00006660000000000000000000000064146431451630014521gustar00rootroot0000000000000052 comment=470cf0018e1ef6fc92eda1356f5f31f7da452abc opencl-clang-14.0.1/000077500000000000000000000000001464314516300141465ustar00rootroot00000000000000opencl-clang-14.0.1/.github/000077500000000000000000000000001464314516300155065ustar00rootroot00000000000000opencl-clang-14.0.1/.github/actions/000077500000000000000000000000001464314516300171465ustar00rootroot00000000000000opencl-clang-14.0.1/.github/actions/build-opencl-clang/000077500000000000000000000000001464314516300226055ustar00rootroot00000000000000opencl-clang-14.0.1/.github/actions/build-opencl-clang/action.yml000066400000000000000000000037101464314516300246060ustar00rootroot00000000000000# ===--- # 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-14.0.1/.github/workflows/000077500000000000000000000000001464314516300175435ustar00rootroot00000000000000opencl-clang-14.0.1/.github/workflows/on-push-verification.yml000066400000000000000000000032461464314516300243440ustar00rootroot00000000000000# ===--- # 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' on: push: branches: - master - ocl-open-* pull_request: branches: - master - ocl-open-* types: - opened - reopened - synchronize # commit pushed to the PR - ready_for_review # moved from draft state jobs: verify_release_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@v3 # This step will fail when the branch naming scheme 'ocl-open-XXX' changes! - name: Parse LLVM version from branch name id: check-llvm-version run: | BRANCH="${{ github.base_ref }}" # on: pull_request, otherwise null BRANCH=${BRANCH:-${{ github.ref_name }}} # on: push LLVM_VERSION_LONG=$(echo $BRANCH | grep -oP '\d+') # Eg. 150 for LLVM 15 LLVM_VERSION_SHORT=${LLVM_VERSION_LONG::-1} # Eg. 15 for LLVM 15 echo "llvm_version=$LLVM_VERSION_SHORT" >> $GITHUB_OUTPUT - name: Run build-opencl-clang action uses: ./.github/actions/build-opencl-clang with: ref_llvm: release/${{ steps.check-llvm-version.outputs.llvm_version }}.x ref_translator: llvm_release_${{ steps.check-llvm-version.outputs.llvm_version }}0 ref_opencl-clang: ${{ github.ref }} opencl-clang-14.0.1/.travis.yml000066400000000000000000000025571464314516300162700ustar00rootroot00000000000000language: cpp os: - linux # Use Ubuntu 18.04 LTS (Bionic) as the Linux testing environment. dist: bionic git: depth: 1 branches: only: - ocl-open-130 env: global: - LLVM_VERSION=13 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: - git clone https://github.com/KhronosGroup/SPIRV-LLVM-Translator.git spirv-llvm-translator -b llvm_release_${LLVM_VERSION}0 - mkdir spirv-llvm-translator/build && cd spirv-llvm-translator/build - cmake .. -DCMAKE_INSTALL_PREFIX=./install -DBUILD_SHARED_LIBS=ON -DLLVM_BUILD_TOOLS=ON -DCMAKE_BUILD_TYPE=${BUILD_TYPE} - make -j`nproc` && make install - cd ../../ 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=${TRAVIS_BUILD_DIR}/spirv-llvm-translator/build/install -DCMAKE_INSTALL_PREFIX=./install .. - make install opencl-clang-14.0.1/CMakeLists.txt000066400000000000000000000271561464314516300167210ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.4.3) if(NOT DEFINED BASE_LLVM_VERSION) set(BASE_LLVM_VERSION 14.0.0) endif(NOT DEFINED BASE_LLVM_VERSION) set(OPENCL_CLANG_VERSION ${BASE_LLVM_VERSION}.0) if(NOT DEFINED OPENCL_CLANG_BUILD_EXTERNAL) # check if we build inside llvm or not if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) set(OPENCL_CLANG_BUILD_EXTERNAL YES) endif(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) endif(NOT DEFINED OPENCL_CLANG_BUILD_EXTERNAL) if(OPENCL_CLANG_BUILD_EXTERNAL) project(OPENCL_CLANG VERSION ${OPENCL_CLANG_VERSION} LANGUAGES CXX C ) endif() # Do not omit TARGET_OBJECTS expression from the SOURCES target # property # `cmake --help-policy CMP0051` for details. cmake_policy(SET CMP0051 NEW) cmake_policy(SET CMP0057 NEW) cmake_policy(SET CMP0022 NEW) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") include(CMakeFunctions) if(LLVM_USE_HOST_TOOLS AND OPENCL_CLANG_BUILD_EXTERNAL) include(CrossCompile) llvm_create_cross_target(${PROJECT_NAME} NATIVE "" Release) endif() option(LLVMSPIRV_INCLUDED_IN_LLVM "Set to ON if libLLVMSPIRVLib is linked into libLLVM" ON) option(APPLY_PATCHES "Apply local patches" ON) 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 "14.0.0") endif(NOT PREFERRED_LLVM_VERSION) message(STATUS "[OPENCL-CLANG] Looking for LLVM version ${PREFERRED_LLVM_VERSION}") find_package(LLVM ${PREFERRED_LLVM_VERSION} REQUIRED) message(STATUS "[OPENCL-CLANG] Using LLVMConfig.cmake in: ${LLVM_DIR}") message(STATUS "[OPENCL-CLANG] Found LLVM ${LLVM_PACKAGE_VERSION}") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${LLVM_CMAKE_DIR}) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) 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() if (CMAKE_SIZEOF_VOID_P EQUAL 4) set(ADDR 32) else () set(ADDR 64) endif (CMAKE_SIZEOF_VOID_P EQUAL 4) # set windows binary suffix if (WIN32) set (BUILD_PLATFORM ${ADDR}) else (WIN32) set (BUILD_PLATFORM "") endif (WIN32) # set that name of the main output file as a target name if (NOT DEFINED COMMON_CLANG_LIBRARY_NAME) set(COMMON_CLANG_LIBRARY_NAME "opencl-clang") endif() set(TARGET_NAME ${COMMON_CLANG_LIBRARY_NAME}${BUILD_PLATFORM} ) if(NOT USE_PREBUILT_LLVM) if(NOT LLVM_EXTERNAL_CLANG_SOURCE_DIR) set(LLVM_BASE_REVISION release_14) set(CLANG_SOURCE_DIR ${LLVM_SOURCE_DIR}/tools/clang) set(CLANG_BASE_REVISION release_14) elseif(EXISTS "${LLVM_EXTERNAL_CLANG_SOURCE_DIR}/CMakeLists.txt") set(LLVM_BASE_REVISION release/14.x) set(CLANG_SOURCE_DIR "${LLVM_EXTERNAL_CLANG_SOURCE_DIR}") set(CLANG_BASE_REVISION release/14.x) 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(SPIRV_BASE_REVISION llvm_release_140) set(TARGET_BRANCH "ocl-open-140") get_filename_component(LLVM_MONOREPO_DIR ${LLVM_SOURCE_DIR} DIRECTORY) set(LLVM_PATCHES_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/patches/llvm ${CMAKE_CURRENT_SOURCE_DIR}/patches/clang) if(APPLY_PATCHES) message(STATUS "APPLY_PATCHES is enabled.") apply_patches(${LLVM_MONOREPO_DIR} "${LLVM_PATCHES_DIRS}" ${LLVM_BASE_REVISION} ${TARGET_BRANCH}) apply_patches(${SPIRV_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/patches/spirv ${SPIRV_BASE_REVISION} ${TARGET_BRANCH}) else() message(STATUS "APPLY_PATCHES is disabled, skip patch apply process.") endif() 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 common_clang.h options.h binary_result.h pch_mgr.h ${COMPILE_OPTIONS_TD} ${COMPILE_OPTIONS_INC} ) set(TARGET_SOURCE_FILES common_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( -DCOMMON_CLANG_EXPORTS ) # # Include directories # if(NOT USE_PREBUILT_LLVM) set(CLANG_BINARY_DIR ${LLVM_BINARY_DIR}/tools/clang/) include_directories( ${CLANG_BINARY_DIR}/include # for tablegened includes ${CLANG_SOURCE_DIR}/include # for basic headers ${SPIRV_SOURCE_DIR}/include) # for SPIRV headers endif(NOT USE_PREBUILT_LLVM) if(USE_PREBUILT_LLVM AND NOT LLVMSPIRV_INCLUDED_IN_LLVM) include_directories(${SPIRV_TRANSLATOR_DIR}/include) link_directories(${SPIRV_TRANSLATOR_DIR}/lib${LLVM_LIBDIR_SUFFIX}) endif(USE_PREBUILT_LLVM AND NOT LLVMSPIRV_INCLUDED_IN_LLVM) include_directories( AFTER ${LLVM_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} ) link_directories( ${LLVM_LIBRARY_DIRS} ) set(OPENCL_CLANG_LINK_LIBS ${CMAKE_DL_LIBS}) if(NOT LLVMSPIRVLib IN_LIST LLVM_AVAILABLE_LIBS OR (USE_PREBUILT_LLVM AND LLVM_LINK_LLVM_DYLIB)) # SPIRV-LLVM-Translator is not included into LLVM as a component. # So, we need to list it here explicitly as an external library list(APPEND OPENCL_CLANG_LINK_LIBS LLVMSPIRVLib) endif() add_subdirectory(cl_headers) set(LLVM_REQUIRES_EH ON) if(USE_PREBUILT_LLVM OR CLANG_LINK_CLANG_DYLIB) list(APPEND OPENCL_CLANG_LINK_LIBS clang-cpp) else() list(APPEND OPENCL_CLANG_LINK_LIBS # The list of clang libraries is taken from clang makefile # (build/tools/clang/tools/driver/CMakeFiles/clang.dir/link.txt) # All duplicate libraries are there on purpose clangBasic clangCodeGen clangDriver clangFrontend clangFrontendTool clangCodeGen clangRewriteFrontend clangARCMigrate clangStaticAnalyzerFrontend clangStaticAnalyzerCheckers clangStaticAnalyzerCore clangCrossTU clangIndex clangFrontend clangDriver clangParse clangSerialization clangSema clangAnalysis clangEdit clangFormat clangToolingInclusions clangToolingCore clangRewrite clangASTMatchers clangAST clangLex clangBasic ) endif() add_llvm_library(${TARGET_NAME} SHARED ${TARGET_INCLUDE_FILES} ${TARGET_SOURCE_FILES} $ DEPENDS CClangCompileOptions LINK_COMPONENTS all LINK_LIBS ${OPENCL_CLANG_LINK_LIBS} ) # Configure resource file on Windows if (WIN32) # windows_resource_file should be defined by llvm_add_library and should # contain full patch to a .rc file # It also might not be defined if this library is built out-of-tree: # let's use our copy of .rc file from LLVM source tree in that case if (NOT DEFINED windows_resource_file) set(windows_resource_file windows_resource_file.rc) endif(NOT DEFINED windows_resource_file) set(RC_CHAR_TM "\\231") set(RC_CHAR_C "\\251") set(RC_CHAR_R "\\256") set(RC_FILE_VERSION "${PRODUCT_VER_MAJOR}.${PRODUCT_VER_MINOR}.${LLVM_VER_MAJOR}.${LLVM_VER_MINOR}") set(RC_PRODUCT_NAME "Intel${RC_CHAR_R} Front-end Library for OpenCL${RC_CHAR_TM} software") # Adjust content of the resource file by specifying compile definitions set_property(SOURCE ${windows_resource_file} PROPERTY COMPILE_DEFINITIONS "RC_VERSION_FIELD_1=${PRODUCT_VER_MAJOR}" "RC_VERSION_FIELD_2=${PRODUCT_VER_MINOR}" "RC_VERSION_FIELD_3=${LLVM_VER_MAJOR}" "RC_VERSION_FIELD_4=${LLVM_VER_MINOR}" "RC_COMPANY_NAME=\"Intel Corporation\"" "RC_FILE_DESCRIPTION=\"${RC_PRODUCT_NAME}\"" "RC_FILE_VERSION=\"${RC_FILE_VERSION}\"" "RC_INTERNAL_NAME=\"${TARGET_NAME}\"" "RC_ORIGINAL_FILENAME=\"${TARGET_NAME}.dll\"" "RC_PRODUCT_NAME=\"${RC_PRODUCT_NAME}\"" "RC_PRODUCT_VERSION=\"${RC_FILE_VERSION}\"" "RC_COPYRIGHT=\"Copyright ${RC_CHAR_C} 2018 Intel Corporation. All rights reserved.\"") # Enable compiler generation of Control Flow Guard security checks. target_compile_options(${TARGET_NAME} PUBLIC "/guard:cf") set_property(TARGET ${TARGET_NAME} APPEND_STRING PROPERTY LINK_FLAGS "/DYNAMICBASE /GUARD:CF") elseif(UNIX) set_property(TARGET ${TARGET_NAME} APPEND_STRING PROPERTY COMPILE_DEFINITIONS LIBCOMMON_CLANG_NAME="$") set_property(TARGET ${TARGET_NAME} APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--no-undefined") endif(WIN32) install(FILES common_clang.h DESTINATION include/cclang COMPONENT ${TARGET_NAME}) SET_LINUX_EXPORTS_FILE( ${TARGET_NAME} common_clang.map ) add_custom_target(deploy DEPENDS install-${TARGET_NAME}) opencl-clang-14.0.1/LICENSE000066400000000000000000000061711464314516300151600ustar00rootroot00000000000000============================================================================== LLVM Release License ============================================================================== University of Illinois/NCSA Open Source License Copyright (c) 2003-2018 University of Illinois at Urbana-Champaign. All rights reserved. Developed by: LLVM Team University of Illinois at Urbana-Champaign http://llvm.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. * Neither the names of the LLVM Team, University of Illinois at Urbana-Champaign, nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. ============================================================================== Copyrights and Licenses for Third Party Software Distributed with LLVM: ============================================================================== The LLVM software contains code written by third parties. Such software will have its own individual LICENSE.TXT file in the directory in which it appears. This file will describe the copyrights, license, and restrictions which apply to that code. The disclaimer of warranty in the University of Illinois Open Source License applies to all code in the LLVM Distribution, and nothing in any of the other licenses gives permission to use the names of the LLVM Team or the University of Illinois to endorse or promote products derived from this Software. The following pieces of software have additional or alternate copyrights, licenses, and/or restrictions: Program Directory ------- --------- Google Test llvm/utils/unittest/googletest OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex} pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT} ARM contributions llvm/lib/Target/ARM/LICENSE.TXT md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h opencl-clang-14.0.1/README.md000066400000000000000000000100551464314516300154260ustar00rootroot00000000000000opencl-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/14.x git clone https://github.com/KhronosGroup/SPIRV-LLVM-Translator.git -b llvm_release_140 git clone https://github.com/intel/opencl-clang.git -b ocl-open-140 ``` 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" \ $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-140 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 14.0.0. You can override target version of LLVM by using the `PREFERRED_LLVM_VERSION` cmake option: Example: ```bash cmake -DPREFERRED_LLVM_VERSION="10.0.0" ../opencl-clang ``` ##### Custom LLVM installation If LLVM is installed somewhere in custom (non-system directories) location, you could point to it using the `LLVM_DIR` cmake option. **Note**: You need to specify the path to a directory containing the `LLVMConfig.cmake` file. This file is available in two different locations. * `/lib/cmake/llvm/LLVMConfig.cmake` where `` is the install prefix of an installed version of LLVM. On Linux this is typically `/usr/lib/cmake/llvm/LLVMConfig.cmake`. * `/lib/cmake/llvm/LLVMConfig.cmake` where `` is the root of the LLVM build tree. **Note: this is only available when building LLVM with CMake.** Example: ```bash cmake -DLLVM_DIR=/path/to/installed/llvm/lib/cmake/llvm ../opencl-clang ``` ##### Location of SPIR-V Translator library By default, opencl-clang's cmake script assumes that SPIR-V Translator library is built as part of LLVM, installed in the same place and libLLVMSPIRVLib is linked into libLLVM. If that is not true for you, you can override this: firstly, you need to set `LLVMSPIRV_INCLUDED_IN_LLVM` cmake option to `OFF`. Then you need to specify directory where SPIR-V Translator is installed by using `SPIRV_TRANSLATOR_DIR` cmake option. Example: ```bash cmake -DLLVMSPIRV_INCLUDED_IN_LLVM=OFF -DSPIRV_TRANSLATOR_DIR=/path/to/installed/spirv/translator ../opencl-clang ``` There is a known issue (linker crash) for this kind of build on Ubuntu 16.04 Xenial. In this case the following cmake option should fix it: ``` -DLLVM_NO_DEAD_STRIP=ON ``` Installation directory of SPIR-V Translator is expected to contain the following files: ``` |-- include | `-- LLVMSPIRVLib | `-- LLVMSPIRVLib.h `-- lib64 `-- libLLVMSPIRVLib.so ``` opencl-clang-14.0.1/binary_result.h000066400000000000000000000044551464314516300172110ustar00rootroot00000000000000/*****************************************************************************\ 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 "common_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-14.0.1/cl_headers/000077500000000000000000000000001464314516300162375ustar00rootroot00000000000000opencl-clang-14.0.1/cl_headers/CMakeLists.txt000066400000000000000000000156521464314516300210100ustar00rootroot00000000000000set(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(LLVM_USE_HOST_TOOLS AND NOT OPENCL_CLANG_BUILD_EXTERNAL) build_native_tool(clang CLANG_COMMAND) endif() function(copy_file SRC DST) add_custom_command( OUTPUT ${DST} MAIN_DEPENDENCY ${SRC} COMMAND ${CMAKE_COMMAND} -E copy "${SRC}" "${DST}" COMMENT "Copying '${SRC}' to ${DST}" ) endfunction(copy_file) if(USE_PREBUILT_LLVM) set(OPENCL_HEADERS_DIR "${LLVM_LIBRARY_DIRS}/clang/${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}/include/") else(USE_PREBUILT_LLVM) set(OPENCL_HEADERS_DIR "${CLANG_SOURCE_DIR}/lib/Headers") endif(USE_PREBUILT_LLVM) copy_file(${OPENCL_HEADERS_DIR}/opencl-c.h opencl-c.h) copy_file(${OPENCL_HEADERS_DIR}/opencl-c-base.h opencl-c-base.h) copy_file(${CMAKE_CURRENT_SOURCE_DIR}/module.modulemap module.modulemap) add_custom_target ( opencl.headers.target DEPENDS module.modulemap opencl-c.h opencl-c-base.h ) function(create_pcm DST MODULE HEADER OPTS DEPS) add_custom_command ( OUTPUT ${DST} MAIN_DEPENDENCY ${MODMAP} DEPENDS ${HEADER} ${DEPS} ${CLANG_COMMAND} COMMAND ${CLANG_COMMAND} -cc1 -x cl -I. -O0 ${OPTS} -fmodules -fmodule-name=${MODULE} -fmodule-map-file-home-is-cwd -emit-module "module.modulemap" -fno-validate-pch -o ${DST} VERBATIM COMMENT "Generating ${DST}" ) endfunction(create_pcm) set(CL12 "-cl-std=CL1.2") set(CL20 "-cl-std=CL2.0") set(CL30 "-cl-std=CL3.0") # Add OpenCL C 3.0 Optional features set(OPTS30 "-cl-ext=+__opencl_c_3d_image_writes,+__opencl_c_atomic_order_acq_rel,+__opencl_c_atomic_order_seq_cst,+__opencl_c_atomic_scope_device,+__opencl_c_atomic_scope_all_devices,+__opencl_c_device_enqueue,+__opencl_c_generic_address_space,+__opencl_c_images,+__opencl_c_int64,+__opencl_c_pipes,+__opencl_c_program_scope_global_variables,+__opencl_c_read_write_images,+__opencl_c_subgroups,+__opencl_c_work_group_collective_functions") set(OPTS30_FP64 "-D__opencl_c_fp64=1") set(SPIR_TRIPLE "-triple;spir-unknown-unknown") set(SPIR64_TRIPLE "-triple;spir64-unknown-unknown") if (BUILD_X64) set(HOST_TRIPLE "${SPIR64_TRIPLE}") else() set(HOST_TRIPLE "${SPIR_TRIPLE}") endif() set(OPTS -cl-ext=+all,-cl_khr_fp64,-__opencl_c_fp64) create_pcm(opencl-c-12-spir.pcm cl12spir opencl-c-base.h "${SPIR_TRIPLE};${CL12};${OPTS}" "${DEPS}") create_pcm(opencl-c-20-spir.pcm cl20spir opencl-c-base.h "${SPIR_TRIPLE};${CL20};${OPTS}" "${DEPS}") create_pcm(opencl-c-30-spir.pcm cl30spir opencl-c-base.h "${SPIR_TRIPLE};${CL30};${OPTS};${OPTS30}" "${DEPS}") create_pcm(opencl-c-12-spir64.pcm cl12spir64 opencl-c-base.h "${SPIR64_TRIPLE};${CL12};${OPTS}" "${DEPS}") create_pcm(opencl-c-20-spir64.pcm cl20spir64 opencl-c-base.h "${SPIR64_TRIPLE};${CL20};${OPTS}" "${DEPS}") create_pcm(opencl-c-30-spir64.pcm cl30spir64 opencl-c-base.h "${SPIR64_TRIPLE};${CL30};${OPTS};${OPTS30}" "${DEPS}") set(OPTS -cl-ext=+all) create_pcm(opencl-c-12-spir-fp64.pcm cl12spirfp64 opencl-c-base.h "${SPIR_TRIPLE};${CL12};${OPTS}" "${DEPS}") create_pcm(opencl-c-20-spir-fp64.pcm cl20spirfp64 opencl-c-base.h "${SPIR_TRIPLE};${CL20};${OPTS}" "${DEPS}") create_pcm(opencl-c-30-spir-fp64.pcm cl30spirfp64 opencl-c-base.h "${SPIR_TRIPLE};${CL30};${OPTS};${OPTS30};${OPTS30_FP64}" "${DEPS}") create_pcm(opencl-c-12-spir64-fp64.pcm cl12spir64fp64 opencl-c-base.h "${SPIR64_TRIPLE};${CL12};${OPTS}" "${DEPS}") create_pcm(opencl-c-20-spir64-fp64.pcm cl20spir64fp64 opencl-c-base.h "${SPIR64_TRIPLE};${CL20};${OPTS}" "${DEPS}") create_pcm(opencl-c-30-spir64-fp64.pcm cl30spir64fp64 opencl-c-base.h "${SPIR64_TRIPLE};${CL30};${OPTS};${OPTS30};${OPTS30_FP64}" "${DEPS}") add_custom_target ( opencl.pcm.target DEPENDS opencl.headers.target opencl-c-12-spir.pcm opencl-c-20-spir.pcm opencl-c-30-spir.pcm opencl-c-12-spir64.pcm opencl-c-20-spir64.pcm opencl-c-30-spir64.pcm opencl-c-12-spir-fp64.pcm opencl-c-20-spir-fp64.pcm opencl-c-30-spir-fp64.pcm opencl-c-12-spir64-fp64.pcm opencl-c-20-spir64-fp64.pcm opencl-c-30-spir64-fp64.pcm ) function(pack_to_obj SRC DST TAG) add_custom_command ( OUTPUT ${DST} DEPENDS ${SRC} linux_resource_linker COMMAND ${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-14.0.1/cl_headers/OpenCL.rc000066400000000000000000000021331464314516300177040ustar00rootroot00000000000000// 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-14.0.1/cl_headers/module.modulemap000066400000000000000000000017441464314516300214370ustar00rootroot00000000000000module 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-14.0.1/cl_headers/resource.h000066400000000000000000000036061464314516300202440ustar00rootroot00000000000000/*****************************************************************************\ 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-14.0.1/cmake/000077500000000000000000000000001464314516300152265ustar00rootroot00000000000000opencl-clang-14.0.1/cmake/modules/000077500000000000000000000000001464314516300166765ustar00rootroot00000000000000opencl-clang-14.0.1/cmake/modules/CMakeFunctions.cmake000066400000000000000000000166271464314516300225650ustar00rootroot00000000000000# # Set compiler RTTI options according to the given flag # macro(use_rtti val) if( CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") if( ${val} ) llvm_replace_compiler_option(CMAKE_CXX_FLAGS "-fno-rtti" "-frtti") else() llvm_replace_compiler_option(CMAKE_CXX_FLAGS "-frtti" "-fno-rtti" ) endif() else(MSVC) if( ${val} ) llvm_replace_compiler_option(CMAKE_CXX_FLAGS "/GR-" "/GR") else() llvm_replace_compiler_option(CMAKE_CXX_FLAGS "/GR" "/GR-" ) endif() endif() set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE ) endmacro(use_rtti) # # Set compiler Exception Handling options according to the given flag # macro(use_eh val) if( CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") if( ${val} ) remove_definitions( -fno-exceptions ) else() add_definitions( -fno-exceptions ) endif() else(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() 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) foreach(patches_dir ${patches_dir}) file(GLOB patches_in_dir ${patches_dir}/*.patch) list(APPEND patches ${patches_in_dir}) endforeach() if(NOT patches) message(STATUS "[OPENCL-CLANG] No patches in ${patches_dir}") return() endif() # Check if it's a git repo if(EXISTS "${repo_dir}/.git") message(STATUS "[OPENCL-CLANG] Patching repository ${repo_dir}") else() message(STATUS "[OPENCL-CLANG][Warning] ${repo_dir} is not a git repository, therefore, local patches are not applied") return() endif() # 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 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 -C0 ${patch} WORKING_DIRECTORY ${repo_dir} OUTPUT_VARIABLE patching_log RESULT_VARIABLE ret_apply_patch ) message(STATUS "[OPENCL-CLANG] Not present - ${patching_log}") if (ret_apply_patch) break() endif() endif() endforeach(patch) elseif(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 RESULT_VARIABLE ret_check_out ) endif() if (NOT (ret_check_out OR ret_apply_patch)) message(STATUS "[OPENCL-CLANG] Applied patch successfully!") else() 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-14.0.1/common_clang.cpp000066400000000000000000000314771464314516300173220ustar00rootroot00000000000000/*****************************************************************************\ 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 common_clang.cpp \*****************************************************************************/ #include "common_clang.h" #include "pch_mgr.h" #include "cl_headers/resource.h" #include "binary_result.h" #include "options.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Twine.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Module.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" #include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/Linker/Linker.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Path.h" #include "llvm/Support/Threading.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/VirtualFileSystem.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticIDs.h" #include "clang/Basic/DiagnosticOptions.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/FrontendTool/Utils.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Serialization/ModuleManager.h" #ifdef USE_PREBUILT_LLVM #include "LLVMSPIRVLib/LLVMSPIRVLib.h" #else // USE_PREBUILT_LLVM #include "LLVMSPIRVLib.h" #endif // USE_PREBUILT_LLVM // The following #defines are used as return value of Compile() API and defined // in https://github.com/KhronosGroup/OpenCL-Headers/blob/master/CL/cl.h #define CL_SUCCESS 0 #define CL_COMPILE_PROGRAM_FAILURE -15 #define CL_OUT_OF_HOST_MEMORY -6 #include "assert.h" #include #include #include #include #include #ifdef _WIN32 #include #endif #if defined _DEBUG #include #include #include #include #endif using namespace Intel::OpenCL::ClangFE; static volatile bool lazyCCInit = true; // the flag must be 'volatile' to prevent caching in a CPU register static llvm::sys::Mutex lazyCCInitMutex; llvm::ManagedStatic> compileMutex; void CommonClangTerminate() { llvm::llvm_shutdown(); } // This function mustn't be invoked from a static object constructor, // from a DllMain function (Windows specific), or from a function // w\ __attribute__ ((constructor)) (Linux specific). void CommonClangInitialize() { if (lazyCCInit) { llvm::sys::ScopedLock lock(lazyCCInitMutex); if (lazyCCInit) { // CommonClangTerminate calls llvm_shutdown to deallocate resources used // by LLVM libraries. llvm_shutdown uses static mutex to make it safe for // multi-threaded envirounment and LLVM libraries user is expected call // llvm_shutdown before static object are destroyed, so we use atexit to // satisfy this requirement. atexit(CommonClangTerminate); llvm::InitializeAllTargets(); llvm::InitializeAllAsmPrinters(); llvm::InitializeAllAsmParsers(); llvm::InitializeAllTargetMCs(); lazyCCInit = false; } } } static bool GetHeaders(std::vector &Result) { struct { const char *ID; const char *Name; } Headers[] = {{OPENCL_C_H, "opencl-c.h"}, {OPENCL_C_BASE_H, "opencl-c-base.h"}, {OPENCL_C_12_SPIR_PCM, "opencl-c-12-spir.pcm"}, {OPENCL_C_20_SPIR_PCM, "opencl-c-20-spir.pcm"}, {OPENCL_C_30_SPIR_PCM, "opencl-c-30-spir.pcm"}, {OPENCL_C_12_SPIR64_PCM, "opencl-c-12-spir64.pcm"}, {OPENCL_C_20_SPIR64_PCM, "opencl-c-20-spir64.pcm"}, {OPENCL_C_30_SPIR64_PCM, "opencl-c-30-spir64.pcm"}, {OPENCL_C_12_SPIR_FP64_PCM, "opencl-c-12-spir-fp64.pcm"}, {OPENCL_C_20_SPIR_FP64_PCM, "opencl-c-20-spir-fp64.pcm"}, {OPENCL_C_30_SPIR_FP64_PCM, "opencl-c-30-spir-fp64.pcm"}, {OPENCL_C_12_SPIR64_FP64_PCM, "opencl-c-12-spir64-fp64.pcm"}, {OPENCL_C_20_SPIR64_FP64_PCM, "opencl-c-20-spir64-fp64.pcm"}, {OPENCL_C_30_SPIR64_FP64_PCM, "opencl-c-30-spir64-fp64.pcm"}, {OPENCL_C_MODULE_MAP, "module.modulemap"}}; Result.clear(); Result.reserve(sizeof(Headers) / sizeof(*Headers)); ResourceManager &RM = ResourceManager::instance(); for (auto Header : Headers) { Resource R = RM.get_resource(Header.Name, Header.ID, "PCM", true); if (!R) { assert(0 && "Resource not found"); return false; } Result.push_back(R); } return true; } static void PrintCompileOptions(const char *pszOptions, const char *pszOptionsEx, const char *pszOpenCLVer, const char * pszSource) { #ifdef _DEBUG static int ID = 0; if (!getenv("CCLANG_OPTIONS_DIR")) return; std::string OptionsDir = getenv("CCLANG_OPTIONS_DIR"); std::stringstream logPath; logPath << OptionsDir << "/log_" << std::this_thread::get_id() << "_" << ID << ".txt"; std::cout << logPath.str() << std::endl; // Creating log file std::ofstream logFile(logPath.str(), std::ios::out); if (!logFile.is_open()) { std::cout << "[ERROR] Can't create log file" << std::endl; return; } logFile << "pszOptions=" << pszOptions << std::endl; logFile << "pszOptionsEx=" << pszOptionsEx << std::endl; logFile << "pszOpenCLVer=" << pszOpenCLVer << std::endl; logFile << pszSource; ++ID; logFile.close(); #endif } class SmallVectorBuffer : public std::streambuf { // All memory management is delegated to llvm::SmallVectorImpl llvm::SmallVectorImpl &OS; // Since we don't touch any pointer in streambuf(pbase, pptr, epptr) this is // the only method we need to override. virtual std::streamsize xsputn(const char *s, std::streamsize n) override { OS.append(s, s + n); return n; } public: SmallVectorBuffer() = delete; SmallVectorBuffer(const SmallVectorBuffer&) = delete; SmallVectorBuffer &operator=(const SmallVectorBuffer&) = delete; SmallVectorBuffer(llvm::SmallVectorImpl &O) : OS(O) {} }; extern "C" CC_DLL_EXPORT int Compile(const char *pszProgramSource, const char **pInputHeaders, unsigned int uiNumInputHeaders, const char **pInputHeadersNames, const char *pPCHBuffer, size_t uiPCHBufferSize, const char *pszOptions, const char *pszOptionsEx, const char *pszOpenCLVer, IOCLFEBinaryResult **pBinaryResult) { // Capturing cclang compile options PrintCompileOptions(pszOptions, pszOptionsEx, pszOpenCLVer, pszProgramSource); // Lazy initialization CommonClangInitialize(); try { #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(OverlayFS); compiler->createSourceManager(compiler->getFileManager()); // Create compiler invocation from user args before trickering with it clang::CompilerInvocation::CreateFromArgs(compiler->getInvocation(), optionsParser.args(), *Diags); // Configure our handling of diagnostics. ProcessWarningOptions(*Diags, compiler->getDiagnosticOpts()); // Map memory buffers to a virtual file system // Source file 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(!"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-14.0.1/common_clang.h000066400000000000000000000107521464314516300167600ustar00rootroot00000000000000/*****************************************************************************\ 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 common_clang.h \*****************************************************************************/ #pragma once #include "assert.h" #include "cstddef" // size_t #if defined(_WIN32) #if defined(COMMON_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-14.0.1/common_clang.map000066400000000000000000000011341464314516300173000ustar00rootroot00000000000000{ 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-14.0.1/linux_linker/000077500000000000000000000000001464314516300166515ustar00rootroot00000000000000opencl-clang-14.0.1/linux_linker/CMakeLists.txt000066400000000000000000000007351464314516300214160ustar00rootroot00000000000000add_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-14.0.1/linux_linker/linux_resource_linker.cpp000066400000000000000000000041641464314516300237740ustar00rootroot00000000000000/*****************************************************************************\ 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-14.0.1/opencl_clang_options.td000066400000000000000000000046271464314516300207070ustar00rootroot00000000000000//===----------------------------------------------------------------------===// // // This file defines the options accepted by common_clang. // //===----------------------------------------------------------------------===// // Include the common option parsing interfaces. include "llvm/Option/OptParser.td" //===----------------------------------------------------------------------===// // OpenCL Options //===----------------------------------------------------------------------===// def g_Flag : Flag<["-"], "g">, HelpText<"Generate source level debug information">; def gline_tables_only_Flag : Flag<["-"], "gline-tables-only">; def profiling : Flag<["-"], "profiling">, HelpText<"Allow profiling">; def w : Flag<["-"], "w">, HelpText<"Suppress all warnings">; def D : JoinedOrSeparate<["-"], "D">; def I : JoinedOrSeparate<["-"], "I">, Flags<[RenderJoined]>, HelpText<"Add directory to include search path">; def s : Separate<["-"], "s">; def Werror : Flag<["-"], "Werror">; def cl_single_precision_constant : Flag<["-"], "cl-single-precision-constant">; def cl_denorms_are_zero : Flag<["-"], "cl-denorms-are-zero">; def cl_fp32_correctly_rounded_divide_sqrt : Flag<["-"], "cl-fp32-correctly-rounded-divide-sqrt">; def cl_opt_disable : Flag<["-"], "cl-opt-disable">; def cl_mad_enable : Flag<["-"], "cl-mad-enable">; def cl_no_signed_zeros : Flag<["-"], "cl-no-signed-zeros">; def cl_unsafe_math_optimizations: Flag<["-"], "cl-unsafe-math-optimizations">; def cl_finite_math_only: Flag<["-"], "cl-finite-math-only">; def cl_fast_relaxed_math: Flag<["-"], "cl-fast-relaxed-math">; def cl_kernel_arg_info: Flag<["-"], "cl-kernel-arg-info">; def cl_std_CL1_1: Flag<["-"], "cl-std=CL1.1">; def cl_std_CL1_2: Flag<["-"], "cl-std=CL1.2">; def cl_std_CL2_0: Flag<["-"], "cl-std=CL2.0">; def cl_std_CL3_0: Flag<["-"], "cl-std=CL3.0">; def cl_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-14.0.1/options.cpp000066400000000000000000000071671464314516300163600ustar00rootroot00000000000000/*****************************************************************************\ 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-14.0.1/options.h000066400000000000000000000170631464314516300160210ustar00rootroot00000000000000/*****************************************************************************\ 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 common_clang.h \brief Defines the common structures for both compile and link options parsing \*****************************************************************************/ #ifndef COMMON_CLANG_OPTIONS_H #define COMMON_CLANG_OPTIONS_H #include "llvm/Option/Arg.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" #include "clang/Basic/OpenCLOptions.h" #include enum COMPILE_OPT_ID { OPT_COMPILE_INVALID = 0, // This is not an option ID. #define PREFIX(NAME, VALUE) #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ HELPTEXT, METAVAR, VALUES) \ OPT_COMPILE_##ID, #include "opencl_clang_options.inc" OPT_COMPILE_LAST_OPTION #undef OPTION #undef PREFIX }; typedef std::list ArgsVector; // // Extend the ArgList to allow the argument parsing from single string. // // Originally llvm::opt::ArgList allowed only parsing or array of options // string. // class OpenCLArgList : public llvm::opt::ArgList { public: OpenCLArgList(const char *pszOptions); const char *getArgString(unsigned index) const override { return m_argStrings[index]; } unsigned getNumInputArgStrings() const override { return m_uiOriginalArgsCount; } std::string getFilteredArgs(int id) const; public: /// MakeIndex - Get an index for the given string(s). unsigned MakeIndex(llvm::StringRef str) const; unsigned MakeIndex(llvm::StringRef str0, llvm::StringRef str1) const; const char *MakeArgStringRef(llvm::StringRef str) const override; 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::OptTable { public: OpenCLOptTable(llvm::ArrayRef pOptionInfos) : OptTable(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-14.0.1/options_compile.cpp000066400000000000000000000415031464314516300200600ustar00rootroot00000000000000/*****************************************************************************\ 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 "common_clang.h" #include "options.h" #include "clang/Driver/Options.h" #include "llvm/ADT/SmallSet.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Mutex.h" #include #include #include #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ HELPTEXT, METAVAR, VALUES) #include "opencl_clang_options.inc" #undef OPTION #undef PREFIX using namespace llvm::opt; extern llvm::ManagedStatic> compileMutex; static const OptTable::Info ClangOptionsInfoTable[] = { #define PREFIX(NAME, VALUE) #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ HELPTEXT, METAVAR, VALUES) \ { \ PREFIX, NAME, HELPTEXT, METAVAR, OPT_COMPILE_##ID, \ llvm::opt::Option::KIND##Class, PARAM, FLAGS, OPT_COMPILE_##GROUP, \ OPT_COMPILE_##ALIAS, ALIASARGS \ } \ , #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_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_uniform_work_group_size: case OPT_COMPILE_cl_no_subgroup_ifp: case OPT_COMPILE_target_triple: case OPT_COMPILE_spir_std_1_0: case OPT_COMPILE_spir_std_1_2: // ignore for now case OPT_COMPILE_cl_kernel_arg_info: // For SPIR, we always create kernel // arg info, so ignoring it here break; case OPT_COMPILE_x: // ensure that the value is spir assert((*it)->getValue() == std::string("spir")); // TODO: move the validation of the value to the check section of the // option processing to be reported as an unknown option break; // Just ignore the unknown options ( they will be listed in the unknown // list inside the ArgsList anyway) // The below assert is usable for manual debugging only // default: // assert(false && "some unknown argument"); case OPT_COMPILE_profiling: case OPT_COMPILE_g_Flag: effectiveArgs.push_back("-debug-info-kind=limited"); effectiveArgs.push_back("-dwarf-version=4"); break; case OPT_COMPILE_gline_tables_only_Flag: effectiveArgs.push_back("-debug-info-kind=line-tables-only"); effectiveArgs.push_back("-dwarf-version=4"); 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 IR, 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) fp64Enabled = true; } 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}}; auto parseClExt = [&](const std::string &clExtStr) { llvm::StringRef clExtRef(clExtStr); clExtRef.consume_front("-cl-ext="); llvm::SmallVector parsedExt; clExtRef.split(parsedExt, ','); for (auto ext : parsedExt) { char sign = ext.front(); bool enabled = sign != '-'; llvm::StringRef extName = ext; if (sign == '+' || sign == '-') extName = extName.drop_front(); if (extName == "all") { for (auto &p : extMap) p.second = enabled; continue; } auto it = extMap.find(extName.str()); if (it != extMap.end()) it->second = enabled; } }; 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-14.0.1/patches/000077500000000000000000000000001464314516300155755ustar00rootroot00000000000000opencl-clang-14.0.1/patches/clang/000077500000000000000000000000001464314516300166615ustar00rootroot00000000000000opencl-clang-14.0.1/patches/clang/0001-Remove-__IMAGE_SUPPORT__-macro-for-SPIR.patch000066400000000000000000000050541464314516300270270ustar00rootroot00000000000000From 1ca45b5f5725a447ded14c0096df39f2751c4e9a Mon Sep 17 00:00:00 2001 From: Haonan Yang Date: Fri, 25 Feb 2022 10:36:57 +0800 Subject: [PATCH] Remove __IMAGE_SUPPORT__ macro for SPIR Signed-off-by: Haonan Yang --- clang/lib/Frontend/InitPreprocessor.cpp | 3 --- clang/test/Preprocessor/predefined-macros.c | 4 ---- 2 files changed, 7 deletions(-) diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index e259ab47c558..0bfdd62f17a2 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -1234,9 +1234,6 @@ static void InitializePredefinedMacros(const TargetInfo &TI, // OpenCL definitions. if (LangOpts.OpenCL) { InitializeOpenCLFeatureTestMacros(TI, LangOpts, Builder); - - if (TI.getTriple().isSPIR() || TI.getTriple().isSPIRV()) - Builder.defineMacro("__IMAGE_SUPPORT__"); } if (TI.hasInt128Type() && LangOpts.CPlusPlus && LangOpts.GNUMode) { diff --git a/clang/test/Preprocessor/predefined-macros.c b/clang/test/Preprocessor/predefined-macros.c index 0b67cbe233ca..aad4a6f05563 100644 --- a/clang/test/Preprocessor/predefined-macros.c +++ b/clang/test/Preprocessor/predefined-macros.c @@ -207,28 +207,24 @@ // RUN: %clang_cc1 %s -E -dM -o - -x cl -triple spir-unknown-unknown \ // RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-SPIR -// CHECK-SPIR-DAG: #define __IMAGE_SUPPORT__ 1 // CHECK-SPIR-DAG: #define __SPIR__ 1 // CHECK-SPIR-DAG: #define __SPIR32__ 1 // CHECK-SPIR-NOT: #define __SPIR64__ 1 // RUN: %clang_cc1 %s -E -dM -o - -x cl -triple spir64-unknown-unknown \ // RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-SPIR64 -// CHECK-SPIR64-DAG: #define __IMAGE_SUPPORT__ 1 // CHECK-SPIR64-DAG: #define __SPIR__ 1 // CHECK-SPIR64-DAG: #define __SPIR64__ 1 // CHECK-SPIR64-NOT: #define __SPIR32__ 1 // RUN: %clang_cc1 %s -E -dM -o - -x cl -triple spirv32-unknown-unknown \ // RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-SPIRV32 -// CHECK-SPIRV32-DAG: #define __IMAGE_SUPPORT__ 1 // CHECK-SPIRV32-DAG: #define __SPIRV__ 1 // CHECK-SPIRV32-DAG: #define __SPIRV32__ 1 // CHECK-SPIRV32-NOT: #define __SPIRV64__ 1 // RUN: %clang_cc1 %s -E -dM -o - -x cl -triple spirv64-unknown-unknown \ // RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-SPIRV64 -// CHECK-SPIRV64-DAG: #define __IMAGE_SUPPORT__ 1 // CHECK-SPIRV64-DAG: #define __SPIRV__ 1 // CHECK-SPIRV64-DAG: #define __SPIRV64__ 1 // CHECK-SPIRV64-NOT: #define __SPIRV32__ 1 -- 2.29.2 opencl-clang-14.0.1/patches/clang/0002-Remove-wrong-check-of-__opencl_c_images-feature-macr.patch000066400000000000000000000032611464314516300323030ustar00rootroot00000000000000From 9780cc0e044c73dcd549c67a1278a4ff7daf3b01 Mon Sep 17 00:00:00 2001 From: Marcin Naczk Date: Fri, 4 Nov 2022 15:41:16 +0100 Subject: [PATCH] Remove wrong check of __opencl_c_images feature macro Deleted mechanism that wrongly assumes that all functions that use image types must be under __opencl_c_images feature macro Mechanism added by https://reviews.llvm.org/D103911 More info on github issue: https://github.com/llvm/llvm-project/issues/58017 --- clang/lib/Sema/SemaType.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index ab47e9f03eaf..f72c2fb57ddd 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1741,13 +1741,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // __opencl_c_3d_image_writes feature. OpenCL C v3.0 API s4.2 - For devices // that support OpenCL 3.0, cl_khr_3d_image_writes must be returned when and // only when the optional feature is supported - if ((Result->isImageType() || Result->isSamplerT()) && - (IsOpenCLC30Compatible && - !OpenCLOptions.isSupported("__opencl_c_images", S.getLangOpts()))) { - S.Diag(DS.getTypeSpecTypeLoc(), diag::err_opencl_requires_extension) - << 0 << Result << "__opencl_c_images"; - declarator.setInvalidType(); - } else if (Result->isOCLImage3dWOType() && + if (Result->isOCLImage3dWOType() && !OpenCLOptions.isSupported("cl_khr_3d_image_writes", S.getLangOpts())) { S.Diag(DS.getTypeSpecTypeLoc(), diag::err_opencl_requires_extension) -- 2.33.0.windows.1 opencl-clang-14.0.1/patches/clang/0003-Fix-checking-mechanism-for-read_write-Image-type.patch000066400000000000000000000032421464314516300314320ustar00rootroot00000000000000From bb5e22800857f7dda9a2491a4f2fc7387d4205b0 Mon Sep 17 00:00:00 2001 From: Marcin Naczk Date: Fri, 4 Nov 2022 15:45:17 +0100 Subject: [PATCH] Fix checking mechanism for read_write Image type The commit https://github.com/llvm/llvm-project/commit/91a0b464a853821734db8b1c521df03f8e2e56e7 Enabled opencl feature macro __opencl_c_read_write_images by default for the SPIR and SPIR-V targets therefore the mechanism of checking read_write image type should take into account if the target is SPIR or SPIR-V --- clang/lib/Sema/SemaDeclAttr.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index e76e7c608e0c..2d60d2b03169 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -7823,8 +7823,9 @@ static void handleOpenCLAccessAttr(Sema &S, Decl *D, const ParsedAttr &AL) { bool ReadWriteImagesUnsupported = (S.getLangOpts().getOpenCLCompatibleVersion() < 200) || (S.getLangOpts().getOpenCLCompatibleVersion() == 300 && - !S.getOpenCLOptions().isSupported("__opencl_c_read_write_images", - S.getLangOpts())); + !S.getOpenCLOptions().isSupported("__opencl_c_read_write_images", S.getLangOpts()) && + !S.getASTContext().getTargetInfo().getTriple().isSPIR() && + !S.getASTContext().getTargetInfo().getTriple().isSPIRV()); if (ReadWriteImagesUnsupported || DeclTy->isPipeType()) { S.Diag(AL.getLoc(), diag::err_opencl_invalid_read_write) << AL << PDecl->getType() << DeclTy->isImageType(); -- 2.33.0.windows.1 opencl-clang-14.0.1/patches/clang/0004-OpenCL-Allow-undefining-header-only-macros.patch000066400000000000000000000112321464314516300302710ustar00rootroot00000000000000From a60b8f468119065f8a6cb4a16598263cb00de0b5 Mon Sep 17 00:00:00 2001 From: Sven van Haastregt Date: Mon, 16 Jan 2023 11:32:12 +0000 Subject: [PATCH] [OpenCL] Allow undefining header-only features `opencl-c-base.h` always defines 5 particular feature macros for SPIR-V, making it impossible to disable those features. To allow disabling any of those features, let the header recognize `__undef_` macros. The user can then pass the `-D__undef_` flag on the command line to disable a specific feature. The __undef macro could potentially also be set from `-cl-ext=-feature`, but for now only change the header and only provide __undef macros for the 5 features that are always enabled in `opencl-c-base.h`. Differential Revision: https://reviews.llvm.org/D141297 --- clang/lib/Headers/opencl-c-base.h | 19 ++++++++++++++++ clang/test/SemaOpenCL/features.cl | 37 ++++++++++++++++++++++--------- 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/clang/lib/Headers/opencl-c-base.h b/clang/lib/Headers/opencl-c-base.h index c433b4f7eb1af..fad2f9c0272bf 100644 --- a/clang/lib/Headers/opencl-c-base.h +++ b/clang/lib/Headers/opencl-c-base.h @@ -74,6 +74,25 @@ #define __opencl_c_atomic_scope_all_devices 1 #define __opencl_c_read_write_images 1 #endif // defined(__SPIR__) + +// Undefine any feature macros that have been explicitly disabled using +// an __undef_ macro. +#ifdef __undef___opencl_c_work_group_collective_functions +#undef __opencl_c_work_group_collective_functions +#endif +#ifdef __undef___opencl_c_atomic_order_seq_cst +#undef __opencl_c_atomic_order_seq_cst +#endif +#ifdef __undef___opencl_c_atomic_scope_device +#undef __opencl_c_atomic_scope_device +#endif +#ifdef __undef___opencl_c_atomic_scope_all_devices +#undef __opencl_c_atomic_scope_all_devices +#endif +#ifdef __undef___opencl_c_read_write_images +#undef __opencl_c_read_write_images +#endif + #endif // (__OPENCL_CPP_VERSION__ == 202100 || __OPENCL_C_VERSION__ == 300) #if !defined(__opencl_c_generic_address_space) diff --git a/clang/test/SemaOpenCL/features.cl b/clang/test/SemaOpenCL/features.cl index af058b5e69828..3f59b4ea3b5ae 100644 --- a/clang/test/SemaOpenCL/features.cl +++ b/clang/test/SemaOpenCL/features.cl @@ -26,6 +26,15 @@ // RUN: %clang_cc1 -triple spir-unknown-unknown %s -E -dM -o - -x cl -cl-std=clc++1.0 \ // RUN: | FileCheck -match-full-lines %s --check-prefix=NO-FEATURES +// For OpenCL C 3.0, header-only features can be disabled using macros. +// RUN: %clang_cc1 -triple spir-unknown-unknown %s -E -dM -o - -x cl -cl-std=CL3.0 -fdeclare-opencl-builtins -finclude-default-header \ +// RUN: -D__undef___opencl_c_work_group_collective_functions=1 \ +// RUN: -D__undef___opencl_c_atomic_order_seq_cst=1 \ +// RUN: -D__undef___opencl_c_atomic_scope_device=1 \ +// RUN: -D__undef___opencl_c_atomic_scope_all_devices=1 \ +// RUN: -D__undef___opencl_c_read_write_images=1 \ +// RUN: | FileCheck %s --check-prefix=NO-HEADERONLY-FEATURES + // Note that __opencl_c_int64 is always defined assuming // always compiling for FULL OpenCL profile @@ -43,14 +52,20 @@ // FEATURES: #define __opencl_c_subgroups 1 // NO-FEATURES: #define __opencl_c_int64 1 -// NO-FEATURES-NOT: __opencl_c_3d_image_writes -// NO-FEATURES-NOT: __opencl_c_atomic_order_acq_rel -// NO-FEATURES-NOT: __opencl_c_atomic_order_seq_cst -// NO-FEATURES-NOT: __opencl_c_device_enqueue -// NO-FEATURES-NOT: __opencl_c_fp64 -// NO-FEATURES-NOT: __opencl_c_generic_address_space -// NO-FEATURES-NOT: __opencl_c_images -// NO-FEATURES-NOT: __opencl_c_pipes -// NO-FEATURES-NOT: __opencl_c_program_scope_global_variables -// NO-FEATURES-NOT: __opencl_c_read_write_images -// NO-FEATURES-NOT: __opencl_c_subgroups +// NO-FEATURES-NOT: #define __opencl_c_3d_image_writes +// NO-FEATURES-NOT: #define __opencl_c_atomic_order_acq_rel +// NO-FEATURES-NOT: #define __opencl_c_atomic_order_seq_cst +// NO-FEATURES-NOT: #define __opencl_c_device_enqueue +// NO-FEATURES-NOT: #define __opencl_c_fp64 +// NO-FEATURES-NOT: #define __opencl_c_generic_address_space +// NO-FEATURES-NOT: #define __opencl_c_images +// NO-FEATURES-NOT: #define __opencl_c_pipes +// NO-FEATURES-NOT: #define __opencl_c_program_scope_global_variables +// NO-FEATURES-NOT: #define __opencl_c_read_write_images +// NO-FEATURES-NOT: #define __opencl_c_subgroups + +// NO-HEADERONLY-FEATURES-NOT: #define __opencl_c_work_group_collective_functions +// NO-HEADERONLY-FEATURES-NOT: #define __opencl_c_atomic_order_seq_cst +// NO-HEADERONLY-FEATURES-NOT: #define __opencl_c_atomic_scope_device +// NO-HEADERONLY-FEATURES-NOT: #define __opencl_c_atomic_scope_all_devices +// NO-HEADERONLY-FEATURES-NOT: #define __opencl_c_read_write_images opencl-clang-14.0.1/patches/clang/0005-Enable-use-of-GNU-C-extension.patch000066400000000000000000000022471464314516300254740ustar00rootroot00000000000000From 62267fec4a0d74472bc64695597f2477cc8c11df Mon Sep 17 00:00:00 2001 From: FirstName LastName Date: Wed, 5 Apr 2023 17:02:38 +0200 Subject: [PATCH] Enable use of GNU C extension - const statement expression as array size This patch partially reverts the commit: llvm/llvm-project@6781fee For backward compatibility, we still need to support the expressions like: ``` const int size = ({ false; }) ? 0 : 1; float array[size]; ``` https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html --- clang/lib/Sema/SemaType.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index ab47e9f03..8cb26be44 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2330,7 +2330,8 @@ static ExprResult checkArraySize(Sema &S, Expr *&ArraySize, } Diagnoser(VLADiag, VLAIsError); ExprResult R = - S.VerifyIntegerConstantExpression(ArraySize, &SizeVal, Diagnoser); + S.VerifyIntegerConstantExpression(ArraySize, &SizeVal, Diagnoser, + S.LangOpts.OpenCL ? Sema::AllowFold : Sema::NoFold); if (Diagnoser.IsVLA) return ExprResult(); return R; -- 2.34.1 opencl-clang-14.0.1/patches/clang/0006-Make-globals-used-for-array-initialization-codegen-c.patch000066400000000000000000000317131464314516300322750ustar00rootroot00000000000000From e9e2434697c3a28f151ce179dd88f0ba73f0f0a0 Mon Sep 17 00:00:00 2001 From: Haonan Yang Date: Tue, 30 May 2023 09:37:00 +0800 Subject: [PATCH] Make globals used for array initialization codegen constant This combines https://reviews.llvm.org/D146211 and https://reviews.llvm.org/D145369 1. Emit const globals with constexpr destructor as constant LLVM values This follows 2b4fa53 which made Clang not emit destructor calls for such objects. However, they would still not get emitted as constants since CodeGenModule::isTypeConstant() returns false if the destructor is constexpr. This change adds a param to make isTypeConstant() ignore the dtor, allowing the caller to check it instead. 2. Make globals used for array initialization codegen constant As pointed out in D133835 these globals will never be written to (they're only used for trivially copyable types), so they can always be constant. --- clang/lib/CodeGen/CGDecl.cpp | 12 ++++++++---- clang/lib/CodeGen/CGDeclCXX.cpp | 4 +++- clang/lib/CodeGen/CGExpr.cpp | 2 +- clang/lib/CodeGen/CGExprAgg.cpp | 4 ++-- clang/lib/CodeGen/CGExprConstant.cpp | 12 ++++++------ clang/lib/CodeGen/CodeGenModule.cpp | 16 +++++++++------- clang/lib/CodeGen/CodeGenModule.h | 2 +- clang/lib/CodeGen/TargetInfo.cpp | 2 +- clang/test/CodeGen/init.c | 2 +- clang/test/CodeGen/label-array-aggregate-init.c | 2 +- clang/test/CodeGenCXX/const-init-cxx2a.cpp | 4 ++-- 11 files changed, 35 insertions(+), 27 deletions(-) diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 18d658436086..372f392402cf 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -379,13 +379,15 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D, OldGV->eraseFromParent(); } - GV->setConstant(CGM.isTypeConstant(D.getType(), true)); + bool NeedsDtor = + D.needsDestruction(getContext()) == QualType::DK_cxx_destructor; + + GV->setConstant(CGM.isTypeConstant(D.getType(), true, !NeedsDtor)); GV->setInitializer(Init); emitter.finalize(GV); - if (D.needsDestruction(getContext()) == QualType::DK_cxx_destructor && - HaveInsertPoint()) { + if (NeedsDtor && HaveInsertPoint()) { // We have a constant initializer, but a nontrivial destructor. We still // need to perform a guarded "initialization" in order to register the // destructor. @@ -1470,10 +1472,12 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { // emit it as a global instead. // Exception is if a variable is located in non-constant address space // in OpenCL. + bool NeedsDtor = + D.needsDestruction(getContext()) == QualType::DK_cxx_destructor; if ((!getLangOpts().OpenCL || Ty.getAddressSpace() == LangAS::opencl_constant) && (CGM.getCodeGenOpts().MergeAllConstants && !NRVO && - !isEscapingByRef && CGM.isTypeConstant(Ty, true))) { + !isEscapingByRef && CGM.isTypeConstant(Ty, true, !NeedsDtor))) { EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage); // Signal this condition to later callbacks. diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 7b880c1354e1..3dfffdbed8eb 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -213,9 +213,11 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, &D, DeclAddr, D.getAttr()->getLocation(), PerformInit, this); } + bool NeedsDtor = + D.needsDestruction(getContext()) == QualType::DK_cxx_destructor; if (PerformInit) EmitDeclInit(*this, D, DeclAddr); - if (CGM.isTypeConstant(D.getType(), true)) + if (CGM.isTypeConstant(D.getType(), true, !NeedsDtor)) EmitDeclInvariant(*this, D, DeclPtr); else EmitDeclDestroy(*this, D, DeclAddr); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 2a9b108c31bc..86ed8b1892ea 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -390,7 +390,7 @@ static Address createReferenceTemporary(CodeGenFunction &CGF, QualType Ty = Inner->getType(); if (CGF.CGM.getCodeGenOpts().MergeAllConstants && (Ty->isArrayType() || Ty->isRecordType()) && - CGF.CGM.isTypeConstant(Ty, true)) + CGF.CGM.isTypeConstant(Ty, true, false)) if (auto Init = ConstantEmitter(CGF).tryEmitAbstract(Inner, Ty)) { auto AS = CGF.CGM.GetGlobalConstantAddressSpace(); auto *GV = new llvm::GlobalVariable( diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 73b05690537d..4f5b5b4cdef3 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -506,8 +506,8 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, if (llvm::Constant *C = Emitter.tryEmitForInitializer(E, AS, ArrayQTy)) { auto GV = new llvm::GlobalVariable( CGM.getModule(), C->getType(), - CGM.isTypeConstant(ArrayQTy, /* ExcludeCtorDtor= */ true), - llvm::GlobalValue::PrivateLinkage, C, "constinit", + /* isConstant= */ true, llvm::GlobalValue::PrivateLinkage, C, + "constinit", /* InsertBefore= */ nullptr, llvm::GlobalVariable::NotThreadLocal, CGM.getContext().getTargetAddressSpace(AS)); Emitter.finalize(GV); diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index ac4b4d1308ab..64129b64e272 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -913,12 +913,12 @@ static ConstantAddress tryEmitGlobalCompoundLiteral(CodeGenModule &CGM, return ConstantAddress::invalid(); } - auto GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), - CGM.isTypeConstant(E->getType(), true), - llvm::GlobalValue::InternalLinkage, - C, ".compoundliteral", nullptr, - llvm::GlobalVariable::NotThreadLocal, - CGM.getContext().getTargetAddressSpace(addressSpace)); + auto GV = new llvm::GlobalVariable( + CGM.getModule(), C->getType(), + CGM.isTypeConstant(E->getType(), true, false), + llvm::GlobalValue::InternalLinkage, C, ".compoundliteral", nullptr, + llvm::GlobalVariable::NotThreadLocal, + CGM.getContext().getTargetAddressSpace(addressSpace)); emitter.finalize(GV); GV->setAlignment(Align.getAsAlign()); CGM.setAddrOfConstantCompoundLiteral(E, GV); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 2777fc22600d..c88228090c17 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2826,7 +2826,7 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) { // codegen for global variables, because they may be marked as threadprivate. if (LangOpts.OpenMP && LangOpts.OpenMPUseTLS && getContext().getTargetInfo().isTLSSupported() && isa(Global) && - !isTypeConstant(Global->getType(), false) && + !isTypeConstant(Global->getType(), false, false) && !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(Global)) return false; @@ -3988,8 +3988,9 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name, /// /// If ExcludeCtor is true, the duration when the object's constructor runs /// will not be considered. The caller will need to verify that the object is -/// not written to during its construction. -bool CodeGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor) { +/// not written to during its construction. ExcludeDtor works similarly. +bool CodeGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor, + bool ExcludeDtor) { if (!Ty.isConstant(Context) && !Ty->isReferenceType()) return false; @@ -3997,7 +3998,7 @@ bool CodeGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor) { if (const CXXRecordDecl *Record = Context.getBaseElementType(Ty)->getAsCXXRecordDecl()) return ExcludeCtor && !Record->hasMutableFields() && - Record->hasTrivialDestructor(); + (Record->hasTrivialDestructor() || ExcludeDtor); } return true; @@ -4108,7 +4109,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty, // FIXME: This code is overly simple and should be merged with other global // handling. - GV->setConstant(isTypeConstant(D->getType(), false)); + GV->setConstant(isTypeConstant(D->getType(), false, false)); GV->setAlignment(getContext().getDeclAlign(D).getAsAlign()); @@ -4642,7 +4643,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, // If it is safe to mark the global 'constant', do so now. GV->setConstant(!NeedsGlobalCtor && !NeedsGlobalDtor && - isTypeConstant(D->getType(), true)); + isTypeConstant(D->getType(), true, true)); // If it is in a read-only section, mark it 'constant'. if (const SectionAttr *SA = D->getAttr()) { @@ -5703,7 +5704,8 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( emitter.emplace(*this); InitialValue = emitter->emitForInitializer(*Value, AddrSpace, MaterializedType); - Constant = isTypeConstant(MaterializedType, /*ExcludeCtor*/Value); + Constant = isTypeConstant(MaterializedType, /*ExcludeCtor*/ Value, + /*ExcludeDtor*/ false); Type = InitialValue->getType(); } else { // No initializer, the initialization will be provided when we diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index a8a63c8da57f..28ea927c448d 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -765,7 +765,7 @@ public: return getTBAAAccessInfo(AccessType); } - bool isTypeConstant(QualType QTy, bool ExcludeCtorDtor); + bool isTypeConstant(QualType QTy, bool ExcludeCtor, bool ExcludeDtor); bool isPaddedAtomicType(QualType type); bool isPaddedAtomicType(const AtomicType *type); diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index d83bc9e529a6..672ca38c6803 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -9440,7 +9440,7 @@ AMDGPUTargetCodeGenInfo::getGlobalVarAddressSpace(CodeGenModule &CGM, return AddrSpace; // Only promote to address space 4 if VarDecl has constant initialization. - if (CGM.isTypeConstant(D->getType(), false) && + if (CGM.isTypeConstant(D->getType(), false, false) && D->hasConstantInitialization()) { if (auto ConstAS = CGM.getTarget().getConstantAddressSpace()) return ConstAS.getValue(); diff --git a/clang/test/CodeGen/init.c b/clang/test/CodeGen/init.c index a21b5f4c09f5..93859924349b 100644 --- a/clang/test/CodeGen/init.c +++ b/clang/test/CodeGen/init.c @@ -10,7 +10,7 @@ unsigned v2[2][3] = {[0 ... 1][0 ... 1] = 2222, 3333}; // CHECK-DAG: [1 x %struct.M] [%struct.M { [2 x %struct.I] [%struct.I { [3 x i32] [i32 4, i32 4, i32 0] }, %struct.I { [3 x i32] [i32 4, i32 4, i32 5] }] }], // CHECK-DAG: [2 x [3 x i32]] {{[[][[]}}3 x i32] [i32 2222, i32 2222, i32 0], [3 x i32] [i32 2222, i32 2222, i32 3333]], -// CHECK-DAG: [[INIT14:.*]] = private global [16 x i32] [i32 0, i32 0, i32 0, i32 0, i32 0, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 0, i32 0, i32 0, i32 0], align 4 +// CHECK-DAG: [[INIT14:.*]] = private constant [16 x i32] [i32 0, i32 0, i32 0, i32 0, i32 0, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 0, i32 0, i32 0, i32 0], align 4 void f1() { // Scalars in braces. diff --git a/clang/test/CodeGen/label-array-aggregate-init.c b/clang/test/CodeGen/label-array-aggregate-init.c index 5cefd8d270c0..3175c2a6a292 100644 --- a/clang/test/CodeGen/label-array-aggregate-init.c +++ b/clang/test/CodeGen/label-array-aggregate-init.c @@ -1,6 +1,6 @@ // RUN: %clang -cc1 -triple x86_64-windows-msvc -emit-llvm %s -o - | FileCheck %s -// CHECK: @constinit = private global [3 x i8*] [i8* blockaddress(@main, %L), i8* null, i8* null] +// CHECK: @constinit = private constant [3 x i8*] [i8* blockaddress(@main, %L), i8* null, i8* null] void receivePtrs(void **); diff --git a/clang/test/CodeGenCXX/const-init-cxx2a.cpp b/clang/test/CodeGenCXX/const-init-cxx2a.cpp index 3eafef094387..3c83a9c94ade 100644 --- a/clang/test/CodeGenCXX/const-init-cxx2a.cpp +++ b/clang/test/CodeGenCXX/const-init-cxx2a.cpp @@ -11,10 +11,10 @@ struct B { constexpr ~B() { n *= 5; } int n = 123; }; -// CHECK: @b ={{.*}} global {{.*}} i32 123 +// CHECK: @b ={{.*}} constant {{.*}} i32 123 extern constexpr B b = B(); -// CHECK: @_ZL1c = internal global {{.*}} i32 123 +// CHECK: @_ZL1c = internal constant {{.*}} i32 123 const B c; int use_c() { return c.n; } -- 2.31.1 opencl-clang-14.0.1/patches/clang/0007-clang-Sema-check-default-argument-promotions-for-pri.patch000066400000000000000000000564001464314516300323420ustar00rootroot00000000000000From f72d0efc9f42802ccf0e3ffcd6ae26ba4dfc8529 Mon Sep 17 00:00:00 2001 From: "Yang, Haonan" Date: Thu, 6 Jun 2024 10:15:54 +0800 Subject: [PATCH] [clang][Sema] check default argument promotions for printf cherry pick https://github.com/llvm/llvm-project/commit/e3bd67eddf65b20956513e91715b1f997dae2690 The main focus of this patch is to make ArgType::matchesType check for possible default parameter promotions when the argType is not a pointer. If so, no warning will be given for `int`, `unsigned int` types as corresponding arguments to %hhd and %hd. However, the usage of %hhd corresponding to short is relatively rare, and it is more likely to be a misuse. This patch keeps the original behavior of clang like this as much as possible, while making it more convenient to consider the default arguments promotion. Fixes https://github.com/llvm/llvm-project/issues/57102 Reviewed By: aaron.ballman, nickdesaulniers, #clang-language-wg Differential Revision: https://reviews.llvm.org/D132568 cherry pick https://github.com/llvm/llvm-project/commit/04e6178ae932c9a1d939dcfe3ef1189f4bbb21aa [Sema] tolerate more promotion matches in format string checking It's been reported that when using __attribute__((format)) on non-variadic functions, certain values that normally get promoted when passed as variadic arguments now unconditionally emit a diagnostic: ```c void foo(const char *fmt, float f) __attribute__((format(printf, 1, 2))); void bar(void) { foo("%g", 123.f); // ^ format specifies type 'double' but the argument has type 'float' } ``` This is normally not an issue because float values get promoted to doubles when passed as variadic arguments, but needless to say, variadic argument promotion does not apply to non-variadic arguments. While this can be fixed by adjusting the prototype of `foo`, this is sometimes undesirable in C (for instance, if `foo` is ABI). In C++, using variadic templates, this might instead require call-site fixing, which is tedious and arguably needless work: ```c++ template void foo(const char *fmt, Args &&...args) __attribute__((format(printf, 1, 2))); void bar(void) { foo("%g", 123.f); // ^ format specifies type 'double' but the argument has type 'float' } ``` To address this issue, we teach FormatString about a few promotions that have always been around but that have never been exercised in the direction that FormatString checks for: * `char`, `unsigned char` -> `int`, `unsigned` * `half`, `float16`, `float` -> `double` This addresses issue https://github.com/llvm/llvm-project/issues/59824 --- clang/docs/ReleaseNotes.rst | 10 ++ clang/include/clang/AST/FormatString.h | 8 +- clang/lib/AST/FormatString.cpp | 121 +++++++++++++++++++---- clang/lib/Sema/SemaChecking.cpp | 44 ++++++--- clang/test/Sema/format-strings-freebsd.c | 4 +- clang/test/Sema/format-strings-scanf.c | 52 ++++++++++ clang/test/Sema/format-strings.c | 54 ++++++++++ 7 files changed, 259 insertions(+), 34 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 0c50e168bf48..a46949dcdc76 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -173,6 +173,13 @@ New Pragmas in Clang Attribute Changes in Clang -------------------------- +- When a non-variadic function is decorated with the ``format`` attribute, + Clang now checks that the format string would match the function's parameters' + types after default argument promotion. As a result, it's no longer an + automatic diagnostic to use parameters of types that the format style + supports but that are never the result of default argument promotion, such as + ``float``. (`#59824: `_) + - Attributes loaded as clang plugins which are sensitive to LangOpts must now override ``acceptsLangOpts`` instead of ``diagLangOpts``. Returning false will produce a generic "attribute ignored" diagnostic, as @@ -223,6 +230,9 @@ Windows Support C Language Changes in Clang --------------------------- +- Adjusted ``-Wformat`` warnings according to `WG14 N2562 `_. + Clang will now consider default argument promotions in printf, and remove unnecessary warnings. + Especially ``int`` argument with specifier ``%hhd`` and ``%hd``. - The value of ``__STDC_VERSION__`` has been bumped to ``202000L`` when passing ``-std=c2x`` so that it can be distinguished from C17 mode. This value is diff --git a/clang/include/clang/AST/FormatString.h b/clang/include/clang/AST/FormatString.h index d7933382f13d..60849bd7f9d3 100644 --- a/clang/include/clang/AST/FormatString.h +++ b/clang/include/clang/AST/FormatString.h @@ -257,8 +257,14 @@ public: /// instance, "%d" and float. NoMatch = 0, /// The conversion specifier and the argument type are compatible. For - /// instance, "%d" and _Bool. + /// instance, "%d" and int. Match = 1, + /// The conversion specifier and the argument type are compatible because of + /// default argument promotions. For instance, "%hhd" and int. + MatchPromotion, + /// The conversion specifier and the argument type are compatible but still + /// seems likely to be an error. For instanace, "%hhd" and short. + NoMatchPromotionTypeConfusion, /// The conversion specifier and the argument type are disallowed by the C /// standard, but are in practice harmless. For instance, "%p" and int*. NoMatchPedantic, diff --git a/clang/lib/AST/FormatString.cpp b/clang/lib/AST/FormatString.cpp index 102bcca96a38..df7917b15810 100644 --- a/clang/lib/AST/FormatString.cpp +++ b/clang/lib/AST/FormatString.cpp @@ -342,7 +342,7 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const { return Match; case AnyCharTy: { - if (const EnumType *ETy = argTy->getAs()) { + if (const auto *ETy = argTy->getAs()) { // If the enum is incomplete we know nothing about the underlying type. // Assume that it's 'int'. if (!ETy->getDecl()->isComplete()) @@ -350,17 +350,34 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const { argTy = ETy->getDecl()->getIntegerType(); } - if (const BuiltinType *BT = argTy->getAs()) + if (const auto *BT = argTy->getAs()) { + // The types are perfectly matched? switch (BT->getKind()) { + default: + break; + case BuiltinType::Char_S: + case BuiltinType::SChar: + case BuiltinType::UChar: + case BuiltinType::Char_U: + case BuiltinType::Bool: + return Match; + } + // "Partially matched" because of promotions? + if (!Ptr) { + switch (BT->getKind()) { default: break; - case BuiltinType::Char_S: - case BuiltinType::SChar: - case BuiltinType::UChar: - case BuiltinType::Char_U: - case BuiltinType::Bool: - return Match; + case BuiltinType::Int: + case BuiltinType::UInt: + return MatchPromotion; + case BuiltinType::Short: + case BuiltinType::UShort: + case BuiltinType::WChar_S: + case BuiltinType::WChar_U: + return NoMatchPromotionTypeConfusion; + } } + } return NoMatch; } @@ -377,8 +394,9 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const { if (T == argTy) return Match; - // Check for "compatible types". - if (const BuiltinType *BT = argTy->getAs()) + if (const auto *BT = argTy->getAs()) { + // Check if the only difference between them is signed vs unsigned + // if true, we consider they are compatible. switch (BT->getKind()) { default: break; @@ -389,25 +407,88 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const { case BuiltinType::Bool: if (T == C.UnsignedShortTy || T == C.ShortTy) return NoMatchTypeConfusion; - return T == C.UnsignedCharTy || T == C.SignedCharTy ? Match - : NoMatch; + if (T == C.UnsignedCharTy || T == C.SignedCharTy) + return Match; + break; case BuiltinType::Short: - return T == C.UnsignedShortTy ? Match : NoMatch; + if (T == C.UnsignedShortTy) + return Match; + break; case BuiltinType::UShort: - return T == C.ShortTy ? Match : NoMatch; + if (T == C.ShortTy) + return Match; + break; case BuiltinType::Int: - return T == C.UnsignedIntTy ? Match : NoMatch; + if (T == C.UnsignedIntTy) + return Match; + break; case BuiltinType::UInt: - return T == C.IntTy ? Match : NoMatch; + if (T == C.IntTy) + return Match; + break; case BuiltinType::Long: - return T == C.UnsignedLongTy ? Match : NoMatch; + if (T == C.UnsignedLongTy) + return Match; + break; case BuiltinType::ULong: - return T == C.LongTy ? Match : NoMatch; + if (T == C.LongTy) + return Match; + break; case BuiltinType::LongLong: - return T == C.UnsignedLongLongTy ? Match : NoMatch; + if (T == C.UnsignedLongLongTy) + return Match; + break; case BuiltinType::ULongLong: - return T == C.LongLongTy ? Match : NoMatch; + if (T == C.LongLongTy) + return Match; + break; } + // "Partially matched" because of promotions? + if (!Ptr) { + switch (BT->getKind()) { + default: + break; + case BuiltinType::Bool: + if (T == C.IntTy || T == C.UnsignedIntTy) + return MatchPromotion; + break; + case BuiltinType::Int: + case BuiltinType::UInt: + if (T == C.SignedCharTy || T == C.UnsignedCharTy || + T == C.ShortTy || T == C.UnsignedShortTy || T == C.WCharTy || + T == C.WideCharTy) + return MatchPromotion; + break; + case BuiltinType::Char_U: + if (T == C.UnsignedIntTy) + return MatchPromotion; + if (T == C.UnsignedShortTy) + return NoMatchPromotionTypeConfusion; + break; + case BuiltinType::Char_S: + if (T == C.IntTy) + return MatchPromotion; + if (T == C.ShortTy) + return NoMatchPromotionTypeConfusion; + break; + case BuiltinType::Half: + case BuiltinType::Float16: + case BuiltinType::Float: + if (T == C.DoubleTy) + return MatchPromotion; + break; + case BuiltinType::Short: + case BuiltinType::UShort: + if (T == C.SignedCharTy || T == C.UnsignedCharTy) + return NoMatchPromotionTypeConfusion; + break; + case BuiltinType::WChar_U: + case BuiltinType::WChar_S: + if (T != C.WCharTy && T != C.WideCharTy) + return NoMatchPromotionTypeConfusion; + } + } + } return NoMatch; } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 69dcc3aaaaf3..1ed01cb7dd9a 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -9557,10 +9557,14 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, return true; } - analyze_printf::ArgType::MatchKind Match = AT.matchesType(S.Context, ExprTy); - if (Match == analyze_printf::ArgType::Match) + ArgType::MatchKind ImplicitMatch = ArgType::NoMatch; + ArgType::MatchKind Match = AT.matchesType(S.Context, ExprTy); + if (Match == ArgType::Match) return true; + // NoMatchPromotionTypeConfusion should be only returned in ImplictCastExpr + assert(Match != ArgType::NoMatchPromotionTypeConfusion); + // Look through argument promotions for our error message's reported type. // This includes the integral and floating promotions, but excludes array // and function pointer decay (seeing that an argument intended to be a @@ -9577,13 +9581,9 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, if (ICE->getType() == S.Context.IntTy || ICE->getType() == S.Context.UnsignedIntTy) { // All further checking is done on the subexpression - const analyze_printf::ArgType::MatchKind ImplicitMatch = - AT.matchesType(S.Context, ExprTy); - if (ImplicitMatch == analyze_printf::ArgType::Match) + ImplicitMatch = AT.matchesType(S.Context, ExprTy); + if (ImplicitMatch == ArgType::Match) return true; - if (ImplicitMatch == ArgType::NoMatchPedantic || - ImplicitMatch == ArgType::NoMatchTypeConfusion) - Match = ImplicitMatch; } } } else if (const CharacterLiteral *CL = dyn_cast(E)) { @@ -9594,10 +9594,29 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, // modifier is provided. if (ExprTy == S.Context.IntTy && FS.getLengthModifier().getKind() != LengthModifier::AsChar) - if (llvm::isUIntN(S.Context.getCharWidth(), CL->getValue())) + if (llvm::isUIntN(S.Context.getCharWidth(), CL->getValue())) { ExprTy = S.Context.CharTy; + // To improve check results, we consider a character literal in C + // to be a 'char' rather than an 'int'. 'printf("%hd", 'a');' is + // more likely a type confusion situation, so we will suggest to + // use '%hhd' instead by discarding the MatchPromotion. + if (Match == ArgType::MatchPromotion) + Match = ArgType::NoMatch; + } } - + if (Match == ArgType::MatchPromotion) { + // WG14 N2562 only clarified promotions in *printf + // For NSLog in ObjC, just preserve -Wformat behavior + if (!S.getLangOpts().ObjC && + ImplicitMatch != ArgType::NoMatchPromotionTypeConfusion && + ImplicitMatch != ArgType::NoMatchTypeConfusion) + return true; + Match = ArgType::NoMatch; + } + if (ImplicitMatch == ArgType::NoMatchPedantic || + ImplicitMatch == ArgType::NoMatchTypeConfusion) + Match = ImplicitMatch; + assert(Match != ArgType::MatchPromotion); // Look through enums to their underlying type. bool IsEnum = false; if (auto EnumTy = ExprTy->getAs()) { @@ -9670,7 +9689,10 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, if (IntendedTy == ExprTy && !ShouldNotPrintDirectly) { unsigned Diag; switch (Match) { - case ArgType::Match: llvm_unreachable("expected non-matching"); + case ArgType::Match: + case ArgType::MatchPromotion: + case ArgType::NoMatchPromotionTypeConfusion: + llvm_unreachable("expected non-matching"); case ArgType::NoMatchPedantic: Diag = diag::warn_format_conversion_argument_type_mismatch_pedantic; break; diff --git a/clang/test/Sema/format-strings-freebsd.c b/clang/test/Sema/format-strings-freebsd.c index 965d7c287be6..f49dea00c876 100644 --- a/clang/test/Sema/format-strings-freebsd.c +++ b/clang/test/Sema/format-strings-freebsd.c @@ -34,9 +34,9 @@ void check_freebsd_kernel_extensions(int i, long l, char *s, short h) freebsd_kernel_printf("%lr", l); // no-warning // h modifier expects a short - freebsd_kernel_printf("%hr", i); // expected-warning{{format specifies type 'short' but the argument has type 'int'}} + freebsd_kernel_printf("%hr", i); // no-warning freebsd_kernel_printf("%hr", h); // no-warning - freebsd_kernel_printf("%hy", i); // expected-warning{{format specifies type 'short' but the argument has type 'int'}} + freebsd_kernel_printf("%hy", i); // no-warning freebsd_kernel_printf("%hy", h); // no-warning // %y expects an int diff --git a/clang/test/Sema/format-strings-scanf.c b/clang/test/Sema/format-strings-scanf.c index b7cdd7dd4a9a..61d20b482c38 100644 --- a/clang/test/Sema/format-strings-scanf.c +++ b/clang/test/Sema/format-strings-scanf.c @@ -241,3 +241,55 @@ void check_conditional_literal(char *s, int *i) { scanf(i ? "%d" : "%d", i, s); // expected-warning{{data argument not used}} scanf(i ? "%s" : "%d", s); // expected-warning{{format specifies type 'int *'}} } + +void test_promotion(void) { + // No promotions for *scanf pointers clarified in N2562 + // https://github.com/llvm/llvm-project/issues/57102 + // N2562: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2562.pdf + int i; + signed char sc; + unsigned char uc; + short ss; + unsigned short us; + + // pointers could not be "promoted" + scanf("%hhd", &i); // expected-warning{{format specifies type 'char *' but the argument has type 'int *'}} + scanf("%hd", &i); // expected-warning{{format specifies type 'short *' but the argument has type 'int *'}} + scanf("%d", &i); // no-warning + // char & uchar + scanf("%hhd", &sc); // no-warning + scanf("%hhd", &uc); // no-warning + scanf("%hd", &sc); // expected-warning{{format specifies type 'short *' but the argument has type 'signed char *'}} + scanf("%hd", &uc); // expected-warning{{format specifies type 'short *' but the argument has type 'unsigned char *'}} + scanf("%d", &sc); // expected-warning{{format specifies type 'int *' but the argument has type 'signed char *'}} + scanf("%d", &uc); // expected-warning{{format specifies type 'int *' but the argument has type 'unsigned char *'}} + // short & ushort + scanf("%hhd", &ss); // expected-warning{{format specifies type 'char *' but the argument has type 'short *'}} + scanf("%hhd", &us); // expected-warning{{format specifies type 'char *' but the argument has type 'unsigned short *'}} + scanf("%hd", &ss); // no-warning + scanf("%hd", &us); // no-warning + scanf("%d", &ss); // expected-warning{{format specifies type 'int *' but the argument has type 'short *'}} + scanf("%d", &us); // expected-warning{{format specifies type 'int *' but the argument has type 'unsigned short *'}} + + // long types + scanf("%ld", &i); // expected-warning{{format specifies type 'long *' but the argument has type 'int *'}} + scanf("%lld", &i); // expected-warning{{format specifies type 'long long *' but the argument has type 'int *'}} + scanf("%ld", &sc); // expected-warning{{format specifies type 'long *' but the argument has type 'signed char *'}} + scanf("%lld", &sc); // expected-warning{{format specifies type 'long long *' but the argument has type 'signed char *'}} + scanf("%ld", &uc); // expected-warning{{format specifies type 'long *' but the argument has type 'unsigned char *'}} + scanf("%lld", &uc); // expected-warning{{format specifies type 'long long *' but the argument has type 'unsigned char *'}} + scanf("%llx", &i); // expected-warning{{format specifies type 'unsigned long long *' but the argument has type 'int *'}} + + // ill-formed floats + scanf("%hf", // expected-warning{{length modifier 'h' results in undefined behavior or no effect with 'f' conversion specifier}} + &sc); + + // pointers in scanf + scanf("%s", i); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}} + + // FIXME: does this match what the C committee allows or should it be pedantically warned on? + char c; + void *vp; + scanf("%hhd", &c); // Pedantic warning? + scanf("%hhd", vp); // expected-warning{{format specifies type 'char *' but the argument has type 'void *'}} +} diff --git a/clang/test/Sema/format-strings.c b/clang/test/Sema/format-strings.c index bb5c4c4d1de7..d9154b6d30f9 100644 --- a/clang/test/Sema/format-strings.c +++ b/clang/test/Sema/format-strings.c @@ -823,3 +823,57 @@ void test_block() { printf_arg2("foo", "%s string %i\n", "aaa", 123); printf_arg2("%s string\n", "foo", "bar"); // expected-warning{{data argument not used by format string}} } + +void test_promotion(void) { + // Default argument promotions for *printf in N2562 + // https://github.com/llvm/llvm-project/issues/57102 + // N2562: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2562.pdf + int i; + signed char sc; + unsigned char uc; + char c; + short ss; + unsigned short us; + + printf("%hhd %hd %d %hhd %hd %d", i, i, i, sc, sc, sc); // no-warning + printf("%hhd %hd %d %hhd %hd %d", uc, uc, uc, c, c, c); // no-warning + + // %ld %lld %llx + printf("%ld", i); // expected-warning{{format specifies type 'long' but the argument has type 'int'}} + printf("%lld", i); // expected-warning{{format specifies type 'long long' but the argument has type 'int'}} + printf("%ld", sc); // expected-warning{{format specifies type 'long' but the argument has type 'signed char'}} + printf("%lld", sc); // expected-warning{{format specifies type 'long long' but the argument has type 'signed char'}} + printf("%ld", uc); // expected-warning{{format specifies type 'long' but the argument has type 'unsigned char'}} + printf("%lld", uc); // expected-warning{{format specifies type 'long long' but the argument has type 'unsigned char'}} + printf("%llx", i); // expected-warning{{format specifies type 'unsigned long long' but the argument has type 'int'}} + + // ill formed spec for floats + printf("%hf", // expected-warning{{length modifier 'h' results in undefined behavior or no effect with 'f' conversion specifier}} + sc); // expected-warning{{format specifies type 'double' but the argument has type 'signed char'}} + + // for %hhd and `short` they are compatible by promotions but more likely misuse + printf("%hd", ss); // no-warning + printf("%hhd", ss); // expected-warning{{format specifies type 'char' but the argument has type 'short'}} + printf("%hu", us); // no-warning + printf("%hhu", ss); // expected-warning{{format specifies type 'unsigned char' but the argument has type 'short'}} + + // floats & integers are not compatible + printf("%f", i); // expected-warning{{format specifies type 'double' but the argument has type 'int'}} + printf("%f", sc); // expected-warning{{format specifies type 'double' but the argument has type 'signed char'}} + printf("%f", uc); // expected-warning{{format specifies type 'double' but the argument has type 'unsigned char'}} + printf("%f", c); // expected-warning{{format specifies type 'double' but the argument has type 'char'}} + printf("%f", ss); // expected-warning{{format specifies type 'double' but the argument has type 'short'}} + printf("%f", us); // expected-warning{{format specifies type 'double' but the argument has type 'unsigned short'}} + + // character literals + // In C language engineering practice, printing a character literal with %hhd or %d is common, but %hd may be misuse. + printf("%hhu", 'a'); // no-warning + printf("%hhd", 'a'); // no-warning + printf("%hd", 'a'); // expected-warning{{format specifies type 'short' but the argument has type 'char'}} + printf("%hu", 'a'); // expected-warning{{format specifies type 'unsigned short' but the argument has type 'char'}} + printf("%d", 'a'); // no-warning + printf("%u", 'a'); // no-warning + + // pointers + printf("%s", i); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}} +} -- 2.31.1 opencl-clang-14.0.1/pch_mgr.cpp000066400000000000000000000161361464314516300163000ustar00rootroot00000000000000/*****************************************************************************\ 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/Object/ELF.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() { } 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, LIBCOMMON_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-14.0.1/pch_mgr.h000066400000000000000000000056351464314516300157470ustar00rootroot00000000000000/*****************************************************************************\ 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; }; opencl-clang-14.0.1/windows_resource_file.rc000066400000000000000000000040361464314516300210770ustar00rootroot00000000000000// This file was copied from LLVM_SOURCE_DIR/resources/windows_version_resource.rc // Microsoft Visual C++ resource script for embedding version information. // The format is described at: // http://msdn.microsoft.com/en-gb/library/windows/desktop/aa380599(v=vs.85).aspx // The VERSIONINFO resource is described at: // https://msdn.microsoft.com/en-gb/library/windows/desktop/aa381058(v=vs.85).aspx // Default values for required fields. #ifndef RC_VERSION_FIELD_1 #define RC_VERSION_FIELD_1 0 #endif #ifndef RC_VERSION_FIELD_2 #define RC_VERSION_FIELD_2 0 #endif #ifndef RC_VERSION_FIELD_3 #define RC_VERSION_FIELD_3 0 #endif #ifndef RC_VERSION_FIELD_4 #define RC_VERSION_FIELD_4 0 #endif #ifndef RC_COMPANY_NAME #define RC_COMPANY_NAME "" #endif #ifndef RC_FILE_DESCRIPTION #define RC_FILE_DESCRIPTION "" #endif #ifndef RC_FILE_VERSION #define RC_FILE_VERSION "" #endif #ifndef RC_INTERNAL_NAME #define RC_INTERNAL_NAME "" #endif #ifndef RC_ORIGINAL_FILENAME #define RC_ORIGINAL_FILENAME "" #endif #ifndef RC_PRODUCT_NAME #define RC_PRODUCT_NAME "" #endif #ifndef RC_PRODUCT_VERSION #define RC_PRODUCT_VERSION "" #endif 1 VERSIONINFO FILEVERSION RC_VERSION_FIELD_1,RC_VERSION_FIELD_2,RC_VERSION_FIELD_3,RC_VERSION_FIELD_4 BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904B0" BEGIN // Required strings VALUE "CompanyName", RC_COMPANY_NAME VALUE "FileDescription", RC_FILE_DESCRIPTION VALUE "FileVersion", RC_FILE_VERSION VALUE "InternalName", RC_INTERNAL_NAME VALUE "OriginalFilename", RC_ORIGINAL_FILENAME VALUE "ProductName", RC_PRODUCT_NAME VALUE "ProductVersion", RC_PRODUCT_VERSION // Optional strings #ifdef RC_COMMENTS VALUE "Comments", RC_COMMENTS #endif #ifdef RC_COPYRIGHT VALUE "LegalCopyright", RC_COPYRIGHT #endif END END BLOCK "VarFileInfo" BEGIN // The translation must correspond to the above BLOCK inside StringFileInfo // langID 0x0409 U.S. English // charsetID 0x04B0 Unicode VALUE "Translation", 0x0409, 0x04B0 END END