pax_global_header00006660000000000000000000000064136352174120014516gustar00rootroot0000000000000052 comment=7743482f2053582be990e93ca46d15239c509c9d SPIRV-LLVM-Translator-10.0.0/000077500000000000000000000000001363521741200153765ustar00rootroot00000000000000SPIRV-LLVM-Translator-10.0.0/.clang-format000066400000000000000000000000241363521741200177450ustar00rootroot00000000000000BasedOnStyle: LLVM SPIRV-LLVM-Translator-10.0.0/.clang-tidy000066400000000000000000000015561363521741200174410ustar00rootroot00000000000000Checks: '-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,-llvm-header-guard' CheckOptions: - key: readability-identifier-naming.ClassCase value: CamelCase - key: readability-identifier-naming.EnumCase value: CamelCase - key: readability-identifier-naming.FunctionCase value: camelBack - key: readability-identifier-naming.MemberCase value: CamelCase - key: readability-identifier-naming.ParameterCase value: CamelCase - key: readability-identifier-naming.UnionCase value: CamelCase - key: readability-identifier-naming.VariableCase value: CamelCase - key: llvm-namespace-comment.ShortNamespaceLines value: '25' SPIRV-LLVM-Translator-10.0.0/.gitignore000066400000000000000000000041361363521741200173720ustar00rootroot00000000000000#==============================================================================# # This file specifies intentionally untracked files that git should ignore. # See: http://www.kernel.org/pub/software/scm/git/docs/gitignore.html # # This file is intentionally different from the output of `git svn show-ignore`, # as most of those are useless. #==============================================================================# build/ #==============================================================================# # File extensions to be ignored anywhere in the tree. #==============================================================================# # Temp files created by most text editors. *~ # Merge files created by git. *.orig # Byte compiled python modules. *.pyc # vim swap files .*.swp .sw? #OS X specific files. .DS_store #==============================================================================# # Explicit files to ignore (only matches one). #==============================================================================# # Various tag programs /tags /TAGS /GPATH /GRTAGS /GSYMS /GTAGS .gitusers autom4te.cache cscope.files cscope.out autoconf/aclocal.m4 autoconf/autom4te.cache compile_commands.json #==============================================================================# # Directories to ignore (do not add trailing '/'s, they skip symlinks). #==============================================================================# # External projects that are tracked independently. projects/* !projects/CMakeLists.txt !projects/Makefile # Clang, which is tracked independently. tools/clang # LLDB, which is tracked independently. tools/lldb # lld, which is tracked independently. tools/lld # llgo, which is tracked independently. tools/llgo # Polly, which is tracked independently. tools/polly # Sphinx build tree, if building in-source dir. docs/_build #==============================================================================# # Files created in tree by the Go bindings. #==============================================================================# bindings/go/llvm/llvm_config.go bindings/go/llvm/workdir SPIRV-LLVM-Translator-10.0.0/.travis.yml000066400000000000000000000136441363521741200175170ustar00rootroot00000000000000language: cpp os: - linux # Use Ubuntu 18.04 LTS (Bionic) as the Linux testing environment. dist: bionic sudo: false git: depth: 1 branches: only: - master - /llvm_release_\d+$/ # From https://docs.travis-ci.com/user/customizing-the-build/#safelisting-or-blocklisting-branches # "Note that safelisting also prevents tagged commits from being built. # If you consistently tag your builds in the format v1.3 you can safelist them # all with regular expressions, for example /^v\d+\.\d+(\.\d+)?(-\S*)?$/." - /^v\d+\.\d+(\.\d+)?(-\S*)?$/ addons: apt: sources: - sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main' key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' - sourceline: 'deb https://packages.lunarg.com/vulkan bionic main' key_url: 'http://packages.lunarg.com/lunarg-signing-key-pub.asc' packages: - llvm-10-dev - clang-10 - clang-format-10 - clang-tidy-10 - spirv-tools compiler: - gcc - clang env: global: - MAKEFLAGS="-j2" - CHECK_FORMAT=0 - CHECK_TIDY=0 matrix: - BUILD_TYPE=Release BUILD_EXTERNAL=1 SHARED_LIBS=ON MAKE_TARGETS="" MAKE_TEST_TARGET="test" - BUILD_TYPE=Debug BUILD_EXTERNAL=1 SHARED_LIBS=ON MAKE_TARGETS="" MAKE_TEST_TARGET="test" - BUILD_TYPE=Release BUILD_EXTERNAL=0 SHARED_LIBS=ON MAKE_TARGETS="llvm-spirv" MAKE_TEST_TARGET="check-llvm-spirv" - BUILD_TYPE=Debug BUILD_EXTERNAL=0 SHARED_LIBS=ON MAKE_TARGETS="llvm-spirv" MAKE_TEST_TARGET="check-llvm-spirv" - BUILD_TYPE=Release BUILD_EXTERNAL=1 SHARED_LIBS=OFF MAKE_TARGETS="" MAKE_TEST_TARGET="test" - BUILD_TYPE=Debug BUILD_EXTERNAL=1 SHARED_LIBS=OFF MAKE_TARGETS="" MAKE_TEST_TARGET="test" - BUILD_TYPE=Release BUILD_EXTERNAL=0 SHARED_LIBS=OFF MAKE_TARGETS="llvm-spirv" MAKE_TEST_TARGET="check-llvm-spirv" - BUILD_TYPE=Debug BUILD_EXTERNAL=0 SHARED_LIBS=OFF MAKE_TARGETS="llvm-spirv" MAKE_TEST_TARGET="check-llvm-spirv" # some bug inside clang-5.0.0, works with 5.0.1 matrix: include: - os: osx env: BUILD_TYPE=Release BUILD_EXTERNAL=0 MAKE_TARGETS="llvm-spirv" MAKE_TEST_TARGET="check-llvm-spirv" osx_image: xcode9.3 - os: osx env: BUILD_TYPE=Debug BUILD_EXTERNAL=0 MAKE_TARGETS="llvm-spirv" MAKE_TEST_TARGET="check-llvm-spirv" osx_image: xcode9.3 - env: BUILD_EXTERNAL=1 CHECK_FORMAT=1 - env: BUILD_EXTERNAL=1 CHECK_TIDY=1 allow_failures: - compiler: clang - os: osx fast_finish: true script: - | if [ $BUILD_EXTERNAL == "0" ]; then mkdir llvm-spirv mv * llvm-spirv git clone https://github.com/llvm/llvm-project --depth 1 -b release/10.x mv llvm-spirv llvm-project/llvm-spirv fi - | if [ $TRAVIS_OS_NAME == "osx" ]; then wget -r --accept="*.tgz" --no-directories https://storage.googleapis.com/spirv-tools/badges/build_link_macos_clang_release.html tar -xf install.tgz sed -i '' -e 's|^prefix=\(.*\)|prefix='$PWD'/install|g' install/lib/pkgconfig/SPIRV-Tools.pc export PKG_CONFIG_PATH=$PWD/install/lib/pkgconfig fi - mkdir build && cd build - | if [ $BUILD_EXTERNAL == "1" ]; then if [ $CHECK_FORMAT != "1" ]; then cmake .. \ -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \ -DBUILD_SHARED_LIBS=${SHARED_LIBS} \ -DLLVM_BUILD_TOOLS=ON \ -DLLVM_EXTERNAL_LIT="/usr/lib/llvm-10/build/utils/lit/lit.py" \ -DLLVM_INCLUDE_TESTS=ON \ -DCMAKE_INSTALL_PREFIX=../install/ \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ -G "Unix Makefiles" fi else BUILDDIR=$(pwd) cmake ../llvm-project/llvm/ \ -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \ -DBUILD_SHARED_LIBS=${SHARED_LIBS} \ -DLLVM_BUILD_TOOLS=ON \ -DLLVM_BUILD_TESTS=ON \ -DLLVM_INCLUDE_TESTS=ON \ -DSPIRV_SKIP_CLANG_BUILD=ON \ -DSPIRV_SKIP_DEBUG_INFO_TESTS=ON \ -DLLVM_LIT_ARGS="-sv --no-progress-bar" \ -DLLVM_EXTERNAL_PROJECTS="llvm-spirv" \ -DLLVM_EXTERNAL_LLVM_SPIRV_SOURCE_DIR=${BUILDDIR}/../llvm-project/llvm-spirv \ -DLLVM_ENABLE_PROJECTS="llvm-spirv" \ -G "Unix Makefiles" ln -s /usr/lib/llvm-10/bin/clang bin/ fi - if [ $CHECK_FORMAT == "1" ]; then cd ..; ln -s /usr/share/clang/clang-format-10/clang-format-diff.py utils/; ./utils/check_code_format.sh; elif [ $CHECK_TIDY == "1" ]; then cd ..; ln -s build/compile_commands.json; ./utils/check_code_tidyness.sh; else make $MAKE_TARGETS && make $MAKE_TEST_TARGET && if [ $BUILD_EXTERNAL == "1" ]; then make install; fi fi before_deploy: # Travis CI relies on the tag name to push to the correct release. # Tag the current master top of the tree as "dev-build". # We must be very careful with "git push -f" and allow it ONLY # for the "dev-build" tag! - if [[ "${TRAVIS_BRANCH}" == "master" && -z "${TRAVIS_TAG}" ]]; then export TRAVIS_TAG=dev-build; git config --global user.name "Travis CI"; git config --global user.email "builds@travis-ci.org"; git tag -f ${TRAVIS_TAG}; git push -f https://${repo_token}@github.com/${TRAVIS_REPO_SLUG} --tags; fi # Create tarball for deployment - echo ${TRAVIS_COMMIT} > ../install/version.txt; - export TARBALL=SPIRV-LLVM-Translator-${TRAVIS_TAG}-${TRAVIS_OS_NAME}-${BUILD_TYPE}.zip; - cd ../install && find . -print | zip -@ ${TARBALL}; deploy: - provider: releases api_key: ${repo_token} on: tags: true condition: ${BUILD_EXTERNAL} == 1 && ${SHARED_LIBS} == ON && ${repo_token} file: ${TARBALL} skip_cleanup: true overwrite: false - provider: releases api_key: ${repo_token} on: tags: false branch: master condition: ${BUILD_EXTERNAL} == 1 && ${SHARED_LIBS} == ON && ${repo_token} file: ${TARBALL} name: Latest development build $(date -u +'%F %R %Z') skip_cleanup: true overwrite: true prerelease: true SPIRV-LLVM-Translator-10.0.0/CMakeLists.txt000066400000000000000000000037561363521741200201510ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.3) set(LLVM_SPIRV_VERSION 10.0.0.1) option(LLVM_SPIRV_INCLUDE_TESTS "Generate build targets for the llvm-spirv lit tests." ${LLVM_INCLUDE_TESTS}) if (NOT DEFINED LLVM_SPIRV_BUILD_EXTERNAL) # check if we build inside llvm or not if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) set(LLVM_SPIRV_BUILD_EXTERNAL YES) endif(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) endif (NOT DEFINED LLVM_SPIRV_BUILD_EXTERNAL) if(LLVM_SPIRV_BUILD_EXTERNAL) project(LLVM_SPIRV VERSION ${LLVM_SPIRV_VERSION} LANGUAGES CXX ) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) if(LLVM_SPIRV_INCLUDE_TESTS) set(LLVM_TEST_COMPONENTS llvm-as llvm-dis ) endif(LLVM_SPIRV_INCLUDE_TESTS) find_package(LLVM 10.0.0 REQUIRED COMPONENTS Analysis BitReader BitWriter Core Support TransformUtils ${LLVM_TEST_COMPONENTS} ) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${LLVM_CMAKE_DIR} ) include(AddLLVM) message(STATUS "Found LLVM: ${LLVM_VERSION}") find_program(CCACHE_EXE_FOUND ccache) if(CCACHE_EXE_FOUND) message(STATUS "Found ccache: ${CCACHE_EXE_FOUND}") set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) endif() endif() set(LLVM_SPIRV_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include) add_subdirectory(lib/SPIRV) add_subdirectory(tools/llvm-spirv) if(LLVM_SPIRV_INCLUDE_TESTS) add_subdirectory(test) endif(LLVM_SPIRV_INCLUDE_TESTS) install( FILES ${LLVM_SPIRV_INCLUDE_DIRS}/LLVMSPIRVLib.h ${LLVM_SPIRV_INCLUDE_DIRS}/LLVMSPIRVOpts.h ${LLVM_SPIRV_INCLUDE_DIRS}/LLVMSPIRVExtensions.inc DESTINATION ${CMAKE_INSTALL_PREFIX}/include/LLVMSPIRVLib ) configure_file(LLVMSPIRVLib.pc.in ${CMAKE_BINARY_DIR}/LLVMSPIRVLib.pc @ONLY) install( FILES ${CMAKE_BINARY_DIR}/LLVMSPIRVLib.pc DESTINATION ${CMAKE_INSTALL_PREFIX}/lib${LLVM_LIBDIR_SUFFIX}/pkgconfig ) SPIRV-LLVM-Translator-10.0.0/CODE_OF_CONDUCT.md000066400000000000000000000004301363521741200201720ustar00rootroot00000000000000A reminder that this issue tracker is managed by the Khronos Group. Interactions here should follow the Khronos Code of Conduct (https://www.khronos.org/developers/code-of-conduct), which prohibits aggressive or derogatory language. Please keep the discussion friendly and civil. SPIRV-LLVM-Translator-10.0.0/LICENSE.TXT000066400000000000000000000063211363521741200170630ustar00rootroot00000000000000============================================================================== LLVM Release License ============================================================================== University of Illinois/NCSA Open Source License Copyright (c) 2003-2014 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 ------- --------- Autoconf llvm/autoconf llvm/projects/ModuleMaker/autoconf 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 SPIRV-LLVM-Translator-10.0.0/LLVMSPIRVLib.pc.in000066400000000000000000000005241363521741200203550ustar00rootroot00000000000000prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} libdir=${prefix}/lib@LLVM_LIBDIR_SUFFIX@ includedir=${prefix}/include Name: LLVMSPIRVLib Description: LLVM/SPIR-V bi-directional translator Version: @LLVM_SPIRV_VERSION@ URL: https://github.com/KhronosGroup/SPIRV-LLVM-Translator Libs: -L${libdir} -lLLVMSPIRVLib Cflags: -I${includedir} SPIRV-LLVM-Translator-10.0.0/README.md000066400000000000000000000175051363521741200166650ustar00rootroot00000000000000# LLVM/SPIR-V Bi-Directional Translator [![Build Status](https://travis-ci.org/KhronosGroup/SPIRV-LLVM-Translator.svg?branch=llvm_release_100)](https://travis-ci.org/KhronosGroup/SPIRV-LLVM-Translator) This repository contains source code for the LLVM/SPIR-V Bi-Directional Translator, a library and tool for translation between LLVM IR and [SPIR-V](https://www.khronos.org/registry/spir-v/). The LLVM/SPIR-V Bi-Directional Translator is open source software. You may freely distribute it under the terms of the license agreement found in LICENSE.txt. ## Directory Structure The files/directories related to the translator: * [include/LLVMSPIRVLib.h](include/LLVMSPIRVLib.h) - header file * [lib/SPIRV](lib/SPIRV) - library for SPIR-V in-memory representation, decoder/encoder and LLVM/SPIR-V translator * [tools/llvm-spirv](tools/llvm-spirv) - command line utility for translating between LLVM bitcode and SPIR-V binary ## Build Instructions The `master` branch of this repo is aimed to be buildable with the latest LLVM `master` or `trunk` revision. ### Build with pre-installed LLVM The translator can be built with the latest(nightly) package of LLVM. For Ubuntu and Debian systems LLVM provides repositories with nightly builds at http://apt.llvm.org/. For example the latest package for Ubuntu 16.04 can be installed with the following commands: ``` sudo add-apt-repository "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial main" sudo apt-get update sudo apt-get install llvm-10-dev llvm-10-tools clang-10 libclang-10-dev ``` The installed version of LLVM will be used by default for out-of-tree build of the translator. ``` git clone https://github.com/KhronosGroup/SPIRV-LLVM-Translator.git mkdir SPIRV-LLVM-Translator/build && cd SPIRV-LLVM-Translator/build cmake .. make llvm-spirv -j`nproc` ``` ### Build with pre-built LLVM If you have a custom build (based on the latest version) of LLVM libraries you can link the translator against it. ``` git clone https://github.com/KhronosGroup/SPIRV-LLVM-Translator.git mkdir SPIRV-LLVM-Translator/build && cd SPIRV-LLVM-Translator/build cmake .. -DLLVM_DIR=/lib/cmake/llvm/ make llvm-spirv -j`nproc` ``` If the translator is used as part of another CMake project, you will need to define `LLVM_SPIRV_BUILD_EXTERNAL`: ``` cmake .. -DLLVM_DIR=/lib/cmake/llvm/ -DLLVM_SPIRV_BUILD_EXTERNAL=YES ``` Where `llvm_build_dir` is the LLVM build directory. ### LLVM in-tree build The translator can be built as a regular LLVM subproject. To do that you need to clone it into the `llvm/projects` or `llvm/tools` directory. ``` git clone https://github.com/llvm/llvm-project.git cd llvm-project/llvm/projects git clone https://github.com/KhronosGroup/SPIRV-LLVM-Translator.git ``` Run (or re-run) cmake as usual for LLVM. After that you should have `llvm-spirv` and `check-llvm-spirv` targets available. ``` mkdir llvm-project/build && cd llvm-project/build cmake ../llvm make llvm-spirv -j`nproc` ``` ## Test instructions All tests related to the translator are placed in the [test](test) directory. A number of the tests require spirv-as (part of SPIR-V Tools) to run, but the remainder of the tests can still be run without this. Optionally the tests can make use of spirv-val (part of SPIRV-Tools) in order to validate the generated SPIR-V against the official SPIR-V specification. In case tests are failing due to SPIRV-Tools not supporting certain SPIR-V features, please get an updated package. The `PKG_CONFIG_PATH` environmental variable can be used to let cmake point to a custom installation. Execute the following command inside the build directory to run translator tests: ``` make test ``` This requires that the `-DLLVM_INCLUDE_TESTS=ON` and `-DLLVM_EXTERNAL_LIT="/usr/lib/llvm-10/build/utils/lit/lit.py"` arguments were passed to CMake during the build step. The translator test suite can be disabled by passing `-DLLVM_SPIRV_INCLUDE_TESTS=OFF` to cmake. ## Run Instructions for `llvm-spirv` To translate between LLVM IR and SPIR-V: 1. Execute the following command to translate `input.bc` to `input.spv` ``` llvm-spirv input.bc ``` 2. Execute the following command to translate `input.spv` to `input.bc` ``` llvm-spirv -r input.spv ``` Recommended options: * `-spirv-ocl-builtins-version` - to specify target version of OpenCL builtins to translate to (default CL1.2) 3. Other options accepted by `llvm-spirv` * `-o file_name` - to specify output name * `-spirv-debug` - output debugging information * `-spirv-text` - read/write SPIR-V in an internal textual format for debugging purpose. The textual format is not defined by SPIR-V spec. * `-help` - to see full list of options Translation from LLVM IR to SPIR-V and then back to LLVM IR is not guaranteed to produce the original LLVM IR. In particular, LLVM intrinsic call instructions may get replaced by function calls to OpenCL builtins and metadata may be dropped. ### Handling SPIR-V versions generated by the translator There is one option to control the behavior of the translator with respect to the version of the SPIR-V file which is being generated/consumed. * `-spirv-max-version=` - this option allows restricting the SPIRV-LLVM-Translator **not** to generate a SPIR-V with a version which is higher than the one specified via this option. If the `-r` option was also specified, the SPIRV-LLVM-Translator will reject the input file and emit an error if the SPIR-V version in it is higher than one specified via this option. Allowed values are `1.0`/`1.1`. More information can be found in [SPIR-V versions and extensions handling](docs/SPIRVVersionsAndExtensionsHandling.rst) ### Handling SPIR-V extensions generated by the translator By default, during SPIR-V generation, the translator doesn't use any extensions. However, during SPIR-V consumption, the translator accepts input files that use any known extensions. If certain extensions are required to be enabled or disabled, the following command line option can be used: * ``--spirv-ext=`` - this options allows controlling which extensions are allowed/disallowed Valid value for this option is comma-separated list of extension names prefixed with ``+`` or ``-`` - plus means allow to use extension, minus means disallow to use extension. There is one more special value which can be used as extension name in this option: ``all`` - it affects all extension which are known to the translator. If ``--spirv-ext`` contains the name of an extension which is not known for the translator, it will emit an error. More information can be found in [SPIR-V versions and extensions handling](docs/SPIRVVersionsAndExtensionsHandling.rst) ## Branching strategy Code on the master branch in this repository is intended to be compatible with master/trunk branch of the [llvm](https://github.com/llvm-mirror/llvm) project. That is, for an OpenCL kernel compiled to llvm bitcode by the latest version(built with the latest git commit or svn revision) of Clang it should be possible to translate it to SPIR-V with the llvm-spirv tool. All new development should be done on the master branch. To have versions compatible with released versions of LLVM and Clang, corresponding branches are available in this repository. For example, to build the translator with LLVM 7.0 ([release_70](https://github.com/llvm-mirror/llvm/tree/release_70)) one should use the [llvm_release_70](https://github.com/KhronosGroup/SPIRV-LLVM-Translator/tree/llvm_release_70) branch. As a general rule, commits from the master branch may be backported to the release branches as long as they do not depend on features from a later LLVM/Clang release and there are no objections from the maintainer(s). There is no guarantee that older release branches are proactively kept up to date with master, but you can request certain commits on older release branches by creating a pull request or raising an issue on GitHub. SPIRV-LLVM-Translator-10.0.0/docs/000077500000000000000000000000001363521741200163265ustar00rootroot00000000000000SPIRV-LLVM-Translator-10.0.0/docs/SPIRVRepresentationInLLVM.rst000066400000000000000000000214671363521741200237020ustar00rootroot00000000000000================================ SPIR-V representation in LLVM IR ================================ .. contents:: :local: Overview ======== As one of the goals of SPIR-V is to `"map easily to other IRs, including LLVM IR" `_, most of SPIR-V entities (global variables, constants, types, functions, basic blocks, instructions) have straightforward counterparts in LLVM. Therefore the focus of this document is those entities in SPIR-V which do not map to LLVM in an obvious way. These include: * SPIR-V types mapped to LLVM types * SPIR-V instructions mapped to LLVM function calls * SPIR-V extended instructions mapped to LLVM function calls * SPIR-V builtins variables mapped to LLVM global variables * SPIR-V instructions mapped to LLVM metadata * SPIR-V types mapped to LLVM opaque types * SPIR-V decorations mapped to LLVM metadata or named attributes SPIR-V Types Mapped to LLVM Types ================================= Limited to this section, we define the following common postfix. * {Access} - Postifix indicating the access qualifier. {Access} take integer literal values which are defined by the SPIR-V spec. OpTypeImage ----------- OpTypeImage is mapped to LLVM opaque type spirv.Image._{SampledType}_{Dim}_{Depth}_{Arrayed}_{MS}_{Sampled}_{Format}_{Access} and mangled as __spirv_Image__{SampledType}_{Dim}_{Depth}_{Arrayed}_{MS}_{Sampled}_{Format}_{Access}, where * {SampledType}={float|half|int|uint|void} - Postfix indicating the sampled data type - void for unknown sampled data type * {Dim} - Postfix indicating the dimension of the image * {Depth} - Postfix indicating whether the image is a depth image * {Arrayed} - Postfix indicating whether the image is arrayed image * {MS} - Postfix indicating whether the image is multi-sampled * {Sampled} - Postfix indicating whether the image is associated with sampler * {Format} - Postfix indicating the image format Postfixes {Dim}, {Depth}, {Arrayed}, {MS}, {Sampled} and {Format} take integer literal values which are defined by the SPIR-V spec. OpTypeSampledImage ------------------ OpTypeSampledImage is mapped to LLVM opaque type spirv.SampledImage._{Postfixes} and mangled as __spirv_SampledImage__{Postfixes}, where {Postfixes} are the same as the postfixes of the original image type, as defined above in this section. OpTypePipe ---------- OpTypePipe is mapped to LLVM opaque type spirv.Pipe._{Access} and mangled as __spirv_Pipe__{Access}. Other SPIR-V Types ------------------ * OpTypeEvent * OpTypeDeviceEvent * OpTypeReserveId * OpTypeQueue * OpTypeSampler * OpTypePipeStorage (SPIR-V 1.1) The above SPIR-V types are mapped to LLVM opaque type spirv.{TypeName} and mangled as __spirv_{TypeName}, where {TypeName} is the name of the SPIR-V type with "OpType" removed, e.g., OpTypeEvent is mapped to spirv.Event and mangled as __spirv_Event. SPIR-V Instructions Mapped to LLVM Function Calls ================================================= Some SPIR-V instructions which can be included in basic blocks do not have corresponding LLVM instructions or intrinsics. These SPIR-V instructions are represented by function calls in LLVM. The function corresponding to a SPIR-V instruction is termed SPIR-V builtin function and its name is `IA64 mangled `_ with extensions for SPIR-V specific types. The unmangled name of a SPIR-V builtin function follows the convention .. code-block:: c __spirv_{OpCodeName}{_OptionalPostfixes} where {OpCodeName} is the op code name of the SPIR-V instructions without the "Op" prefix, e.g. EnqueueKernel. {OptionalPostfixes} are optional postfixes to specify decorations for the SPIR-V instruction. The SPIR-V op code name and each postfix does not contain "_". SPIR-V builtin functions accepts all argument types accepted by the corresponding SPIR-V instructions. The literal operands of extended instruction are mapped to function call arguments with type i32. Optional Postfixes for SPIR-V Builtin Function Names ---------------------------------------------------- SPIR-V builtin functions corresponding to the following SPIR-V instructions are postfixed following the order specified as below: * Instructions having identical argument types but different return types are postfixed with "_R{ReturnType}" where - {ReturnType} = {ScalarType}|{VectorType} - {ScalarType} = char|uchar|short|ushort|int|uint|long|ulong|half|float|double|bool - {VectorType} = {ScalarType}{2|3|4|8|16} * Instructions with saturation decoration are postfixed with "_sat" * Instructions with floating point rounding mode decoration are postfixed with "_rtp|_rtn|_rtz|_rte" SPIR-V Builtin Conversion Function Names ---------------------------------------- The unmangled names of SPIR-V builtin conversion functions follow the convention: .. code-block:: c __spirv_{ConversionOpCodeName}_R{ReturnType}{_sat}{_rtp|_rtn|_rtz|_rte} where * {ConversionOpCodeName} = ConvertFToU|ConvertFToS|ConvertUToF|ConvertUToS|UConvert|SConvert|FConvert|SatConvertSToU|SatConvertUToS SPIR-V Builtin Reinterpret / Bitcast Function Names --------------------------------------------------- The unmangled names of SPIR-V builtin reinterpret / bitcast functions follow the convention: .. code-block:: c __spirv_{BitcastOpCodeName}_R{ReturnType} SPIR-V Builtin ImageSample Function Names ---------------------------------------- The unmangled names of SPIR-V builtin ImageSample functions follow the convention: .. code-block:: c __spirv_{ImageSampleOpCodeName}_R{ReturnType} SPIR-V Builtin GenericCastToPtr Function Name ---------------------------------------- The unmangled names of SPIR-V builtin GenericCastToPtrExplicit function follow the convention: .. code-block:: c __spirv_GenericCastToPtrExplicit_To{Global|Local|Private} SPIR-V 1.1 Builtin CreatePipeFromPipeStorage Function Name ---------------------------------------- The unmangled names of SPIR-V builtin CreatePipeFromPipeStorage function follow the convention: .. code-block:: c __spirv_CreatePipeFromPipeStorage_{read|write} SPIR-V Extended Instructions Mapped to LLVM Function Calls ========================================================== SPIR-V extended instructions are mapped to LLVM function calls. The function name is IA64 mangled and the unmangled name has the format .. code-block:: c __spirv_{ExtendedInstructionSetName}_{ExtendedInstrutionName}{__OptionalPostfixes} where {ExtendedInstructionSetName} for OpenCL is "ocl". The translated functions accepts all argument types accepted by the corresponding SPIR-V instructions. The literal operands of extended instruction are mapped to function call arguments with type i32. The optional postfixes take the same format as SPIR-V builtin functions. The first postfix starts with two underscores to facilitate identification since extended instruction name may contain underscore. The remaining postfixes start with one underscore. OpenCL Extended Builtin Vector Load Function Names ---------------------------------------- The unmangled names of OpenCL extended vector load functions follow the convention: .. code-block:: c __spirv_ocl_{VectorLoadOpCodeName}__R{ReturnType} where * {VectorLoadOpCodeName} = vloadn|vload_half|vload_halfn|vloada_halfn SPIR-V Builtins Variables Mapped to LLVM Global Variables ========================================================= SPIR-V builtin variables are mapped to LLVM global variables with unmangled name __spirv_BuiltIn{Name}. SPIR-V instructions mapped to LLVM metadata =========================================== SPIR-V specification allows multiple module scope instructions, whereas LLVM named metadata must be unique, so encoding of such instructions has the following format: .. code-block:: llvm !spirv. = !{!, , ..} ! = !{, , ..} ! = !{, , ..} For example: .. code-block:: llvm !spirv.Source = !{!0} !spirv.SourceExtension = !{!2, !3} !spirv.Extension = !{!2} !spirv.Capability = !{!4} !spirv.MemoryModel = !{!5} !spirv.EntryPoint = !{!6 ,!7} !spirv.ExecutionMode = !{!8, !9} !spirv.Generator = !{!10 } ; 3 - OpenCL_C, 102000 - OpenCL version 1.2, !1 - optional file id. !0 = !{i32 3, i32 102000, !1} !1 = !{!"/tmp/opencl/program.cl"} !2 = !{!"cl_khr_fp16"} !3 = !{!"cl_khr_gl_sharing"} !4 = !{i32 10} ; Float64 - program uses doubles !5 = !{i32 1, i32 2} ; 1 - 32-bit addressing model, 2 - OpenCL memory model !6 = !{i32 6, TBD, !"kernel1", TBD} !7 = !{i32 6, TBD, !"kernel2", TBD} !8 = !{!6, i32 18, i32 16, i32 1, i32 1} ; local size hint <16, 1, 1> for 'kernel1' !9 = !{!7, i32 32} ; independent forward progress is required for 'kernel2' !10 = !{i16 6, i16 123} ; 6 - Generator Id, 123 - Generator Version SPIRV-LLVM-Translator-10.0.0/docs/SPIRVVersionsAndExtensionsHandling.rst000066400000000000000000000226351363521741200256740ustar00rootroot00000000000000======================================= SPIR-V versions and extensions handling ======================================= .. contents:: :local: Overview ======== This document describes how the translator makes decisions about using instructions from different version of the SPIR-V core and extension specifications. Being able to control the resulting SPIR-V version is important: the target consumer might be quite old, without support for new SPIR-V versions and there must be the possibility to control which version of the SPIR-V specification that will be used during translation. SPIR-V extensions is another thing which must be controllable. Extensions can update and re-define semantics and validation rules for existing SPIR-V entries and it is important to ensure that the translator is able to generate valid SPIR-V according to the core spec, without uses of any extensions if such SPIR-V was requested by user. For example, without such infrastructure it is impossible to disable use of ``SPV_KHR_no_integer_wrap_decoration`` - it will be always generated if corresponding LLVM IR counterparts are encountered in input module. It is worth mentioning that SPIR-V versions and extensions the handling of SPIR-V versions and extension is mostly important for the SPIR-V generation step. On the consumer side it is the responsibility of the consumer to analyze the incoming SPIR-V file and reject it if it contains something that is not supported by the consumer. However, translator simplifies this step for downstream users by checking version and extensions in SPIR-V module during ``readSpirv``/``readSpirvModule`` phases. SPIR-V Versions =============== SPIR-V Generation step ---------------------- By default translator selects version of generated SPIR-V file based on features used in this file. For example, if it contains ``dereferencable`` LLVM IR attribute, ``MaxByteOffset`` decoration will be generated and resulting SPIR-V version will be raised to 1.1. .. note:: There is no documentation about which exact features from newest SPIR-V spec versions will be used by the translator. If you are interested when or why a particular SPIR-V instruction is generated, please check this in the source code. Consider this as an implementation detail and if you disagree with something, you can always open an issue or submit pull request - contributions are welcome! There is one option to control the behavior of the translator with respect to the version of the SPIR-V file which is being generated/consumed. * ``--spirv-max-version=`` - instructs the translator to generate SPIR-V file corresponding to any spec version which is less than or equal to the specified one. Behavior of the translator is the same as by default with only one exception: resulting SPIR-V version cannot be raised higher than specified by this option. Allowed values are ``1.0`` and ``1.1``. .. warning:: These two options are mutually exclusive and cannot be specified at the same time. If the translator encounters something that cannot be represented by set of allowed SPIR-V versions (which might contain only one version), it does one of the following things: * ignores LLVM IR entity in the input file. For example, ``dereferencable`` LLVM IR attribute can be ignored if it is not allowed to generate SPIR-V 1.1 and higher. * tries to represent LLVM IR entity with allowed instructions. For example, ``OpPtrEqual`` can be used if SPIR-V 1.4 is not allowed and can be emulated via ``OpConvertPtrToU`` + ``OpIEqual`` sequence. * emits error if LLVM IR entity cannot be ignored and cannot be emulated using available instructions. For example, if global constructors/destructors (represented by @llvm.global_ctors/@llvm.global_dtors) are present in a module then the translator should emit error if it cannot use SPIR-V 1.1 and higher where ``Initializer`` and ``Finalizer`` execution modes are described. SPIR-V Consumption step ----------------------- By default, translator consumes SPIR-V of any version which is supported. This behavior, however, can be controlled via the same switches described in the previous section. If one of the switches present and translator encountered SPIR-V file corresponding to a spec version which is not included into set of allowed SPIR-V versions, translator emits error. SPIR-V Extensions ================= SPIR-V Generation step ---------------------- By default, translator doesn't use any extensions. If it required to enable certain extension, the following command line option can be used: * ``--spirv-ext=`` - allows to control list of allowed/disallowed extensions. Valid value for this option is comma-separated list of extension names prefixed with ``+`` or ``-`` - plus means allow to use extension, minus means disallow to use extension. There is one more special value which can be used as extension name in this option: ``all`` - it affects all extension which are known to the translator. If ``--spirv-ext`` contains name of extension which is not know for the translator, it will emit error. Examples: * ``--spirv-ext=+SPV_KHR_no_integer_wrap_decoration,+SPV_INTEL_subgroups`` * ``--spirv-ext=+all,-SPV_INTEL_fpga_loop_controls`` .. warning:: Extension name cannot be allowed and disallowed at the same time: for inputs like ``--spirv-ext=+SPV_INTEL_subgroups,-SPV_INTEL_subgroups`` translator will emit error about invalid arguments. .. note:: Since by default during SPIR-V generation all extensions are disabled, this means that ``-all,`` is implicitly added at the beggining of the ``-spirv-ext`` value. If the translator encounters something that cannot be represented by set of allowed SPIR-V extensions (which might be empty), it does one of the following things: * ignores LLVM IR entity in the input file. For example, ``nsw``/``nuw`` LLVM IR attributes can be ignored if it is not allowed to generate SPIR-V 1.4 and ``SPV_KHR_no_integer_wrap_decoration`` extension is disallowed. * tries to represent LLVM IR entity with allowed instructions. Translator could translate calls to a new built-in functions defined by some extensions as usual call instructions without using special SPIR-V instructions. However, this could result in a strange SPIR-V and most likely will lead to errors during consumption. Having that, translator should emit errors if it encounters a call to a built-in function from an extension which must be represented as a special SPIR-V instruction from extension which wasn't allowed to be used. I.e. if translator knows that this certain LLVM IR entity belongs to an extension functionality and this extension is disallowed, it should emit error rather than emulating it. * emits error if LLVM IR entity cannot be ignored and cannot be emulated using available instructions. For example, new built-in types defined by ``cl_intel_device_side_avc_motion_estimation`` cannot be represented in SPIR-V if ``SPV_INTEL_device_side_avc_motion_estimation`` is disallowed. SPIR-V Consumption step ----------------------- By default, translator consumes SPIR-V regardless of list extensions which are used by the input file, i.e. all extensions are allowed by default during consumption step. .. note:: This is opposite to the generation step and this is done on purpose: to not broke workflows of existing users of the translator. .. note:: Since by default during SPIR-V consumption all extensions are enabled, this means that ``+all,`` is implicitly added at the beggining of the ``-spirv-ext`` value. This behavior, however, can be controlled via the same switches described in the previous section. If ``--spirv-ext`` switch presents, translator will emit error if it finds out that input SPIR-V file uses disallowed extension. .. note:: If the translator encounters unknown extension in the input SPIR-V file, it will emit error regardless of ``-spirv-ext`` option value. If one of the switches present and translator encountered SPIR-V file corresponding to a spec version which is not included into set of allowed SPIR-V versions, translator emits error. How to control translator behavior when using it as library =========================================================== When using translator as library it can be controlled via bunch of alternative APIs that have additional argument: ``TranslatorOpts`` object which encapsulates information about available SPIR-V versions and extensions. List of new APIs is: ``readSpirvModule``, ``writeSpirv`` and ``readSpirv``. .. note:: See ``LLVMSPIRVOpts.h`` for more details. How to get ``TranslatorOpts`` object ------------------------------------ 1. Default constructor. Equal to: ``--spirv-max-version=MaxKnownVersion --spirv-ext=-all`` .. note:: There is method ``TranslatorOpts::enableAllExtensions()`` that allows you to quickly enable all known extensions if it is needed. 2. Constructor which accepts all parameters Consumes both max SPIR-V version and optional map with extensions status (i.e. which one is allowed and which one is disallowed) Extensions status map ^^^^^^^^^^^^^^^^^^^^^ This map is defined as ``std::map`` and it is intended to show which extension is allowed to be used (``true`` as value) and which is not (``false`` as value). .. note:: If certain ``ExtensionID`` value is missed in the map, it automatically means that extension is not allowed to be used. This implies that by default, all extensions are disallowed. SPIRV-LLVM-Translator-10.0.0/include/000077500000000000000000000000001363521741200170215ustar00rootroot00000000000000SPIRV-LLVM-Translator-10.0.0/include/LLVMSPIRVExtensions.inc000066400000000000000000000007231363521741200231740ustar00rootroot00000000000000 #ifndef EXT #error "EXT macro must be defined" #endif EXT(SPV_KHR_no_integer_wrap_decoration) EXT(SPV_INTEL_subgroups) EXT(SPV_INTEL_media_block_io) EXT(SPV_INTEL_device_side_avc_motion_estimation) EXT(SPV_INTEL_fpga_loop_controls) EXT(SPV_INTEL_fpga_memory_attributes) EXT(SPV_INTEL_unstructured_loop_controls) EXT(SPV_INTEL_fpga_reg) EXT(SPV_INTEL_blocking_pipes) EXT(SPV_INTEL_function_pointers) EXT(SPV_INTEL_kernel_attributes) EXT(SPV_INTEL_inline_assembly) SPIRV-LLVM-Translator-10.0.0/include/LLVMSPIRVLib.h000066400000000000000000000173561363521741200212330ustar00rootroot00000000000000//===- LLVMSPIRVLib.h - Read and write SPIR-V binary ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file LLVMSPIRVLib.h /// /// This files declares functions and passes for translating between LLVM and /// SPIR-V. /// /// //===----------------------------------------------------------------------===// #ifndef SPIRV_H #define SPIRV_H #include "LLVMSPIRVOpts.h" #include #include namespace llvm { // Pass initialization functions need to be declared before inclusion of // PassSupport.h. class PassRegistry; void initializeLLVMToSPIRVPass(PassRegistry &); void initializeOCL20ToSPIRVPass(PassRegistry &); void initializeOCL21ToSPIRVPass(PassRegistry &); void initializeOCLTypeToSPIRVPass(PassRegistry &); void initializeSPIRVLowerBoolPass(PassRegistry &); void initializeSPIRVLowerConstExprPass(PassRegistry &); void initializeSPIRVLowerSPIRBlocksPass(PassRegistry &); void initializeSPIRVLowerOCLBlocksPass(PassRegistry &); void initializeSPIRVLowerMemmovePass(PassRegistry &); void initializeSPIRVRegularizeLLVMPass(PassRegistry &); void initializeSPIRVToOCL12Pass(PassRegistry &); void initializeSPIRVToOCL20Pass(PassRegistry &); void initializePreprocessMetadataPass(PassRegistry &); class ModulePass; } // namespace llvm #include "llvm/IR/Module.h" namespace SPIRV { class SPIRVModule; /// \brief Check if a string contains SPIR-V binary. bool isSpirvBinary(std::string &Img); #ifdef _SPIRV_SUPPORT_TEXT_FMT /// \brief Convert SPIR-V between binary and internal textual formats. /// This function is not thread safe and should not be used in multi-thread /// applications unless guarded by a critical section. /// \returns true if succeeds. bool convertSpirv(std::istream &IS, std::ostream &OS, std::string &ErrMsg, bool FromText, bool ToText); /// \brief Convert SPIR-V between binary and internal text formats. /// This function is not thread safe and should not be used in multi-thread /// applications unless guarded by a critical section. bool convertSpirv(std::string &Input, std::string &Out, std::string &ErrMsg, bool ToText); /// \brief Check if a string contains SPIR-V in internal text format. bool isSpirvText(std::string &Img); #endif /// \brief Load SPIR-V from istream as a SPIRVModule. /// \returns null on failure. std::unique_ptr readSpirvModule(std::istream &IS, std::string &ErrMsg); /// \brief Load SPIR-V from istream as a SPIRVModule. /// \returns null on failure. std::unique_ptr readSpirvModule(std::istream &IS, const SPIRV::TranslatorOpts &Opts, std::string &ErrMsg); } // End namespace SPIRV namespace llvm { /// \brief Translate LLVM module to SPIR-V and write to ostream. /// \returns true if succeeds. bool writeSpirv(Module *M, std::ostream &OS, std::string &ErrMsg); /// \brief Load SPIR-V from istream and translate to LLVM module. /// \returns true if succeeds. bool readSpirv(LLVMContext &C, std::istream &IS, Module *&M, std::string &ErrMsg); /// \brief Translate LLVM module to SPIR-V and write to ostream. /// \returns true if succeeds. bool writeSpirv(Module *M, const SPIRV::TranslatorOpts &Opts, std::ostream &OS, std::string &ErrMsg); /// \brief Load SPIR-V from istream and translate to LLVM module. /// \returns true if succeeds. bool readSpirv(LLVMContext &C, const SPIRV::TranslatorOpts &Opts, std::istream &IS, Module *&M, std::string &ErrMsg); using SpecConstInfoTy = std::pair; void getSpecConstInfo(std::istream &IS, std::vector &SpecConstInfo); /// \brief Convert a SPIRVModule into LLVM IR. /// \returns null on failure. std::unique_ptr convertSpirvToLLVM(LLVMContext &C, SPIRV::SPIRVModule &BM, std::string &ErrMsg); /// \brief Regularize LLVM module by removing entities not representable by /// SPIRV. bool regularizeLlvmForSpirv(Module *M, std::string &ErrMsg); /// \brief Mangle OpenCL builtin function function name. void mangleOpenClBuiltin(const std::string &UnmangledName, ArrayRef ArgTypes, std::string &MangledName); /// Create a pass for translating LLVM to SPIR-V. ModulePass *createLLVMToSPIRV(SPIRV::SPIRVModule *); /// Create a pass for translating OCL 2.0 builtin functions to SPIR-V builtin /// functions. ModulePass *createOCL20ToSPIRV(); /// Create a pass for translating OCL 2.1 builtin functions to SPIR-V builtin /// functions. ModulePass *createOCL21ToSPIRV(); /// Create a pass for adapting OCL types for SPIRV. ModulePass *createOCLTypeToSPIRV(); /// Create a pass for lowering cast instructions of i1 type. ModulePass *createSPIRVLowerBool(); /// Create a pass for lowering constant expressions to instructions. ModulePass *createSPIRVLowerConstExpr(); /// Create a pass for lowering SPIR 2.0 blocks to functions calls. ModulePass *createSPIRVLowerSPIRBlocks(); /// Create a pass for removing function pointers related to OCL 2.0 blocks ModulePass *createSPIRVLowerOCLBlocks(); /// Create a pass for lowering llvm.memmove to llvm.memcpys with a temporary /// variable. ModulePass *createSPIRVLowerMemmove(); /// Create a pass for regularize LLVM module to be translated to SPIR-V. ModulePass *createSPIRVRegularizeLLVM(); /// Create a pass for translating SPIR-V builtin functions to OCL builtin /// functions. ModulePass *createSPIRVToOCL(Module &M); /// Create a pass for translating SPIR-V builtin functions to OCL 1.2 builtin /// functions. ModulePass *createSPIRVToOCL12(); /// Create a pass for translating SPIR-V builtin functions to OCL 2.0 builtin /// functions. ModulePass *createSPIRVToOCL20(); /// Create a pass for translating SPIR 1.2/2.0 metadata to SPIR-V friendly /// metadata. ModulePass *createPreprocessMetadata(); /// Create and return a pass that writes the module to the specified /// ostream. ModulePass *createSPIRVWriterPass(std::ostream &Str); } // namespace llvm #endif // SPIRV_H SPIRV-LLVM-Translator-10.0.0/include/LLVMSPIRVOpts.h000066400000000000000000000105071363521741200214410ustar00rootroot00000000000000//===- LLVMSPIRVOpts.h - Specify options for translation --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2019 Intel Corporation. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file LLVMSPIRVOpts.h /// /// This files declares helper classes to handle SPIR-V versions and extensions. /// //===----------------------------------------------------------------------===// #ifndef SPIRV_LLVMSPIRVOPTS_H #define SPIRV_LLVMSPIRVOPTS_H #include #include #include #include namespace SPIRV { enum class VersionNumber : uint32_t { // See section 2.3 of SPIR-V spec: Physical Layout of a SPIR_V Module and // Instruction SPIRV_1_0 = 0x00010000, SPIRV_1_1 = 0x00010100, // TODO: populate this enum with the latest versions (up to 1.4) once // translator get support of correponding features MinimumVersion = SPIRV_1_0, MaximumVersion = SPIRV_1_1 }; enum class ExtensionID : uint32_t { First, #define EXT(X) X, #include "LLVMSPIRVExtensions.inc" #undef EXT Last, }; /// \brief Helper class to manage SPIR-V translation class TranslatorOpts { public: using ExtensionsStatusMap = std::map; TranslatorOpts() = default; TranslatorOpts(VersionNumber Max, const ExtensionsStatusMap &Map = {}, bool ArgNameMD = false) : MaxVersion(Max), ExtStatusMap(Map), GenKernelArgNameMD(ArgNameMD) {} bool isAllowedToUseVersion(VersionNumber RequestedVersion) const { return RequestedVersion <= MaxVersion; } bool isAllowedToUseExtension(ExtensionID Extension) const { auto I = ExtStatusMap.find(Extension); if (ExtStatusMap.end() == I) return false; return I->second; } VersionNumber getMaxVersion() const { return MaxVersion; } bool isGenArgNameMDEnabled() const { return GenKernelArgNameMD; } void enableAllExtensions() { #define EXT(X) ExtStatusMap[ExtensionID::X] = true; #include "LLVMSPIRVExtensions.inc" #undef EXT } void enableGenArgNameMD() { GenKernelArgNameMD = true; } void setSpecConst(uint32_t SpecId, uint64_t SpecValue) { ExternalSpecialization[SpecId] = SpecValue; } bool getSpecializationConstant(uint32_t SpecId, uint64_t &Value) const { auto It = ExternalSpecialization.find(SpecId); if (It == ExternalSpecialization.end()) return false; Value = It->second; return true; } private: // Common translation options VersionNumber MaxVersion = VersionNumber::MaximumVersion; ExtensionsStatusMap ExtStatusMap; // SPIR-V to LLVM translation options bool GenKernelArgNameMD; std::unordered_map ExternalSpecialization; }; } // namespace SPIRV #endif // SPIRV_LLVMSPIRVOPTS_H SPIRV-LLVM-Translator-10.0.0/lib/000077500000000000000000000000001363521741200161445ustar00rootroot00000000000000SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/000077500000000000000000000000001363521741200170475ustar00rootroot00000000000000SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/CMakeLists.txt000066400000000000000000000022401363521741200216050ustar00rootroot00000000000000add_llvm_library(LLVMSPIRVLib LLVMToSPIRVDbgTran.cpp Mangler/FunctionDescriptor.cpp Mangler/Mangler.cpp Mangler/ManglingUtils.cpp Mangler/ParameterType.cpp OCL20ToSPIRV.cpp OCL21ToSPIRV.cpp OCLTypeToSPIRV.cpp OCLUtil.cpp SPIRVLowerBool.cpp SPIRVLowerConstExpr.cpp SPIRVLowerMemmove.cpp SPIRVLowerOCLBlocks.cpp SPIRVLowerSPIRBlocks.cpp SPIRVReader.cpp SPIRVRegularizeLLVM.cpp SPIRVToLLVMDbgTran.cpp SPIRVToOCL.cpp SPIRVToOCL12.cpp SPIRVToOCL20.cpp SPIRVUtil.cpp SPIRVWriter.cpp SPIRVWriterPass.cpp PreprocessMetadata.cpp libSPIRV/SPIRVBasicBlock.cpp libSPIRV/SPIRVDebug.cpp libSPIRV/SPIRVDecorate.cpp libSPIRV/SPIRVEntry.cpp libSPIRV/SPIRVFunction.cpp libSPIRV/SPIRVInstruction.cpp libSPIRV/SPIRVModule.cpp libSPIRV/SPIRVStream.cpp libSPIRV/SPIRVType.cpp libSPIRV/SPIRVValue.cpp LINK_COMPONENTS Analysis BitWriter Core Support TransformUtils DEPENDS intrinsics_gen ) target_include_directories(LLVMSPIRVLib PRIVATE ${LLVM_INCLUDE_DIRS} ${LLVM_SPIRV_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/libSPIRV ${CMAKE_CURRENT_SOURCE_DIR}/Mangler ) SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/LLVMBuild.txt000066400000000000000000000013161363521741200213430ustar00rootroot00000000000000;===- ./lib/Target/SPIRV/Common/LLVMBuild.txt ------------------*- Conf -*--===; ; ; The LLVM Compiler Infrastructure ; ; This file is distributed under the University of Illinois Open Source ; License. See LICENSE.TXT for details. ; ;===------------------------------------------------------------------------===; ; ; This is an LLVMBuild description file for the components in this subdirectory. ; ; For more information on the LLVMBuild system, please see: ; ; http://llvm.org/docs/LLVMBuild.html ; ;===------------------------------------------------------------------------===; [component_0] type = Library name = SPIRVLib parent = Libraries required_libraries = Core Support Analysis IPO SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/LLVMToSPIRVDbgTran.cpp000066400000000000000000001145251363521741200227260ustar00rootroot00000000000000//===- LLVMToSPIRVDbgTran.cpp - Converts debug info to SPIR-V ---*- C++ -*-===// // // The LLVM/SPIR-V Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2018 Intel Corporation. All rights reserved. // // 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 Intel Corporation, 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. // //===----------------------------------------------------------------------===// // // This file implements translation of debug info from LLVM metadata to SPIR-V // //===----------------------------------------------------------------------===// #include "LLVMToSPIRVDbgTran.h" #include "SPIRVWriter.h" #include "llvm/IR/DebugInfo.h" using namespace SPIRV; // Public interface /// This function is looking for debug information in the LLVM module /// and translates it to SPIRV void LLVMToSPIRVDbgTran::transDebugMetadata() { DIF.processModule(*M); if (DIF.compile_unit_count() == 0) return; DICompileUnit *CU = *DIF.compile_units().begin(); transDbgEntry(CU); for (DIImportedEntity *IE : CU->getImportedEntities()) transDbgEntry(IE); for (const DIType *T : DIF.types()) transDbgEntry(T); for (const DIScope *S : DIF.scopes()) transDbgEntry(S); for (const DIGlobalVariableExpression *G : DIF.global_variables()) { transDbgEntry(G->getVariable()); } for (const DISubprogram *F : DIF.subprograms()) transDbgEntry(F); for (const DbgDeclareInst *DDI : DbgDeclareIntrinsics) finalizeDebugDeclare(DDI); for (const DbgValueInst *DVI : DbgValueIntrinsics) finalizeDebugValue(DVI); transLocationInfo(); } // llvm.dbg.declare intrinsic. SPIRVValue * LLVMToSPIRVDbgTran::createDebugDeclarePlaceholder(const DbgDeclareInst *DbgDecl, SPIRVBasicBlock *BB) { DbgDeclareIntrinsics.push_back(DbgDecl); using namespace SPIRVDebug::Operand::DebugDeclare; SPIRVWordVec Ops(OperandCount, getDebugInfoNoneId()); SPIRVId ExtSetId = BM->getExtInstSetId(SPIRVEIS_Debug); return BM->addExtInst(getVoidTy(), ExtSetId, SPIRVDebug::Declare, Ops, BB); } void LLVMToSPIRVDbgTran::finalizeDebugDeclare(const DbgDeclareInst *DbgDecl) { SPIRVValue *V = SPIRVWriter->getTranslatedValue(DbgDecl); assert(V && "llvm.dbg.declare intrinsic isn't mapped to a SPIRV instruction"); assert(V->isExtInst(SPIRV::SPIRVEIS_Debug, SPIRVDebug::Declare) && "llvm.dbg.declare intrinsic has been translated wrong!"); if (!V || !V->isExtInst(SPIRV::SPIRVEIS_Debug, SPIRVDebug::Declare)) return; SPIRVExtInst *DD = static_cast(V); SPIRVBasicBlock *BB = DD->getBasicBlock(); llvm::Value *Alloca = DbgDecl->getAddress(); using namespace SPIRVDebug::Operand::DebugDeclare; SPIRVWordVec Ops(OperandCount); Ops[DebugLocalVarIdx] = transDbgEntry(DbgDecl->getVariable())->getId(); Ops[VariableIdx] = Alloca ? SPIRVWriter->transValue(Alloca, BB)->getId() : getDebugInfoNoneId(); Ops[ExpressionIdx] = transDbgEntry(DbgDecl->getExpression())->getId(); DD->setArguments(Ops); } // llvm.dbg.value intrinsic. SPIRVValue * LLVMToSPIRVDbgTran::createDebugValuePlaceholder(const DbgValueInst *DbgValue, SPIRVBasicBlock *BB) { if (!DbgValue->getValue()) return nullptr; // It is pointless without new value DbgValueIntrinsics.push_back(DbgValue); using namespace SPIRVDebug::Operand::DebugValue; SPIRVWordVec Ops(MinOperandCount, getDebugInfoNone()->getId()); SPIRVId ExtSetId = BM->getExtInstSetId(SPIRVEIS_Debug); return BM->addExtInst(getVoidTy(), ExtSetId, SPIRVDebug::Value, Ops, BB); } void LLVMToSPIRVDbgTran::finalizeDebugValue(const DbgValueInst *DbgValue) { SPIRVValue *V = SPIRVWriter->getTranslatedValue(DbgValue); assert(V && "llvm.dbg.value intrinsic isn't mapped to a SPIRV instruction"); assert(V->isExtInst(SPIRV::SPIRVEIS_Debug, SPIRVDebug::Value) && "llvm.dbg.value intrinsic has been translated wrong!"); if (!V || !V->isExtInst(SPIRV::SPIRVEIS_Debug, SPIRVDebug::Value)) return; SPIRVExtInst *DV = static_cast(V); SPIRVBasicBlock *BB = DV->getBasicBlock(); Value *Val = DbgValue->getValue(); using namespace SPIRVDebug::Operand::DebugValue; SPIRVWordVec Ops(MinOperandCount); Ops[DebugLocalVarIdx] = transDbgEntry(DbgValue->getVariable())->getId(); Ops[ValueIdx] = SPIRVWriter->transValue(Val, BB)->getId(); Ops[ExpressionIdx] = transDbgEntry(DbgValue->getExpression())->getId(); DV->setArguments(Ops); } // Emitting DebugScope and OpLine instructions void LLVMToSPIRVDbgTran::transLocationInfo() { for (const Function &F : *M) { for (const BasicBlock &BB : F) { SPIRVValue *V = SPIRVWriter->getTranslatedValue(&BB); assert(V && V->isBasicBlock() && "Basic block is expected to be translated"); SPIRVBasicBlock *SBB = static_cast(V); MDNode *DbgScope = nullptr; MDNode *InlinedAt = nullptr; SPIRVString *File = nullptr; unsigned LineNo = 0; unsigned Col = 0; for (const Instruction &I : BB) { if (auto *II = dyn_cast(&I)) { if (II->getIntrinsicID() == Intrinsic::dbg_label) { // SPIR-V doesn't support llvm.dbg.label intrinsic translation continue; } if (II->getIntrinsicID() == Intrinsic::annotation || II->getIntrinsicID() == Intrinsic::var_annotation || II->getIntrinsicID() == Intrinsic::ptr_annotation) { // llvm call instruction for llvm .*annotation intrinsics // is translated into SPIR-V instruction only if it represents // call of __builtin_intel_fpga_reg() builtin. In other cases this // instruction is dropped. In these cases debug info for this call // should be skipped too. // TODO: Remove skipping of debug info when *.annotation call will // be handled in a better way during SPIR-V translation. V = SPIRVWriter->getTranslatedValue(&I); if (!V || V->getOpCode() != OpFPGARegINTEL) continue; } } const DebugLoc &DL = I.getDebugLoc(); if (!DL.get()) { if (DbgScope || InlinedAt) { // Emit DebugNoScope DbgScope = nullptr; InlinedAt = nullptr; V = SPIRVWriter->getTranslatedValue(&I); transDebugLoc(DL, SBB, static_cast(V)); } continue; } // Once scope or inlining has changed emit another DebugScope if (DL.getScope() != DbgScope || DL.getInlinedAt() != InlinedAt) { DbgScope = DL.getScope(); InlinedAt = DL.getInlinedAt(); V = SPIRVWriter->getTranslatedValue(&I); transDebugLoc(DL, SBB, static_cast(V)); } // If any component of OpLine has changed emit another OpLine SPIRVString *DirAndFile = BM->getString(getFullPath(DL.get())); if (File != DirAndFile || LineNo != DL.getLine() || Col != DL.getCol()) { File = DirAndFile; LineNo = DL.getLine(); Col = DL.getCol(); V = SPIRVWriter->getTranslatedValue(&I); // According to the spec, OpLine for an OpBranch/OpBranchConditional // must precede the merge instruction and not the branch instruction auto *VPrev = static_cast(V)->getPrevious(); if (VPrev && (VPrev->getOpCode() == OpLoopMerge || VPrev->getOpCode() == OpLoopControlINTEL)) { assert(V->getOpCode() == OpBranch || V->getOpCode() == OpBranchConditional); V = VPrev; } BM->addLine(V, File ? File->getId() : getDebugInfoNone()->getId(), LineNo, Col); } } // Instructions } // Basic Blocks } // Functions } // Translation of single debug entry SPIRVEntry *LLVMToSPIRVDbgTran::transDbgEntry(const MDNode *DIEntry) { // Caching auto It = MDMap.find(DIEntry); if (It != MDMap.end()) { assert(It->second && "Invalid SPIRVEntry is cached!"); return It->second; } SPIRVEntry *Res = transDbgEntryImpl(DIEntry); assert(Res && "Translation failure"); MDMap[DIEntry] = Res; return Res; } // Dispatcher implementation SPIRVEntry *LLVMToSPIRVDbgTran::transDbgEntryImpl(const MDNode *MDN) { if (!MDN) return BM->addDebugInfo(SPIRVDebug::DebugInfoNone, getVoidTy(), SPIRVWordVec()); if (const DINode *DIEntry = dyn_cast(MDN)) { switch (DIEntry->getTag()) { // Types case dwarf::DW_TAG_base_type: case dwarf::DW_TAG_unspecified_type: return transDbgBaseType(cast(DIEntry)); case dwarf::DW_TAG_reference_type: case dwarf::DW_TAG_rvalue_reference_type: case dwarf::DW_TAG_pointer_type: return transDbgPointerType(cast(DIEntry)); case dwarf::DW_TAG_array_type: return transDbgArrayType(cast(DIEntry)); case dwarf::DW_TAG_const_type: case dwarf::DW_TAG_restrict_type: case dwarf::DW_TAG_volatile_type: case dwarf::DW_TAG_atomic_type: return transDbgQualifiedType(cast(DIEntry)); case dwarf::DW_TAG_subroutine_type: return transDbgSubroutineType(cast(DIEntry)); case dwarf::DW_TAG_class_type: case dwarf::DW_TAG_structure_type: case dwarf::DW_TAG_union_type: return transDbgCompositeType(cast(DIEntry)); case dwarf::DW_TAG_member: return transDbgMemberType(cast(DIEntry)); case dwarf::DW_TAG_inheritance: return transDbgInheritance(cast(DIEntry)); case dwarf::DW_TAG_enumeration_type: return transDbgEnumType(cast(DIEntry)); case dwarf::DW_TAG_file_type: return transDbgFileType(cast(DIEntry)); case dwarf::DW_TAG_typedef: return transDbgTypeDef(cast(DIEntry)); case dwarf::DW_TAG_ptr_to_member_type: return transDbgPtrToMember(cast(DIEntry)); // Scope case dwarf::DW_TAG_namespace: case dwarf::DW_TAG_lexical_block: return transDbgScope(cast(DIEntry)); // Function case dwarf::DW_TAG_subprogram: return transDbgFunction(cast(DIEntry)); // Variables case dwarf::DW_TAG_variable: if (const DILocalVariable *LV = dyn_cast(DIEntry)) return transDbgLocalVariable(LV); if (const DIGlobalVariable *GV = dyn_cast(DIEntry)) return transDbgGlobalVariable(GV); llvm_unreachable("Unxpected debug info type for variable"); case dwarf::DW_TAG_formal_parameter: return transDbgLocalVariable(cast(DIEntry)); // Compilation unit case dwarf::DW_TAG_compile_unit: return transDbgCompilationUnit(cast(DIEntry)); // Templates case dwarf::DW_TAG_template_type_parameter: case dwarf::DW_TAG_template_value_parameter: return transDbgTemplateParameter(cast(DIEntry)); case dwarf::DW_TAG_GNU_template_template_param: return transDbgTemplateTemplateParameter( cast(DIEntry)); case dwarf::DW_TAG_GNU_template_parameter_pack: return transDbgTemplateParameterPack( cast(DIEntry)); case dwarf::DW_TAG_imported_module: case dwarf::DW_TAG_imported_declaration: return transDbgImportedEntry(cast(DIEntry)); default: return getDebugInfoNone(); } } if (const DIExpression *Expr = dyn_cast(MDN)) return transDbgExpression(Expr); if (const DILocation *Loc = dyn_cast(MDN)) { return transDbgInlinedAt(Loc); } llvm_unreachable("Not implemented debug info entry!"); } // Helper methods SPIRVType *LLVMToSPIRVDbgTran::getVoidTy() { if (!VoidT) { assert(M && "Pointer to LLVM Module is expected to be initialized!"); // Cache void type in a member. VoidT = SPIRVWriter->transType(Type::getVoidTy(M->getContext())); } return VoidT; } SPIRVEntry *LLVMToSPIRVDbgTran::getScope(DIScope *S) { if (S) return transDbgEntry(S); else { assert(SPIRVCU && "Compile unit is expected to be already translated"); return SPIRVCU; } } SPIRVEntry *LLVMToSPIRVDbgTran::getGlobalVariable(const DIGlobalVariable *GV) { for (GlobalVariable &V : M->globals()) { SmallVector GVs; V.getDebugInfo(GVs); for (DIGlobalVariableExpression *GVE : GVs) { if (GVE->getVariable() == GV) return SPIRVWriter->transValue(&V, nullptr); } } return getDebugInfoNone(); } SPIRVWord mapDebugFlags(DINode::DIFlags DFlags) { SPIRVWord Flags = 0; if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPublic) Flags |= SPIRVDebug::FlagIsPublic; if ((DFlags & DINode::FlagAccessibility) == DINode::FlagProtected) Flags |= SPIRVDebug::FlagIsProtected; if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPrivate) Flags |= SPIRVDebug::FlagIsPrivate; if (DFlags & DINode::FlagFwdDecl) Flags |= SPIRVDebug::FlagIsFwdDecl; if (DFlags & DINode::FlagArtificial) Flags |= SPIRVDebug::FlagIsArtificial; if (DFlags & DINode::FlagExplicit) Flags |= SPIRVDebug::FlagIsExplicit; if (DFlags & DINode::FlagPrototyped) Flags |= SPIRVDebug::FlagIsPrototyped; if (DFlags & DINode::FlagObjectPointer) Flags |= SPIRVDebug::FlagIsObjectPointer; if (DFlags & DINode::FlagStaticMember) Flags |= SPIRVDebug::FlagIsStaticMember; // inderect variable flag ? if (DFlags & DINode::FlagLValueReference) Flags |= SPIRVDebug::FlagIsLValueReference; if (DFlags & DINode::FlagRValueReference) Flags |= SPIRVDebug::FlagIsRValueReference; if (DFlags & DINode::FlagTypePassByValue) Flags |= SPIRVDebug::FlagTypePassByValue; if (DFlags & DINode::FlagTypePassByReference) Flags |= SPIRVDebug::FlagTypePassByReference; return Flags; } SPIRVWord transDebugFlags(const DINode *DN) { SPIRVWord Flags = 0; if (const DIGlobalVariable *GV = dyn_cast(DN)) { if (GV->isLocalToUnit()) Flags |= SPIRVDebug::FlagIsLocal; if (GV->isDefinition()) Flags |= SPIRVDebug::FlagIsDefinition; } if (const DISubprogram *DS = dyn_cast(DN)) { if (DS->isLocalToUnit()) Flags |= SPIRVDebug::FlagIsLocal; if (DS->isOptimized()) Flags |= SPIRVDebug::FlagIsOptimized; if (DS->isDefinition()) Flags |= SPIRVDebug::FlagIsDefinition; Flags |= mapDebugFlags(DS->getFlags()); } if (DN->getTag() == dwarf::DW_TAG_reference_type) Flags |= SPIRVDebug::FlagIsLValueReference; if (DN->getTag() == dwarf::DW_TAG_rvalue_reference_type) Flags |= SPIRVDebug::FlagIsRValueReference; if (const DIType *DT = dyn_cast(DN)) Flags |= mapDebugFlags(DT->getFlags()); if (const DILocalVariable *DLocVar = dyn_cast(DN)) Flags |= mapDebugFlags(DLocVar->getFlags()); return Flags; } /// The following methods (till the end of the file) implement translation of /// debug instrtuctions described in the spec. // Absent Debug Info SPIRVEntry *LLVMToSPIRVDbgTran::getDebugInfoNone() { if (!DebugInfoNone) { DebugInfoNone = transDbgEntry(nullptr); } return DebugInfoNone; } SPIRVId LLVMToSPIRVDbgTran::getDebugInfoNoneId() { return getDebugInfoNone()->getId(); } // Compilation unit SPIRVEntry * LLVMToSPIRVDbgTran::transDbgCompilationUnit(const DICompileUnit *CU) { using namespace SPIRVDebug::Operand::CompilationUnit; SPIRVWordVec Ops(OperandCount); Ops[SPIRVDebugInfoVersionIdx] = SPIRVDebug::DebugInfoVersion; Ops[DWARFVersionIdx] = M->getDwarfVersion(); Ops[SourceIdx] = getSource(CU)->getId(); Ops[LanguageIdx] = CU->getSourceLanguage(); // Cache CU in a member. SPIRVCU = static_cast( BM->addDebugInfo(SPIRVDebug::CompilationUnit, getVoidTy(), Ops)); return SPIRVCU; } // Types SPIRVEntry *LLVMToSPIRVDbgTran::transDbgBaseType(const DIBasicType *BT) { using namespace SPIRVDebug::Operand::TypeBasic; SPIRVWordVec Ops(OperandCount); Ops[NameIdx] = BM->getString(BT->getName())->getId(); ConstantInt *Size = getUInt(M, BT->getSizeInBits()); Ops[SizeIdx] = SPIRVWriter->transValue(Size, nullptr)->getId(); auto Encoding = static_cast(BT->getEncoding()); SPIRVDebug::EncodingTag EncTag = SPIRVDebug::Unspecified; SPIRV::DbgEncodingMap::find(Encoding, &EncTag); Ops[EncodingIdx] = EncTag; return BM->addDebugInfo(SPIRVDebug::TypeBasic, getVoidTy(), Ops); } SPIRVEntry *LLVMToSPIRVDbgTran::transDbgPointerType(const DIDerivedType *PT) { using namespace SPIRVDebug::Operand::TypePointer; SPIRVWordVec Ops(OperandCount); SPIRVEntry *Base = transDbgEntry(PT->getBaseType()); Ops[BaseTypeIdx] = Base->getId(); Ops[StorageClassIdx] = ~0U; // all ones denote no address space Optional AS = PT->getDWARFAddressSpace(); if (AS.hasValue()) { SPIRAddressSpace SPIRAS = static_cast(AS.getValue()); Ops[StorageClassIdx] = SPIRSPIRVAddrSpaceMap::map(SPIRAS); } Ops[FlagsIdx] = transDebugFlags(PT); SPIRVEntry *Res = BM->addDebugInfo(SPIRVDebug::TypePointer, getVoidTy(), Ops); return Res; } SPIRVEntry *LLVMToSPIRVDbgTran::transDbgQualifiedType(const DIDerivedType *QT) { using namespace SPIRVDebug::Operand::TypeQualifier; SPIRVWordVec Ops(OperandCount); SPIRVEntry *Base = transDbgEntry(QT->getBaseType()); Ops[BaseTypeIdx] = Base->getId(); Ops[QualifierIdx] = SPIRV::DbgTypeQulifierMap::map( static_cast(QT->getTag())); return BM->addDebugInfo(SPIRVDebug::TypeQualifier, getVoidTy(), Ops); } SPIRVEntry *LLVMToSPIRVDbgTran::transDbgArrayType(const DICompositeType *AT) { using namespace SPIRVDebug::Operand::TypeArray; SPIRVWordVec Ops(MinOperandCount); SPIRVEntry *Base = transDbgEntry(AT->getBaseType()); Ops[BaseTypeIdx] = Base->getId(); DINodeArray AR(AT->getElements()); // For N-dimensianal arrays AR.getNumElements() == N const unsigned N = AR.size(); Ops.resize(ComponentCountIdx + N); for (unsigned I = 0; I < N; ++I) { DISubrange *SR = cast(AR[I]); ConstantInt *Count = SR->getCount().get(); if (AT->isVector()) { assert(N == 1 && "Multidimensional vector is not expected!"); Ops[ComponentCountIdx] = static_cast(Count->getZExtValue()); return BM->addDebugInfo(SPIRVDebug::TypeVector, getVoidTy(), Ops); } SPIRVValue *C = SPIRVWriter->transValue(Count, nullptr); Ops[ComponentCountIdx + I] = C->getId(); } return BM->addDebugInfo(SPIRVDebug::TypeArray, getVoidTy(), Ops); } SPIRVEntry *LLVMToSPIRVDbgTran::transDbgTypeDef(const DIDerivedType *DT) { using namespace SPIRVDebug::Operand::Typedef; SPIRVWordVec Ops(OperandCount); Ops[NameIdx] = BM->getString(DT->getName())->getId(); SPIRVEntry *BaseTy = transDbgEntry(DT->getBaseType()); assert(BaseTy && "Couldn't translate base type!"); Ops[BaseTypeIdx] = BaseTy->getId(); Ops[SourceIdx] = getSource(DT)->getId(); Ops[LineIdx] = 0; // This version of DIDerivedType has no line number Ops[ColumnIdx] = 0; // This version of DIDerivedType has no column number SPIRVEntry *Scope = getScope(DT->getScope()); assert(Scope && "Couldn't translate scope!"); Ops[ParentIdx] = Scope->getId(); return BM->addDebugInfo(SPIRVDebug::Typedef, getVoidTy(), Ops); } SPIRVEntry * LLVMToSPIRVDbgTran::transDbgSubroutineType(const DISubroutineType *FT) { using namespace SPIRVDebug::Operand::TypeFunction; SPIRVWordVec Ops(MinOperandCount); Ops[FlagsIdx] = transDebugFlags(FT); DITypeRefArray Types = FT->getTypeArray(); const size_t NumElements = Types.size(); if (NumElements) { Ops.resize(1 + NumElements); // First element of the TypeArray is the type of the return value, // followed by types of the function arguments' types. // The same order is preserved in SPIRV. for (unsigned I = 0; I < NumElements; ++I) Ops[ReturnTypeIdx + I] = transDbgEntry(Types[I])->getId(); } else { // void foo(); Ops[ReturnTypeIdx] = getVoidTy()->getId(); } return BM->addDebugInfo(SPIRVDebug::TypeFunction, getVoidTy(), Ops); } SPIRVEntry *LLVMToSPIRVDbgTran::transDbgEnumType(const DICompositeType *ET) { using namespace SPIRVDebug::Operand::TypeEnum; SPIRVWordVec Ops(MinOperandCount); SPIRVEntry *UnderlyingType = getVoidTy(); if (DIType *DerivedFrom = ET->getBaseType()) UnderlyingType = transDbgEntry(DerivedFrom); ConstantInt *Size = getUInt(M, ET->getSizeInBits()); Ops[NameIdx] = BM->getString(ET->getName())->getId(); Ops[UnderlyingTypeIdx] = UnderlyingType->getId(); Ops[SourceIdx] = getSource(ET)->getId(); Ops[LineIdx] = ET->getLine(); Ops[ColumnIdx] = 0; // This version of DICompositeType has no column number Ops[ParentIdx] = getScope(ET->getScope())->getId(); Ops[SizeIdx] = SPIRVWriter->transValue(Size, nullptr)->getId(); Ops[FlagsIdx] = transDebugFlags(ET); DINodeArray Elements = ET->getElements(); size_t ElemCount = Elements.size(); for (unsigned I = 0; I < ElemCount; ++I) { DIEnumerator *E = cast(Elements[I]); ConstantInt *EnumValue = getInt(M, E->getValue()); SPIRVValue *Val = SPIRVWriter->transValue(EnumValue, nullptr); assert(Val->getOpCode() == OpConstant && "LLVM constant must be translated to SPIRV constant"); Ops.push_back(Val->getId()); SPIRVString *Name = BM->getString(E->getName()); Ops.push_back(Name->getId()); } return BM->addDebugInfo(SPIRVDebug::TypeEnum, getVoidTy(), Ops); } SPIRVEntry * LLVMToSPIRVDbgTran::transDbgCompositeType(const DICompositeType *CT) { using namespace SPIRVDebug::Operand::TypeComposite; SPIRVWordVec Ops(MinOperandCount); SPIRVForward *Tmp = BM->addForward(nullptr); MDMap.insert(std::make_pair(CT, Tmp)); auto Tag = static_cast(CT->getTag()); SPIRVId UniqId = getDebugInfoNoneId(); StringRef Identifier = CT->getIdentifier(); if (!Identifier.empty()) UniqId = BM->getString(Identifier)->getId(); ConstantInt *Size = getUInt(M, CT->getSizeInBits()); Ops[NameIdx] = BM->getString(CT->getName())->getId(); Ops[TagIdx] = SPIRV::DbgCompositeTypeMap::map(Tag); Ops[SourceIdx] = getSource(CT)->getId(); Ops[LineIdx] = CT->getLine(); Ops[ColumnIdx] = 0; // This version of DICompositeType has no column number Ops[ParentIdx] = getScope(CT->getScope())->getId(); Ops[LinkageNameIdx] = UniqId; Ops[SizeIdx] = SPIRVWriter->transValue(Size, nullptr)->getId(); Ops[FlagsIdx] = transDebugFlags(CT); for (DINode *N : CT->getElements()) { Ops.push_back(transDbgEntry(N)->getId()); } SPIRVEntry *Res = BM->addDebugInfo(SPIRVDebug::TypeComposite, getVoidTy(), Ops); // Translate template parameters. if (DITemplateParameterArray TP = CT->getTemplateParams()) { const unsigned int NumTParams = TP.size(); SPIRVWordVec Args(1 + NumTParams); Args[0] = Res->getId(); for (unsigned int I = 0; I < NumTParams; ++I) { Args[I + 1] = transDbgEntry(TP[I])->getId(); } Res = BM->addDebugInfo(SPIRVDebug::TypeTemplate, getVoidTy(), Args); } BM->replaceForward(Tmp, Res); MDMap[CT] = Res; return Res; } SPIRVEntry *LLVMToSPIRVDbgTran::transDbgMemberType(const DIDerivedType *MT) { using namespace SPIRVDebug::Operand::TypeMember; SPIRVWordVec Ops(MinOperandCount); Ops[NameIdx] = BM->getString(MT->getName())->getId(); Ops[TypeIdx] = transDbgEntry(MT->getBaseType())->getId(); Ops[SourceIdx] = getSource(MT)->getId(); Ops[LineIdx] = MT->getLine(); Ops[ColumnIdx] = 0; // This version of DIDerivedType has no column number Ops[ParentIdx] = transDbgEntry(MT->getScope())->getId(); ConstantInt *Offset = getUInt(M, MT->getOffsetInBits()); Ops[OffsetIdx] = SPIRVWriter->transValue(Offset, nullptr)->getId(); ConstantInt *Size = getUInt(M, MT->getSizeInBits()); Ops[SizeIdx] = SPIRVWriter->transValue(Size, nullptr)->getId(); Ops[FlagsIdx] = transDebugFlags(MT); if (MT->isStaticMember()) { if (llvm::Constant *C = MT->getConstant()) { SPIRVValue *Val = SPIRVWriter->transValue(C, nullptr); assert(isConstantOpCode(Val->getOpCode()) && "LLVM constant must be translated to SPIRV constant"); Ops.push_back(Val->getId()); } } return BM->addDebugInfo(SPIRVDebug::TypeMember, getVoidTy(), Ops); } SPIRVEntry *LLVMToSPIRVDbgTran::transDbgInheritance(const DIDerivedType *DT) { using namespace SPIRVDebug::Operand::TypeInheritance; SPIRVWordVec Ops(OperandCount); Ops[ChildIdx] = transDbgEntry(DT->getScope())->getId(); Ops[ParentIdx] = transDbgEntry(DT->getBaseType())->getId(); ConstantInt *Offset = getUInt(M, DT->getOffsetInBits()); Ops[OffsetIdx] = SPIRVWriter->transValue(Offset, nullptr)->getId(); ConstantInt *Size = getUInt(M, DT->getSizeInBits()); Ops[SizeIdx] = SPIRVWriter->transValue(Size, nullptr)->getId(); Ops[FlagsIdx] = transDebugFlags(DT); return BM->addDebugInfo(SPIRVDebug::Inheritance, getVoidTy(), Ops); } SPIRVEntry *LLVMToSPIRVDbgTran::transDbgPtrToMember(const DIDerivedType *DT) { using namespace SPIRVDebug::Operand::PtrToMember; SPIRVWordVec Ops(OperandCount); Ops[MemberTypeIdx] = transDbgEntry(DT->getBaseType())->getId(); Ops[ParentIdx] = transDbgEntry(DT->getClassType())->getId(); return BM->addDebugInfo(SPIRVDebug::TypePtrToMember, getVoidTy(), Ops); } // Templates SPIRVEntry * LLVMToSPIRVDbgTran::transDbgTemplateParams(DITemplateParameterArray TPA, const SPIRVEntry *Target) { using namespace SPIRVDebug::Operand::Template; SPIRVWordVec Ops(MinOperandCount); Ops[TargetIdx] = Target->getId(); for (DITemplateParameter *TP : TPA) { Ops.push_back(transDbgEntry(TP)->getId()); } return BM->addDebugInfo(SPIRVDebug::TypeTemplate, getVoidTy(), Ops); } SPIRVEntry * LLVMToSPIRVDbgTran::transDbgTemplateParameter(const DITemplateParameter *TP) { using namespace SPIRVDebug::Operand::TemplateParameter; SPIRVWordVec Ops(OperandCount); Ops[NameIdx] = BM->getString(TP->getName())->getId(); Ops[TypeIdx] = transDbgEntry(TP->getType())->getId(); Ops[ValueIdx] = getDebugInfoNoneId(); if (TP->getTag() == dwarf::DW_TAG_template_value_parameter) { const DITemplateValueParameter *TVP = cast(TP); Constant *C = cast(TVP->getValue())->getValue(); Ops[ValueIdx] = SPIRVWriter->transValue(C, nullptr)->getId(); } Ops[SourceIdx] = getDebugInfoNoneId(); Ops[LineIdx] = 0; // This version of DITemplateParameter has no line number Ops[ColumnIdx] = 0; // This version of DITemplateParameter has no column info return BM->addDebugInfo(SPIRVDebug::TypeTemplateParameter, getVoidTy(), Ops); } SPIRVEntry *LLVMToSPIRVDbgTran::transDbgTemplateTemplateParameter( const DITemplateValueParameter *TVP) { using namespace SPIRVDebug::Operand::TemplateTemplateParameter; SPIRVWordVec Ops(OperandCount); assert(isa(TVP->getValue())); MDString *Val = cast(TVP->getValue()); Ops[NameIdx] = BM->getString(TVP->getName())->getId(); Ops[TemplateNameIdx] = BM->getString(Val->getString())->getId(); Ops[SourceIdx] = getDebugInfoNoneId(); Ops[LineIdx] = 0; // This version of DITemplateValueParameter has no line info Ops[ColumnIdx] = 0; // This version of DITemplateValueParameter has no column return BM->addDebugInfo(SPIRVDebug::TypeTemplateTemplateParameter, getVoidTy(), Ops); } SPIRVEntry *LLVMToSPIRVDbgTran::transDbgTemplateParameterPack( const DITemplateValueParameter *TVP) { using namespace SPIRVDebug::Operand::TemplateParameterPack; SPIRVWordVec Ops(MinOperandCount); assert(isa(TVP->getValue())); MDNode *Params = cast(TVP->getValue()); Ops[NameIdx] = BM->getString(TVP->getName())->getId(); Ops[SourceIdx] = getDebugInfoNoneId(); Ops[LineIdx] = 0; // This version of DITemplateValueParameter has no line info Ops[ColumnIdx] = 0; // This version of DITemplateValueParameter has no column for (const MDOperand &Op : Params->operands()) { SPIRVEntry *P = transDbgEntry(cast(Op.get())); Ops.push_back(P->getId()); } return BM->addDebugInfo(SPIRVDebug::TypeTemplateParameterPack, getVoidTy(), Ops); } // Global objects SPIRVEntry * LLVMToSPIRVDbgTran::transDbgGlobalVariable(const DIGlobalVariable *GV) { using namespace SPIRVDebug::Operand::GlobalVariable; SPIRVWordVec Ops(MinOperandCount); Ops[NameIdx] = BM->getString(GV->getName())->getId(); Ops[TypeIdx] = transDbgEntry(GV->getType())->getId(); Ops[SourceIdx] = getSource(GV)->getId(); Ops[LineIdx] = GV->getLine(); Ops[ColumnIdx] = 0; // This version of DIGlobalVariable has no column number // Parent scope DIScope *Context = GV->getScope(); SPIRVEntry *Parent = SPIRVCU; // Global variable may be declared in scope of a namespace or it may be a // static variable declared in scope of a function if (Context && (isa(Context) || isa(Context))) Parent = transDbgEntry(Context); Ops[ParentIdx] = Parent->getId(); Ops[LinkageNameIdx] = BM->getString(GV->getLinkageName())->getId(); Ops[VariableIdx] = getGlobalVariable(GV)->getId(); Ops[FlagsIdx] = transDebugFlags(GV); // Check if GV is the definition of previously declared static member if (DIDerivedType *StaticMember = GV->getStaticDataMemberDeclaration()) Ops.push_back(transDbgEntry(StaticMember)->getId()); return BM->addDebugInfo(SPIRVDebug::GlobalVariable, getVoidTy(), Ops); } SPIRVEntry *LLVMToSPIRVDbgTran::transDbgFunction(const DISubprogram *Func) { auto It = MDMap.find(Func); if (It != MDMap.end()) return static_cast(It->second); // As long as indexes of FunctionDeclaration operands match with Function using namespace SPIRVDebug::Operand::FunctionDeclaration; SPIRVWordVec Ops(OperandCount); Ops[NameIdx] = BM->getString(Func->getName())->getId(); Ops[TypeIdx] = transDbgEntry(Func->getType())->getId(); Ops[SourceIdx] = getSource(Func)->getId(); Ops[LineIdx] = Func->getLine(); Ops[ColumnIdx] = 0; // This version of DISubprogram has no column number auto Scope = Func->getScope(); if (Scope && isa(Scope)) Ops[ParentIdx] = SPIRVCU->getId(); else Ops[ParentIdx] = getScope(Scope)->getId(); Ops[LinkageNameIdx] = BM->getString(Func->getLinkageName())->getId(); Ops[FlagsIdx] = transDebugFlags(Func); SPIRVEntry *DebugFunc = nullptr; if (!Func->isDefinition()) { DebugFunc = BM->addDebugInfo(SPIRVDebug::FunctionDecl, getVoidTy(), Ops); } else { // Here we add operands specific function definition using namespace SPIRVDebug::Operand::Function; Ops.resize(MinOperandCount); Ops[ScopeLineIdx] = Func->getScopeLine(); Ops[FunctionIdIdx] = getDebugInfoNoneId(); for (const llvm::Function &F : M->functions()) { if (Func->describes(&F)) { SPIRVValue *SPIRVFunc = SPIRVWriter->getTranslatedValue(&F); assert(SPIRVFunc && "All function must be already translated"); Ops[FunctionIdIdx] = SPIRVFunc->getId(); break; } } if (DISubprogram *FuncDecl = Func->getDeclaration()) Ops.push_back(transDbgEntry(FuncDecl)->getId()); else Ops.push_back(getDebugInfoNoneId()); DebugFunc = BM->addDebugInfo(SPIRVDebug::Function, getVoidTy(), Ops); MDMap.insert(std::make_pair(Func, DebugFunc)); // Functions local variable might be not refered to anywhere else, except // here. // Just translate them. for (const DINode *Var : Func->getRetainedNodes()) transDbgEntry(Var); } // If the function has template parameters the function *is* a template. if (DITemplateParameterArray TPA = Func->getTemplateParams()) { DebugFunc = transDbgTemplateParams(TPA, DebugFunc); } return DebugFunc; } // Location information SPIRVEntry *LLVMToSPIRVDbgTran::transDbgScope(const DIScope *S) { if (const DILexicalBlockFile *LBF = dyn_cast(S)) { using namespace SPIRVDebug::Operand::LexicalBlockDiscriminator; SPIRVWordVec Ops(OperandCount); Ops[SourceIdx] = getSource(S)->getId(); Ops[DiscriminatorIdx] = LBF->getDiscriminator(); Ops[ParentIdx] = getScope(S->getScope())->getId(); return BM->addDebugInfo(SPIRVDebug::LexicalBlockDiscriminator, getVoidTy(), Ops); } using namespace SPIRVDebug::Operand::LexicalBlock; SPIRVWordVec Ops(MinOperandCount); Ops[SourceIdx] = getSource(S)->getId(); Ops[ParentIdx] = getScope(S->getScope())->getId(); if (const DILexicalBlock *LB = dyn_cast(S)) { Ops[LineIdx] = LB->getLine(); Ops[ColumnIdx] = LB->getColumn(); } else if (const DINamespace *NS = dyn_cast(S)) { Ops[LineIdx] = 0; // This version of DINamespace has no line number Ops[ColumnIdx] = 0; // This version of DINamespace has no column number Ops.push_back(BM->getString(NS->getName())->getId()); } return BM->addDebugInfo(SPIRVDebug::LexicalBlock, getVoidTy(), Ops); } // Generating DebugScope and DebugNoScope instructions. They can interleave with // core instructions. SPIRVEntry *LLVMToSPIRVDbgTran::transDebugLoc(const DebugLoc &Loc, SPIRVBasicBlock *BB, SPIRVInstruction *InsertBefore) { SPIRVId ExtSetId = BM->getExtInstSetId(SPIRVEIS_Debug); if (!Loc.get()) return BM->addExtInst(getVoidTy(), ExtSetId, SPIRVDebug::NoScope, std::vector(), BB, InsertBefore); using namespace SPIRVDebug::Operand::Scope; SPIRVWordVec Ops(MinOperandCount); Ops[ScopeIdx] = getScope(static_cast(Loc.getScope()))->getId(); if (DILocation *IA = Loc.getInlinedAt()) Ops.push_back(transDbgEntry(IA)->getId()); return BM->addExtInst(getVoidTy(), ExtSetId, SPIRVDebug::Scope, Ops, BB, InsertBefore); } SPIRVEntry *LLVMToSPIRVDbgTran::transDbgInlinedAt(const DILocation *Loc) { using namespace SPIRVDebug::Operand::InlinedAt; SPIRVWordVec Ops(MinOperandCount); Ops[LineIdx] = Loc->getLine(); Ops[ScopeIdx] = getScope(Loc->getScope())->getId(); if (DILocation *IA = Loc->getInlinedAt()) Ops.push_back(transDbgEntry(IA)->getId()); return BM->addDebugInfo(SPIRVDebug::InlinedAt, getVoidTy(), Ops); } template SPIRVExtInst *LLVMToSPIRVDbgTran::getSource(const T *DIEntry) { const std::string FileName = getFullPath(DIEntry); auto It = FileMap.find(FileName); if (It != FileMap.end()) return It->second; using namespace SPIRVDebug::Operand::Source; SPIRVWordVec Ops(OperandCount); Ops[FileIdx] = BM->getString(FileName)->getId(); Ops[TextIdx] = getDebugInfoNone()->getId(); SPIRVExtInst *Source = static_cast( BM->addDebugInfo(SPIRVDebug::Source, getVoidTy(), Ops)); FileMap[FileName] = Source; return Source; } SPIRVEntry *LLVMToSPIRVDbgTran::transDbgFileType(const DIFile *F) { return BM->getString(getFullPath(F)); } // Local variables SPIRVEntry * LLVMToSPIRVDbgTran::transDbgLocalVariable(const DILocalVariable *Var) { using namespace SPIRVDebug::Operand::LocalVariable; SPIRVWordVec Ops(MinOperandCount); Ops[NameIdx] = BM->getString(Var->getName())->getId(); Ops[TypeIdx] = transDbgEntry(Var->getType())->getId(); Ops[SourceIdx] = getSource(Var->getFile())->getId(); Ops[LineIdx] = Var->getLine(); Ops[ColumnIdx] = 0; // This version of DILocalVariable has no column number Ops[ParentIdx] = getScope(Var->getScope())->getId(); Ops[FlagsIdx] = transDebugFlags(Var); if (SPIRVWord ArgNumber = Var->getArg()) Ops.push_back(ArgNumber); return BM->addDebugInfo(SPIRVDebug::LocalVariable, getVoidTy(), Ops); } // DWARF Operations and expressions SPIRVEntry *LLVMToSPIRVDbgTran::transDbgExpression(const DIExpression *Expr) { SPIRVWordVec Operations; for (unsigned I = 0, N = Expr->getNumElements(); I < N; ++I) { using namespace SPIRVDebug::Operand::Operation; auto DWARFOpCode = static_cast(Expr->getElement(I)); SPIRVDebug::ExpressionOpCode OC = SPIRV::DbgExpressionOpCodeMap::map(DWARFOpCode); assert(OpCountMap.find(OC) != OpCountMap.end() && "unhandled opcode found in DIExpression"); unsigned OpCount = OpCountMap[OC]; SPIRVWordVec Op(OpCount); Op[OpCodeIdx] = OC; for (unsigned J = 1; J < OpCount; ++J) Op[J] = Expr->getElement(++I); auto *Operation = BM->addDebugInfo(SPIRVDebug::Operation, getVoidTy(), Op); Operations.push_back(Operation->getId()); } return BM->addDebugInfo(SPIRVDebug::Expression, getVoidTy(), Operations); } // Imported entries (C++ using directive) SPIRVEntry * LLVMToSPIRVDbgTran::transDbgImportedEntry(const DIImportedEntity *IE) { using namespace SPIRVDebug::Operand::ImportedEntity; SPIRVWordVec Ops(OperandCount); auto Tag = static_cast(IE->getTag()); Ops[NameIdx] = BM->getString(IE->getName())->getId(); Ops[TagIdx] = SPIRV::DbgImportedEntityMap::map(Tag); Ops[SourceIdx] = getSource(IE->getFile())->getId(); Ops[EntityIdx] = transDbgEntry(IE->getEntity())->getId(); Ops[LineIdx] = IE->getLine(); Ops[ColumnIdx] = 0; // This version of DIImportedEntity has no column number Ops[ParentIdx] = getScope(IE->getScope())->getId(); return BM->addDebugInfo(SPIRVDebug::ImportedEntity, getVoidTy(), Ops); } SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/LLVMToSPIRVDbgTran.h000066400000000000000000000151521363521741200223670ustar00rootroot00000000000000//===- LLVMToSPIRVDbgTran.h - Converts LLVM DebugInfo to SPIR-V -*- C++ -*-===// // // The LLVM/SPIR-V Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2018 Intel Corporation. All rights reserved. // // 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 Intel Corporation, 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. // //===----------------------------------------------------------------------===// // // This file implements translation of debug info from LLVM metadata to SPIR-V // //===----------------------------------------------------------------------===// #ifndef LLVMTOSPIRVDBGTRAN_HPP_ #define LLVMTOSPIRVDBGTRAN_HPP_ #include "SPIRVModule.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/Module.h" #include using namespace llvm; namespace SPIRV { class LLVMToSPIRV; class LLVMToSPIRVDbgTran { public: typedef std::vector SPIRVWordVec; LLVMToSPIRVDbgTran(Module *TM = nullptr, SPIRVModule *TBM = nullptr, LLVMToSPIRV *Writer = nullptr) : BM(TBM), M(TM), SPIRVWriter(Writer), VoidT(nullptr), DebugInfoNone(nullptr) {} void transDebugMetadata(); void setModule(Module *Mod) { M = Mod; } // Mixing translation of regular instructions and debug info creates a mess. // To avoid it we translate debug info intrinsics in two steps: // 1. First time we meet debug info intrinsic during translation of a basic // block. At this time we create corresponding SPIRV debug info instruction, // but with dummy operands. Doing so we a) map llvm value to spirv value, // b) get a place for SPIRV debug info intrinsic in SPIRV basic block. // We also remember all debug intrinsics. SPIRVValue *createDebugDeclarePlaceholder(const DbgDeclareInst *DbgDecl, SPIRVBasicBlock *BB); SPIRVValue *createDebugValuePlaceholder(const DbgValueInst *DbgValue, SPIRVBasicBlock *BB); private: // 2. After translation of all regular instructions we deal with debug info. // We iterate over debug intrinsics stored on the first step, get its mapped // SPIRV instruction and tweak the operands. void finalizeDebugDeclare(const DbgDeclareInst *DbgDecl); void finalizeDebugValue(const DbgValueInst *DbgValue); // Emit DebugScope and OpLine instructions void transLocationInfo(); // Dispatcher SPIRVEntry *transDbgEntry(const MDNode *DIEntry); SPIRVEntry *transDbgEntryImpl(const MDNode *MDN); // Helper methods SPIRVType *getVoidTy(); SPIRVEntry *getScope(DIScope *SR); SPIRVEntry *getGlobalVariable(const DIGlobalVariable *GV); // No debug info SPIRVEntry *getDebugInfoNone(); SPIRVId getDebugInfoNoneId(); // Compilation unit SPIRVEntry *transDbgCompilationUnit(const DICompileUnit *CU); /// The following methods (till the end of the file) implement translation /// of debug instrtuctions described in the spec. // Types SPIRVEntry *transDbgBaseType(const DIBasicType *BT); SPIRVEntry *transDbgPointerType(const DIDerivedType *PT); SPIRVEntry *transDbgQualifiedType(const DIDerivedType *QT); SPIRVEntry *transDbgArrayType(const DICompositeType *AT); SPIRVEntry *transDbgTypeDef(const DIDerivedType *D); SPIRVEntry *transDbgSubroutineType(const DISubroutineType *FT); SPIRVEntry *transDbgEnumType(const DICompositeType *ET); SPIRVEntry *transDbgCompositeType(const DICompositeType *CT); SPIRVEntry *transDbgMemberType(const DIDerivedType *MT); SPIRVEntry *transDbgInheritance(const DIDerivedType *DT); SPIRVEntry *transDbgPtrToMember(const DIDerivedType *DT); // Templates SPIRVEntry *transDbgTemplateParams(DITemplateParameterArray TPA, const SPIRVEntry *Target); SPIRVEntry *transDbgTemplateParameter(const DITemplateParameter *TP); SPIRVEntry * transDbgTemplateTemplateParameter(const DITemplateValueParameter *TP); SPIRVEntry *transDbgTemplateParameterPack(const DITemplateValueParameter *TP); // Global objects SPIRVEntry *transDbgGlobalVariable(const DIGlobalVariable *GV); SPIRVEntry *transDbgFunction(const DISubprogram *Func); // Location information SPIRVEntry *transDbgScope(const DIScope *S); SPIRVEntry *transDebugLoc(const DebugLoc &Loc, SPIRVBasicBlock *BB, SPIRVInstruction *InsertBefore = nullptr); SPIRVEntry *transDbgInlinedAt(const DILocation *D); template SPIRVExtInst *getSource(const T *DIEntry); SPIRVEntry *transDbgFileType(const DIFile *F); // Local Variables SPIRVEntry *transDbgLocalVariable(const DILocalVariable *Var); // DWARF expressions SPIRVEntry *transDbgExpression(const DIExpression *Expr); // Imported declarations and modules SPIRVEntry *transDbgImportedEntry(const DIImportedEntity *IE); SPIRVModule *BM; Module *M; LLVMToSPIRV *SPIRVWriter; std::unordered_map MDMap; std::unordered_map FileMap; DebugInfoFinder DIF; SPIRVType *VoidT; SPIRVEntry *DebugInfoNone; SPIRVExtInst *SPIRVCU; std::vector DbgDeclareIntrinsics; std::vector DbgValueIntrinsics; }; // class LLVMToSPIRVDbgTran } // namespace SPIRV #endif // LLVMTOSPIRVDBGTRAN_HPP_ SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/Mangler/000077500000000000000000000000001363521741200204345ustar00rootroot00000000000000SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/Mangler/FunctionDescriptor.cpp000066400000000000000000000044651363521741200247750ustar00rootroot00000000000000//===---------------------- FunctionDescriptor.cpp -----------------------===// // // SPIR Tools // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===---------------------------------------------------------------------===// /* * Contributed by: Intel Corporation. */ #include "FunctionDescriptor.h" #include "ParameterType.h" #include namespace SPIR { std::string FunctionDescriptor::nullString() { return std::string(""); } std::string FunctionDescriptor::toString() const { std::stringstream Stream; if (isNull()) { return FunctionDescriptor::nullString(); } Stream << Name << "("; size_t ParamCount = Parameters.size(); if (ParamCount > 0) { for (size_t I = 0; I < ParamCount - 1; ++I) Stream << Parameters[I]->toString() << ", "; Stream << Parameters[ParamCount - 1]->toString(); } Stream << ")"; return Stream.str(); } static bool equal(const TypeVector &L, const TypeVector &R) { if (&L == &R) return true; if (L.size() != R.size()) return false; TypeVector::const_iterator Itl = L.begin(), Itr = R.begin(), Endl = L.end(); while (Itl != Endl) { if (!(*Itl)->equals(*Itr)) return false; ++Itl; ++Itr; } return true; } // // FunctionDescriptor // bool FunctionDescriptor::operator==(const FunctionDescriptor &That) const { if (this == &That) return true; if (Name != That.Name) return false; return equal(Parameters, That.Parameters); } bool FunctionDescriptor::operator<(const FunctionDescriptor &That) const { int StrCmp = Name.compare(That.Name); if (StrCmp) return (StrCmp < 0); size_t Len = Parameters.size(), ThatLen = That.Parameters.size(); if (Len != ThatLen) return Len < ThatLen; TypeVector::const_iterator It = Parameters.begin(), E = Parameters.end(), Thatit = That.Parameters.begin(); while (It != E) { int Cmp = (*It)->toString().compare((*Thatit)->toString()); if (Cmp) return (Cmp < 0); ++Thatit; ++It; } return false; } bool FunctionDescriptor::isNull() const { return (Name.empty() && Parameters.empty()); } FunctionDescriptor FunctionDescriptor::null() { FunctionDescriptor Fd; Fd.Name = ""; return Fd; } } // namespace SPIR SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/Mangler/FunctionDescriptor.h000066400000000000000000000027741363521741200244430ustar00rootroot00000000000000//===----------------------- FunctionDescriptor.h ------------------------===// // // SPIR Tools // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===---------------------------------------------------------------------===// /* * Contributed by: Intel Corporation. */ #ifndef SPIRV_MANGLER_FUNCTIONDESCRIPTOR_H #define SPIRV_MANGLER_FUNCTIONDESCRIPTOR_H #include "ParameterType.h" #include "Refcount.h" #include #include namespace SPIR { typedef std::vector> TypeVector; struct FunctionDescriptor { /// @brief Returns a human readable string representation of the function's /// prototype. /// @returns std::string representing the function's prototype. std::string toString() const; /// The name of the function (stripped). std::string Name; /// Parameter list of the function. TypeVector Parameters; bool operator==(const FunctionDescriptor &) const; /// @brief Enables function descriptors to serve as keys in stl maps. bool operator<(const FunctionDescriptor &) const; bool isNull() const; /// @brief Create a singular value, that represents a 'null' /// FunctionDescriptor. static FunctionDescriptor null(); static std::string nullString(); }; template std::ostream &operator<<(T &O, const SPIR::FunctionDescriptor &Fd) { O << Fd.toString(); return O; } } // namespace SPIR #endif // SPIRV_MANGLER_FUNCTIONDESCRIPTOR_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/Mangler/Mangler.cpp000066400000000000000000000157461363521741200225420ustar00rootroot00000000000000//===--------------------------- Mangler.cpp -----------------------------===// // // SPIR Tools // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===---------------------------------------------------------------------===// /* * Contributed by: Intel Corporation. */ #include "FunctionDescriptor.h" #include "ManglingUtils.h" #include "NameMangleAPI.h" #include "ParameterType.h" #include "SPIRVInternal.h" #include #include #include #include // According to IA64 name mangling spec, // builtin vector types should not be substituted // This is a workaround till this gets fixed in CLang #define ENABLE_MANGLER_VECTOR_SUBSTITUTION 1 namespace SPIR { class MangleVisitor : public TypeVisitor { public: MangleVisitor(SPIRversion Ver, std::stringstream &S) : TypeVisitor(Ver), Stream(S), SeqId(0) {} // // mangle substitution methods // void mangleSequenceID(unsigned SeqID) { if (SeqID == 1) Stream << '0'; else if (SeqID > 1) { std::string Bstr; std::string Charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; SeqID--; Bstr.reserve(7); for (; SeqID != 0; SeqID /= 36) Bstr += Charset.substr(SeqID % 36, 1); std::reverse(Bstr.begin(), Bstr.end()); Stream << Bstr; } Stream << '_'; } bool mangleSubstitution(const ParamType *Type, std::string TypeStr) { size_t Fpos; std::stringstream ThistypeStr; ThistypeStr << TypeStr; if ((Fpos = Stream.str().find(TypeStr)) != std::string::npos) { const char *NType; if (const PointerType *P = SPIR::dynCast(Type)) { if ((NType = mangledPrimitiveStringfromName(P->getPointee()->toString()))) ThistypeStr << NType; } #if defined(ENABLE_MANGLER_VECTOR_SUBSTITUTION) else if (const VectorType *PVec = SPIR::dynCast(Type)) { if ((NType = mangledPrimitiveStringfromName( PVec->getScalarType()->toString()))) ThistypeStr << NType; } #endif std::map::iterator I = Substitutions.find(ThistypeStr.str()); if (I == Substitutions.end()) return false; unsigned SeqID = I->second; Stream << 'S'; mangleSequenceID(SeqID); return true; } return false; } // // Visit methods // MangleError visit(const PrimitiveType *T) override { MangleError Me = MANGLE_SUCCESS; std::string MangledPrimitive = std::string(mangledPrimitiveString(T->getPrimitive())); #if defined(SPIRV_SPIR20_MANGLING_REQUIREMENTS) Stream << MangledPrimitive; #else // Builtin primitives such as int are not substitution candidates, but // all other primitives are. Even though most of these do not appear // repeatedly in builtin function signatures, we need to track them in // the substitution map. if (T->getPrimitive() >= PRIMITIVE_STRUCT_FIRST) { if (!mangleSubstitution(T, MangledPrimitive)) { size_t Index = Stream.str().size(); Stream << MangledPrimitive; recordSubstitution(Stream.str().substr(Index)); } } else { Stream << MangledPrimitive; } #endif return Me; } MangleError visit(const PointerType *P) override { size_t Fpos = Stream.str().size(); std::string QualStr; MangleError Me = MANGLE_SUCCESS; QualStr += getMangledAttribute((P->getAddressSpace())); for (unsigned int I = ATTR_QUALIFIER_FIRST; I <= ATTR_QUALIFIER_LAST; I++) { TypeAttributeEnum Qualifier = (TypeAttributeEnum)I; if (P->hasQualifier(Qualifier)) { QualStr += getMangledAttribute(Qualifier); } } if (!mangleSubstitution(P, "P" + QualStr)) { // A pointee type is substituted when it is a user type, a vector type // (but see a comment in the beginning of this file), a pointer type, // or a primitive type with qualifiers (addr. space and/or CV qualifiers). // So, stream "P", type qualifiers Stream << "P" << QualStr; // and the pointee type itself. Me = P->getPointee()->accept(this); // The type qualifiers plus a pointee type is a substitutable entity recordSubstitution(Stream.str().substr(Fpos + 1)); // The complete pointer type is substitutable as well recordSubstitution(Stream.str().substr(Fpos)); } return Me; } MangleError visit(const VectorType *V) override { size_t Index = Stream.str().size(); std::stringstream TypeStr; TypeStr << "Dv" << V->getLength() << "_"; MangleError Me = MANGLE_SUCCESS; #if defined(ENABLE_MANGLER_VECTOR_SUBSTITUTION) if (!mangleSubstitution(V, TypeStr.str())) #endif { Stream << TypeStr.str(); Me = V->getScalarType()->accept(this); recordSubstitution(Stream.str().substr(Index)); } return Me; } MangleError visit(const AtomicType *P) override { MangleError Me = MANGLE_SUCCESS; size_t Index = Stream.str().size(); const char *TypeStr = "U7_Atomic"; if (!mangleSubstitution(P, TypeStr)) { Stream << TypeStr; Me = P->getBaseType()->accept(this); recordSubstitution(Stream.str().substr(Index)); } return Me; } MangleError visit(const BlockType *P) override { Stream << "U" << "13block_pointerFv"; if (P->getNumOfParams() == 0) Stream << "v"; else for (unsigned int I = 0; I < P->getNumOfParams(); ++I) { MangleError Err = P->getParam(I)->accept(this); if (Err != MANGLE_SUCCESS) { return Err; } } Stream << "E"; return MANGLE_SUCCESS; } MangleError visit(const UserDefinedType *PTy) override { std::string Name = PTy->toString(); Stream << Name.size() << Name; return MANGLE_SUCCESS; } private: void recordSubstitution(const std::string &Str) { Substitutions[Str] = SeqId++; } // Holds the mangled string representing the prototype of the function. std::stringstream &Stream; unsigned SeqId; std::map Substitutions; }; // // NameMangler // NameMangler::NameMangler(SPIRversion Version) : SpirVersion(Version) {} MangleError NameMangler::mangle(const FunctionDescriptor &Fd, std::string &MangledName) { if (Fd.isNull()) { MangledName.assign(FunctionDescriptor::nullString()); return MANGLE_NULL_FUNC_DESCRIPTOR; } std::stringstream Ret; Ret << "_Z" << Fd.Name.length() << Fd.Name; MangleVisitor Visitor(SpirVersion, Ret); for (unsigned int I = 0; I < Fd.Parameters.size(); ++I) { MangleError Err = Fd.Parameters[I]->accept(&Visitor); if (Err == MANGLE_TYPE_NOT_SUPPORTED) { MangledName.assign("Type "); MangledName.append(Fd.Parameters[I]->toString()); MangledName.append(" is not supported in "); std::string Ver = getSPIRVersionAsString(SpirVersion); MangledName.append(Ver); return Err; } } MangledName.assign(Ret.str()); return MANGLE_SUCCESS; } } // namespace SPIR SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/Mangler/ManglingUtils.cpp000066400000000000000000000264321363521741200237240ustar00rootroot00000000000000//===------------------------- ManglingUtils.cpp -------------------------===// // // SPIR Tools // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===---------------------------------------------------------------------===// /* * Contributed by: Intel Corporation. */ #include "ManglingUtils.h" namespace SPIR { // String represenration for the primitive types. static const char *PrimitiveNames[PRIMITIVE_NUM] = { "bool", "uchar", "char", "ushort", "short", "uint", "int", "ulong", "long", "half", "float", "double", "void", "...", "image1d_ro_t", "image1d_array_ro_t", "image1d_buffer_ro_t", "image2d_ro_t", "image2d_array_ro_t", "image2d_depth_ro_t", "image2d_array_depth_ro_t", "image2d_msaa_ro_t", "image2d_array_msaa_ro_t", "image2d_msaa_depth_ro_t", "image2d_array_msaa_depth_ro_t", "image3d_ro_t", "image1d_wo_t", "image1d_array_wo_t", "image1d_buffer_wo_t", "image2d_wo_t", "image2d_array_wo_t", "image2d_depth_wo_t", "image2d_array_depth_wo_t", "image2d_msaa_wo_t", "image2d_array_msaa_wo_t", "image2d_msaa_depth_wo_t", "image2d_array_msaa_depth_wo_t", "image3d_wo_t", "image1d_rw_t", "image1d_array_rw_t", "image1d_buffer_rw_t", "image2d_rw_t", "image2d_array_rw_t", "image2d_depth_rw_t", "image2d_array_depth_rw_t", "image2d_msaa_rw_t", "image2d_array_msaa_rw_t", "image2d_msaa_depth_rw_t", "image2d_array_msaa_depth_rw_t", "image3d_rw_t", "event_t", "pipe_ro_t", "pipe_wo_t", "reserve_id_t", "queue_t", "ndrange_t", "clk_event_t", "sampler_t", "kernel_enqueue_flags_t", "clk_profiling_info", "memory_order", "memory_scope", "intel_sub_group_avc_mce_payload_t", "intel_sub_group_avc_ime_payload_t", "intel_sub_group_avc_ref_payload_t", "intel_sub_group_avc_sic_payload_t", "intel_sub_group_avc_mce_result_t", "intel_sub_group_avc_ime_result_t", "intel_sub_group_avc_ref_result_t", "intel_sub_group_avc_sic_result_t", "intel_sub_group_avc_ime_result_single_reference_streamout_t", "intel_sub_group_avc_ime_result_dual_reference_streamout_t", "intel_sub_group_avc_ime_result_single_reference_streamin_t", "intel_sub_group_avc_ime_result_dual_reference_streamin_t" }; const char *MangledTypes[PRIMITIVE_NUM] = { "b", // BOOL "h", // UCHAR "c", // CHAR "t", // USHORT "s", // SHORT "j", // UINT "i", // INT "m", // ULONG "l", // LONG "Dh", // HALF "f", // FLOAT "d", // DOUBLE "v", // VOID "z", // VarArg "14ocl_image1d_ro", // PRIMITIVE_IMAGE1D_RO_T "20ocl_image1d_array_ro", // PRIMITIVE_IMAGE1D_ARRAY_RO_T "21ocl_image1d_buffer_ro", // PRIMITIVE_IMAGE1D_BUFFER_RO_T "14ocl_image2d_ro", // PRIMITIVE_IMAGE2D_RO_T "20ocl_image2d_array_ro", // PRIMITIVE_IMAGE2D_ARRAY_RO_T "20ocl_image2d_depth_ro", // PRIMITIVE_IMAGE2D_DEPTH_RO_T "26ocl_image2d_array_depth_ro", // PRIMITIVE_IMAGE2D_ARRAY_DEPTH_RO_T "19ocl_image2d_msaa_ro", // PRIMITIVE_IMAGE2D_MSAA_RO_T "25ocl_image2d_array_msaa_ro", // PRIMITIVE_IMAGE2D_ARRAY_MSAA_RO_T "25ocl_image2d_msaa_depth_ro", // PRIMITIVE_IMAGE2D_MSAA_DEPTH_RO_T "31ocl_image2d_array_msaa_depth_ro", // PRIMITIVE_IMAGE2D_ARRAY_MSAA_DEPTH_RO_T "14ocl_image3d_ro", // PRIMITIVE_IMAGE3D_RO_T "14ocl_image1d_wo", // PRIMITIVE_IMAGE1D_WO_T "20ocl_image1d_array_wo", // PRIMITIVE_IMAGE1D_ARRAY_WO_T "21ocl_image1d_buffer_wo", // PRIMITIVE_IMAGE1D_BUFFER_WO_T "14ocl_image2d_wo", // PRIMITIVE_IMAGE2D_WO_T "20ocl_image2d_array_wo", // PRIMITIVE_IMAGE2D_ARRAY_WO_T "20ocl_image2d_depth_wo", // PRIMITIVE_IMAGE2D_DEPTH_WO_T "26ocl_image2d_array_depth_wo", // PRIMITIVE_IMAGE2D_ARRAY_DEPTH_WO_T "19ocl_image2d_msaa_wo", // PRIMITIVE_IMAGE2D_MSAA_WO_T "25ocl_image2d_array_msaa_wo", // PRIMITIVE_IMAGE2D_ARRAY_MSAA_WO_T "25ocl_image2d_msaa_depth_wo", // PRIMITIVE_IMAGE2D_MSAA_DEPTH_WO_T "31ocl_image2d_array_msaa_depth_wo", // PRIMITIVE_IMAGE2D_ARRAY_MSAA_DEPTH_WO_T "14ocl_image3d_wo", // PRIMITIVE_IMAGE3D_WO_T "14ocl_image1d_rw", // PRIMITIVE_IMAGE1D_RW_T "20ocl_image1d_array_rw", // PRIMITIVE_IMAGE1D_ARRAY_RW_T "21ocl_image1d_buffer_rw", // PRIMITIVE_IMAGE1D_BUFFER_RW_T "14ocl_image2d_rw", // PRIMITIVE_IMAGE2D_RW_T "20ocl_image2d_array_rw", // PRIMITIVE_IMAGE2D_ARRAY_RW_T "20ocl_image2d_depth_rw", // PRIMITIVE_IMAGE2D_DEPTH_RW_T "26ocl_image2d_array_depth_rw", // PRIMITIVE_IMAGE2D_ARRAY_DEPTH_RW_T "19ocl_image2d_msaa_rw", // PRIMITIVE_IMAGE2D_MSAA_RW_T "25ocl_image2d_array_msaa_rw", // PRIMITIVE_IMAGE2D_ARRAY_MSAA_RW_T "25ocl_image2d_msaa_depth_rw", // PRIMITIVE_IMAGE2D_MSAA_DEPTH_RW_T "31ocl_image2d_array_msaa_depth_rw", // PRIMITIVE_IMAGE2D_ARRAY_MSAA_DEPTH_RW_T "14ocl_image3d_rw", // PRIMITIVE_IMAGE3D_RW_T "9ocl_event", // PRIMITIVE_EVENT_T "11ocl_pipe_ro", // PRIMITIVE_PIPE_RO_T "11ocl_pipe_wo", // PRIMITIVE_PIPE_WO_T "13ocl_reserveid", // PRIMITIVE_RESERVE_ID_T "9ocl_queue", // PRIMITIVE_QUEUE_T "9ndrange_t", // PRIMITIVE_NDRANGE_T "12ocl_clkevent", // PRIMITIVE_CLK_EVENT_T "11ocl_sampler", // PRIMITIVE_SAMPLER_T "i", // PRIMITIVE_KERNEL_ENQUEUE_FLAGS_T "i", // PRIMITIVE_CLK_PROFILING_INFO #if defined(SPIRV_SPIR20_MANGLING_REQUIREMENTS) "i", // PRIMITIVE_MEMORY_ORDER "i", // PRIMITIVE_MEMORY_SCOPE #else "12memory_order", // PRIMITIVE_MEMORY_ORDER "12memory_scope", // PRIMITIVE_MEMORY_SCOPE #endif "37ocl_intel_sub_group_avc_mce_payload_t", // PRIMITIVE_SUB_GROUP_AVC_MCE_PAYLOAD_T "37ocl_intel_sub_group_avc_ime_payload_t", // PRIMITIVE_SUB_GROUP_AVC_IME_PAYLOAD_T "37ocl_intel_sub_group_avc_ref_payload_t", // PRIMITIVE_SUB_GROUP_AVC_REF_PAYLOAD_T "37ocl_intel_sub_group_avc_sic_payload_t", // PRIMITIVE_SUB_GROUP_AVC_SIC_PAYLOAD_T "36ocl_intel_sub_group_avc_mce_result_t", // PRIMITIVE_SUB_GROUP_AVC_MCE_RESULT_T "36ocl_intel_sub_group_avc_ime_result_t", // PRIMITIVE_SUB_GROUP_AVC_IME_RESULT_T "36ocl_intel_sub_group_avc_ref_result_t", // PRIMITIVE_SUB_GROUP_AVC_REF_RESULT_T "36ocl_intel_sub_group_avc_sic_result_t", // PRIMITIVE_SUB_GROUP_AVC_REF_RESULT_T "63ocl_intel_sub_group_avc_ime_result_single_reference_streamout_t", // PRIMITIVE_SUB_GROUP_AVC_IME_SINGLE_REF_STREAMOUT_T "61ocl_intel_sub_group_avc_ime_result_dual_reference_streamout_t", // PRIMITIVE_SUB_GROUP_AVC_IME_DUAL_REF_STREAMOUT_T "55ocl_intel_sub_group_avc_ime_single_reference_streamin_t", // PRIMITIVE_SUB_GROUP_AVC_IME_SINGLE_REF_STREAMIN_T "53ocl_intel_sub_group_avc_ime_dual_reference_streamin_t" // PRIMITIVE_SUB_GROUP_AVC_IME_DUAL_REF_STREAMIN_T }; const char *ReadableAttribute[ATTR_NUM] = { "restrict", "volatile", "const", "__private", "__global", "__constant", "__local", "__generic", }; const char *MangledAttribute[ATTR_NUM] = { "r", "V", "K", "", "U3AS1", "U3AS2", "U3AS3", "U3AS4", }; // SPIR supported version - stated version is oldest supported version. static const SPIRversion PrimitiveSupportedVersions[PRIMITIVE_NUM] = { SPIR12, // BOOL SPIR12, // UCHAR SPIR12, // CHAR SPIR12, // USHORT SPIR12, // SHORT SPIR12, // UINT SPIR12, // INT SPIR12, // ULONG SPIR12, // LONG SPIR12, // HALF SPIR12, // FLOAT SPIR12, // DOUBLE SPIR12, // VOID SPIR12, // VarArg SPIR12, // PRIMITIVE_IMAGE1D_RO_T SPIR12, // PRIMITIVE_IMAGE1D_ARRAY_RO_T SPIR12, // PRIMITIVE_IMAGE1D_BUFFER_RO_T SPIR12, // PRIMITIVE_IMAGE2D_RO_T SPIR12, // PRIMITIVE_IMAGE2D_ARRAY_RO_T SPIR12, // PRIMITIVE_IMAGE2D_DEPTH_RO_T SPIR12, // PRIMITIVE_IMAGE2D_ARRAY_DEPTH_RO_T SPIR12, // PRIMITIVE_IMAGE2D_MSAA_RO_T SPIR12, // PRIMITIVE_IMAGE2D_ARRAY_MSAA_RO_T SPIR12, // PRIMITIVE_IMAGE2D_MSAA_DEPTH_RO_T SPIR12, // PRIMITIVE_IMAGE2D_ARRAY_MSAA_DEPTH_RO_T SPIR12, // PRIMITIVE_IMAGE3D_RO_T SPIR12, // PRIMITIVE_IMAGE1D_WO_T SPIR12, // PRIMITIVE_IMAGE1D_ARRAY_WO_T SPIR12, // PRIMITIVE_IMAGE1D_BUFFER_WO_T SPIR12, // PRIMITIVE_IMAGE2D_WO_T SPIR12, // PRIMITIVE_IMAGE2D_ARRAY_WO_T SPIR12, // PRIMITIVE_IMAGE2D_DEPTH_WO_T SPIR12, // PRIMITIVE_IMAGE2D_ARRAY_DEPTH_WO_T SPIR12, // PRIMITIVE_IMAGE2D_MSAA_WO_T SPIR12, // PRIMITIVE_IMAGE2D_ARRAY_MSAA_WO_T SPIR12, // PRIMITIVE_IMAGE2D_MSAA_DEPTH_WO_T SPIR12, // PRIMITIVE_IMAGE2D_ARRAY_MSAA_DEPTH_WO_T SPIR12, // PRIMITIVE_IMAGE3D_WO_T SPIR12, // PRIMITIVE_IMAGE1D_RW_T SPIR12, // PRIMITIVE_IMAGE1D_ARRAY_RW_T SPIR12, // PRIMITIVE_IMAGE1D_BUFFER_RW_T SPIR12, // PRIMITIVE_IMAGE2D_RW_T SPIR12, // PRIMITIVE_IMAGE2D_ARRAY_RW_T SPIR12, // PRIMITIVE_IMAGE2D_DEPTH_RW_T SPIR12, // PRIMITIVE_IMAGE2D_ARRAY_DEPTH_RW_T SPIR12, // PRIMITIVE_IMAGE2D_MSAA_RW_T SPIR12, // PRIMITIVE_IMAGE2D_ARRAY_MSAA_RW_T SPIR12, // PRIMITIVE_IMAGE2D_MSAA_DEPTH_RW_T SPIR12, // PRIMITIVE_IMAGE2D_ARRAY_MSAA_DEPTH_RW_T SPIR12, // PRIMITIVE_IMAGE3D_RW_T SPIR12, // PRIMITIVE_EVENT_T SPIR20, // PRIMITIVE_PIPE_RO_T SPIR20, // PRIMITIVE_PIPE_WO_T SPIR20, // PRIMITIVE_RESERVE_ID_T SPIR20, // PRIMITIVE_QUEUE_T SPIR20, // PRIMITIVE_NDRANGE_T SPIR20, // PRIMITIVE_CLK_EVENT_T SPIR12 // PRIMITIVE_SAMPLER_T }; const char *mangledPrimitiveString(TypePrimitiveEnum T) { return MangledTypes[T]; } const char *readablePrimitiveString(TypePrimitiveEnum T) { return PrimitiveNames[T]; } const char *getMangledAttribute(TypeAttributeEnum Attribute) { return MangledAttribute[Attribute]; } const char *getReadableAttribute(TypeAttributeEnum Attribute) { return ReadableAttribute[Attribute]; } SPIRversion getSupportedVersion(TypePrimitiveEnum T) { return PrimitiveSupportedVersions[T]; } const char *mangledPrimitiveStringfromName(std::string Type) { for (size_t I = 0; I < (sizeof(PrimitiveNames) / sizeof(PrimitiveNames[0])); I++) if (Type == PrimitiveNames[I]) return MangledTypes[I]; return NULL; } const char *getSPIRVersionAsString(SPIRversion Version) { switch (Version) { case SPIR12: return "SPIR 1.2"; case SPIR20: return "SPIR 2.0"; } assert(false && "Unknown SPIR Version"); return "Unknown SPIR Version"; } } // namespace SPIR SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/Mangler/ManglingUtils.h000066400000000000000000000017341363521741200233670ustar00rootroot00000000000000//===------------------------- ManglingUtils.h ---------------------------===// // // SPIR Tools // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===---------------------------------------------------------------------===// /* * Contributed by: Intel Corporation. */ #ifndef SPIRV_MANGLER_MANGLINGUTILS_H #define SPIRV_MANGLER_MANGLINGUTILS_H #include "ParameterType.h" namespace SPIR { const char *mangledPrimitiveString(TypePrimitiveEnum Primitive); const char *readablePrimitiveString(TypePrimitiveEnum Primitive); const char *getMangledAttribute(TypeAttributeEnum Attribute); const char *getReadableAttribute(TypeAttributeEnum Attribute); SPIRversion getSupportedVersion(TypePrimitiveEnum T); const char *getSPIRVersionAsString(SPIRversion Version); const char *mangledPrimitiveStringfromName(std::string Type); } // namespace SPIR #endif // SPIRV_MANGLER_MANGLINGUTILS_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/Mangler/NameMangleAPI.h000066400000000000000000000025211363521741200231430ustar00rootroot00000000000000//===------------------------- NameMangleAPI.h ---------------------------===// // // SPIR Tools // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===---------------------------------------------------------------------===// /* * Contributed by: Intel Corporation. */ #ifndef SPIRV_MANGLER_NAMEMANGLEAPI_H #define SPIRV_MANGLER_NAMEMANGLEAPI_H #include "FunctionDescriptor.h" #include namespace SPIR { struct NameMangler { /// @brief Constructor. /// @param SPIRversion spir version to mangle according to. NameMangler(SPIRversion); /// @brief Converts the given function descriptor to string that represents /// the function's prototype. /// The mangling algorithm is based on Itanium mangling algorithm /// (http://sourcery.mentor.com/public/cxx-abi/abi.html#mangling), with /// SPIR extensions. /// @param FunctionDescriptor function to be mangled. /// @param std::string the mangled name if the mangling succeeds, /// the error otherwise. /// @return MangleError enum representing the status - success or the error. MangleError mangle(const FunctionDescriptor &, std::string &); private: SPIRversion SpirVersion; }; } // namespace SPIR #endif // SPIRV_MANGLER_NAMEMANGLEAPI_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/Mangler/ParameterType.cpp000066400000000000000000000141731363521741200237300ustar00rootroot00000000000000//===------------------------ ParameterType.cpp --------------------------===// // // SPIR Tools // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===---------------------------------------------------------------------===// /* * Contributed by: Intel Corporation. */ #include "ParameterType.h" #include "ManglingUtils.h" #include #include #include namespace SPIR { // // Primitive Type // PrimitiveType::PrimitiveType(TypePrimitiveEnum Primitive) : ParamType(TYPE_ID_PRIMITIVE), Primitive(Primitive) {} MangleError PrimitiveType::accept(TypeVisitor *Visitor) const { if (getSupportedVersion(this->getPrimitive()) >= SPIR20 && Visitor->SpirVer < SPIR20) { return MANGLE_TYPE_NOT_SUPPORTED; } return Visitor->visit(this); } std::string PrimitiveType::toString() const { assert((Primitive >= PRIMITIVE_FIRST && Primitive <= PRIMITIVE_LAST) && "illegal primitive"); std::stringstream MyName; MyName << readablePrimitiveString(Primitive); return MyName.str(); } bool PrimitiveType::equals(const ParamType *Type) const { const PrimitiveType *P = SPIR::dynCast(Type); return P && (Primitive == P->Primitive); } // // Pointer Type // PointerType::PointerType(const RefParamType Type) : ParamType(TYPE_ID_POINTER), PType(Type) { for (unsigned int I = ATTR_QUALIFIER_FIRST; I <= ATTR_QUALIFIER_LAST; I++) { setQualifier((TypeAttributeEnum)I, false); } AddressSpace = ATTR_PRIVATE; } MangleError PointerType::accept(TypeVisitor *Visitor) const { return Visitor->visit(this); } void PointerType::setAddressSpace(TypeAttributeEnum Attr) { if (Attr < ATTR_ADDR_SPACE_FIRST || Attr > ATTR_ADDR_SPACE_LAST) { return; } AddressSpace = Attr; } TypeAttributeEnum PointerType::getAddressSpace() const { return AddressSpace; } void PointerType::setQualifier(TypeAttributeEnum Qual, bool Enabled) { if (Qual < ATTR_QUALIFIER_FIRST || Qual > ATTR_QUALIFIER_LAST) { return; } Qualifiers[Qual - ATTR_QUALIFIER_FIRST] = Enabled; } bool PointerType::hasQualifier(TypeAttributeEnum Qual) const { if (Qual < ATTR_QUALIFIER_FIRST || Qual > ATTR_QUALIFIER_LAST) { return false; } return Qualifiers[Qual - ATTR_QUALIFIER_FIRST]; } std::string PointerType::toString() const { std::stringstream MyName; for (unsigned int I = ATTR_QUALIFIER_FIRST; I <= ATTR_QUALIFIER_LAST; I++) { TypeAttributeEnum Qual = (TypeAttributeEnum)I; if (hasQualifier(Qual)) { MyName << getReadableAttribute(Qual) << " "; } } MyName << getReadableAttribute(TypeAttributeEnum(AddressSpace)) << " "; MyName << getPointee()->toString() << " *"; return MyName.str(); } bool PointerType::equals(const ParamType *Type) const { const PointerType *P = SPIR::dynCast(Type); if (!P) { return false; } if (getAddressSpace() != P->getAddressSpace()) { return false; } for (unsigned int I = ATTR_QUALIFIER_FIRST; I <= ATTR_QUALIFIER_LAST; I++) { TypeAttributeEnum Qual = (TypeAttributeEnum)I; if (hasQualifier(Qual) != P->hasQualifier(Qual)) { return false; } } return (*getPointee()).equals(&*(P->getPointee())); } // // Vector Type // VectorType::VectorType(const RefParamType Type, int Len) : ParamType(TYPE_ID_VECTOR), PType(Type), Len(Len) {} MangleError VectorType::accept(TypeVisitor *Visitor) const { return Visitor->visit(this); } std::string VectorType::toString() const { std::stringstream MyName; MyName << getScalarType()->toString(); MyName << Len; return MyName.str(); } bool VectorType::equals(const ParamType *Type) const { const VectorType *PVec = SPIR::dynCast(Type); return PVec && (Len == PVec->Len) && (*getScalarType()).equals(&*(PVec->getScalarType())); } // // Atomic Type // AtomicType::AtomicType(const RefParamType Type) : ParamType(TYPE_ID_ATOMIC), PType(Type) {} MangleError AtomicType::accept(TypeVisitor *Visitor) const { if (Visitor->SpirVer < SPIR20) { return MANGLE_TYPE_NOT_SUPPORTED; } return Visitor->visit(this); } std::string AtomicType::toString() const { std::stringstream MyName; MyName << "atomic_" << getBaseType()->toString(); return MyName.str(); } bool AtomicType::equals(const ParamType *Type) const { const AtomicType *A = dynCast(Type); return (A && (*getBaseType()).equals(&*(A->getBaseType()))); } // // Block Type // BlockType::BlockType() : ParamType(TYPE_ID_BLOCK) {} MangleError BlockType::accept(TypeVisitor *Visitor) const { if (Visitor->SpirVer < SPIR20) { return MANGLE_TYPE_NOT_SUPPORTED; } return Visitor->visit(this); } std::string BlockType::toString() const { std::stringstream MyName; MyName << "void ("; for (unsigned int I = 0; I < getNumOfParams(); ++I) { if (I > 0) MyName << ", "; MyName << Params[I]->toString(); } MyName << ")*"; return MyName.str(); } bool BlockType::equals(const ParamType *Type) const { const BlockType *PBlock = dynCast(Type); if (!PBlock || getNumOfParams() != PBlock->getNumOfParams()) { return false; } for (unsigned int I = 0; I < getNumOfParams(); ++I) { if (!getParam(I)->equals(&*PBlock->getParam(I))) { return false; } } return true; } // // User Defined Type // UserDefinedType::UserDefinedType(const std::string &Name) : ParamType(TYPE_ID_STRUCTURE), Name(Name) {} MangleError UserDefinedType::accept(TypeVisitor *Visitor) const { return Visitor->visit(this); } std::string UserDefinedType::toString() const { std::stringstream MyName; MyName << Name; return MyName.str(); } bool UserDefinedType::equals(const ParamType *PType) const { const UserDefinedType *PTy = SPIR::dynCast(PType); return PTy && (Name == PTy->Name); } // // Static enums // const TypeEnum PrimitiveType::EnumTy = TYPE_ID_PRIMITIVE; const TypeEnum PointerType::EnumTy = TYPE_ID_POINTER; const TypeEnum VectorType::EnumTy = TYPE_ID_VECTOR; const TypeEnum AtomicType::EnumTy = TYPE_ID_ATOMIC; const TypeEnum BlockType::EnumTy = TYPE_ID_BLOCK; const TypeEnum UserDefinedType::EnumTy = TYPE_ID_STRUCTURE; } // namespace SPIR SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/Mangler/ParameterType.h000066400000000000000000000372031363521741200233740ustar00rootroot00000000000000//===------------------------- ParameterType.h ---------------------------===// // // SPIR Tools // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===---------------------------------------------------------------------===// /* * Contributed by: Intel Corporation. */ #ifndef SPIRV_MANGLER_PARAMETERTYPE_H #define SPIRV_MANGLER_PARAMETERTYPE_H #include "Refcount.h" #include #include // The Type class hierarchy models the different types in OCL. namespace SPIR { // Supported SPIR versions enum SPIRversion { SPIR12 = 1, SPIR20 = 2 }; // Error Status values enum MangleError { MANGLE_SUCCESS, MANGLE_TYPE_NOT_SUPPORTED, MANGLE_NULL_FUNC_DESCRIPTOR }; enum TypePrimitiveEnum { PRIMITIVE_FIRST, PRIMITIVE_BOOL = PRIMITIVE_FIRST, PRIMITIVE_UCHAR, PRIMITIVE_CHAR, PRIMITIVE_USHORT, PRIMITIVE_SHORT, PRIMITIVE_UINT, PRIMITIVE_INT, PRIMITIVE_ULONG, PRIMITIVE_LONG, PRIMITIVE_HALF, PRIMITIVE_FLOAT, PRIMITIVE_DOUBLE, PRIMITIVE_VOID, PRIMITIVE_VAR_ARG, PRIMITIVE_STRUCT_FIRST, PRIMITIVE_IMAGE1D_RO_T = PRIMITIVE_STRUCT_FIRST, PRIMITIVE_IMAGE1D_ARRAY_RO_T, PRIMITIVE_IMAGE1D_BUFFER_RO_T, PRIMITIVE_IMAGE2D_RO_T, PRIMITIVE_IMAGE2D_ARRAY_RO_T, PRIMITIVE_IMAGE2D_DEPTH_RO_T, PRIMITIVE_IMAGE2D_ARRAY_DEPTH_RO_T, PRIMITIVE_IMAGE2D_MSAA_RO_T, PRIMITIVE_IMAGE2D_ARRAY_MSAA_RO_T, PRIMITIVE_IMAGE2D_MSAA_DEPTH_RO_T, PRIMITIVE_IMAGE2D_ARRAY_MSAA_DEPTH_RO_T, PRIMITIVE_IMAGE3D_RO_T, PRIMITIVE_IMAGE1D_WO_T, PRIMITIVE_IMAGE1D_ARRAY_WO_T, PRIMITIVE_IMAGE1D_BUFFER_WO_T, PRIMITIVE_IMAGE2D_WO_T, PRIMITIVE_IMAGE2D_ARRAY_WO_T, PRIMITIVE_IMAGE2D_DEPTH_WO_T, PRIMITIVE_IMAGE2D_ARRAY_DEPTH_WO_T, PRIMITIVE_IMAGE2D_MSAA_WO_T, PRIMITIVE_IMAGE2D_ARRAY_MSAA_WO_T, PRIMITIVE_IMAGE2D_MSAA_DEPTH_WO_T, PRIMITIVE_IMAGE2D_ARRAY_MSAA_DEPTH_WO_T, PRIMITIVE_IMAGE3D_WO_T, PRIMITIVE_IMAGE1D_RW_T, PRIMITIVE_IMAGE1D_ARRAY_RW_T, PRIMITIVE_IMAGE1D_BUFFER_RW_T, PRIMITIVE_IMAGE2D_RW_T, PRIMITIVE_IMAGE2D_ARRAY_RW_T, PRIMITIVE_IMAGE2D_DEPTH_RW_T, PRIMITIVE_IMAGE2D_ARRAY_DEPTH_RW_T, PRIMITIVE_IMAGE2D_MSAA_RW_T, PRIMITIVE_IMAGE2D_ARRAY_MSAA_RW_T, PRIMITIVE_IMAGE2D_MSAA_DEPTH_RW_T, PRIMITIVE_IMAGE2D_ARRAY_MSAA_DEPTH_RW_T, PRIMITIVE_IMAGE3D_RW_T, PRIMITIVE_EVENT_T, PRIMITIVE_PIPE_RO_T, PRIMITIVE_PIPE_WO_T, PRIMITIVE_RESERVE_ID_T, PRIMITIVE_QUEUE_T, PRIMITIVE_NDRANGE_T, PRIMITIVE_CLK_EVENT_T, PRIMITIVE_STRUCT_LAST = PRIMITIVE_CLK_EVENT_T, PRIMITIVE_SAMPLER_T, PRIMITIVE_KERNEL_ENQUEUE_FLAGS_T, PRIMITIVE_CLK_PROFILING_INFO, PRIMITIVE_MEMORY_ORDER, PRIMITIVE_MEMORY_SCOPE, PRIMITIVE_SUB_GROUP_AVC_MCE_PAYLOAD_T, PRIMITIVE_SUB_GROUP_AVC_IME_PAYLOAD_T, PRIMITIVE_SUB_GROUP_AVC_REF_PAYLOAD_T, PRIMITIVE_SUB_GROUP_AVC_SIC_PAYLOAD_T, PRIMITIVE_SUB_GROUP_AVC_MCE_RESULT_T, PRIMITIVE_SUB_GROUP_AVC_IME_RESULT_T, PRIMITIVE_SUB_GROUP_AVC_REF_RESULT_T, PRIMITIVE_SUB_GROUP_AVC_SIC_RESULT_T, PRIMITIVE_SUB_GROUP_AVC_IME_SINGLE_REF_STREAMOUT_T, PRIMITIVE_SUB_GROUP_AVC_IME_DUAL_REF_STREAMOUT_T, PRIMITIVE_SUB_GROUP_AVC_IME_SINGLE_REF_STREAMIN_T, PRIMITIVE_SUB_GROUP_AVC_IME_DUAL_REF_STREAMIN_T, PRIMITIVE_LAST = PRIMITIVE_SUB_GROUP_AVC_IME_DUAL_REF_STREAMIN_T, PRIMITIVE_NONE, // Keep this at the end. PRIMITIVE_NUM = PRIMITIVE_NONE }; enum TypeEnum { TYPE_ID_PRIMITIVE, TYPE_ID_POINTER, TYPE_ID_VECTOR, TYPE_ID_ATOMIC, TYPE_ID_BLOCK, TYPE_ID_STRUCTURE }; enum TypeAttributeEnum { ATTR_QUALIFIER_FIRST = 0, ATTR_RESTRICT = ATTR_QUALIFIER_FIRST, ATTR_VOLATILE, ATTR_CONST, ATTR_QUALIFIER_LAST = ATTR_CONST, ATTR_ADDR_SPACE_FIRST, ATTR_PRIVATE = ATTR_ADDR_SPACE_FIRST, ATTR_GLOBAL, ATTR_CONSTANT, ATTR_LOCAL, ATTR_GENERIC, ATTR_ADDR_SPACE_LAST = ATTR_GENERIC, ATTR_NONE, ATTR_NUM = ATTR_NONE }; // Forward declaration for abstract structure. struct ParamType; typedef RefCount RefParamType; // Forward declaration for abstract structure. struct TypeVisitor; struct ParamType { /// @brief Constructor. /// @param TypeEnum type id. ParamType(TypeEnum TypeId) : TypeId(TypeId){}; /// @brief Destructor. virtual ~ParamType(){}; /// Abstract Methods /// /// @brief Visitor service method. (see TypeVisitor for more details). /// When overridden in subclasses, preform a 'double dispatch' to the /// appropriate visit method in the given visitor. /// @param TypeVisitor type visitor. virtual MangleError accept(TypeVisitor *) const = 0; /// @brief Returns a string representation of the underlying type. /// @return type as string. virtual std::string toString() const = 0; /// @brief Returns true if given param type is equal to this type. /// @param ParamType given param type. /// @return true if given param type is equal to this type and false /// otherwise. virtual bool equals(const ParamType *) const = 0; /// Common Base-Class Methods /// /// @brief Returns type id of underlying type. /// @return type id. TypeEnum getTypeId() const { return TypeId; } private: // @brief Default Constructor. ParamType(); protected: /// An enumeration to identify the type id of this instance. TypeEnum TypeId; }; struct PrimitiveType : public ParamType { /// An enumeration to identify the type id of this class. const static TypeEnum EnumTy; /// @brief Constructor. /// @param TypePrimitiveEnum primitive id. PrimitiveType(TypePrimitiveEnum); /// Implementation of Abstract Methods /// /// @brief Visitor service method. (see TypeVisitor for more details). /// When overridden in subclasses, preform a 'double dispatch' to the /// appropriate visit method in the given visitor. /// @param TypeVisitor type visitor. MangleError accept(TypeVisitor *) const override; /// @brief Returns a string representation of the underlying type. /// @return type as string. std::string toString() const override; /// @brief Returns true if given param type is equal to this type. /// @param ParamType given param type. /// @return true if given param type is equal to this type and false /// otherwise. bool equals(const ParamType *) const override; /// Non-Common Methods /// /// @brief Returns the primitive enumeration of the type. /// @return primitive type. TypePrimitiveEnum getPrimitive() const { return Primitive; } protected: /// An enumeration to identify the primitive type. TypePrimitiveEnum Primitive; }; struct PointerType : public ParamType { /// An enumeration to identify the type id of this class. const static TypeEnum EnumTy; /// @brief Constructor. /// @param RefParamType the type of pointee (that the pointer points at). PointerType(const RefParamType Type); /// Implementation of Abstract Methods /// /// @brief Visitor service method. (see TypeVisitor for more details). /// When overridden in subclasses, preform a 'double dispatch' to the /// appropriate visit method in the given visitor. /// @param TypeVisitor type visitor MangleError accept(TypeVisitor *) const override; /// @brief Returns a string representation of the underlying type. /// @return type as string. std::string toString() const override; /// @brief Returns true if given param type is equal to this type. /// @param ParamType given param type. /// @return true if given param type is equal to this type and false /// otherwise. bool equals(const ParamType *) const override; /// Non-Common Methods /// /// @brief Returns the type the pointer is pointing at. /// @return pointee type. const RefParamType &getPointee() const { return PType; } /// @brief Sets the address space attribute - default is __private /// @param TypeAttributeEnum address space attribute id. void setAddressSpace(TypeAttributeEnum Attr); /// @brief Returns the pointer's address space. /// @return pointer's address space. TypeAttributeEnum getAddressSpace() const; /// @brief Adds or removes a pointer's qualifier. /// @param TypeAttributeEnum qual - qualifier to add/remove. /// @param bool enabled - true if qualifier should exist false otherwise. /// default is set to false. void setQualifier(TypeAttributeEnum Qual, bool Enabled); /// @brief Checks if the pointer has a certain qualifier. /// @param TypeAttributeEnum qual - qualifier to check. /// @return true if the qualifier exists and false otherwise. bool hasQualifier(TypeAttributeEnum Qual) const; private: /// The type this pointer is pointing at. RefParamType PType; /// Array of the pointer's enabled type qualifiers. bool Qualifiers[ATTR_QUALIFIER_LAST - ATTR_QUALIFIER_FIRST + 1]; /// Pointer's address space. TypeAttributeEnum AddressSpace; }; struct VectorType : public ParamType { /// An enumeration to identify the type id of this class. const static TypeEnum EnumTy; /// @brief Constructor. /// @param RefParamType the type of each scalar element in the vector. /// @param int the length of the vector. VectorType(const RefParamType Type, int Len); /// Implementation of Abstract Methods /// /// @brief Visitor service method. (see TypeVisitor for more details). /// When overridden in subclasses, preform a 'double dispatch' to the /// appropriate visit method in the given visitor. /// @param TypeVisitor type visitor. MangleError accept(TypeVisitor *) const override; /// @brief Returns a string representation of the underlying type. /// @return type as string. std::string toString() const override; /// @brief Returns true if given param type is equal to this type. /// @param ParamType given param type. /// @return true if given param type is equal to this type and false /// otherwise. bool equals(const ParamType *) const override; /// Non-Common Methods /// /// @brief Returns the type the vector is packing. /// @return scalar type. const RefParamType &getScalarType() const { return PType; } /// @brief Returns the length of the vector type. /// @return vector type length. int getLength() const { return Len; } private: /// The scalar type of this vector type. RefParamType PType; /// The length of the vector. int Len; }; struct AtomicType : public ParamType { /// an enumeration to identify the type id of this class const static TypeEnum EnumTy; /// @brief Constructor /// @param RefParamType the type refernced as atomic. AtomicType(const RefParamType Type); /// Implementation of Abstract Methods /// /// @brief visitor service method. (see TypeVisitor for more details). /// When overridden in subclasses, preform a 'double dispatch' to the /// appropriate visit method in the given visitor. /// @param TypeVisitor type visitor MangleError accept(TypeVisitor *) const override; /// @brief returns a string representation of the underlying type. /// @return type as string std::string toString() const override; /// @brief returns true if given param type is equal to this type. /// @param ParamType given param type /// @return true if given param type is equal to this type and false otherwise bool equals(const ParamType *) const override; /// Non-Common Methods /// /// @brief returns the base type of the atomic parameter. /// @return base type const RefParamType &getBaseType() const { return PType; } private: /// the type this pointer is pointing at RefParamType PType; }; struct BlockType : public ParamType { /// an enumeration to identify the type id of this class const static TypeEnum EnumTy; ///@brief Constructor BlockType(); /// Implementation of Abstract Methods /// /// @brief visitor service method. (see TypeVisitor for more details). /// When overridden in subclasses, preform a 'double dispatch' to the /// appropriate visit method in the given visitor. /// @param TypeVisitor type visitor MangleError accept(TypeVisitor *) const override; /// @brief returns a string representation of the underlying type. /// @return type as string std::string toString() const override; /// @brief returns true if given param type is equal to this type. /// @param ParamType given param type /// @return true if given param type is equal to this type and false otherwise bool equals(const ParamType *) const override; /// Non-Common Methods /// /// @brief returns the number of parameters of the block. /// @return parameters count unsigned int getNumOfParams() const { return (unsigned int)Params.size(); } ///@brief returns the type of parameter "index" of the block. // @param index the sequential number of the queried parameter ///@return parameter type const RefParamType &getParam(unsigned int Index) const { assert(Params.size() > Index && "index is OOB"); return Params[Index]; } ///@brief set the type of parameter "index" of the block. // @param index the sequential number of the queried parameter // @param type the parameter type void setParam(unsigned int Index, RefParamType Type) { if (Index < getNumOfParams()) { Params[Index] = Type; } else if (Index == getNumOfParams()) { Params.push_back(Type); } else { assert(false && "index is OOB"); } } protected: /// an enumeration to identify the primitive type std::vector Params; }; struct UserDefinedType : public ParamType { /// An enumeration to identify the type id of this class. const static TypeEnum EnumTy; /// @brief Constructor. UserDefinedType(const std::string &); /// Implementation of Abstract Methods /// /// @brief Visitor service method. (see TypeVisitor for more details). /// When overridden in subclasses, preform a 'double dispatch' to the /// appropriate visit method in the given visitor. /// @param TypeVisitor type visitor. MangleError accept(TypeVisitor *) const override; /// @brief Returns a string representation of the underlying type. /// @return type as string. std::string toString() const override; /// @brief Returns true if given param type is equal to this type. /// @param ParamType given param type. /// @return true if given param type is equal to this type and false /// otherwise. bool equals(const ParamType *) const override; protected: /// The name of the user defined type. std::string Name; }; /// @brief Can be overridden so an object of static type Type* will /// dispatch the correct visit method according to its dynamic type. struct TypeVisitor { SPIRversion SpirVer; TypeVisitor(SPIRversion Ver) : SpirVer(Ver) {} virtual ~TypeVisitor() {} virtual MangleError visit(const PrimitiveType *) = 0; virtual MangleError visit(const VectorType *) = 0; virtual MangleError visit(const PointerType *) = 0; virtual MangleError visit(const AtomicType *) = 0; virtual MangleError visit(const BlockType *) = 0; virtual MangleError visit(const UserDefinedType *) = 0; }; /// @brief Template dynamic cast function for ParamType derived classes. /// @param ParamType given param type. /// @return required casting type if given param type is an instance if // that type, NULL otherwise. template T *dynCast(ParamType *PType) { assert(PType && "dyn_cast does not support casting of NULL"); return (T::EnumTy == PType->getTypeId()) ? (T *)PType : NULL; } /// @brief Template dynamic cast function for ParamType derived classes /// (the constant version). /// @param ParamType given param type. /// @return required casting type if given param type is an instance if // that type, NULL otherwise. template const T *dynCast(const ParamType *PType) { assert(PType && "dyn_cast does not support casting of NULL"); return (T::EnumTy == PType->getTypeId()) ? (const T *)PType : NULL; } } // namespace SPIR #endif // SPIRV_MANGLER_PARAMETERTYPE_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/Mangler/README.md000066400000000000000000000010531363521741200217120ustar00rootroot00000000000000Contributed by: Intel Corporation. SPIR Name Mangler ================= The NameMangler Library Converts the given function descriptor to a string that represents the function's prototype. The mangling algorithm is based on clang 3.0 Itanium mangling algorithm (http://sourcery.mentor.com/public/cxx-abi/abi.html#mangling). The algorithm is adapted to support mangling of SPIR built-in functions and was tested on SPIR built-ins only. The mangler supports mangling according to SPIR 1.2 and SPIR 2.0 For usage examples see unittest/spir_name_mangler. SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/Mangler/Refcount.h000066400000000000000000000036071363521741200224000ustar00rootroot00000000000000//===--------------------------- Refcount.h ------------------------------===// // // SPIR Tools // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===---------------------------------------------------------------------===// /* * Contributed by: Intel Corporation */ #ifndef SPIRV_MANGLER_REFCOUNT_H #define SPIRV_MANGLER_REFCOUNT_H #include namespace SPIR { template class RefCount { public: RefCount() : Count(0), Ptr(0) {} RefCount(T *Ptr) : Ptr(Ptr) { Count = new int(1); } RefCount(const RefCount &Other) { cpy(Other); } ~RefCount() { if (Count) dispose(); } RefCount &operator=(const RefCount &Other) { if (this == &Other) return *this; if (Count) dispose(); cpy(Other); return *this; } void init(T *Ptr) { assert(!Ptr && "overrunning non NULL pointer"); assert(!Count && "overrunning non NULL pointer"); Count = new int(1); this->Ptr = Ptr; } bool isNull() const { return (!Ptr); } // Pointer access const T &operator*() const { sanity(); return *Ptr; } T &operator*() { sanity(); return *Ptr; } operator T *() { return Ptr; } operator const T *() const { return Ptr; } T *operator->() { return Ptr; } const T *operator->() const { return Ptr; } private: void sanity() const { assert(Ptr && "NULL pointer"); assert(Count && "NULL ref counter"); assert(*Count && "zero ref counter"); } void cpy(const RefCount &Other) { Count = Other.Count; Ptr = Other.Ptr; if (Count) ++*Count; } void dispose() { sanity(); if (0 == --*Count) { delete Count; delete Ptr; Ptr = 0; Count = 0; } } int *Count; T *Ptr; }; // End RefCount } // namespace SPIR #endif // SPIRV_MANGLER_REFCOUNT_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/OCL20ToSPIRV.cpp000066400000000000000000002261421363521741200214700ustar00rootroot00000000000000//===- OCL20ToSPIRV.cpp - Transform OCL20 to SPIR-V builtins ----*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// // // This file implements translation of OCL20 builtin functions. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "cl20tospv" #include "OCLTypeToSPIRV.h" #include "OCLUtil.h" #include "SPIRVInternal.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstVisitor.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Verifier.h" #include "llvm/Pass.h" #include "llvm/PassSupport.h" #include "llvm/Support/Debug.h" #include #include using namespace llvm; using namespace SPIRV; using namespace OCLUtil; namespace SPIRV { static size_t getOCLCpp11AtomicMaxNumOps(StringRef Name) { return StringSwitch(Name) .Cases("load", "flag_test_and_set", "flag_clear", 3) .Cases("store", "exchange", 4) .StartsWith("compare_exchange", 6) .StartsWith("fetch", 4) .Default(0); } class OCL20ToSPIRV : public ModulePass, public InstVisitor { public: OCL20ToSPIRV() : ModulePass(ID), M(nullptr), Ctx(nullptr), CLVer(0) { initializeOCL20ToSPIRVPass(*PassRegistry::getPassRegistry()); } bool runOnModule(Module &M) override; void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired(); } virtual void visitCallInst(CallInst &CI); /// Transform barrier/work_group_barrier/sub_group_barrier /// to __spirv_ControlBarrier. /// barrier(flag) => /// __spirv_ControlBarrier(workgroup, workgroup, map(flag)) /// work_group_barrier(scope, flag) => /// __spirv_ControlBarrier(workgroup, map(scope), map(flag)) /// sub_group_barrier(scope, flag) => /// __spirv_ControlBarrier(subgroup, map(scope), map(flag)) void visitCallBarrier(CallInst *CI); /// Erase useless convert functions. /// \return true if the call instruction is erased. bool eraseUselessConvert(CallInst *Call, const std::string &MangledName, const std::string &DeMangledName); /// Transform convert_ to /// __spirv_{CastOpName}_R{TargeTyName}{_sat}{_rt[p|n|z|e]} void visitCallConvert(CallInst *CI, StringRef MangledName, const std::string &DemangledName); /// Transform async_work_group{_strided}_copy. /// async_work_group_copy(dst, src, n, event) /// => async_work_group_strided_copy(dst, src, n, 1, event) /// async_work_group_strided_copy(dst, src, n, stride, event) /// => __spirv_AsyncGroupCopy(ScopeWorkGroup, dst, src, n, stride, event) void visitCallAsyncWorkGroupCopy(CallInst *CI, const std::string &DemangledName); /// Transform OCL builtin function to SPIR-V builtin function. void transBuiltin(CallInst *CI, OCLBuiltinTransInfo &Info); /// Transform OCL work item builtin functions to SPIR-V builtin variables. void transWorkItemBuiltinsToVariables(); /// Transform atomic_work_item_fence/mem_fence to __spirv_MemoryBarrier. /// func(flag, order, scope) => /// __spirv_MemoryBarrier(map(scope), map(flag)|map(order)) void transMemoryBarrier(CallInst *CI, AtomicWorkItemFenceLiterals); /// Transform all to __spirv_Op(All|Any). Note that the types mismatch so // some extra code is emitted to convert between the two. void visitCallAllAny(spv::Op OC, CallInst *CI); /// Transform atomic_* to __spirv_Atomic*. /// atomic_x(ptr_arg, args, order, scope) => /// __spirv_AtomicY(ptr_arg, map(order), map(scope), args) void transAtomicBuiltin(CallInst *CI, OCLBuiltinTransInfo &Info); /// Transform atomic_work_item_fence to __spirv_MemoryBarrier. /// atomic_work_item_fence(flag, order, scope) => /// __spirv_MemoryBarrier(map(scope), map(flag)|map(order)) void visitCallAtomicWorkItemFence(CallInst *CI); /// Transform atomic_compare_exchange call. /// In atomic_compare_exchange, the expected value parameter is a pointer. /// However in SPIR-V it is a value. The transformation adds a load /// instruction, result of which is passed to atomic_compare_exchange as /// argument. /// The transformation adds a store instruction after the call, to update the /// value in expected with the value pointed to by object. Though, it is not /// necessary in case they are equal, this approach makes result code simpler. /// Also ICmp instruction is added, because the call must return result of /// comparison. /// \returns the call instruction of atomic_compare_exchange_strong. CallInst *visitCallAtomicCmpXchg(CallInst *CI, const std::string &DemangledName); /// Transform atomic_init. /// atomic_init(p, x) => store p, x void visitCallAtomicInit(CallInst *CI); /// Transform legacy OCL 1.x atomic builtins to SPIR-V builtins for extensions /// cl_khr_int64_base_atomics /// cl_khr_int64_extended_atomics /// Do nothing if the called function is not a legacy atomic builtin. void visitCallAtomicLegacy(CallInst *CI, StringRef MangledName, const std::string &DemangledName); /// Transform OCL 2.0 C++11 atomic builtins to SPIR-V builtins. /// Do nothing if the called function is not a C++11 atomic builtin. void visitCallAtomicCpp11(CallInst *CI, StringRef MangledName, const std::string &DemangledName); /// Transform OCL builtin function to SPIR-V builtin function. /// Assuming there is a simple name mapping without argument changes. /// Should be called at last. void visitCallBuiltinSimple(CallInst *CI, StringRef MangledName, const std::string &DemangledName); /// Transform get_image_{width|height|depth|dim}. /// get_image_xxx(...) => /// dimension = __spirv_ImageQuerySizeLod_R{ReturnType}(...); /// return dimension.{x|y|z}; void visitCallGetImageSize(CallInst *CI, StringRef MangledName, const std::string &DemangledName); /// Transform {work|sub}_group_x => /// __spirv_{OpName} /// /// Special handling of work_group_broadcast. /// work_group_broadcast(a, x, y, z) /// => /// __spirv_GroupBroadcast(a, vec3(x, y, z)) void visitCallGroupBuiltin(CallInst *CI, StringRef MangledName, const std::string &DemangledName); /// Transform mem_fence to __spirv_MemoryBarrier. /// mem_fence(flag) => __spirv_MemoryBarrier(Workgroup, map(flag)) void visitCallMemFence(CallInst *CI); void visitCallNDRange(CallInst *CI, const std::string &DemangledName); /// Transform read_image with sampler arguments. /// read_image(image, sampler, ...) => /// sampled_image = __spirv_SampledImage(image, sampler); /// return __spirv_ImageSampleExplicitLod_R{ReturnType}(sampled_image, ...); void visitCallReadImageWithSampler(CallInst *CI, StringRef MangledName, const std::string &DemangledName); /// Transform read_image with msaa image arguments. /// Sample argument must be acoded as Image Operand. void visitCallReadImageMSAA(CallInst *CI, StringRef MangledName, const std::string &DemangledName); /// Transform {read|write}_image without sampler arguments. void visitCallReadWriteImage(CallInst *CI, StringRef MangledName, const std::string &DemangledName); /// Transform to_{global|local|private}. /// /// T* a = ...; /// addr T* b = to_addr(a); /// => /// i8* x = cast(a); /// addr i8* y = __spirv_GenericCastToPtr_ToAddr(x); /// addr T* b = cast(y); void visitCallToAddr(CallInst *CI, StringRef MangledName, const std::string &DemangledName); /// Transform return type of relatinal built-in functions like isnan, isfinite /// to boolean values. void visitCallRelational(CallInst *CI, const std::string &DemangledName); /// Transform vector load/store functions to SPIR-V extended builtin /// functions /// {vload|vstore{a}}{_half}{n}{_rte|_rtz|_rtp|_rtn} => /// __spirv_ocl_{ExtendedInstructionOpCodeName}__R{ReturnType} void visitCallVecLoadStore(CallInst *CI, StringRef MangledName, const std::string &DemangledName); /// Transforms get_mem_fence built-in to SPIR-V function and aligns result /// values with SPIR 1.2. get_mem_fence(ptr) => __spirv_GenericPtrMemSemantics /// GenericPtrMemSemantics valid values are 0x100, 0x200 and 0x300, where is /// SPIR 1.2 defines them as 0x1, 0x2 and 0x3, so this function adjusts /// GenericPtrMemSemantics results to SPIR 1.2 values. void visitCallGetFence(CallInst *CI, StringRef MangledName, const std::string &DemangledName); /// Transforms OpDot instructions with a scalar type to a fmul instruction void visitCallDot(CallInst *CI); /// Fixes for built-in functions with vector+scalar arguments that are /// translated to the SPIR-V instructions where all arguments must have the /// same type. void visitCallScalToVec(CallInst *CI, StringRef MangledName, const std::string &DemangledName); /// Transform get_image_channel_{order|data_type} built-in functions to /// __spirv_ocl_{ImageQueryOrder|ImageQueryFormat} void visitCallGetImageChannel(CallInst *CI, StringRef MangledName, const std::string &DemangledName, unsigned int Offset); /// Transform enqueue_kernel and kernel query built-in functions to /// spirv-friendly format filling arguments, required for device-side enqueue /// instructions, but missed in the original call void visitCallEnqueueKernel(CallInst *CI, const std::string &DemangledName); void visitCallKernelQuery(CallInst *CI, const std::string &DemangledName); /// For cl_intel_subgroups block read built-ins: void visitSubgroupBlockReadINTEL(CallInst *CI, StringRef MangledName, const std::string &DemangledName); /// For cl_intel_subgroups block write built-ins: void visitSubgroupBlockWriteINTEL(CallInst *CI, StringRef MangledName, const std::string &DemangledName); /// For cl_intel_media_block_io built-ins: void visitSubgroupImageMediaBlockINTEL(CallInst *CI, const std::string &DemangledName); // For cl_intel_device_side_avc_motion_estimation built-ins void visitSubgroupAVCBuiltinCall(CallInst *CI, StringRef MangledName, const std::string &DemangledName); void visitSubgroupAVCWrapperBuiltinCall(CallInst *CI, Op WrappedOC, const std::string &DemangledName); void visitSubgroupAVCBuiltinCallWithSampler(CallInst *CI, StringRef MangledName, const std::string &DemangledName); static char ID; private: Module *M; LLVMContext *Ctx; unsigned CLVer; /// OpenCL version as major*10+minor std::set ValuesToDelete; ConstantInt *addInt32(int I) { return getInt32(M, I); } ConstantInt *addSizet(uint64_t I) { return getSizet(M, I); } /// Get vector width from OpenCL vload* function name. SPIRVWord getVecLoadWidth(const std::string &DemangledName) { SPIRVWord Width = 0; if (DemangledName == "vloada_half") Width = 1; else { unsigned Loc = 5; if (DemangledName.find("vload_half") == 0) Loc = 10; else if (DemangledName.find("vloada_half") == 0) Loc = 11; std::stringstream SS(DemangledName.substr(Loc)); SS >> Width; } return Width; } /// Transform OpenCL vload/vstore function name. void transVecLoadStoreName(std::string &DemangledName, const std::string &Stem, bool AlwaysN) { auto HalfStem = Stem + "_half"; auto HalfStemR = HalfStem + "_r"; if (!AlwaysN && DemangledName == HalfStem) return; if (!AlwaysN && DemangledName.find(HalfStemR) == 0) { DemangledName = HalfStemR; return; } if (DemangledName.find(HalfStem) == 0) { auto OldName = DemangledName; DemangledName = HalfStem + "n"; if (OldName.find("_r") != std::string::npos) DemangledName += "_r"; return; } if (DemangledName.find(Stem) == 0) { DemangledName = Stem + "n"; return; } } }; char OCL20ToSPIRV::ID = 0; bool OCL20ToSPIRV::runOnModule(Module &Module) { M = &Module; Ctx = &M->getContext(); auto Src = getSPIRVSource(&Module); if (std::get<0>(Src) != spv::SourceLanguageOpenCL_C) return false; CLVer = std::get<1>(Src); if (CLVer > kOCLVer::CL20) return false; LLVM_DEBUG(dbgs() << "Enter OCL20ToSPIRV:\n"); transWorkItemBuiltinsToVariables(); visit(*M); for (auto &I : ValuesToDelete) if (auto Inst = dyn_cast(I)) Inst->eraseFromParent(); for (auto &I : ValuesToDelete) if (auto GV = dyn_cast(I)) GV->eraseFromParent(); eraseUselessFunctions(M); // remove unused functions declarations LLVM_DEBUG(dbgs() << "After OCL20ToSPIRV:\n" << *M); std::string Err; raw_string_ostream ErrorOS(Err); if (verifyModule(*M, &ErrorOS)) { LLVM_DEBUG(errs() << "Fails to verify module: " << ErrorOS.str()); } return true; } // The order of handling OCL builtin functions is important. // Workgroup functions need to be handled before pipe functions since // there are functions fall into both categories. void OCL20ToSPIRV::visitCallInst(CallInst &CI) { LLVM_DEBUG(dbgs() << "[visistCallInst] " << CI << '\n'); auto F = CI.getCalledFunction(); if (!F) return; auto MangledName = F->getName(); std::string DemangledName; if (!oclIsBuiltin(MangledName, &DemangledName)) return; LLVM_DEBUG(dbgs() << "DemangledName: " << DemangledName << '\n'); if (DemangledName.find(kOCLBuiltinName::NDRangePrefix) == 0) { visitCallNDRange(&CI, DemangledName); return; } if (DemangledName == kOCLBuiltinName::All) { visitCallAllAny(OpAll, &CI); return; } if (DemangledName == kOCLBuiltinName::Any) { visitCallAllAny(OpAny, &CI); return; } if (DemangledName.find(kOCLBuiltinName::AsyncWorkGroupCopy) == 0 || DemangledName.find(kOCLBuiltinName::AsyncWorkGroupStridedCopy) == 0) { visitCallAsyncWorkGroupCopy(&CI, DemangledName); return; } if (DemangledName.find(kOCLBuiltinName::AtomicPrefix) == 0 || DemangledName.find(kOCLBuiltinName::AtomPrefix) == 0) { // Compute atomic builtins do not support floating types. if (CI.getType()->isFloatingPointTy() && isComputeAtomicOCLBuiltin(DemangledName)) return; auto PCI = &CI; if (DemangledName == kOCLBuiltinName::AtomicInit) { visitCallAtomicInit(PCI); return; } if (DemangledName == kOCLBuiltinName::AtomicWorkItemFence) { visitCallAtomicWorkItemFence(PCI); return; } if (DemangledName == kOCLBuiltinName::AtomicCmpXchgWeak || DemangledName == kOCLBuiltinName::AtomicCmpXchgStrong || DemangledName == kOCLBuiltinName::AtomicCmpXchgWeakExplicit || DemangledName == kOCLBuiltinName::AtomicCmpXchgStrongExplicit) { assert(CLVer == kOCLVer::CL20 && "Wrong version of OpenCL"); PCI = visitCallAtomicCmpXchg(PCI, DemangledName); } visitCallAtomicLegacy(PCI, MangledName, DemangledName); visitCallAtomicCpp11(PCI, MangledName, DemangledName); return; } if (DemangledName.find(kOCLBuiltinName::ConvertPrefix) == 0) { visitCallConvert(&CI, MangledName, DemangledName); return; } if (DemangledName == kOCLBuiltinName::GetImageWidth || DemangledName == kOCLBuiltinName::GetImageHeight || DemangledName == kOCLBuiltinName::GetImageDepth || DemangledName == kOCLBuiltinName::GetImageDim || DemangledName == kOCLBuiltinName::GetImageArraySize) { visitCallGetImageSize(&CI, MangledName, DemangledName); return; } if ((DemangledName.find(kOCLBuiltinName::WorkGroupPrefix) == 0 && DemangledName != kOCLBuiltinName::WorkGroupBarrier) || DemangledName == kOCLBuiltinName::WaitGroupEvent || (DemangledName.find(kOCLBuiltinName::SubGroupPrefix) == 0 && DemangledName != kOCLBuiltinName::SubGroupBarrier)) { visitCallGroupBuiltin(&CI, MangledName, DemangledName); return; } if (DemangledName == kOCLBuiltinName::MemFence) { visitCallMemFence(&CI); return; } if (DemangledName.find(kOCLBuiltinName::ReadImage) == 0) { if (MangledName.find(kMangledName::Sampler) != StringRef::npos) { visitCallReadImageWithSampler(&CI, MangledName, DemangledName); return; } if (MangledName.find("msaa") != StringRef::npos) { visitCallReadImageMSAA(&CI, MangledName, DemangledName); return; } } if (DemangledName.find(kOCLBuiltinName::ReadImage) == 0 || DemangledName.find(kOCLBuiltinName::WriteImage) == 0) { visitCallReadWriteImage(&CI, MangledName, DemangledName); return; } if (DemangledName == kOCLBuiltinName::ToGlobal || DemangledName == kOCLBuiltinName::ToLocal || DemangledName == kOCLBuiltinName::ToPrivate) { visitCallToAddr(&CI, MangledName, DemangledName); return; } if (DemangledName.find(kOCLBuiltinName::VLoadPrefix) == 0 || DemangledName.find(kOCLBuiltinName::VStorePrefix) == 0) { visitCallVecLoadStore(&CI, MangledName, DemangledName); return; } if (DemangledName == kOCLBuiltinName::IsFinite || DemangledName == kOCLBuiltinName::IsInf || DemangledName == kOCLBuiltinName::IsNan || DemangledName == kOCLBuiltinName::IsNormal || DemangledName == kOCLBuiltinName::Signbit) { visitCallRelational(&CI, DemangledName); return; } if (DemangledName == kOCLBuiltinName::WorkGroupBarrier || DemangledName == kOCLBuiltinName::Barrier || DemangledName == kOCLBuiltinName::SubGroupBarrier) { visitCallBarrier(&CI); return; } if (DemangledName == kOCLBuiltinName::GetFence) { visitCallGetFence(&CI, MangledName, DemangledName); return; } if (DemangledName == kOCLBuiltinName::Dot && !(CI.getOperand(0)->getType()->isVectorTy())) { visitCallDot(&CI); return; } if (DemangledName == kOCLBuiltinName::FMin || DemangledName == kOCLBuiltinName::FMax || DemangledName == kOCLBuiltinName::Min || DemangledName == kOCLBuiltinName::Max || DemangledName == kOCLBuiltinName::Step || DemangledName == kOCLBuiltinName::SmoothStep || DemangledName == kOCLBuiltinName::Clamp || DemangledName == kOCLBuiltinName::Mix) { visitCallScalToVec(&CI, MangledName, DemangledName); return; } if (DemangledName == kOCLBuiltinName::GetImageChannelDataType) { visitCallGetImageChannel(&CI, MangledName, DemangledName, OCLImageChannelDataTypeOffset); return; } if (DemangledName == kOCLBuiltinName::GetImageChannelOrder) { visitCallGetImageChannel(&CI, MangledName, DemangledName, OCLImageChannelOrderOffset); return; } if (isEnqueueKernelBI(MangledName)) { visitCallEnqueueKernel(&CI, DemangledName); return; } if (isKernelQueryBI(MangledName)) { visitCallKernelQuery(&CI, DemangledName); return; } if (DemangledName.find(kOCLBuiltinName::SubgroupBlockReadINTELPrefix) == 0) { visitSubgroupBlockReadINTEL(&CI, MangledName, DemangledName); return; } if (DemangledName.find(kOCLBuiltinName::SubgroupBlockWriteINTELPrefix) == 0) { visitSubgroupBlockWriteINTEL(&CI, MangledName, DemangledName); return; } if (DemangledName.find(kOCLBuiltinName::SubgroupImageMediaBlockINTELPrefix) == 0) { visitSubgroupImageMediaBlockINTEL(&CI, DemangledName); return; } // Handle 'cl_intel_device_side_avc_motion_estimation' extension built-ins if (DemangledName.find(kOCLSubgroupsAVCIntel::Prefix) == 0 || // Workaround for a bug in the extension specification DemangledName.find("intel_sub_group_ime_ref_window_size") == 0) { if (MangledName.find(kMangledName::Sampler) != StringRef::npos) visitSubgroupAVCBuiltinCallWithSampler(&CI, MangledName, DemangledName); else visitSubgroupAVCBuiltinCall(&CI, MangledName, DemangledName); return; } visitCallBuiltinSimple(&CI, MangledName, DemangledName); } void OCL20ToSPIRV::visitCallNDRange(CallInst *CI, const std::string &DemangledName) { assert(DemangledName.find(kOCLBuiltinName::NDRangePrefix) == 0); std::string LenStr = DemangledName.substr(8, 1); auto Len = atoi(LenStr.c_str()); assert(Len >= 1 && Len <= 3); // SPIR-V ndrange structure requires 3 members in the following order: // global work offset // global work size // local work size // The arguments need to add missing members. AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInstSPIRV( M, CI, [=](CallInst *, std::vector &Args) { for (size_t I = 1, E = Args.size(); I != E; ++I) Args[I] = getScalarOrArray(Args[I], Len, CI); switch (Args.size()) { case 2: { // Has global work size. auto T = Args[1]->getType(); auto C = getScalarOrArrayConstantInt(CI, T, Len, 0); Args.push_back(C); Args.push_back(C); } break; case 3: { // Has global and local work size. auto T = Args[1]->getType(); Args.push_back(getScalarOrArrayConstantInt(CI, T, Len, 0)); } break; case 4: { // Move offset arg to the end auto OffsetPos = Args.begin() + 1; Value *OffsetVal = *OffsetPos; Args.erase(OffsetPos); Args.push_back(OffsetVal); } break; default: assert(0 && "Invalid number of arguments"); } // Translate ndrange_ND into differently named SPIR-V decorated // functions because they have array arugments of different dimension // which mangled the same way. return getSPIRVFuncName(OpBuildNDRange, "_" + LenStr + "D"); }, &Attrs); } void OCL20ToSPIRV::visitCallAsyncWorkGroupCopy( CallInst *CI, const std::string &DemangledName) { assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInstSPIRV(M, CI, [=](CallInst *, std::vector &Args) { if (DemangledName == OCLUtil::kOCLBuiltinName::AsyncWorkGroupCopy) { Args.insert(Args.begin() + 3, addSizet(1)); } Args.insert(Args.begin(), addInt32(ScopeWorkgroup)); return getSPIRVFuncName(OpGroupAsyncCopy); }, &Attrs); } CallInst * OCL20ToSPIRV::visitCallAtomicCmpXchg(CallInst *CI, const std::string &DemangledName) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); Value *Expected = nullptr; CallInst *NewCI = nullptr; mutateCallInstOCL( M, CI, [&](CallInst *CI, std::vector &Args, Type *&RetTy) { Expected = Args[1]; // temporary save second argument. Args[1] = new LoadInst(Args[1], "exp", false, CI); RetTy = Args[2]->getType(); assert(Args[0]->getType()->getPointerElementType()->isIntegerTy() && Args[1]->getType()->isIntegerTy() && Args[2]->getType()->isIntegerTy() && "In SPIR-V 1.0 arguments of OpAtomicCompareExchange must be " "an integer type scalars"); return kOCLBuiltinName::AtomicCmpXchgStrong; }, [&](CallInst *NCI) -> Instruction * { NewCI = NCI; Instruction *Store = new StoreInst(NCI, Expected, NCI->getNextNode()); return new ICmpInst(Store->getNextNode(), CmpInst::ICMP_EQ, NCI, NCI->getArgOperand(1)); }, &Attrs); return NewCI; } void OCL20ToSPIRV::visitCallAtomicInit(CallInst *CI) { auto ST = new StoreInst(CI->getArgOperand(1), CI->getArgOperand(0), CI); ST->takeName(CI); CI->dropAllReferences(); CI->eraseFromParent(); } void OCL20ToSPIRV::visitCallAllAny(spv::Op OC, CallInst *CI) { assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); auto Args = getArguments(CI); assert(Args.size() == 1); auto *ArgTy = Args[0]->getType(); auto Zero = Constant::getNullValue(Args[0]->getType()); auto *Cmp = CmpInst::Create(CmpInst::ICmp, CmpInst::ICMP_SLT, Args[0], Zero, "cast", CI); if (!isa(ArgTy)) { auto *Cast = CastInst::CreateZExtOrBitCast(Cmp, Type::getInt32Ty(*Ctx), "", Cmp->getNextNode()); CI->replaceAllUsesWith(Cast); CI->eraseFromParent(); } else { mutateCallInstSPIRV( M, CI, [&](CallInst *, std::vector &Args, Type *&Ret) { Args[0] = Cmp; Ret = Type::getInt1Ty(*Ctx); return getSPIRVFuncName(OC); }, [&](CallInst *CI) -> Instruction * { return CastInst::CreateZExtOrBitCast(CI, Type::getInt32Ty(*Ctx), "", CI->getNextNode()); }, &Attrs); } } void OCL20ToSPIRV::visitCallAtomicWorkItemFence(CallInst *CI) { transMemoryBarrier(CI, getAtomicWorkItemFenceLiterals(CI)); } void OCL20ToSPIRV::visitCallMemFence(CallInst *CI) { transMemoryBarrier( CI, std::make_tuple(cast(CI->getArgOperand(0))->getZExtValue(), OCLMO_relaxed, OCLMS_work_group)); } void OCL20ToSPIRV::transMemoryBarrier(CallInst *CI, AtomicWorkItemFenceLiterals Lit) { assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInstSPIRV(M, CI, [=](CallInst *, std::vector &Args) { Args.resize(2); Args[0] = addInt32(map(std::get<2>(Lit))); Args[1] = addInt32(mapOCLMemSemanticToSPIRV( std::get<0>(Lit), std::get<1>(Lit))); return getSPIRVFuncName(OpMemoryBarrier); }, &Attrs); } void OCL20ToSPIRV::visitCallAtomicLegacy(CallInst *CI, StringRef MangledName, const std::string &DemangledName) { StringRef Stem = DemangledName; if (Stem.startswith("atom_")) Stem = Stem.drop_front(strlen("atom_")); else if (Stem.startswith("atomic_")) Stem = Stem.drop_front(strlen("atomic_")); else return; std::string Sign; std::string Postfix; std::string Prefix; if (Stem == "add" || Stem == "sub" || Stem == "and" || Stem == "or" || Stem == "xor" || Stem == "min" || Stem == "max") { if ((Stem == "min" || Stem == "max") && isMangledTypeUnsigned(MangledName.back())) Sign = 'u'; Prefix = "fetch_"; Postfix = "_explicit"; } else if (Stem == "xchg") { Stem = "exchange"; Postfix = "_explicit"; } else if (Stem == "cmpxchg") { Stem = "compare_exchange_strong"; Postfix = "_explicit"; } else if (Stem == "inc" || Stem == "dec") { // do nothing } else return; OCLBuiltinTransInfo Info; Info.UniqName = "atomic_" + Prefix + Sign + Stem.str() + Postfix; std::vector PostOps; PostOps.push_back(OCLLegacyAtomicMemOrder); if (Stem.startswith("compare_exchange")) PostOps.push_back(OCLLegacyAtomicMemOrder); PostOps.push_back(OCLLegacyAtomicMemScope); Info.PostProc = [=](std::vector &Ops) { for (auto &I : PostOps) { Ops.push_back(addInt32(I)); } }; transAtomicBuiltin(CI, Info); } void OCL20ToSPIRV::visitCallAtomicCpp11(CallInst *CI, StringRef MangledName, const std::string &DemangledName) { StringRef Stem = DemangledName; if (Stem.startswith("atomic_")) Stem = Stem.drop_front(strlen("atomic_")); else return; std::string NewStem = Stem; std::vector PostOps; if (Stem.startswith("store") || Stem.startswith("load") || Stem.startswith("exchange") || Stem.startswith("compare_exchange") || Stem.startswith("fetch") || Stem.startswith("flag")) { if ((Stem.startswith("fetch_min") || Stem.startswith("fetch_max")) && containsUnsignedAtomicType(MangledName)) NewStem.insert(NewStem.begin() + strlen("fetch_"), 'u'); if (!Stem.endswith("_explicit")) { NewStem = NewStem + "_explicit"; PostOps.push_back(OCLMO_seq_cst); if (Stem.startswith("compare_exchange")) PostOps.push_back(OCLMO_seq_cst); PostOps.push_back(OCLMS_device); } else { auto MaxOps = getOCLCpp11AtomicMaxNumOps(Stem.drop_back(strlen("_explicit"))); if (CI->getNumArgOperands() < MaxOps) PostOps.push_back(OCLMS_device); } } else if (Stem == "work_item_fence") { // do nothing } else return; OCLBuiltinTransInfo Info; Info.UniqName = std::string("atomic_") + NewStem; Info.PostProc = [=](std::vector &Ops) { for (auto &I : PostOps) { Ops.push_back(addInt32(I)); } }; transAtomicBuiltin(CI, Info); } void OCL20ToSPIRV::transAtomicBuiltin(CallInst *CI, OCLBuiltinTransInfo &Info) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInstSPIRV( M, CI, [=](CallInst *CI, std::vector &Args) { Info.PostProc(Args); // Order of args in OCL20: // object, 0-2 other args, 1-2 order, scope const size_t NumOrder = getAtomicBuiltinNumMemoryOrderArgs(Info.UniqName); const size_t ArgsCount = Args.size(); const size_t ScopeIdx = ArgsCount - 1; const size_t OrderIdx = ScopeIdx - NumOrder; if (auto ScopeInt = dyn_cast_or_null(Args[ScopeIdx])) { Args[ScopeIdx] = mapUInt(M, ScopeInt, [](unsigned I) { return map(static_cast(I)); }); } else { Args[ScopeIdx] = getOrCreateSwitchFunc(kSPIRVName::TranslateOCLMemScope, Args[ScopeIdx], OCLMemScopeMap::getMap(), false /*IsReverse*/, OCLMS_device, CI, M); } for (size_t I = 0; I < NumOrder; ++I) { if (auto OrderInt = dyn_cast_or_null(Args[OrderIdx + I])) { Args[OrderIdx + I] = mapUInt(M, OrderInt, [](unsigned Ord) { return mapOCLMemSemanticToSPIRV( 0, static_cast(Ord)); }); } else { Args[OrderIdx + I] = getOrCreateSwitchFunc( kSPIRVName::TranslateOCLMemOrder, Args[OrderIdx + I], OCLMemOrderMap::getMap(), false /*IsReverse*/, OCLMO_seq_cst, CI, M); } } // Order of args in SPIR-V: // object, scope, 1-2 order, 0-2 other args std::swap(Args[1], Args[ScopeIdx]); if (OrderIdx > 2) { // For atomic_compare_exchange the swap above puts Comparator/Expected // argument just where it should be, so don't move the last argument // then. int Offset = Info.UniqName.find("atomic_compare_exchange") == 0 ? 1 : 0; std::rotate(Args.begin() + 2, Args.begin() + OrderIdx, Args.end() - Offset); } return getSPIRVFuncName(OCLSPIRVBuiltinMap::map(Info.UniqName)); }, &Attrs); } void OCL20ToSPIRV::visitCallBarrier(CallInst *CI) { auto Lit = getBarrierLiterals(CI); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInstSPIRV(M, CI, [=](CallInst *, std::vector &Args) { Args.resize(3); // Execution scope Args[0] = addInt32(map(std::get<2>(Lit))); // Memory scope Args[1] = addInt32(map(std::get<1>(Lit))); // Use sequential consistent memory order by default. // But if the flags argument is set to 0, we use // None(Relaxed) memory order. unsigned MemFenceFlag = std::get<0>(Lit); OCLMemOrderKind MemOrder = MemFenceFlag ? OCLMO_seq_cst : OCLMO_relaxed; Args[2] = addInt32(mapOCLMemSemanticToSPIRV( MemFenceFlag, MemOrder)); // Memory semantics return getSPIRVFuncName(OpControlBarrier); }, &Attrs); } void OCL20ToSPIRV::visitCallConvert(CallInst *CI, StringRef MangledName, const std::string &DemangledName) { if (eraseUselessConvert(CI, MangledName, DemangledName)) return; Op OC = OpNop; auto TargetTy = CI->getType(); auto SrcTy = CI->getArgOperand(0)->getType(); if (isa(TargetTy)) TargetTy = TargetTy->getVectorElementType(); if (isa(SrcTy)) SrcTy = SrcTy->getVectorElementType(); auto IsTargetInt = isa(TargetTy); std::string TargetTyName = DemangledName.substr(strlen(kOCLBuiltinName::ConvertPrefix)); auto FirstUnderscoreLoc = TargetTyName.find('_'); if (FirstUnderscoreLoc != std::string::npos) TargetTyName = TargetTyName.substr(0, FirstUnderscoreLoc); TargetTyName = std::string("_R") + TargetTyName; std::string Sat = DemangledName.find("_sat") != std::string::npos ? "_sat" : ""; auto TargetSigned = DemangledName[8] != 'u'; if (isa(SrcTy)) { bool Signed = isLastFuncParamSigned(MangledName); if (IsTargetInt) { if (!Sat.empty() && TargetSigned != Signed) { OC = Signed ? OpSatConvertSToU : OpSatConvertUToS; Sat = ""; } else OC = Signed ? OpSConvert : OpUConvert; } else OC = Signed ? OpConvertSToF : OpConvertUToF; } else { if (IsTargetInt) { OC = TargetSigned ? OpConvertFToS : OpConvertFToU; } else OC = OpFConvert; } auto Loc = DemangledName.find("_rt"); std::string Rounding; if (Loc != std::string::npos && !(isa(SrcTy) && IsTargetInt)) { Rounding = DemangledName.substr(Loc, 4); } assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInstSPIRV(M, CI, [=](CallInst *, std::vector &Args) { return getSPIRVFuncName(OC, TargetTyName + Sat + Rounding); }, &Attrs); } void OCL20ToSPIRV::visitCallGroupBuiltin(CallInst *CI, StringRef MangledName, const std::string &OrigDemangledName) { auto F = CI->getCalledFunction(); std::vector PreOps; std::string DemangledName = OrigDemangledName; if (DemangledName == kOCLBuiltinName::WorkGroupBarrier) return; if (DemangledName == kOCLBuiltinName::WaitGroupEvent) { PreOps.push_back(ScopeWorkgroup); } else if (DemangledName.find(kOCLBuiltinName::WorkGroupPrefix) == 0) { DemangledName.erase(0, strlen(kOCLBuiltinName::WorkPrefix)); PreOps.push_back(ScopeWorkgroup); } else if (DemangledName.find(kOCLBuiltinName::SubGroupPrefix) == 0) { DemangledName.erase(0, strlen(kOCLBuiltinName::SubPrefix)); PreOps.push_back(ScopeSubgroup); } else return; if (DemangledName != kOCLBuiltinName::WaitGroupEvent) { StringRef GroupOp = DemangledName; GroupOp = GroupOp.drop_front(strlen(kSPIRVName::GroupPrefix)); SPIRSPIRVGroupOperationMap::foreachConditional( [&](const std::string &S, SPIRVGroupOperationKind G) { if (!GroupOp.startswith(S)) return true; // continue PreOps.push_back(G); StringRef Op = GroupOp.drop_front(S.size() + 1); assert(!Op.empty() && "Invalid OpenCL group builtin function"); char OpTyC = 0; auto NeedSign = Op == "max" || Op == "min"; auto OpTy = F->getReturnType(); if (OpTy->isFloatingPointTy()) OpTyC = 'f'; else if (OpTy->isIntegerTy()) { if (!NeedSign) OpTyC = 'i'; else { if (isLastFuncParamSigned(F->getName())) OpTyC = 's'; else OpTyC = 'u'; } } else llvm_unreachable("Invalid OpenCL group builtin argument type"); DemangledName = std::string(kSPIRVName::GroupPrefix) + OpTyC + Op.str(); return false; // break out of loop }); } bool IsGroupAllAny = (DemangledName.find("_all") != std::string::npos || DemangledName.find("_any") != std::string::npos); auto Consts = getInt32(M, PreOps); OCLBuiltinTransInfo Info; if (IsGroupAllAny) Info.RetTy = Type::getInt1Ty(*Ctx); Info.UniqName = DemangledName; Info.PostProc = [=](std::vector &Ops) { if (IsGroupAllAny) { IRBuilder<> IRB(CI); Ops[0] = IRB.CreateICmpNE(Ops[0], ConstantInt::get(Type::getInt32Ty(*Ctx), 0)); } size_t E = Ops.size(); if (DemangledName == "group_broadcast" && E > 2) { assert(E == 3 || E == 4); makeVector(CI, Ops, std::make_pair(Ops.begin() + 1, Ops.end())); } Ops.insert(Ops.begin(), Consts.begin(), Consts.end()); }; transBuiltin(CI, Info); } void OCL20ToSPIRV::transBuiltin(CallInst *CI, OCLBuiltinTransInfo &Info) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); Op OC = OpNop; unsigned ExtOp = ~0U; if (StringRef(Info.UniqName).startswith(kSPIRVName::Prefix)) return; if (OCLSPIRVBuiltinMap::find(Info.UniqName, &OC)) { if (OC == OpImageRead) { // There are several read_image* functions defined by OpenCL C spec, but // all of them use the same SPIR-V Instruction - some of them might only // differ by return type, so, we need to include return type into the // mangling scheme to get them differentiated. // // Example: int4 read_imagei(image2d_t, sampler_t, int2) // uint4 read_imageui(image2d_t, sampler_t, int2) // Both functions above are represented by the same SPIR-V // instruction: argument types are the same, only return type is // different Info.UniqName = getSPIRVFuncName(OC, CI->getType()); } else { Info.UniqName = getSPIRVFuncName(OC); } } else if ((ExtOp = getExtOp(Info.MangledName, Info.UniqName)) != ~0U) Info.UniqName = getSPIRVExtFuncName(SPIRVEIS_OpenCL, ExtOp); else return; if (!Info.RetTy) mutateCallInstSPIRV(M, CI, [=](CallInst *, std::vector &Args) { Info.PostProc(Args); return Info.UniqName + Info.Postfix; }, &Attrs); else mutateCallInstSPIRV( M, CI, [=](CallInst *, std::vector &Args, Type *&RetTy) { Info.PostProc(Args); RetTy = Info.RetTy; return Info.UniqName + Info.Postfix; }, [=](CallInst *NewCI) -> Instruction * { if (NewCI->getType()->isIntegerTy() && CI->getType()->isIntegerTy()) return CastInst::CreateIntegerCast(NewCI, CI->getType(), Info.IsRetSigned, "", CI); else return CastInst::CreatePointerBitCastOrAddrSpaceCast( NewCI, CI->getType(), "", CI); }, &Attrs); } void OCL20ToSPIRV::visitCallReadImageMSAA(CallInst *CI, StringRef MangledName, const std::string &DemangledName) { assert(MangledName.find("msaa") != StringRef::npos); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInstSPIRV( M, CI, [=](CallInst *, std::vector &Args) { Args.insert(Args.begin() + 2, getInt32(M, ImageOperandsSampleMask)); return getSPIRVFuncName(OpImageRead, std::string(kSPIRVPostfix::ExtDivider) + getPostfixForReturnType(CI)); }, &Attrs); } void OCL20ToSPIRV::visitCallReadImageWithSampler( CallInst *CI, StringRef MangledName, const std::string &DemangledName) { assert(MangledName.find(kMangledName::Sampler) != StringRef::npos); assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); bool IsRetScalar = !CI->getType()->isVectorTy(); mutateCallInstSPIRV( M, CI, [=](CallInst *, std::vector &Args, Type *&Ret) { auto ImageTy = getAnalysis().getAdaptedType(Args[0]); if (isOCLImageType(ImageTy)) ImageTy = getSPIRVImageTypeFromOCL(M, ImageTy); auto SampledImgTy = getSPIRVTypeByChangeBaseTypeName( M, ImageTy, kSPIRVTypeName::Image, kSPIRVTypeName::SampledImg); Value *SampledImgArgs[] = {Args[0], Args[1]}; auto SampledImg = addCallInstSPIRV( M, getSPIRVFuncName(OpSampledImage), SampledImgTy, SampledImgArgs, nullptr, CI, kSPIRVName::TempSampledImage); Args[0] = SampledImg; Args.erase(Args.begin() + 1, Args.begin() + 2); switch (Args.size()) { case 2: // no lod Args.push_back(getInt32(M, ImageOperandsMask::ImageOperandsLodMask)); Args.push_back(getFloat32(M, 0.f)); break; case 3: // explicit lod Args.insert(Args.begin() + 2, getInt32(M, ImageOperandsMask::ImageOperandsLodMask)); break; case 4: // gradient Args.insert(Args.begin() + 2, getInt32(M, ImageOperandsMask::ImageOperandsGradMask)); break; default: assert(0 && "read_image* with unhandled number of args!"); } // SPIR-V instruction always returns 4-element vector if (IsRetScalar) Ret = VectorType::get(Ret, 4); return getSPIRVFuncName(OpImageSampleExplicitLod, std::string(kSPIRVPostfix::ExtDivider) + getPostfixForReturnType(Ret)); }, [&](CallInst *CI) -> Instruction * { if (IsRetScalar) return ExtractElementInst::Create(CI, getSizet(M, 0), "", CI->getNextNode()); return CI; }, &Attrs); } void OCL20ToSPIRV::visitCallGetImageSize(CallInst *CI, StringRef MangledName, const std::string &DemangledName) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); StringRef TyName; SmallVector SubStrs; auto IsImg = isOCLImageType(CI->getArgOperand(0)->getType(), &TyName); (void)IsImg; assert(IsImg); std::string ImageTyName = getImageBaseTypeName(TyName); auto Desc = map(ImageTyName); unsigned Dim = getImageDimension(Desc.Dim) + Desc.Arrayed; assert(Dim > 0 && "Invalid image dimension."); mutateCallInstSPIRV( M, CI, [&](CallInst *, std::vector &Args, Type *&Ret) { assert(Args.size() == 1); Ret = CI->getType()->isIntegerTy(64) ? Type::getInt64Ty(*Ctx) : Type::getInt32Ty(*Ctx); if (Dim > 1) Ret = VectorType::get(Ret, Dim); if (Desc.Dim == DimBuffer) return getSPIRVFuncName(OpImageQuerySize, CI->getType()); else { Args.push_back(getInt32(M, 0)); return getSPIRVFuncName(OpImageQuerySizeLod, CI->getType()); } }, [&](CallInst *NCI) -> Instruction * { if (Dim == 1) return NCI; if (DemangledName == kOCLBuiltinName::GetImageDim) { if (Desc.Dim == Dim3D) { auto ZeroVec = ConstantVector::getSplat( 3, Constant::getNullValue(NCI->getType()->getVectorElementType())); Constant *Index[] = {getInt32(M, 0), getInt32(M, 1), getInt32(M, 2), getInt32(M, 3)}; return new ShuffleVectorInst(NCI, ZeroVec, ConstantVector::get(Index), "", CI); } else if (Desc.Dim == Dim2D && Desc.Arrayed) { Constant *Index[] = {getInt32(M, 0), getInt32(M, 1)}; Constant *Mask = ConstantVector::get(Index); return new ShuffleVectorInst(NCI, UndefValue::get(NCI->getType()), Mask, NCI->getName(), CI); } return NCI; } unsigned I = StringSwitch(DemangledName) .Case(kOCLBuiltinName::GetImageWidth, 0) .Case(kOCLBuiltinName::GetImageHeight, 1) .Case(kOCLBuiltinName::GetImageDepth, 2) .Case(kOCLBuiltinName::GetImageArraySize, Dim - 1); return ExtractElementInst::Create(NCI, getUInt32(M, I), "", NCI->getNextNode()); }, &Attrs); } /// Remove trivial conversion functions bool OCL20ToSPIRV::eraseUselessConvert(CallInst *CI, const std::string &MangledName, const std::string &DemangledName) { auto TargetTy = CI->getType(); auto SrcTy = CI->getArgOperand(0)->getType(); if (isa(TargetTy)) TargetTy = TargetTy->getVectorElementType(); if (isa(SrcTy)) SrcTy = SrcTy->getVectorElementType(); if (TargetTy == SrcTy) { if (isa(TargetTy) && DemangledName.find("_sat") != std::string::npos && isLastFuncParamSigned(MangledName) != (DemangledName[8] != 'u')) return false; CI->getArgOperand(0)->takeName(CI); SPIRVDBG(dbgs() << "[regularizeOCLConvert] " << *CI << " <- " << *CI->getArgOperand(0) << '\n'); CI->replaceAllUsesWith(CI->getArgOperand(0)); ValuesToDelete.insert(CI); ValuesToDelete.insert(CI->getCalledFunction()); return true; } return false; } void OCL20ToSPIRV::visitCallBuiltinSimple(CallInst *CI, StringRef MangledName, const std::string &DemangledName) { OCLBuiltinTransInfo Info; Info.MangledName = MangledName.str(); Info.UniqName = DemangledName; transBuiltin(CI, Info); } /// Translates OCL work-item builtin functions to SPIRV builtin variables. /// Function like get_global_id(i) -> x = load GlobalInvocationId; extract x, i /// Function like get_work_dim() -> load WorkDim void OCL20ToSPIRV::transWorkItemBuiltinsToVariables() { LLVM_DEBUG(dbgs() << "Enter transWorkItemBuiltinsToVariables\n"); std::vector WorkList; for (auto &I : *M) { std::string DemangledName; if (!oclIsBuiltin(I.getName(), &DemangledName)) continue; LLVM_DEBUG(dbgs() << "Function demangled name: " << DemangledName << '\n'); std::string BuiltinVarName; SPIRVBuiltinVariableKind BVKind; if (!SPIRSPIRVBuiltinVariableMap::find(DemangledName, &BVKind)) continue; BuiltinVarName = std::string(kSPIRVName::Prefix) + SPIRVBuiltInNameMap::map(BVKind); LLVM_DEBUG(dbgs() << "builtin variable name: " << BuiltinVarName << '\n'); bool IsVec = I.getFunctionType()->getNumParams() > 0; Type *GVType = IsVec ? VectorType::get(I.getReturnType(), 3) : I.getReturnType(); auto BV = new GlobalVariable(*M, GVType, true, GlobalValue::ExternalLinkage, nullptr, BuiltinVarName, 0, GlobalVariable::NotThreadLocal, SPIRAS_Input); std::vector InstList; for (auto UI = I.user_begin(), UE = I.user_end(); UI != UE; ++UI) { auto CI = dyn_cast(*UI); assert(CI && "invalid instruction"); Value *NewValue = new LoadInst(BV, "", CI); LLVM_DEBUG(dbgs() << "Transform: " << *CI << " => " << *NewValue << '\n'); if (IsVec) { NewValue = ExtractElementInst::Create(NewValue, CI->getArgOperand(0), "", CI); LLVM_DEBUG(dbgs() << *NewValue << '\n'); } NewValue->takeName(CI); CI->replaceAllUsesWith(NewValue); InstList.push_back(CI); } for (auto &Inst : InstList) { Inst->eraseFromParent(); } WorkList.push_back(&I); } for (auto &I : WorkList) { I->eraseFromParent(); } } void OCL20ToSPIRV::visitCallReadWriteImage(CallInst *CI, StringRef MangledName, const std::string &DemangledName) { OCLBuiltinTransInfo Info; if (DemangledName.find(kOCLBuiltinName::ReadImage) == 0) Info.UniqName = kOCLBuiltinName::ReadImage; if (DemangledName.find(kOCLBuiltinName::WriteImage) == 0) { Info.UniqName = kOCLBuiltinName::WriteImage; Info.PostProc = [&](std::vector &Args) { if (Args.size() == 4) // write with lod { auto Lod = Args[2]; Args.erase(Args.begin() + 2); Args.push_back(getInt32(M, ImageOperandsMask::ImageOperandsLodMask)); Args.push_back(Lod); } }; } transBuiltin(CI, Info); } void OCL20ToSPIRV::visitCallToAddr(CallInst *CI, StringRef MangledName, const std::string &DemangledName) { auto AddrSpace = static_cast(CI->getType()->getPointerAddressSpace()); OCLBuiltinTransInfo Info; Info.UniqName = DemangledName; Info.Postfix = std::string(kSPIRVPostfix::Divider) + "To" + SPIRAddrSpaceCapitalizedNameMap::map(AddrSpace); auto StorageClass = addInt32(SPIRSPIRVAddrSpaceMap::map(AddrSpace)); Info.RetTy = getInt8PtrTy(cast(CI->getType())); Info.PostProc = [=](std::vector &Ops) { auto P = Ops.back(); Ops.pop_back(); Ops.push_back(castToInt8Ptr(P, CI)); Ops.push_back(StorageClass); }; transBuiltin(CI, Info); } void OCL20ToSPIRV::visitCallRelational(CallInst *CI, const std::string &DemangledName) { assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); Op OC = OpNop; OCLSPIRVBuiltinMap::find(DemangledName, &OC); std::string SPIRVName = getSPIRVFuncName(OC); mutateCallInstSPIRV( M, CI, [=](CallInst *, std::vector &Args, Type *&Ret) { Ret = Type::getInt1Ty(*Ctx); if (CI->getOperand(0)->getType()->isVectorTy()) Ret = VectorType::get( Type::getInt1Ty(*Ctx), CI->getOperand(0)->getType()->getVectorNumElements()); return SPIRVName; }, [=](CallInst *NewCI) -> Instruction * { Value *False = nullptr, *True = nullptr; if (NewCI->getType()->isVectorTy()) { Type *IntTy = Type::getInt32Ty(*Ctx); if (cast(NewCI->getOperand(0)->getType()) ->getElementType() ->isDoubleTy()) IntTy = Type::getInt64Ty(*Ctx); if (cast(NewCI->getOperand(0)->getType()) ->getElementType() ->isHalfTy()) IntTy = Type::getInt16Ty(*Ctx); Type *VTy = VectorType::get(IntTy, NewCI->getType()->getVectorNumElements()); False = Constant::getNullValue(VTy); True = Constant::getAllOnesValue(VTy); } else { False = getInt32(M, 0); True = getInt32(M, 1); } return SelectInst::Create(NewCI, True, False, "", NewCI->getNextNode()); }, &Attrs); } void OCL20ToSPIRV::visitCallVecLoadStore(CallInst *CI, StringRef MangledName, const std::string &OrigDemangledName) { std::vector PreOps; std::string DemangledName = OrigDemangledName; if (DemangledName.find(kOCLBuiltinName::VLoadPrefix) == 0 && DemangledName != kOCLBuiltinName::VLoadHalf) { SPIRVWord Width = getVecLoadWidth(DemangledName); SPIRVDBG(spvdbgs() << "[visitCallVecLoadStore] DemangledName: " << DemangledName << " Width: " << Width << '\n'); PreOps.push_back(Width); } else if (DemangledName.find(kOCLBuiltinName::RoundingPrefix) != std::string::npos) { auto R = SPIRSPIRVFPRoundingModeMap::map(DemangledName.substr( DemangledName.find(kOCLBuiltinName::RoundingPrefix) + 1, 3)); PreOps.push_back(R); } if (DemangledName.find(kOCLBuiltinName::VLoadAPrefix) == 0) transVecLoadStoreName(DemangledName, kOCLBuiltinName::VLoadAPrefix, true); else transVecLoadStoreName(DemangledName, kOCLBuiltinName::VLoadPrefix, false); if (DemangledName.find(kOCLBuiltinName::VStoreAPrefix) == 0) transVecLoadStoreName(DemangledName, kOCLBuiltinName::VStoreAPrefix, true); else transVecLoadStoreName(DemangledName, kOCLBuiltinName::VStorePrefix, false); auto Consts = getInt32(M, PreOps); OCLBuiltinTransInfo Info; Info.MangledName = MangledName; Info.UniqName = DemangledName; if (DemangledName.find(kOCLBuiltinName::VLoadPrefix) == 0) Info.Postfix = std::string(kSPIRVPostfix::ExtDivider) + getPostfixForReturnType(CI); Info.PostProc = [=](std::vector &Ops) { Ops.insert(Ops.end(), Consts.begin(), Consts.end()); }; transBuiltin(CI, Info); } void OCL20ToSPIRV::visitCallGetFence(CallInst *CI, StringRef MangledName, const std::string &DemangledName) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); Op OC = OpNop; OCLSPIRVBuiltinMap::find(DemangledName, &OC); std::string SPIRVName = getSPIRVFuncName(OC); mutateCallInstSPIRV(M, CI, [=](CallInst *, std::vector &Args, Type *&Ret) { return SPIRVName; }, [=](CallInst *NewCI) -> Instruction * { return BinaryOperator::CreateLShr(NewCI, getInt32(M, 8), "", CI); }, &Attrs); } void OCL20ToSPIRV::visitCallDot(CallInst *CI) { IRBuilder<> Builder(CI); Value *FMulVal = Builder.CreateFMul(CI->getOperand(0), CI->getOperand(1)); CI->replaceAllUsesWith(FMulVal); CI->eraseFromParent(); } void OCL20ToSPIRV::visitCallScalToVec(CallInst *CI, StringRef MangledName, const std::string &DemangledName) { // Check if all arguments have the same type - it's simple case. auto Uniform = true; auto IsArg0Vector = isa(CI->getOperand(0)->getType()); for (unsigned I = 1, E = CI->getNumArgOperands(); Uniform && (I != E); ++I) { Uniform = isa(CI->getOperand(I)->getType()) == IsArg0Vector; } if (Uniform) { visitCallBuiltinSimple(CI, MangledName, DemangledName); return; } std::vector VecPos; std::vector ScalarPos; if (DemangledName == kOCLBuiltinName::FMin || DemangledName == kOCLBuiltinName::FMax || DemangledName == kOCLBuiltinName::Min || DemangledName == kOCLBuiltinName::Max) { VecPos.push_back(0); ScalarPos.push_back(1); } else if (DemangledName == kOCLBuiltinName::Clamp) { VecPos.push_back(0); ScalarPos.push_back(1); ScalarPos.push_back(2); } else if (DemangledName == kOCLBuiltinName::Mix) { VecPos.push_back(0); VecPos.push_back(1); ScalarPos.push_back(2); } else if (DemangledName == kOCLBuiltinName::Step) { VecPos.push_back(1); ScalarPos.push_back(0); } else if (DemangledName == kOCLBuiltinName::SmoothStep) { VecPos.push_back(2); ScalarPos.push_back(0); ScalarPos.push_back(1); } AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInstSPIRV( M, CI, [=](CallInst *, std::vector &Args) { Args.resize(VecPos.size() + ScalarPos.size()); for (auto I : VecPos) { Args[I] = CI->getOperand(I); } auto VecArgWidth = CI->getOperand(VecPos[0])->getType()->getVectorNumElements(); for (auto I : ScalarPos) { Instruction *Inst = InsertElementInst::Create( UndefValue::get(CI->getOperand(VecPos[0])->getType()), CI->getOperand(I), getInt32(M, 0), "", CI); Value *NewVec = new ShuffleVectorInst( Inst, UndefValue::get(CI->getOperand(VecPos[0])->getType()), ConstantVector::getSplat(VecArgWidth, getInt32(M, 0)), "", CI); Args[I] = NewVec; } return getSPIRVExtFuncName(SPIRVEIS_OpenCL, getExtOp(MangledName, DemangledName)); }, &Attrs); } void OCL20ToSPIRV::visitCallGetImageChannel(CallInst *CI, StringRef MangledName, const std::string &DemangledName, unsigned int Offset) { assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); Op OC = OpNop; OCLSPIRVBuiltinMap::find(DemangledName, &OC); std::string SPIRVName = getSPIRVFuncName(OC); mutateCallInstSPIRV(M, CI, [=](CallInst *, std::vector &Args, Type *&Ret) { return SPIRVName; }, [=](CallInst *NewCI) -> Instruction * { return BinaryOperator::CreateAdd( NewCI, getInt32(M, Offset), "", CI); }, &Attrs); } void OCL20ToSPIRV::visitCallEnqueueKernel(CallInst *CI, const std::string &DemangledName) { const DataLayout &DL = M->getDataLayout(); bool HasEvents = DemangledName.find("events") != std::string::npos; // SPIRV OpEnqueueKernel instruction has 10+ arguments. SmallVector Args; // Copy all arguments before block invoke function pointer // which match with what Clang 6.0 produced const unsigned BlockFIdx = HasEvents ? 6 : 3; Args.assign(CI->arg_begin(), CI->arg_begin() + BlockFIdx); // If no event arguments in original call, add dummy ones if (!HasEvents) { Args.push_back(getInt32(M, 0)); // dummy num events Args.push_back(getOCLNullClkEventPtr(M)); // dummy wait events Args.push_back(getOCLNullClkEventPtr(M)); // dummy ret event } // Invoke: Pointer to invoke function Value *BlockFunc = CI->getArgOperand(BlockFIdx); Args.push_back(cast(GetUnderlyingObject(BlockFunc, DL))); // Param: Pointer to block literal Value *BlockLiteral = CI->getArgOperand(BlockFIdx + 1); Args.push_back(BlockLiteral); // Param Size: Size of block literal structure // Param Aligment: Aligment of block literal structure // TODO: these numbers should be obtained from block literal structure Type *ParamType = GetUnderlyingObject(BlockLiteral, DL)->getType(); if (PointerType *PT = dyn_cast(ParamType)) ParamType = PT->getElementType(); Args.push_back(getInt32(M, DL.getTypeStoreSize(ParamType))); Args.push_back(getInt32(M, DL.getPrefTypeAlignment(ParamType))); // Local sizes arguments: Sizes of block invoke arguments // Clang 6.0 and higher generates local size operands as an array, // so we need to unpack them if (DemangledName.find("_varargs") != std::string::npos) { const unsigned LocalSizeArrayIdx = HasEvents ? 9 : 6; auto *LocalSizeArray = cast(CI->getArgOperand(LocalSizeArrayIdx)); auto *LocalSizeArrayTy = cast(LocalSizeArray->getSourceElementType()); const uint64_t LocalSizeNum = LocalSizeArrayTy->getNumElements(); for (unsigned I = 0; I < LocalSizeNum; ++I) Args.push_back(GetElementPtrInst::Create( LocalSizeArray->getSourceElementType(), // Pointee type LocalSizeArray->getPointerOperand(), // Alloca {getInt32(M, 0), getInt32(M, I)}, // Indices "", CI)); } StringRef NewName = "__spirv_EnqueueKernel__"; FunctionType *FT = FunctionType::get(CI->getType(), getTypes(Args), false /*isVarArg*/); Function *NewF = Function::Create(FT, GlobalValue::ExternalLinkage, NewName, M); NewF->setCallingConv(CallingConv::SPIR_FUNC); CallInst *NewCall = CallInst::Create(NewF, Args, "", CI); NewCall->setCallingConv(NewF->getCallingConv()); CI->replaceAllUsesWith(NewCall); CI->eraseFromParent(); } void OCL20ToSPIRV::visitCallKernelQuery(CallInst *CI, const std::string &DemangledName) { const DataLayout &DL = M->getDataLayout(); bool HasNDRange = DemangledName.find("_for_ndrange_impl") != std::string::npos; // BIs with "_for_ndrange_impl" suffix has NDRange argument first, and // Invoke argument following. For other BIs Invoke function is the first arg const unsigned BlockFIdx = HasNDRange ? 1 : 0; Value *BlockFVal = CI->getArgOperand(BlockFIdx)->stripPointerCasts(); auto *BlockF = cast(GetUnderlyingObject(BlockFVal, DL)); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInst(M, CI, [=](CallInst *CI, std::vector &Args) { Value *Param = *Args.rbegin(); Type *ParamType = GetUnderlyingObject(Param, DL)->getType(); if (PointerType *PT = dyn_cast(ParamType)) { ParamType = PT->getElementType(); } // Last arg corresponds to SPIRV Param operand. // Insert Invoke in front of Param. // Add Param Size and Param Align at the end. Args[BlockFIdx] = BlockF; Args.push_back(getInt32(M, DL.getTypeStoreSize(ParamType))); Args.push_back( getInt32(M, DL.getPrefTypeAlignment(ParamType))); Op Opcode = OCLSPIRVBuiltinMap::map(DemangledName); // Adding "__" postfix, so in case we have multiple such // functions and their names will have numerical postfix, // then the numerical postfix will be droped and we will get // correct function name. return getSPIRVFuncName(Opcode, kSPIRVName::Postfix); }, /*BuiltinFuncMangleInfo*/ nullptr, &Attrs); } // The intel_sub_group_block_read built-ins are overloaded to support both // buffers and images, but need to be mapped to distinct SPIR-V instructions. // Additionally, for block reads, need to distinguish between scalar block // reads and vector block reads. void OCL20ToSPIRV::visitSubgroupBlockReadINTEL( CallInst *CI, StringRef MangledName, const std::string &DemangledName) { OCLBuiltinTransInfo Info; if (isOCLImageType(CI->getArgOperand(0)->getType())) Info.UniqName = getSPIRVFuncName(spv::OpSubgroupImageBlockReadINTEL); else Info.UniqName = getSPIRVFuncName(spv::OpSubgroupBlockReadINTEL); if (CI->getType()->isVectorTy()) { switch (CI->getType()->getVectorNumElements()) { case 2: Info.Postfix = "_v2"; break; case 4: Info.Postfix = "_v4"; break; case 8: Info.Postfix = "_v8"; break; default: break; } } if (CI->getType()->getScalarSizeInBits() == 16) Info.Postfix += "_us"; else Info.Postfix += "_ui"; assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInstSPIRV(M, CI, [=](CallInst *, std::vector &Args) { Info.PostProc(Args); return Info.UniqName + Info.Postfix; }, &Attrs); } // The intel_sub_group_block_write built-ins are similarly overloaded to support // both buffers and images but need to be mapped to distinct SPIR-V // instructions. Since the type of data to be written is encoded in the mangled // name there is no need to do additional work to distinguish between scalar // block writes and vector block writes. void OCL20ToSPIRV::visitSubgroupBlockWriteINTEL( CallInst *CI, StringRef MangledName, const std::string &DemangledName) { OCLBuiltinTransInfo Info; if (isOCLImageType(CI->getArgOperand(0)->getType())) Info.UniqName = getSPIRVFuncName(spv::OpSubgroupImageBlockWriteINTEL); else Info.UniqName = getSPIRVFuncName(spv::OpSubgroupBlockWriteINTEL); unsigned NumArgs = CI->getNumArgOperands(); if (NumArgs && CI->getArgOperand(NumArgs - 1)->getType()->isVectorTy()) { switch (CI->getArgOperand(NumArgs - 1)->getType()->getVectorNumElements()) { case 2: Info.Postfix = "_v2"; break; case 4: Info.Postfix = "_v4"; break; case 8: Info.Postfix = "_v8"; break; default: break; } } assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInstSPIRV(M, CI, [=](CallInst *, std::vector &Args) { Info.PostProc(Args); return Info.UniqName + Info.Postfix; }, &Attrs); } void OCL20ToSPIRV::visitSubgroupImageMediaBlockINTEL( CallInst *CI, const std::string &DemangledName) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); spv::Op OpCode = DemangledName.rfind("read") != std::string::npos ? spv::OpSubgroupImageMediaBlockReadINTEL : spv::OpSubgroupImageMediaBlockWriteINTEL; mutateCallInstSPIRV( M, CI, [=](CallInst *, std::vector &Args) { // Moving the last argument to the beginning. std::rotate(Args.begin(), Args.end() - 1, Args.end()); return getSPIRVFuncName(OpCode, CI->getType()); }, &Attrs); } static const char *getSubgroupAVCIntelOpKind(const std::string &Name) { return StringSwitch(Name) .StartsWith(kOCLSubgroupsAVCIntel::IMEPrefix, "ime") .StartsWith(kOCLSubgroupsAVCIntel::REFPrefix, "ref") .StartsWith(kOCLSubgroupsAVCIntel::SICPrefix, "sic"); } static const char *getSubgroupAVCIntelTyKind(Type *Ty) { auto STy = cast(cast(Ty)->getElementType()); auto TName = STy->getName(); return TName.endswith("_payload_t") ? "payload" : "result"; } static Type *getSubgroupAVCIntelMCEType(Module *M, std::string &TName) { auto Ty = M->getTypeByName(TName); if (Ty) return Ty; return StructType::create(M->getContext(), TName); } static Op getSubgroupAVCIntelMCEOpCodeForWrapper(const std::string &DemangledName) { if (DemangledName.size() <= strlen(kOCLSubgroupsAVCIntel::MCEPrefix)) return OpNop; // this is not a VME built-in std::string MCEName = DemangledName; MCEName.replace(0, strlen(kOCLSubgroupsAVCIntel::MCEPrefix), kOCLSubgroupsAVCIntel::MCEPrefix); Op MCEOC = OpNop; OCLSPIRVSubgroupAVCIntelBuiltinMap::find(MCEName, &MCEOC); return MCEOC; } // Handles Subgroup AVC Intel extension generic built-ins. void OCL20ToSPIRV::visitSubgroupAVCBuiltinCall( CallInst *CI, StringRef MangledName, const std::string &DemangledName) { Op OC = OpNop; std::string FName = DemangledName; std::string Prefix = kOCLSubgroupsAVCIntel::Prefix; // Update names for built-ins mapped on two or more SPIRV instructions if (FName.find(Prefix + "ime_get_streamout_major_shape_") == 0) { auto PTy = cast(CI->getArgOperand(0)->getType()); auto STy = cast(PTy->getElementType()); assert(STy->hasName() && "Invalid Subgroup AVC Intel built-in call"); FName += (STy->getName().contains("single")) ? "_single_reference" : "_dual_reference"; } else if (FName.find(Prefix + "sic_configure_ipe") == 0) { FName += (CI->getNumArgOperands() == 8) ? "_luma" : "_luma_chroma"; } OCLSPIRVSubgroupAVCIntelBuiltinMap::find(FName, &OC); if (OC == OpNop) { if (Op MCEOC = getSubgroupAVCIntelMCEOpCodeForWrapper(DemangledName)) // The called function is a VME wrapper built-in return visitSubgroupAVCWrapperBuiltinCall(CI, MCEOC, DemangledName); else // The called function isn't a VME built-in return; } AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInstSPIRV( M, CI, [=](CallInst *, std::vector &Args) { return getSPIRVFuncName(OC); }, &Attrs); } // Handles Subgroup AVC Intel extension wrapper built-ins. // 'IME', 'REF' and 'SIC' sets contain wrapper built-ins which don't have // corresponded instructions in SPIRV and should be translated to a // conterpart from 'MCE' with conversion for an argument and result (if needed). void OCL20ToSPIRV::visitSubgroupAVCWrapperBuiltinCall( CallInst *CI, Op WrappedOC, const std::string &DemangledName) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); std::string Prefix = kOCLSubgroupsAVCIntel::Prefix; // Find 'to_mce' conversion function. // The operand required conversion is always the last one. const char *OpKind = getSubgroupAVCIntelOpKind(DemangledName); const char *TyKind = getSubgroupAVCIntelTyKind( CI->getArgOperand(CI->getNumArgOperands() - 1)->getType()); std::string MCETName = std::string(kOCLSubgroupsAVCIntel::TypePrefix) + "mce_" + TyKind + "_t"; auto *MCETy = PointerType::get(getSubgroupAVCIntelMCEType(M, MCETName), SPIRAS_Private); std::string ToMCEFName = Prefix + OpKind + "_convert_to_mce_" + TyKind; Op ToMCEOC = OpNop; OCLSPIRVSubgroupAVCIntelBuiltinMap::find(ToMCEFName, &ToMCEOC); assert(ToMCEOC != OpNop && "Invalid Subgroup AVC Intel built-in call"); if (std::strcmp(TyKind, "payload") == 0) { // Wrapper built-ins which take the 'payload_t' argument return it as // the result: two conversion calls required. std::string FromMCEFName = Prefix + "mce_convert_to_" + OpKind + "_" + TyKind; Op FromMCEOC = OpNop; OCLSPIRVSubgroupAVCIntelBuiltinMap::find(FromMCEFName, &FromMCEOC); assert(FromMCEOC != OpNop && "Invalid Subgroup AVC Intel built-in call"); mutateCallInstSPIRV( M, CI, [=](CallInst *, std::vector &Args, Type *&Ret) { Ret = MCETy; // Create conversion function call for the last operand Args[Args.size() - 1] = addCallInstSPIRV(M, getSPIRVFuncName(ToMCEOC), MCETy, Args[Args.size() - 1], nullptr, CI, ""); return getSPIRVFuncName(WrappedOC); }, [=](CallInst *NewCI) -> Instruction * { // Create conversion function call for the return result return addCallInstSPIRV(M, getSPIRVFuncName(FromMCEOC), CI->getType(), NewCI, nullptr, CI, ""); }, &Attrs); } else { // Wrapper built-ins which take the 'result_t' argument requires only one // conversion for the argument mutateCallInstSPIRV( M, CI, [=](CallInst *, std::vector &Args) { // Create conversion function call for the last // operand Args[Args.size() - 1] = addCallInstSPIRV(M, getSPIRVFuncName(ToMCEOC), MCETy, Args[Args.size() - 1], nullptr, CI, ""); return getSPIRVFuncName(WrappedOC); }, &Attrs); } } // Handles Subgroup AVC Intel extension built-ins which take sampler as // an argument (their SPIR-V counterparts take OpTypeVmeImageIntel instead) void OCL20ToSPIRV::visitSubgroupAVCBuiltinCallWithSampler( CallInst *CI, StringRef MangledName, const std::string &DemangledName) { std::string FName = DemangledName; std::string Prefix = kOCLSubgroupsAVCIntel::Prefix; // Update names for built-ins mapped on two or more SPIRV instructions if (FName.find(Prefix + "ref_evaluate_with_multi_reference") == 0 || FName.find(Prefix + "sic_evaluate_with_multi_reference") == 0) { FName += (CI->getNumArgOperands() == 5) ? "_interlaced" : ""; } Op OC = OpNop; OCLSPIRVSubgroupAVCIntelBuiltinMap::find(FName, &OC); if (OC == OpNop) return; // this is not a VME built-in AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInstSPIRV( M, CI, [=](CallInst *, std::vector &Args) { auto SamplerIt = std::find_if(Args.begin(), Args.end(), [](Value *V) { return OCLUtil::isSamplerTy(V->getType()); }); assert(SamplerIt != Args.end() && "Invalid Subgroup AVC Intel built-in call"); auto *SamplerVal = *SamplerIt; Args.erase(SamplerIt); for (unsigned I = 0, E = Args.size(); I < E; ++I) { if (!isOCLImageType(Args[I]->getType())) continue; auto *ImageTy = getAnalysis().getAdaptedType(Args[I]); if (isOCLImageType(ImageTy)) ImageTy = getSPIRVImageTypeFromOCL(M, ImageTy); auto *SampledImgTy = getSPIRVTypeByChangeBaseTypeName( M, ImageTy, kSPIRVTypeName::Image, kSPIRVTypeName::VmeImageINTEL); Value *SampledImgArgs[] = {Args[I], SamplerVal}; Args[I] = addCallInstSPIRV(M, getSPIRVFuncName(OpVmeImageINTEL), SampledImgTy, SampledImgArgs, nullptr, CI, kSPIRVName::TempSampledImage); } return getSPIRVFuncName(OC); }, &Attrs); } } // namespace SPIRV INITIALIZE_PASS_BEGIN(OCL20ToSPIRV, "cl20tospv", "Transform OCL 2.0 to SPIR-V", false, false) INITIALIZE_PASS_DEPENDENCY(OCLTypeToSPIRV) INITIALIZE_PASS_END(OCL20ToSPIRV, "cl20tospv", "Transform OCL 2.0 to SPIR-V", false, false) ModulePass *llvm::createOCL20ToSPIRV() { return new OCL20ToSPIRV(); } SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/OCL21ToSPIRV.cpp000066400000000000000000000217761363521741200214770ustar00rootroot00000000000000//===- OCL21ToSPIRV.cpp - Transform OCL21 to SPIR-V builtins ----*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// // // This file implements translation of OCL21 builtin functions. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "cl21tospv" #include "OCLUtil.h" #include "SPIRVInternal.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstVisitor.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Verifier.h" #include "llvm/Pass.h" #include "llvm/PassSupport.h" #include "llvm/Support/Debug.h" #include using namespace llvm; using namespace SPIRV; using namespace OCLUtil; namespace SPIRV { class OCL21ToSPIRV : public ModulePass, public InstVisitor { public: OCL21ToSPIRV() : ModulePass(ID), M(nullptr), Ctx(nullptr), CLVer(0) { initializeOCL21ToSPIRVPass(*PassRegistry::getPassRegistry()); } bool runOnModule(Module &M) override; virtual void visitCallInst(CallInst &CI); /// Transform SPIR-V convert function // __spirv{N}Op{ConvertOpName}(src, dummy) /// => /// __spirv_{ConvertOpName}_R{TargeTyName} void visitCallConvert(CallInst *CI, StringRef MangledName, Op OC); /// Transform SPIR-V decoration /// x = __spirv_{OpName}; /// y = __spirv{N}Op{Decorate}(x, type, value, dummy) /// => /// y = __spirv_{OpName}{Postfix(type,value)} void visitCallDecorate(CallInst *CI, StringRef MangledName); /// Transform sub_group_barrier to __spirv_ControlBarrier. /// sub_group_barrier(scope, flag) => /// __spirv_ControlBarrier(subgroup, map(scope), map(flag)) void visitCallSubGroupBarrier(CallInst *CI); /// Transform OCL C++ builtin function to SPIR-V builtin function. /// Assuming there is no argument changes. /// Should be called at last. void transBuiltin(CallInst *CI, Op OC); static char ID; private: ConstantInt *addInt32(int I) { return getInt32(M, I); } Module *M; LLVMContext *Ctx; unsigned CLVer; /// OpenCL version as major*10+minor std::set ValuesToDelete; }; char OCL21ToSPIRV::ID = 0; bool OCL21ToSPIRV::runOnModule(Module &Module) { M = &Module; Ctx = &M->getContext(); auto Src = getSPIRVSource(&Module); if (std::get<0>(Src) != spv::SourceLanguageOpenCL_CPP) return false; CLVer = std::get<1>(Src); if (CLVer < kOCLVer::CL21) return false; LLVM_DEBUG(dbgs() << "Enter OCL21ToSPIRV:\n"); visit(*M); for (auto &I : ValuesToDelete) if (auto Inst = dyn_cast(I)) Inst->eraseFromParent(); for (auto &I : ValuesToDelete) if (auto GV = dyn_cast(I)) GV->eraseFromParent(); LLVM_DEBUG(dbgs() << "After OCL21ToSPIRV:\n" << *M); std::string Err; raw_string_ostream ErrorOS(Err); if (verifyModule(*M, &ErrorOS)) { LLVM_DEBUG(errs() << "Fails to verify module: " << ErrorOS.str()); } return true; } // The order of handling OCL builtin functions is important. // Workgroup functions need to be handled before pipe functions since // there are functions fall into both categories. void OCL21ToSPIRV::visitCallInst(CallInst &CI) { LLVM_DEBUG(dbgs() << "[visistCallInst] " << CI << '\n'); auto F = CI.getCalledFunction(); if (!F) return; auto MangledName = F->getName(); std::string DemangledName; if (oclIsBuiltin(MangledName, &DemangledName)) { if (DemangledName == kOCLBuiltinName::SubGroupBarrier) { visitCallSubGroupBarrier(&CI); return; } } if (!oclIsBuiltin(MangledName, &DemangledName, true)) return; LLVM_DEBUG(dbgs() << "DemangledName:" << DemangledName << '\n'); StringRef Ref(DemangledName); Op OC = OpNop; if (!OpCodeNameMap::rfind(Ref.str(), &OC)) return; LLVM_DEBUG(dbgs() << "maps to opcode " << OC << '\n'); if (isCvtOpCode(OC)) { visitCallConvert(&CI, MangledName, OC); return; } if (OC == OpDecorate) { visitCallDecorate(&CI, MangledName); return; } transBuiltin(&CI, OC); } void OCL21ToSPIRV::visitCallConvert(CallInst *CI, StringRef MangledName, Op OC) { assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInstSPIRV( M, CI, [=](CallInst *, std::vector &Args) { Args.pop_back(); return getSPIRVFuncName( OC, kSPIRVPostfix::Divider + getPostfixForReturnType(CI, OC == OpSConvert || OC == OpConvertFToS || OC == OpSatConvertUToS)); }, &Attrs); ValuesToDelete.insert(CI); ValuesToDelete.insert(CI->getCalledFunction()); } void OCL21ToSPIRV::visitCallDecorate(CallInst *CI, StringRef MangledName) { auto Target = cast(CI->getArgOperand(0)); assert(Target->getCalledFunction() && "Unexpected indirect call"); auto F = Target->getCalledFunction(); auto Name = F->getName().str(); std::string DemangledName; oclIsBuiltin(Name, &DemangledName); BuiltinFuncMangleInfo Info; F->setName(mangleBuiltin( DemangledName + kSPIRVPostfix::Divider + getPostfix(getArgAsDecoration(CI, 1), getArgAsInt(CI, 2)), getTypes(getArguments(CI)), &Info)); CI->replaceAllUsesWith(Target); ValuesToDelete.insert(CI); ValuesToDelete.insert(CI->getCalledFunction()); } void OCL21ToSPIRV::visitCallSubGroupBarrier(CallInst *CI) { LLVM_DEBUG(dbgs() << "[visitCallSubGroupBarrier] " << *CI << '\n'); auto Lit = getBarrierLiterals(CI); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInstSPIRV(M, CI, [=](CallInst *, std::vector &Args) { Args.resize(3); // Execution scope Args[0] = addInt32(map(std::get<2>(Lit))); // Memory scope Args[1] = addInt32(map(std::get<1>(Lit))); // Use sequential consistent memory order by default. // But if the flags argument is set to 0, we use // None(Relaxed) memory order. unsigned MemFenceFlag = std::get<0>(Lit); OCLMemOrderKind MemOrder = MemFenceFlag ? OCLMO_seq_cst : OCLMO_relaxed; Args[2] = addInt32(mapOCLMemSemanticToSPIRV( MemFenceFlag, MemOrder)); // Memory semantics return getSPIRVFuncName(OpControlBarrier); }, &Attrs); } void OCL21ToSPIRV::transBuiltin(CallInst *CI, Op OC) { assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); assert(OC != OpExtInst && "not supported"); mutateCallInstSPIRV(M, CI, [=](CallInst *, std::vector &Args) { return getSPIRVFuncName(OC); }, &Attrs); ValuesToDelete.insert(CI); ValuesToDelete.insert(CI->getCalledFunction()); } } // namespace SPIRV INITIALIZE_PASS(OCL21ToSPIRV, "cl21tospv", "Transform OCL 2.1 to SPIR-V", false, false) ModulePass *llvm::createOCL21ToSPIRV() { return new OCL21ToSPIRV(); } SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/OCLTypeToSPIRV.cpp000066400000000000000000000256311363521741200221700ustar00rootroot00000000000000//===- OCLTypeToSPIRV.cpp - Adapt types from OCL for SPIRV ------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// // // This file implements adaptation of OCL types for SPIRV. // // It first maps kernel arguments of OCL opaque types to SPIR-V type, then // propagates the mapping to the uses of the kernel arguments. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "cltytospv" #include "OCLTypeToSPIRV.h" #include "OCLUtil.h" #include "SPIRVInternal.h" #include "llvm/Pass.h" #include "llvm/PassSupport.h" #include "llvm/Support/Debug.h" #include #include using namespace llvm; using namespace SPIRV; using namespace OCLUtil; namespace SPIRV { char OCLTypeToSPIRV::ID = 0; OCLTypeToSPIRV::OCLTypeToSPIRV() : ModulePass(ID), M(nullptr), Ctx(nullptr), CLVer(0) { initializeOCLTypeToSPIRVPass(*PassRegistry::getPassRegistry()); } void OCLTypeToSPIRV::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); } bool OCLTypeToSPIRV::runOnModule(Module &Module) { LLVM_DEBUG(dbgs() << "Enter OCLTypeToSPIRV:\n"); M = &Module; Ctx = &M->getContext(); auto Src = getSPIRVSource(&Module); if (std::get<0>(Src) != spv::SourceLanguageOpenCL_C) return false; for (auto &F : Module.functions()) adaptArgumentsByMetadata(&F); for (auto &F : Module.functions()) adaptFunctionArguments(&F); adaptArgumentsBySamplerUse(Module); while (!WorkSet.empty()) { Function *F = *WorkSet.begin(); WorkSet.erase(WorkSet.begin()); adaptFunction(F); } return false; } void OCLTypeToSPIRV::addAdaptedType(Value *V, Type *T) { LLVM_DEBUG(dbgs() << "[add adapted type] "; V->printAsOperand(dbgs(), true, M); dbgs() << " => " << *T << '\n'); AdaptedTy[V] = T; } void OCLTypeToSPIRV::addWork(Function *F) { LLVM_DEBUG(dbgs() << "[add work] "; F->printAsOperand(dbgs(), true, M); dbgs() << '\n'); WorkSet.insert(F); } /// Find index of \param V as argument of function call \param CI. static unsigned getArgIndex(CallInst *CI, Value *V) { for (unsigned AI = 0, AE = CI->getNumArgOperands(); AI != AE; ++AI) { if (CI->getArgOperand(AI) == V) return AI; } llvm_unreachable("Not argument of function call"); return ~0U; } /// Find index of \param V as argument of function call \param CI. static unsigned getArgIndex(Function *F, Value *V) { auto A = F->arg_begin(), E = F->arg_end(); for (unsigned I = 0; A != E; ++I, ++A) { if (&(*A) == V) return I; } llvm_unreachable("Not argument of function"); return ~0U; } /// Get i-th argument of a function. static Argument *getArg(Function *F, unsigned I) { auto AI = F->arg_begin(); std::advance(AI, I); return &(*AI); } /// Create a new function type if \param F has arguments in AdaptedTy, and /// propagates the adapted arguments to functions called by \param F. void OCLTypeToSPIRV::adaptFunction(Function *F) { LLVM_DEBUG(dbgs() << "\n[work on function] "; F->printAsOperand(dbgs(), true, M); dbgs() << '\n'); assert(AdaptedTy.count(F) == 0); std::vector ArgTys; bool Changed = false; for (auto &I : F->args()) { auto Loc = AdaptedTy.find(&I); auto Found = (Loc != AdaptedTy.end()); Changed |= Found; ArgTys.push_back(Found ? Loc->second : I.getType()); if (Found) { for (auto U : I.users()) { if (auto CI = dyn_cast(U)) { auto ArgIndex = getArgIndex(CI, &I); auto CF = CI->getCalledFunction(); if (AdaptedTy.count(CF) == 0) { addAdaptedType(getArg(CF, ArgIndex), Loc->second); addWork(CF); } } } } } if (!Changed) return; auto FT = F->getFunctionType(); FT = FunctionType::get(FT->getReturnType(), ArgTys, FT->isVarArg()); addAdaptedType(F, FT); } // Handle functions with sampler arguments that don't get called by // a kernel function. void OCLTypeToSPIRV::adaptArgumentsBySamplerUse(Module &M) { SmallPtrSet Processed; std::function TraceArg = [&](Function *F, unsigned Idx) { // If we have cycles in the call graph in the future, bail out // if we've already processed this function. if (Processed.insert(F).second == false) return; for (auto U : F->users()) { auto *CI = dyn_cast(U); if (!CI) continue; auto SamplerArg = CI->getArgOperand(Idx); if (!isa(SamplerArg) || AdaptedTy.count(SamplerArg) != 0) // Already traced this, move on. continue; if (isSPIRVType(SamplerArg->getType(), kSPIRVTypeName::Sampler)) return; addAdaptedType(SamplerArg, getSamplerType(&M)); auto Caller = cast(SamplerArg)->getParent(); addWork(Caller); TraceArg(Caller, getArgIndex(Caller, SamplerArg)); } }; for (auto &F : M) { if (!F.empty()) // not decl continue; auto MangledName = F.getName(); std::string DemangledName; if (!oclIsBuiltin(MangledName, &DemangledName, false)) continue; if (DemangledName.find(kSPIRVName::SampledImage) == std::string::npos) continue; TraceArg(&F, 1); } } void OCLTypeToSPIRV::adaptFunctionArguments(Function *F) { auto TypeMD = F->getMetadata(SPIR_MD_KERNEL_ARG_BASE_TYPE); if (TypeMD) return; bool Changed = false; auto FT = F->getFunctionType(); auto PI = FT->param_begin(); auto Arg = F->arg_begin(); for (unsigned I = 0; I < F->arg_size(); ++I, ++PI, ++Arg) { auto NewTy = *PI; if (isPointerToOpaqueStructType(NewTy)) { auto STName = NewTy->getPointerElementType()->getStructName(); if (!hasAccessQualifiedName(STName)) continue; if (STName.startswith(kSPR2TypeName::ImagePrefix)) { auto Ty = STName.str(); auto AccStr = getAccessQualifier(Ty); addAdaptedType(&*Arg, getOrCreateOpaquePtrType( M, mapOCLTypeNameToSPIRV(Ty, AccStr))); Changed = true; } } } if (Changed) addWork(F); } /// Go through all kernel functions, get access qualifier for image and pipe /// types and use them to map the function arguments to the SPIR-V type. /// ToDo: Map other OpenCL opaque types to SPIR-V types. void OCLTypeToSPIRV::adaptArgumentsByMetadata(Function *F) { auto TypeMD = F->getMetadata(SPIR_MD_KERNEL_ARG_BASE_TYPE); if (!TypeMD) return; bool Changed = false; auto FT = F->getFunctionType(); auto PI = FT->param_begin(); auto Arg = F->arg_begin(); for (unsigned I = 0, E = TypeMD->getNumOperands(); I != E; ++I, ++PI, ++Arg) { auto OCLTyStr = getMDOperandAsString(TypeMD, I); auto NewTy = *PI; if (OCLTyStr == OCL_TYPE_NAME_SAMPLER_T && !NewTy->isStructTy()) { addAdaptedType(&(*Arg), getSamplerType(M)); Changed = true; } else if (isPointerToOpaqueStructType(NewTy)) { auto STName = NewTy->getPointerElementType()->getStructName(); if (STName.startswith(kSPR2TypeName::ImagePrefix)) { auto Ty = STName.str(); auto AccMD = F->getMetadata(SPIR_MD_KERNEL_ARG_ACCESS_QUAL); assert(AccMD && "Invalid access qualifier metadata"); auto AccStr = getMDOperandAsString(AccMD, I); addAdaptedType(&(*Arg), getOrCreateOpaquePtrType( M, mapOCLTypeNameToSPIRV(Ty, AccStr))); Changed = true; } } } if (Changed) addWork(F); } // OCL sampler, image and pipe type need to be regularized before converting // to SPIRV types. // // OCL sampler type is represented as i32 in LLVM, however in SPIRV it is // represented as OpTypeSampler. Also LLVM uses the same pipe type to // represent pipe types with different underlying data types, however // in SPIRV they are different types. OCL image and pipie types do not // encode access qualifier, which is part of SPIRV types for image and pipe. // // The function types in LLVM need to be regularized before translating // to SPIRV function types: // // sampler type as i32 -> opencl.sampler_t opaque type // opencl.pipe_t opaque type with underlying opencl type x and access // qualifier y -> opencl.pipe_t.x.y opaque type // opencl.image_x opaque type with access qualifier y -> // opencl.image_x.y opaque type // // The converter relies on kernel_arg_base_type to identify the sampler // type, the underlying data type of pipe type, and access qualifier for // image and pipe types. The FE is responsible to generate the correct // kernel_arg_base_type metadata. // // Alternatively,the FE may choose to use opencl.sampler_t to represent // sampler type, use opencl.pipe_t.x.y to represent pipe type with underlying // opencl data type x and access qualifier y, and use opencl.image_x.y to // represent image_x type with access qualifier y. // Type *OCLTypeToSPIRV::getAdaptedType(Value *V) { auto Loc = AdaptedTy.find(V); if (Loc != AdaptedTy.end()) return Loc->second; if (auto F = dyn_cast(V)) return F->getFunctionType(); return V->getType(); } } // namespace SPIRV INITIALIZE_PASS(OCLTypeToSPIRV, "cltytospv", "Adapt OCL types for SPIR-V", false, true) ModulePass *llvm::createOCLTypeToSPIRV() { return new OCLTypeToSPIRV(); } SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/OCLTypeToSPIRV.h000066400000000000000000000066551363521741200216420ustar00rootroot00000000000000//===- OCLTypeToSPIRV.h - Adapt types from OCL for SPIRV --------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// // // This file implements adaptation of OCL types for SPIRV. It does not modify // the module. Instead, it returns adapted function type based on kernel // argument metadata. Later LLVM/SPIRV translator will translate the adapted // type instead of the original type. // //===----------------------------------------------------------------------===// #ifndef SPIRV_OCLTYPETOSPIRV_H #define SPIRV_OCLTYPETOSPIRV_H #include "LLVMSPIRVLib.h" #include "llvm/IR/Function.h" #include "llvm/IR/LLVMContext.h" #include "llvm/Pass.h" #include #include using namespace llvm; namespace SPIRV { class OCLTypeToSPIRV : public ModulePass { public: OCLTypeToSPIRV(); void getAnalysisUsage(AnalysisUsage &AU) const override; bool runOnModule(Module &M) override; /// \return Adapted type based on kernel argument metadata. If \p V is /// a function, returns function type. /// E.g. for a function with argument of read only opencl.image_2d_t* type /// returns a function with argument of type opencl.image2d_t.read_only*. Type *getAdaptedType(Value *V); static char ID; private: Module *M; LLVMContext *Ctx; unsigned CLVer; std::map AdaptedTy; // Adapted types for values std::set WorkSet; // Functions to be adapted void adaptFunctionArguments(Function *F); void adaptArgumentsByMetadata(Function *F); void adaptArgumentsBySamplerUse(Module &M); void adaptFunction(Function *F); void addAdaptedType(Value *V, Type *T); void addWork(Function *F); }; } // namespace SPIRV #endif // SPIRV_OCLTYPETOSPIRV_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/OCLUtil.cpp000066400000000000000000001050771363521741200210400ustar00rootroot00000000000000//===- OCLUtil.cpp - OCL Utilities ----------------------------------------===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// // // This file implements OCL utility functions. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "oclutil" #include "OCLUtil.h" #include "SPIRVEntry.h" #include "SPIRVFunction.h" #include "SPIRVInstruction.h" #include "SPIRVInternal.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstVisitor.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Verifier.h" #include "llvm/Pass.h" #include "llvm/PassSupport.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" using namespace llvm; using namespace SPIRV; namespace OCLUtil { #ifndef SPIRV_OCL_SPECIAL_TYPES_DEFAULT_ADDR_SPACE #define SPIRV_OCL_SPECIAL_TYPES_DEFAULT_ADDR_SPACE SPIRAS_Private #endif #ifndef SPIRV_QUEUE_T_ADDR_SPACE #define SPIRV_QUEUE_T_ADDR_SPACE SPIRV_OCL_SPECIAL_TYPES_DEFAULT_ADDR_SPACE #endif #ifndef SPIRV_EVENT_T_ADDR_SPACE #define SPIRV_EVENT_T_ADDR_SPACE SPIRV_OCL_SPECIAL_TYPES_DEFAULT_ADDR_SPACE #endif #ifndef SPIRV_AVC_INTEL_T_ADDR_SPACE #define SPIRV_AVC_INTEL_T_ADDR_SPACE SPIRV_OCL_SPECIAL_TYPES_DEFAULT_ADDR_SPACE #endif #ifndef SPIRV_CLK_EVENT_T_ADDR_SPACE #define SPIRV_CLK_EVENT_T_ADDR_SPACE SPIRV_OCL_SPECIAL_TYPES_DEFAULT_ADDR_SPACE #endif #ifndef SPIRV_SAMPLER_T_ADDR_SPACE #define SPIRV_SAMPLER_T_ADDR_SPACE SPIRAS_Constant #endif #ifndef SPIRV_RESERVE_ID_T_ADDR_SPACE #define SPIRV_RESERVE_ID_T_ADDR_SPACE SPIRV_OCL_SPECIAL_TYPES_DEFAULT_ADDR_SPACE #endif // Excerpt from SPIR 2.0 spec.: // Pipe objects are represented using pointers to the opaque %opencl.pipe LLVM // structure type which reside in the global address space. #ifndef SPIRV_PIPE_ADDR_SPACE #define SPIRV_PIPE_ADDR_SPACE SPIRAS_Global #endif // Excerpt from SPIR 2.0 spec.: // Note: Images data types reside in global memory and hence should be marked // as such in the "kernel arg addr space" metadata. #ifndef SPIRV_IMAGE_ADDR_SPACE #define SPIRV_IMAGE_ADDR_SPACE SPIRAS_Global #endif /////////////////////////////////////////////////////////////////////////////// // // Functions for getting builtin call info // /////////////////////////////////////////////////////////////////////////////// AtomicWorkItemFenceLiterals getAtomicWorkItemFenceLiterals(CallInst *CI) { return std::make_tuple(getArgAsInt(CI, 0), static_cast(getArgAsInt(CI, 1)), static_cast(getArgAsInt(CI, 2))); } size_t getAtomicBuiltinNumMemoryOrderArgs(StringRef Name) { if (Name.startswith("atomic_compare_exchange")) return 2; return 1; } size_t getSPIRVAtomicBuiltinNumMemoryOrderArgs(Op OC) { if (OC == OpAtomicCompareExchange || OC == OpAtomicCompareExchangeWeak) return 2; return 1; } bool isComputeAtomicOCLBuiltin(StringRef DemangledName) { if (!DemangledName.startswith(kOCLBuiltinName::AtomicPrefix) && !DemangledName.startswith(kOCLBuiltinName::AtomPrefix)) return false; return llvm::StringSwitch(DemangledName) .EndsWith("add", true) .EndsWith("sub", true) .EndsWith("inc", true) .EndsWith("dec", true) .EndsWith("cmpxchg", true) .EndsWith("min", true) .EndsWith("max", true) .EndsWith("and", true) .EndsWith("or", true) .EndsWith("xor", true) .EndsWith("add_explicit", true) .EndsWith("sub_explicit", true) .EndsWith("or_explicit", true) .EndsWith("xor_explicit", true) .EndsWith("and_explicit", true) .EndsWith("min_explicit", true) .EndsWith("max_explicit", true) .Default(false); } BarrierLiterals getBarrierLiterals(CallInst *CI) { auto N = CI->getNumArgOperands(); assert(N == 1 || N == 2); std::string DemangledName; assert(CI->getCalledFunction() && "Unexpected indirect call"); if (!oclIsBuiltin(CI->getCalledFunction()->getName(), &DemangledName)) { assert(0 && "call must a builtin (work_group_barrier or sub_group_barrier)"); } OCLScopeKind Scope = OCLMS_work_group; if (DemangledName == kOCLBuiltinName::SubGroupBarrier) { Scope = OCLMS_sub_group; } return std::make_tuple(getArgAsInt(CI, 0), N == 1 ? OCLMS_work_group : static_cast(getArgAsInt(CI, 1)), Scope); } unsigned getExtOp(StringRef OrigName, const std::string &GivenDemangledName) { std::string DemangledName = GivenDemangledName; if (!oclIsBuiltin(OrigName, DemangledName.empty() ? &DemangledName : nullptr)) return ~0U; LLVM_DEBUG(dbgs() << "getExtOp: demangled name: " << DemangledName << '\n'); OCLExtOpKind EOC; bool Found = OCLExtOpMap::rfind(DemangledName, &EOC); if (!Found) { std::string Prefix; switch (lastFuncParamType(OrigName)) { case ParamType::UNSIGNED: Prefix = "u_"; break; case ParamType::SIGNED: Prefix = "s_"; break; case ParamType::FLOAT: Prefix = "f"; break; case ParamType::UNKNOWN: break; } Found = OCLExtOpMap::rfind(Prefix + DemangledName, &EOC); } if (Found) return EOC; else return ~0U; } /////////////////////////////////////////////////////////////////////////////// // // Functions for getting module info // /////////////////////////////////////////////////////////////////////////////// unsigned encodeOCLVer(unsigned short Major, unsigned char Minor, unsigned char Rev) { return (Major * 100 + Minor) * 1000 + Rev; } std::tuple decodeOCLVer(unsigned Ver) { unsigned short Major = Ver / 100000; unsigned char Minor = (Ver % 100000) / 1000; unsigned char Rev = Ver % 1000; return std::make_tuple(Major, Minor, Rev); } unsigned getOCLVersion(Module *M, bool AllowMulti) { NamedMDNode *NamedMD = M->getNamedMetadata(kSPIR2MD::OCLVer); if (!NamedMD) return 0; assert(NamedMD->getNumOperands() > 0 && "Invalid SPIR"); if (!AllowMulti && NamedMD->getNumOperands() != 1) report_fatal_error("Multiple OCL version metadata not allowed"); // If the module was linked with another module, there may be multiple // operands. auto GetVer = [=](unsigned I) { auto MD = NamedMD->getOperand(I); return std::make_pair(getMDOperandAsInt(MD, 0), getMDOperandAsInt(MD, 1)); }; auto Ver = GetVer(0); for (unsigned I = 1, E = NamedMD->getNumOperands(); I != E; ++I) if (Ver != GetVer(I)) report_fatal_error("OCL version mismatch"); return encodeOCLVer(Ver.first, Ver.second, 0); } void decodeMDNode(MDNode *N, unsigned &X, unsigned &Y, unsigned &Z) { if (N == NULL) return; X = getMDOperandAsInt(N, 0); Y = getMDOperandAsInt(N, 1); Z = getMDOperandAsInt(N, 2); } /// Encode LLVM type by SPIR-V execution mode VecTypeHint unsigned encodeVecTypeHint(Type *Ty) { if (Ty->isHalfTy()) return 4; if (Ty->isFloatTy()) return 5; if (Ty->isDoubleTy()) return 6; if (IntegerType *IntTy = dyn_cast(Ty)) { switch (IntTy->getIntegerBitWidth()) { case 8: return 0; case 16: return 1; case 32: return 2; case 64: return 3; default: llvm_unreachable("invalid integer type"); } } if (VectorType *VecTy = dyn_cast(Ty)) { Type *EleTy = VecTy->getElementType(); unsigned Size = VecTy->getVectorNumElements(); return Size << 16 | encodeVecTypeHint(EleTy); } llvm_unreachable("invalid type"); return ~0U; } Type *decodeVecTypeHint(LLVMContext &C, unsigned Code) { unsigned VecWidth = Code >> 16; unsigned Scalar = Code & 0xFFFF; Type *ST = nullptr; switch (Scalar) { case 0: case 1: case 2: case 3: ST = IntegerType::get(C, 1 << (3 + Scalar)); break; case 4: ST = Type::getHalfTy(C); break; case 5: ST = Type::getFloatTy(C); break; case 6: ST = Type::getDoubleTy(C); break; default: llvm_unreachable("Invalid vec type hint"); return nullptr; } if (VecWidth < 1) return ST; return VectorType::get(ST, VecWidth); } unsigned transVecTypeHint(MDNode *Node) { return encodeVecTypeHint(getMDOperandAsType(Node, 0)); } SPIRAddressSpace getOCLOpaqueTypeAddrSpace(Op OpCode) { switch (OpCode) { case OpTypeQueue: return SPIRV_QUEUE_T_ADDR_SPACE; case OpTypeEvent: return SPIRV_EVENT_T_ADDR_SPACE; case OpTypeDeviceEvent: return SPIRV_CLK_EVENT_T_ADDR_SPACE; case OpTypeReserveId: return SPIRV_RESERVE_ID_T_ADDR_SPACE; case OpTypePipe: case OpTypePipeStorage: return SPIRV_PIPE_ADDR_SPACE; case OpTypeImage: case OpTypeSampledImage: return SPIRV_IMAGE_ADDR_SPACE; case OpConstantSampler: case OpTypeSampler: return SPIRV_SAMPLER_T_ADDR_SPACE; default: if (isSubgroupAvcINTELTypeOpCode(OpCode)) return SPIRV_AVC_INTEL_T_ADDR_SPACE; assert(false && "No address space is determined for some OCL type"); return SPIRV_OCL_SPECIAL_TYPES_DEFAULT_ADDR_SPACE; } } static SPIR::TypeAttributeEnum mapAddrSpaceEnums(SPIRAddressSpace Addrspace) { switch (Addrspace) { case SPIRAS_Private: return SPIR::ATTR_PRIVATE; case SPIRAS_Global: return SPIR::ATTR_GLOBAL; case SPIRAS_Constant: return SPIR::ATTR_CONSTANT; case SPIRAS_Local: return SPIR::ATTR_LOCAL; case SPIRAS_Generic: return SPIR::ATTR_GENERIC; default: llvm_unreachable("Invalid addrspace enum member"); } return SPIR::ATTR_NONE; } SPIR::TypeAttributeEnum getOCLOpaqueTypeAddrSpace(SPIR::TypePrimitiveEnum Prim) { switch (Prim) { case SPIR::PRIMITIVE_QUEUE_T: return mapAddrSpaceEnums(SPIRV_QUEUE_T_ADDR_SPACE); case SPIR::PRIMITIVE_EVENT_T: return mapAddrSpaceEnums(SPIRV_EVENT_T_ADDR_SPACE); case SPIR::PRIMITIVE_CLK_EVENT_T: return mapAddrSpaceEnums(SPIRV_CLK_EVENT_T_ADDR_SPACE); case SPIR::PRIMITIVE_RESERVE_ID_T: return mapAddrSpaceEnums(SPIRV_RESERVE_ID_T_ADDR_SPACE); case SPIR::PRIMITIVE_PIPE_RO_T: case SPIR::PRIMITIVE_PIPE_WO_T: return mapAddrSpaceEnums(SPIRV_PIPE_ADDR_SPACE); case SPIR::PRIMITIVE_IMAGE1D_RO_T: case SPIR::PRIMITIVE_IMAGE1D_ARRAY_RO_T: case SPIR::PRIMITIVE_IMAGE1D_BUFFER_RO_T: case SPIR::PRIMITIVE_IMAGE2D_RO_T: case SPIR::PRIMITIVE_IMAGE2D_ARRAY_RO_T: case SPIR::PRIMITIVE_IMAGE2D_DEPTH_RO_T: case SPIR::PRIMITIVE_IMAGE2D_ARRAY_DEPTH_RO_T: case SPIR::PRIMITIVE_IMAGE2D_MSAA_RO_T: case SPIR::PRIMITIVE_IMAGE2D_ARRAY_MSAA_RO_T: case SPIR::PRIMITIVE_IMAGE2D_MSAA_DEPTH_RO_T: case SPIR::PRIMITIVE_IMAGE2D_ARRAY_MSAA_DEPTH_RO_T: case SPIR::PRIMITIVE_IMAGE3D_RO_T: case SPIR::PRIMITIVE_IMAGE1D_WO_T: case SPIR::PRIMITIVE_IMAGE1D_ARRAY_WO_T: case SPIR::PRIMITIVE_IMAGE1D_BUFFER_WO_T: case SPIR::PRIMITIVE_IMAGE2D_WO_T: case SPIR::PRIMITIVE_IMAGE2D_ARRAY_WO_T: case SPIR::PRIMITIVE_IMAGE2D_DEPTH_WO_T: case SPIR::PRIMITIVE_IMAGE2D_ARRAY_DEPTH_WO_T: case SPIR::PRIMITIVE_IMAGE2D_MSAA_WO_T: case SPIR::PRIMITIVE_IMAGE2D_ARRAY_MSAA_WO_T: case SPIR::PRIMITIVE_IMAGE2D_MSAA_DEPTH_WO_T: case SPIR::PRIMITIVE_IMAGE2D_ARRAY_MSAA_DEPTH_WO_T: case SPIR::PRIMITIVE_IMAGE3D_WO_T: case SPIR::PRIMITIVE_IMAGE1D_RW_T: case SPIR::PRIMITIVE_IMAGE1D_ARRAY_RW_T: case SPIR::PRIMITIVE_IMAGE1D_BUFFER_RW_T: case SPIR::PRIMITIVE_IMAGE2D_RW_T: case SPIR::PRIMITIVE_IMAGE2D_ARRAY_RW_T: case SPIR::PRIMITIVE_IMAGE2D_DEPTH_RW_T: case SPIR::PRIMITIVE_IMAGE2D_ARRAY_DEPTH_RW_T: case SPIR::PRIMITIVE_IMAGE2D_MSAA_RW_T: case SPIR::PRIMITIVE_IMAGE2D_ARRAY_MSAA_RW_T: case SPIR::PRIMITIVE_IMAGE2D_MSAA_DEPTH_RW_T: case SPIR::PRIMITIVE_IMAGE2D_ARRAY_MSAA_DEPTH_RW_T: case SPIR::PRIMITIVE_IMAGE3D_RW_T: return mapAddrSpaceEnums(SPIRV_IMAGE_ADDR_SPACE); default: llvm_unreachable("No address space is determined for a SPIR primitive"); } return SPIR::ATTR_NONE; } // Fetch type of invoke function passed to device execution built-ins static FunctionType *getBlockInvokeTy(Function *F, unsigned BlockIdx) { auto Params = F->getFunctionType()->params(); PointerType *FuncPtr = cast(Params[BlockIdx]); return cast(FuncPtr->getElementType()); } class OCLBuiltinFuncMangleInfo : public SPIRV::BuiltinFuncMangleInfo { public: OCLBuiltinFuncMangleInfo(Function *F) : F(F) {} OCLBuiltinFuncMangleInfo(ArrayRef ArgTypes) : ArgTypes(ArgTypes.vec()) {} void init(const std::string &UniqName) override { UnmangledName = UniqName; size_t Pos = std::string::npos; auto EraseSubstring = [](std::string &Str, std::string ToErase) { size_t Pos = Str.find(ToErase); if (Pos != std::string::npos) { Str.erase(Pos, ToErase.length()); } }; if (UnmangledName.find("async_work_group") == 0) { addUnsignedArg(-1); setArgAttr(1, SPIR::ATTR_CONST); } else if (UnmangledName.find("write_imageui") == 0) addUnsignedArg(2); else if (UnmangledName == "prefetch") { addUnsignedArg(1); setArgAttr(0, SPIR::ATTR_CONST); } else if (UnmangledName == "get_kernel_work_group_size" || UnmangledName == "get_kernel_preferred_work_group_size_multiple") { assert(F && "lack of necessary information"); const size_t BlockArgIdx = 0; FunctionType *InvokeTy = getBlockInvokeTy(F, BlockArgIdx); if (InvokeTy->getNumParams() > 1) setLocalArgBlock(BlockArgIdx); } else if (UnmangledName == "enqueue_kernel") { assert(F && "lack of necessary information"); setEnumArg(1, SPIR::PRIMITIVE_KERNEL_ENQUEUE_FLAGS_T); addUnsignedArg(3); setArgAttr(4, SPIR::ATTR_CONST); // If there are arguments other then block context then these are pointers // to local memory so this built-in must be mangled accordingly. const size_t BlockArgIdx = 6; FunctionType *InvokeTy = getBlockInvokeTy(F, BlockArgIdx); if (InvokeTy->getNumParams() > 1) { setLocalArgBlock(BlockArgIdx); addUnsignedArg(BlockArgIdx + 1); setVarArg(BlockArgIdx + 2); } } else if (UnmangledName.find("get_") == 0 || UnmangledName == "nan" || UnmangledName == "mem_fence" || UnmangledName.find("shuffle") == 0) { addUnsignedArg(-1); if (UnmangledName.find(kOCLBuiltinName::GetFence) == 0) { setArgAttr(0, SPIR::ATTR_CONST); addVoidPtrArg(0); } } else if (UnmangledName.find("barrier") != std::string::npos) { addUnsignedArg(0); if (UnmangledName == "work_group_barrier" || UnmangledName == "sub_group_barrier") setEnumArg(1, SPIR::PRIMITIVE_MEMORY_SCOPE); } else if (UnmangledName.find("atomic_work_item_fence") == 0) { addUnsignedArg(0); setEnumArg(1, SPIR::PRIMITIVE_MEMORY_ORDER); setEnumArg(2, SPIR::PRIMITIVE_MEMORY_SCOPE); } else if (UnmangledName.find("atomic") == 0) { setArgAttr(0, SPIR::ATTR_VOLATILE); if (UnmangledName.find("atomic_umax") == 0 || UnmangledName.find("atomic_umin") == 0) { addUnsignedArg(0); addUnsignedArg(1); UnmangledName.erase(7, 1); } else if (UnmangledName.find("atomic_fetch_umin") == 0 || UnmangledName.find("atomic_fetch_umax") == 0) { addUnsignedArg(0); addUnsignedArg(1); UnmangledName.erase(13, 1); } if (UnmangledName.find("store_explicit") != std::string::npos || UnmangledName.find("exchange_explicit") != std::string::npos || (UnmangledName.find("atomic_fetch") == 0 && UnmangledName.find("explicit") != std::string::npos)) { setEnumArg(2, SPIR::PRIMITIVE_MEMORY_ORDER); setEnumArg(3, SPIR::PRIMITIVE_MEMORY_SCOPE); } else if (UnmangledName.find("load_explicit") != std::string::npos || (UnmangledName.find("atomic_flag") == 0 && UnmangledName.find("explicit") != std::string::npos)) { setEnumArg(1, SPIR::PRIMITIVE_MEMORY_ORDER); setEnumArg(2, SPIR::PRIMITIVE_MEMORY_SCOPE); } else if (UnmangledName.find("compare_exchange_strong_explicit") != std::string::npos || UnmangledName.find("compare_exchange_weak_explicit") != std::string::npos) { setEnumArg(3, SPIR::PRIMITIVE_MEMORY_ORDER); setEnumArg(4, SPIR::PRIMITIVE_MEMORY_ORDER); setEnumArg(5, SPIR::PRIMITIVE_MEMORY_SCOPE); } // Don't set atomic property to the first argument of 1.2 atomic // built-ins. if (UnmangledName.find("atomic_add") != 0 && UnmangledName.find("atomic_sub") != 0 && UnmangledName.find("atomic_xchg") != 0 && UnmangledName.find("atomic_inc") != 0 && UnmangledName.find("atomic_dec") != 0 && UnmangledName.find("atomic_cmpxchg") != 0 && UnmangledName.find("atomic_min") != 0 && UnmangledName.find("atomic_max") != 0 && UnmangledName.find("atomic_and") != 0 && UnmangledName.find("atomic_or") != 0 && UnmangledName.find("atomic_xor") != 0 && UnmangledName.find("atom_") != 0) { addAtomicArg(0); } } else if (UnmangledName.find("uconvert_") == 0) { addUnsignedArg(0); UnmangledName.erase(0, 1); } else if (UnmangledName.find("s_") == 0) { if (UnmangledName == "s_upsample") addUnsignedArg(1); UnmangledName.erase(0, 2); } else if (UnmangledName.find("u_") == 0) { addUnsignedArg(-1); UnmangledName.erase(0, 2); } else if (UnmangledName == "fclamp") { UnmangledName.erase(0, 1); } // handle [read|write]pipe builtins (plus two i32 literal args // required by SPIR 2.0 provisional specification): else if (UnmangledName == "read_pipe_2" || UnmangledName == "write_pipe_2") { // with 2 arguments (plus two i32 literals): // int read_pipe (read_only pipe gentype p, gentype *ptr) // int write_pipe (write_only pipe gentype p, const gentype *ptr) addVoidPtrArg(1); addUnsignedArg(2); addUnsignedArg(3); // OpenCL-like representation of blocking pipes } else if (UnmangledName == "read_pipe_2_bl" || UnmangledName == "write_pipe_2_bl") { // with 2 arguments (plus two i32 literals): // int read_pipe_bl (read_only pipe gentype p, gentype *ptr) // int write_pipe_bl (write_only pipe gentype p, const gentype *ptr) addVoidPtrArg(1); addUnsignedArg(2); addUnsignedArg(3); } else if (UnmangledName == "read_pipe_4" || UnmangledName == "write_pipe_4") { // with 4 arguments (plus two i32 literals): // int read_pipe (read_only pipe gentype p, reserve_id_t reserve_id, uint // index, gentype *ptr) int write_pipe (write_only pipe gentype p, // reserve_id_t reserve_id, uint index, const gentype *ptr) addUnsignedArg(2); addVoidPtrArg(3); addUnsignedArg(4); addUnsignedArg(5); } else if (UnmangledName.find("reserve_read_pipe") != std::string::npos || UnmangledName.find("reserve_write_pipe") != std::string::npos) { // process [|work_group|sub_group]reserve[read|write]pipe builtins addUnsignedArg(1); addUnsignedArg(2); addUnsignedArg(3); } else if (UnmangledName.find("commit_read_pipe") != std::string::npos || UnmangledName.find("commit_write_pipe") != std::string::npos) { // process [|work_group|sub_group]commit[read|write]pipe builtins addUnsignedArg(2); addUnsignedArg(3); } else if (UnmangledName == "capture_event_profiling_info") { addVoidPtrArg(2); setEnumArg(1, SPIR::PRIMITIVE_CLK_PROFILING_INFO); } else if (UnmangledName == "enqueue_marker") { setArgAttr(2, SPIR::ATTR_CONST); addUnsignedArg(1); } else if (UnmangledName.find("vload") == 0) { addUnsignedArg(0); setArgAttr(1, SPIR::ATTR_CONST); } else if (UnmangledName.find("vstore") == 0) { addUnsignedArg(1); } else if (UnmangledName.find("ndrange_") == 0) { addUnsignedArg(-1); if (UnmangledName[8] == '2' || UnmangledName[8] == '3') { setArgAttr(-1, SPIR::ATTR_CONST); } } else if ((Pos = UnmangledName.find("umax")) != std::string::npos || (Pos = UnmangledName.find("umin")) != std::string::npos) { addUnsignedArg(-1); UnmangledName.erase(Pos, 1); } else if (UnmangledName.find("broadcast") != std::string::npos) { addUnsignedArg(-1); } else if (UnmangledName.find(kOCLBuiltinName::SampledReadImage) == 0) { UnmangledName.erase(0, strlen(kOCLBuiltinName::Sampled)); addSamplerArg(1); } else if (UnmangledName.find(kOCLSubgroupsAVCIntel::Prefix) != std::string::npos) { if (UnmangledName.find("evaluate_ipe") != std::string::npos) addSamplerArg(1); else if (UnmangledName.find("evaluate_with_single_reference") != std::string::npos) addSamplerArg(2); else if (UnmangledName.find("evaluate_with_multi_reference") != std::string::npos) { addUnsignedArg(1); std::string PostFix = "_interlaced"; if (UnmangledName.find(PostFix) != std::string::npos) { addUnsignedArg(2); addSamplerArg(3); size_t Pos = UnmangledName.find(PostFix); if (Pos != std::string::npos) UnmangledName.erase(Pos, PostFix.length()); } else addSamplerArg(2); } else if (UnmangledName.find("evaluate_with_dual_reference") != std::string::npos) addSamplerArg(3); else if (UnmangledName.find("fme_initialize") != std::string::npos) addUnsignedArgs(0, 6); else if (UnmangledName.find("bme_initialize") != std::string::npos) addUnsignedArgs(0, 7); else if (UnmangledName.find("set_inter_base_multi_reference_penalty") != std::string::npos || UnmangledName.find("set_inter_shape_penalty") != std::string::npos || UnmangledName.find("set_inter_direction_penalty") != std::string::npos) addUnsignedArg(0); else if (UnmangledName.find("set_motion_vector_cost_function") != std::string::npos) addUnsignedArgs(0, 2); else if (UnmangledName.find("interlaced_field_polarity") != std::string::npos) addUnsignedArg(0); else if (UnmangledName.find("interlaced_field_polarities") != std::string::npos) addUnsignedArgs(0, 1); else if (UnmangledName.find(kOCLSubgroupsAVCIntel::MCEPrefix) != std::string::npos) { if (UnmangledName.find("get_default") != std::string::npos) addUnsignedArgs(0, 1); } else if (UnmangledName.find(kOCLSubgroupsAVCIntel::IMEPrefix) != std::string::npos) { if (UnmangledName.find("initialize") != std::string::npos) addUnsignedArgs(0, 2); else if (UnmangledName.find("set_single_reference") != std::string::npos) addUnsignedArg(1); else if (UnmangledName.find("set_dual_reference") != std::string::npos) addUnsignedArg(2); else if (UnmangledName.find("set_weighted_sad") != std::string::npos || UnmangledName.find("set_early_search_termination_threshold") != std::string::npos) addUnsignedArg(0); else if (UnmangledName.find("adjust_ref_offset") != std::string::npos) addUnsignedArgs(1, 3); else if (UnmangledName.find("set_max_motion_vector_count") != std::string::npos || UnmangledName.find("get_border_reached") != std::string::npos) addUnsignedArg(0); else if (UnmangledName.find("shape_distortions") != std::string::npos || UnmangledName.find("shape_motion_vectors") != std::string::npos || UnmangledName.find("shape_reference_ids") != std::string::npos) { if (UnmangledName.find("single_reference") != std::string::npos) { addUnsignedArg(1); EraseSubstring(UnmangledName, "_single_reference"); } else if (UnmangledName.find("dual_reference") != std::string::npos) { addUnsignedArgs(1, 2); EraseSubstring(UnmangledName, "_dual_reference"); } } else if (UnmangledName.find("ref_window_size") != std::string::npos) addUnsignedArg(0); } else if (UnmangledName.find(kOCLSubgroupsAVCIntel::SICPrefix) != std::string::npos) { if (UnmangledName.find("initialize") != std::string::npos || UnmangledName.find("set_intra_luma_shape_penalty") != std::string::npos) addUnsignedArg(0); else if (UnmangledName.find("configure_ipe") != std::string::npos) { if (UnmangledName.find("_luma") != std::string::npos) { addUnsignedArgs(0, 6); EraseSubstring(UnmangledName, "_luma"); } if (UnmangledName.find("_chroma") != std::string::npos) { addUnsignedArgs(7, 9); EraseSubstring(UnmangledName, "_chroma"); } } else if (UnmangledName.find("configure_skc") != std::string::npos) addUnsignedArgs(0, 4); else if (UnmangledName.find("set_skc") != std::string::npos) { if (UnmangledName.find("forward_transform_enable")) addUnsignedArg(0); } else if (UnmangledName.find("set_block") != std::string::npos) { if (UnmangledName.find("based_raw_skip_sad") != std::string::npos) addUnsignedArg(0); } else if (UnmangledName.find("get_motion_vector_mask") != std::string::npos) { addUnsignedArgs(0, 1); } else if (UnmangledName.find("luma_mode_cost_function") != std::string::npos) addUnsignedArgs(0, 2); else if (UnmangledName.find("chroma_mode_cost_function") != std::string::npos) addUnsignedArg(0); } } else if (UnmangledName == "intel_sub_group_shuffle_down" || UnmangledName == "intel_sub_group_shuffle_up") { addUnsignedArg(2); } else if (UnmangledName == "intel_sub_group_shuffle" || UnmangledName == "intel_sub_group_shuffle_xor") { addUnsignedArg(1); } else if (UnmangledName.find("intel_sub_group_block_write") != std::string::npos) { // distinguish write to image and other data types as position // of uint argument is different though name is the same. assert(ArgTypes.size() && "lack of necessary information"); if (ArgTypes[0]->isPointerTy() && ArgTypes[0]->getPointerElementType()->isIntegerTy()) { addUnsignedArg(0); addUnsignedArg(1); } else { addUnsignedArg(2); } } else if (UnmangledName.find("intel_sub_group_block_read") != std::string::npos) { // distinguish read from image and other data types as position // of uint argument is different though name is the same. assert(ArgTypes.size() && "lack of necessary information"); if (ArgTypes[0]->isPointerTy() && ArgTypes[0]->getPointerElementType()->isIntegerTy()) { setArgAttr(0, SPIR::ATTR_CONST); addUnsignedArg(0); } } else if (UnmangledName.find("intel_sub_group_media_block_write") != std::string::npos) { addUnsignedArg(3); } } // Auxiliarry information, it is expected that it is relevant at the moment // the init method is called. Function *F; // SPIRV decorated function std::vector ArgTypes; // Arguments of OCL builtin }; CallInst *mutateCallInstOCL( Module *M, CallInst *CI, std::function &)> ArgMutate, AttributeList *Attrs) { OCLBuiltinFuncMangleInfo BtnInfo(CI->getCalledFunction()); return mutateCallInst(M, CI, ArgMutate, &BtnInfo, Attrs); } Instruction *mutateCallInstOCL( Module *M, CallInst *CI, std::function &, Type *&RetTy)> ArgMutate, std::function RetMutate, AttributeList *Attrs) { OCLBuiltinFuncMangleInfo BtnInfo(CI->getCalledFunction()); return mutateCallInst(M, CI, ArgMutate, RetMutate, &BtnInfo, Attrs); } static std::pair getSrcAndDstElememntTypeName(BitCastInst *BIC) { if (!BIC) return std::pair("", ""); Type *SrcTy = BIC->getSrcTy(); Type *DstTy = BIC->getDestTy(); if (SrcTy->isPointerTy()) SrcTy = SrcTy->getPointerElementType(); if (DstTy->isPointerTy()) DstTy = DstTy->getPointerElementType(); auto SrcST = dyn_cast(SrcTy); auto DstST = dyn_cast(DstTy); if (!DstST || !DstST->hasName() || !SrcST || !SrcST->hasName()) return std::pair("", ""); return std::make_pair(SrcST->getName(), DstST->getName()); } bool isSamplerInitializer(Instruction *Inst) { BitCastInst *BIC = dyn_cast(Inst); auto Names = getSrcAndDstElememntTypeName(BIC); if (Names.second == getSPIRVTypeName(kSPIRVTypeName::Sampler) && Names.first == getSPIRVTypeName(kSPIRVTypeName::ConstantSampler)) return true; return false; } bool isPipeStorageInitializer(Instruction *Inst) { BitCastInst *BIC = dyn_cast(Inst); auto Names = getSrcAndDstElememntTypeName(BIC); if (Names.second == getSPIRVTypeName(kSPIRVTypeName::PipeStorage) && Names.first == getSPIRVTypeName(kSPIRVTypeName::ConstantPipeStorage)) return true; return false; } bool isSpecialTypeInitializer(Instruction *Inst) { return isSamplerInitializer(Inst) || isPipeStorageInitializer(Inst); } bool isSamplerTy(Type *Ty) { auto PTy = dyn_cast(Ty); if (!PTy) return false; auto STy = dyn_cast(PTy->getElementType()); return STy && STy->hasName() && STy->getName() == kSPR2TypeName::Sampler; } bool isPipeOrAddressSpaceCastBI(const StringRef MangledName) { return MangledName == "write_pipe_2" || MangledName == "read_pipe_2" || MangledName == "write_pipe_2_bl" || MangledName == "read_pipe_2_bl" || MangledName == "write_pipe_4" || MangledName == "read_pipe_4" || MangledName == "reserve_write_pipe" || MangledName == "reserve_read_pipe" || MangledName == "commit_write_pipe" || MangledName == "commit_read_pipe" || MangledName == "work_group_reserve_write_pipe" || MangledName == "work_group_reserve_read_pipe" || MangledName == "work_group_commit_write_pipe" || MangledName == "work_group_commit_read_pipe" || MangledName == "get_pipe_num_packets_ro" || MangledName == "get_pipe_max_packets_ro" || MangledName == "get_pipe_num_packets_wo" || MangledName == "get_pipe_max_packets_wo" || MangledName == "sub_group_reserve_write_pipe" || MangledName == "sub_group_reserve_read_pipe" || MangledName == "sub_group_commit_write_pipe" || MangledName == "sub_group_commit_read_pipe" || MangledName == "to_global" || MangledName == "to_local" || MangledName == "to_private"; } bool isEnqueueKernelBI(const StringRef MangledName) { return MangledName == "__enqueue_kernel_basic" || MangledName == "__enqueue_kernel_basic_events" || MangledName == "__enqueue_kernel_varargs" || MangledName == "__enqueue_kernel_events_varargs"; } bool isKernelQueryBI(const StringRef MangledName) { return MangledName == "__get_kernel_work_group_size_impl" || MangledName == "__get_kernel_sub_group_count_for_ndrange_impl" || MangledName == "__get_kernel_max_sub_group_size_for_ndrange_impl" || MangledName == "__get_kernel_preferred_work_group_size_multiple_impl"; } // Checks if we have the following (most common for fp contranction) pattern // in LLVM IR: // %mul = fmul float %a, %b // %add = fadd float %mul, %c // This pattern indicates that fp contraction could have been disabled by // // #pragma OPENCL FP_CONTRACT OFF. Otherwise the current version of clang // would generate: // %0 = call float @llvm.fmuladd.f32(float %a, float %b, float %c) // TODO We need a more reliable mechanism to expres the FP_CONTRACT pragma // in LLVM IR. Fox example adding the 'contract' attribute to fp operations // by default (according the OpenCL spec fp contraction is enabled by default). void checkFpContract(BinaryOperator *B, SPIRVBasicBlock *BB) { if (B->getOpcode() != Instruction::FAdd && B->getOpcode() != Instruction::FSub) return; // Ok, this is fadd or fsub. Now check its operands. for (auto *Op : B->operand_values()) { if (auto *I = dyn_cast(Op)) { if (I->getOpcode() == Instruction::FMul) { SPIRVFunction *BF = BB->getParent(); BF->setUncontractedFMulAddFound(); break; } } } } } // namespace OCLUtil void llvm::mangleOpenClBuiltin(const std::string &UniqName, ArrayRef ArgTypes, std::string &MangledName) { OCLUtil::OCLBuiltinFuncMangleInfo BtnInfo(ArgTypes); MangledName = SPIRV::mangleBuiltin(UniqName, ArgTypes, &BtnInfo); } SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/OCLUtil.h000066400000000000000000001173201363521741200204770ustar00rootroot00000000000000//===- OCLUtil.h - OCL Utilities declarations -------------------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// // // This file declares OCL utility functions. // //===----------------------------------------------------------------------===// #ifndef SPIRV_OCLUTIL_H #define SPIRV_OCLUTIL_H #include "SPIRVInternal.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/IRBuilder.h" #include "llvm/Support/Path.h" #include #include #include #include using namespace SPIRV; using namespace llvm; using namespace spv; namespace OCLUtil { /////////////////////////////////////////////////////////////////////////////// // // Enums // /////////////////////////////////////////////////////////////////////////////// enum OCLMemFenceKind { OCLMF_Local = 1, OCLMF_Global = 2, OCLMF_Image = 4, }; // This enum declares extra constants for OpenCL mem_fence flag. It includes // combinations of local/global/image flags. enum OCLMemFenceExtendedKind { OCLMFEx_Local = OCLMF_Local, OCLMFEx_Global = OCLMF_Global, OCLMFEx_Local_Global = OCLMF_Global | OCLMF_Local, OCLMFEx_Image = OCLMF_Image, OCLMFEx_Image_Local = OCLMF_Image | OCLMF_Local, OCLMFEx_Image_Global = OCLMF_Image | OCLMF_Global, OCLMFEx_Image_Local_Global = OCLMF_Image | OCLMF_Global | OCLMF_Local, }; enum OCLScopeKind { OCLMS_work_item, OCLMS_work_group, OCLMS_device, OCLMS_all_svm_devices, OCLMS_sub_group, }; // The enum below declares constants corresponding to memory synchronization // operations constants defined in // https://www.khronos.org/registry/OpenCL/sdk/2.1/docs/man/xhtml/memory_order.html // To avoid any inconsistence here, constants are explicitly initialized with // the corresponding constants from 'std::memory_order' enum. enum OCLMemOrderKind { OCLMO_relaxed = std::memory_order::memory_order_relaxed, OCLMO_acquire = std::memory_order::memory_order_acquire, OCLMO_release = std::memory_order::memory_order_release, OCLMO_acq_rel = std::memory_order::memory_order_acq_rel, OCLMO_seq_cst = std::memory_order::memory_order_seq_cst }; /////////////////////////////////////////////////////////////////////////////// // // Types // /////////////////////////////////////////////////////////////////////////////// typedef SPIRVMap OCLMemFenceMap; typedef SPIRVMap OCLMemFenceExtendedMap; typedef SPIRVMap OCLMemOrderMap; typedef SPIRVMap OCLMemScopeMap; typedef SPIRVMap SPIRSPIRVGroupOperationMap; typedef SPIRVMap SPIRSPIRVFPRoundingModeMap; typedef SPIRVMap OCLSPIRVBuiltinMap; class OCL12Builtin; typedef SPIRVMap OCL12SPIRVBuiltinMap; typedef SPIRVMap SPIRSPIRVBuiltinVariableMap; /// Tuple of literals for atomic_work_item_fence (flag, order, scope) typedef std::tuple AtomicWorkItemFenceLiterals; /// Tuple of literals for work_group_barrier or sub_group_barrier /// (flag, mem_scope, exec_scope) typedef std::tuple BarrierLiterals; class OCLOpaqueType; typedef SPIRVMap OCLOpaqueTypeOpCodeMap; /// Information for translating OCL builtin. struct OCLBuiltinTransInfo { std::string UniqName; std::string MangledName; std::string Postfix; // Postfix to be added /// Postprocessor of operands std::function &)> PostProc; Type *RetTy; // Return type of the translated function bool IsRetSigned; // When RetTy is int, determines if extensions // on it should be a sext or zet. OCLBuiltinTransInfo() : RetTy(nullptr), IsRetSigned(false) { PostProc = [](std::vector &) {}; } }; /////////////////////////////////////////////////////////////////////////////// // // Constants // /////////////////////////////////////////////////////////////////////////////// namespace kOCLBuiltinName { const static char All[] = "all"; const static char Any[] = "any"; const static char AsyncWorkGroupCopy[] = "async_work_group_copy"; const static char AsyncWorkGroupStridedCopy[] = "async_work_group_strided_copy"; const static char AtomPrefix[] = "atom_"; const static char AtomCmpXchg[] = "atom_cmpxchg"; const static char AtomicPrefix[] = "atomic_"; const static char AtomicCmpXchg[] = "atomic_cmpxchg"; const static char AtomicCmpXchgStrong[] = "atomic_compare_exchange_strong"; const static char AtomicCmpXchgStrongExplicit[] = "atomic_compare_exchange_strong_explicit"; const static char AtomicCmpXchgWeak[] = "atomic_compare_exchange_weak"; const static char AtomicCmpXchgWeakExplicit[] = "atomic_compare_exchange_weak_explicit"; const static char AtomicInit[] = "atomic_init"; const static char AtomicWorkItemFence[] = "atomic_work_item_fence"; const static char Barrier[] = "barrier"; const static char Clamp[] = "clamp"; const static char ConvertPrefix[] = "convert_"; const static char Dot[] = "dot"; const static char EnqueueKernel[] = "enqueue_kernel"; const static char FMax[] = "fmax"; const static char FMin[] = "fmin"; const static char FPGARegIntel[] = "__builtin_intel_fpga_reg"; const static char GetFence[] = "get_fence"; const static char GetImageArraySize[] = "get_image_array_size"; const static char GetImageChannelOrder[] = "get_image_channel_order"; const static char GetImageChannelDataType[] = "get_image_channel_data_type"; const static char GetImageDepth[] = "get_image_depth"; const static char GetImageDim[] = "get_image_dim"; const static char GetImageHeight[] = "get_image_height"; const static char GetImageWidth[] = "get_image_width"; const static char IsFinite[] = "isfinite"; const static char IsNan[] = "isnan"; const static char IsNormal[] = "isnormal"; const static char IsInf[] = "isinf"; const static char Max[] = "max"; const static char MemFence[] = "mem_fence"; const static char Min[] = "min"; const static char Mix[] = "mix"; const static char NDRangePrefix[] = "ndrange_"; const static char Pipe[] = "pipe"; const static char ReadImage[] = "read_image"; const static char ReadPipe[] = "read_pipe"; const static char ReadPipeBlockingINTEL[] = "read_pipe_bl"; const static char RoundingPrefix[] = "_r"; const static char Sampled[] = "sampled_"; const static char SampledReadImage[] = "sampled_read_image"; const static char Signbit[] = "signbit"; const static char SmoothStep[] = "smoothstep"; const static char Step[] = "step"; const static char SubGroupPrefix[] = "sub_group_"; const static char SubGroupBarrier[] = "sub_group_barrier"; const static char SubPrefix[] = "sub_"; const static char ToGlobal[] = "to_global"; const static char ToLocal[] = "to_local"; const static char ToPrivate[] = "to_private"; const static char VLoadPrefix[] = "vload"; const static char VLoadAPrefix[] = "vloada"; const static char VLoadHalf[] = "vload_half"; const static char VStorePrefix[] = "vstore"; const static char VStoreAPrefix[] = "vstorea"; const static char WaitGroupEvent[] = "wait_group_events"; const static char WriteImage[] = "write_image"; const static char WorkGroupBarrier[] = "work_group_barrier"; const static char WritePipe[] = "write_pipe"; const static char WritePipeBlockingINTEL[] = "write_pipe_bl"; const static char WorkGroupPrefix[] = "work_group_"; const static char WorkGroupAll[] = "work_group_all"; const static char WorkGroupAny[] = "work_group_any"; const static char SubGroupAll[] = "sub_group_all"; const static char SubGroupAny[] = "sub_group_any"; const static char WorkPrefix[] = "work_"; const static char SubgroupBlockReadINTELPrefix[] = "intel_sub_group_block_read"; const static char SubgroupBlockWriteINTELPrefix[] = "intel_sub_group_block_write"; const static char SubgroupImageMediaBlockINTELPrefix[] = "intel_sub_group_media_block"; } // namespace kOCLBuiltinName /// Offset for OpenCL image channel order enumeration values. const unsigned int OCLImageChannelOrderOffset = 0x10B0; /// Offset for OpenCL image channel data type enumeration values. const unsigned int OCLImageChannelDataTypeOffset = 0x10D0; /// OCL 1.x atomic memory order when translated to 2.0 atomics. const OCLMemOrderKind OCLLegacyAtomicMemOrder = OCLMO_seq_cst; /// OCL 1.x atomic memory scope when translated to 2.0 atomics. const OCLScopeKind OCLLegacyAtomicMemScope = OCLMS_device; namespace kOCLVer { const unsigned CL12 = 102000; const unsigned CL20 = 200000; const unsigned CL21 = 201000; } // namespace kOCLVer namespace OclExt { // clang-format off enum Kind { #define _SPIRV_OP(x) x, _SPIRV_OP(cl_images) _SPIRV_OP(cl_doubles) _SPIRV_OP(cl_khr_int64_base_atomics) _SPIRV_OP(cl_khr_int64_extended_atomics) _SPIRV_OP(cl_khr_fp16) _SPIRV_OP(cl_khr_gl_sharing) _SPIRV_OP(cl_khr_gl_event) _SPIRV_OP(cl_khr_d3d10_sharing) _SPIRV_OP(cl_khr_media_sharing) _SPIRV_OP(cl_khr_d3d11_sharing) _SPIRV_OP(cl_khr_global_int32_base_atomics) _SPIRV_OP(cl_khr_global_int32_extended_atomics) _SPIRV_OP(cl_khr_local_int32_base_atomics) _SPIRV_OP(cl_khr_local_int32_extended_atomics) _SPIRV_OP(cl_khr_byte_addressable_store) _SPIRV_OP(cl_khr_3d_image_writes) _SPIRV_OP(cl_khr_gl_msaa_sharing) _SPIRV_OP(cl_khr_depth_images) _SPIRV_OP(cl_khr_gl_depth_images) _SPIRV_OP(cl_khr_subgroups) _SPIRV_OP(cl_khr_mipmap_image) _SPIRV_OP(cl_khr_mipmap_image_writes) _SPIRV_OP(cl_khr_egl_event) _SPIRV_OP(cl_khr_srgb_image_writes) #undef _SPIRV_OP }; // clang-format on } // namespace OclExt namespace kOCLSubgroupsAVCIntel { const static char Prefix[] = "intel_sub_group_avc_"; const static char MCEPrefix[] = "intel_sub_group_avc_mce_"; const static char IMEPrefix[] = "intel_sub_group_avc_ime_"; const static char REFPrefix[] = "intel_sub_group_avc_ref_"; const static char SICPrefix[] = "intel_sub_group_avc_sic_"; const static char TypePrefix[] = "opencl.intel_sub_group_avc_"; } // namespace kOCLSubgroupsAVCIntel /////////////////////////////////////////////////////////////////////////////// // // Functions // /////////////////////////////////////////////////////////////////////////////// /// Get instruction index for SPIR-V extended instruction for OpenCL.std /// extended instruction set. /// \param MangledName The mangled name of OpenCL builtin function. /// \param DemangledName The demangled name of OpenCL builtin function if /// not empty. /// \return instruction index of extended instruction if the OpenCL builtin /// function is translated to an extended instruction, otherwise ~0U. unsigned getExtOp(StringRef MangledName, const std::string &DemangledName = ""); /// Get literal arguments of call of atomic_work_item_fence. AtomicWorkItemFenceLiterals getAtomicWorkItemFenceLiterals(CallInst *CI); /// Get literal arguments of call of work_group_barrier or sub_group_barrier. BarrierLiterals getBarrierLiterals(CallInst *CI); /// Get number of memory order arguments for atomic builtin function. size_t getAtomicBuiltinNumMemoryOrderArgs(StringRef Name); /// Get number of memory order arguments for spirv atomic builtin function. size_t getSPIRVAtomicBuiltinNumMemoryOrderArgs(Op OC); /// Return true for OpenCL builtins which do compute operations /// (like add, sub, min, max, inc, dec, ...) atomically bool isComputeAtomicOCLBuiltin(StringRef DemangledName); /// Get OCL version from metadata opencl.ocl.version. /// \param AllowMulti Allows multiple operands if true. /// \return OCL version encoded as Major*10^5+Minor*10^3+Rev, /// e.g. 201000 for OCL 2.1, 200000 for OCL 2.0, 102000 for OCL 1.2, /// 0 if metadata not found. /// If there are multiple operands, check they are identical. unsigned getOCLVersion(Module *M, bool AllowMulti = false); /// Encode OpenCL version as Major*10^5+Minor*10^3+Rev. unsigned encodeOCLVer(unsigned short Major, unsigned char Minor, unsigned char Rev); /// Decode OpenCL version which is encoded as Major*10^5+Minor*10^3+Rev std::tuple decodeOCLVer(unsigned Ver); /// Decode a MDNode assuming it contains three integer constants. void decodeMDNode(MDNode *N, unsigned &X, unsigned &Y, unsigned &Z); /// Get full path from debug info metadata /// Return empty string if the path is not available. template std::string getFullPath(const T *Scope) { if (!Scope) return std::string(); std::string Filename = Scope->getFilename().str(); if (sys::path::is_absolute(Filename)) return Filename; SmallString<16> DirName = Scope->getDirectory(); sys::path::append(DirName, sys::path::Style::posix, Filename); return DirName.str().str(); } /// Decode OpenCL vector type hint MDNode and encode it as SPIR-V execution /// mode VecTypeHint. unsigned transVecTypeHint(MDNode *Node); /// Decode SPIR-V encoding of vector type hint execution mode. Type *decodeVecTypeHint(LLVMContext &C, unsigned Code); SPIRAddressSpace getOCLOpaqueTypeAddrSpace(Op OpCode); SPIR::TypeAttributeEnum getOCLOpaqueTypeAddrSpace(SPIR::TypePrimitiveEnum Prim); inline unsigned mapOCLMemSemanticToSPIRV(unsigned MemFenceFlag, OCLMemOrderKind Order) { return OCLMemOrderMap::map(Order) | mapBitMask(MemFenceFlag); } inline unsigned mapOCLMemFenceFlagToSPIRV(unsigned MemFenceFlag) { return mapBitMask(MemFenceFlag); } inline std::pair mapSPIRVMemSemanticToOCL(unsigned Sema) { return std::make_pair( rmapBitMask(Sema), OCLMemOrderMap::rmap(extractSPIRVMemOrderSemantic(Sema))); } inline OCLMemOrderKind mapSPIRVMemOrderToOCL(unsigned Sema) { return OCLMemOrderMap::rmap(extractSPIRVMemOrderSemantic(Sema)); } /// Mutate call instruction to call OpenCL builtin function. CallInst *mutateCallInstOCL( Module *M, CallInst *CI, std::function &)> ArgMutate, AttributeList *Attrs = nullptr); /// Mutate call instruction to call OpenCL builtin function. Instruction *mutateCallInstOCL( Module *M, CallInst *CI, std::function &, Type *&RetTy)> ArgMutate, std::function RetMutate, AttributeList *Attrs = nullptr); /// Check if instruction is bitcast from spirv.ConstantSampler to spirv.Sampler bool isSamplerInitializer(Instruction *Inst); /// Check if instruction is bitcast from spirv.ConstantPipeStorage /// to spirv.PipeStorage bool isPipeStorageInitializer(Instruction *Inst); /// Check (isSamplerInitializer || isPipeStorageInitializer) bool isSpecialTypeInitializer(Instruction *Inst); bool isPipeOrAddressSpaceCastBI(const StringRef MangledName); bool isEnqueueKernelBI(const StringRef MangledName); bool isKernelQueryBI(const StringRef MangledName); /// Check that the type is the sampler_t bool isSamplerTy(Type *Ty); // Checks if clang did not generate llvm.fmuladd for fp multiply-add operations. // If so, it applies ContractionOff ExecutionMode to the kernel. void checkFpContract(BinaryOperator *B, SPIRVBasicBlock *BB); template std::string toString(const T *Object) { std::string S; llvm::raw_string_ostream RSOS(S); Object->print(RSOS); RSOS.flush(); return S; } } // namespace OCLUtil /////////////////////////////////////////////////////////////////////////////// // // Map definitions // /////////////////////////////////////////////////////////////////////////////// using namespace OCLUtil; namespace SPIRV { template <> inline void SPIRVMap::init() { add(OCLMF_Local, MemorySemanticsWorkgroupMemoryMask); add(OCLMF_Global, MemorySemanticsCrossWorkgroupMemoryMask); add(OCLMF_Image, MemorySemanticsImageMemoryMask); } template <> inline void SPIRVMap::init() { add(OCLMFEx_Local, MemorySemanticsWorkgroupMemoryMask); add(OCLMFEx_Global, MemorySemanticsCrossWorkgroupMemoryMask); add(OCLMFEx_Local_Global, MemorySemanticsWorkgroupMemoryMask | MemorySemanticsCrossWorkgroupMemoryMask); add(OCLMFEx_Image, MemorySemanticsImageMemoryMask); add(OCLMFEx_Image_Local, MemorySemanticsWorkgroupMemoryMask | MemorySemanticsImageMemoryMask); add(OCLMFEx_Image_Global, MemorySemanticsCrossWorkgroupMemoryMask | MemorySemanticsImageMemoryMask); add(OCLMFEx_Image_Local_Global, MemorySemanticsWorkgroupMemoryMask | MemorySemanticsCrossWorkgroupMemoryMask | MemorySemanticsImageMemoryMask); } template <> inline void SPIRVMap::init() { add(OCLMO_relaxed, MemorySemanticsMaskNone); add(OCLMO_acquire, MemorySemanticsAcquireMask); add(OCLMO_release, MemorySemanticsReleaseMask); add(OCLMO_acq_rel, MemorySemanticsAcquireReleaseMask); add(OCLMO_seq_cst, MemorySemanticsSequentiallyConsistentMask); } template <> inline void SPIRVMap::init() { add(OCLMS_work_item, ScopeInvocation); add(OCLMS_work_group, ScopeWorkgroup); add(OCLMS_device, ScopeDevice); add(OCLMS_all_svm_devices, ScopeCrossDevice); add(OCLMS_sub_group, ScopeSubgroup); } template Instruction * getOrCreateSwitchFunc(StringRef MapName, Value *V, const SPIRVMap &Map, bool IsReverse, Optional DefaultCase, Instruction *InsertPoint, Module *M, int KeyMask = 0) { static_assert(std::is_convertible::value && std::is_convertible::value, "Can map only integer values"); Type *Ty = V->getType(); assert(Ty && Ty->isIntegerTy() && "Can't map non-integer types"); Function *F = getOrCreateFunction(M, Ty, Ty, MapName); if (!F->empty()) // The switch function already exists. just call it. return addCallInst(M, MapName, Ty, V, nullptr, InsertPoint); F->setLinkage(GlobalValue::PrivateLinkage); LLVMContext &Ctx = M->getContext(); BasicBlock *BB = BasicBlock::Create(Ctx, "entry", F); IRBuilder<> IRB(BB); SwitchInst *SI; F->arg_begin()->setName("key"); if (KeyMask) { Value *MaskV = ConstantInt::get(Type::getInt32Ty(Ctx), KeyMask); Value *NewKey = IRB.CreateAnd(MaskV, F->arg_begin()); NewKey->setName("key.masked"); SI = IRB.CreateSwitch(NewKey, BB); } else { SI = IRB.CreateSwitch(F->arg_begin(), BB); } if (!DefaultCase) { BasicBlock *DefaultBB = BasicBlock::Create(Ctx, "default", F); IRBuilder<> DefaultIRB(DefaultBB); DefaultIRB.CreateUnreachable(); SI->setDefaultDest(DefaultBB); } Map.foreach ([&](int Key, int Val) { if (IsReverse) std::swap(Key, Val); BasicBlock *CaseBB = BasicBlock::Create(Ctx, "case." + Twine(Key), F); IRBuilder<> CaseIRB(CaseBB); CaseIRB.CreateRet(CaseIRB.getInt32(Val)); SI->addCase(IRB.getInt32(Key), CaseBB); if (Key == DefaultCase) SI->setDefaultDest(CaseBB); }); assert(SI->getDefaultDest() != BB && "Invalid default destination in switch"); return addCallInst(M, MapName, Ty, V, nullptr, InsertPoint); } template <> inline void SPIRVMap::init() { add("reduce", GroupOperationReduce); add("scan_inclusive", GroupOperationInclusiveScan); add("scan_exclusive", GroupOperationExclusiveScan); } template <> inline void SPIRVMap::init() { add("rte", FPRoundingModeRTE); add("rtz", FPRoundingModeRTZ); add("rtp", FPRoundingModeRTP); add("rtn", FPRoundingModeRTN); } template <> inline void SPIRVMap::init() { #define _SPIRV_OP(x) add(OclExt::x, #x); _SPIRV_OP(cl_images) _SPIRV_OP(cl_doubles) _SPIRV_OP(cl_khr_int64_base_atomics) _SPIRV_OP(cl_khr_int64_extended_atomics) _SPIRV_OP(cl_khr_fp16) _SPIRV_OP(cl_khr_gl_sharing) _SPIRV_OP(cl_khr_gl_event) _SPIRV_OP(cl_khr_d3d10_sharing) _SPIRV_OP(cl_khr_media_sharing) _SPIRV_OP(cl_khr_d3d11_sharing) _SPIRV_OP(cl_khr_global_int32_base_atomics) _SPIRV_OP(cl_khr_global_int32_extended_atomics) _SPIRV_OP(cl_khr_local_int32_base_atomics) _SPIRV_OP(cl_khr_local_int32_extended_atomics) _SPIRV_OP(cl_khr_byte_addressable_store) _SPIRV_OP(cl_khr_3d_image_writes) _SPIRV_OP(cl_khr_gl_msaa_sharing) _SPIRV_OP(cl_khr_depth_images) _SPIRV_OP(cl_khr_gl_depth_images) _SPIRV_OP(cl_khr_subgroups) _SPIRV_OP(cl_khr_mipmap_image) _SPIRV_OP(cl_khr_mipmap_image_writes) _SPIRV_OP(cl_khr_egl_event) _SPIRV_OP(cl_khr_srgb_image_writes) #undef _SPIRV_OP } template <> inline void SPIRVMap::init() { add(OclExt::cl_images, CapabilityImageBasic); add(OclExt::cl_doubles, CapabilityFloat64); add(OclExt::cl_khr_int64_base_atomics, CapabilityInt64Atomics); add(OclExt::cl_khr_int64_extended_atomics, CapabilityInt64Atomics); add(OclExt::cl_khr_fp16, CapabilityFloat16); add(OclExt::cl_khr_subgroups, CapabilityGroups); add(OclExt::cl_khr_mipmap_image, CapabilityImageMipmap); add(OclExt::cl_khr_mipmap_image_writes, CapabilityImageMipmap); } /// Map OpenCL work functions to SPIR-V builtin variables. template <> inline void SPIRVMap::init() { add("get_work_dim", BuiltInWorkDim); add("get_global_size", BuiltInGlobalSize); add("get_global_id", BuiltInGlobalInvocationId); add("get_global_offset", BuiltInGlobalOffset); add("get_local_size", BuiltInWorkgroupSize); add("get_enqueued_local_size", BuiltInEnqueuedWorkgroupSize); add("get_local_id", BuiltInLocalInvocationId); add("get_num_groups", BuiltInNumWorkgroups); add("get_group_id", BuiltInWorkgroupId); add("get_global_linear_id", BuiltInGlobalLinearId); add("get_local_linear_id", BuiltInLocalInvocationIndex); add("get_sub_group_size", BuiltInSubgroupSize); add("get_max_sub_group_size", BuiltInSubgroupMaxSize); add("get_num_sub_groups", BuiltInNumSubgroups); add("get_enqueued_num_sub_groups", BuiltInNumEnqueuedSubgroups); add("get_sub_group_id", BuiltInSubgroupId); add("get_sub_group_local_id", BuiltInSubgroupLocalInvocationId); } // Maps uniqued OCL builtin function name to SPIR-V op code. // A uniqued OCL builtin function name may be different from the real // OCL builtin function name. e.g. instead of atomic_min, atomic_umin // is used for atomic_min with unsigned integer parameter. // work_group_ and sub_group_ functions are unified as group_ functions // except work_group_barrier. class SPIRVInstruction; template <> inline void SPIRVMap::init() { #define _SPIRV_OP(x, y) add("atom_" #x, OpAtomic##y); // cl_khr_int64_base_atomics builtins _SPIRV_OP(add, IAdd) _SPIRV_OP(sub, ISub) _SPIRV_OP(xchg, Exchange) _SPIRV_OP(dec, IDecrement) _SPIRV_OP(inc, IIncrement) _SPIRV_OP(cmpxchg, CompareExchange) // cl_khr_int64_extended_atomics builtins _SPIRV_OP(min, SMin) _SPIRV_OP(max, SMax) _SPIRV_OP(and, And) _SPIRV_OP(or, Or) _SPIRV_OP (xor, Xor) #undef _SPIRV_OP #define _SPIRV_OP(x, y) add("atomic_" #x, Op##y); // CL 2.0 atomic builtins _SPIRV_OP(flag_test_and_set_explicit, AtomicFlagTestAndSet) _SPIRV_OP(flag_clear_explicit, AtomicFlagClear) _SPIRV_OP(load_explicit, AtomicLoad) _SPIRV_OP(store_explicit, AtomicStore) _SPIRV_OP(exchange_explicit, AtomicExchange) _SPIRV_OP(compare_exchange_strong_explicit, AtomicCompareExchange) _SPIRV_OP(compare_exchange_weak_explicit, AtomicCompareExchangeWeak) _SPIRV_OP(inc, AtomicIIncrement) _SPIRV_OP(dec, AtomicIDecrement) _SPIRV_OP(fetch_add_explicit, AtomicIAdd) _SPIRV_OP(fetch_sub_explicit, AtomicISub) _SPIRV_OP(fetch_umin_explicit, AtomicUMin) _SPIRV_OP(fetch_umax_explicit, AtomicUMax) _SPIRV_OP(fetch_min_explicit, AtomicSMin) _SPIRV_OP(fetch_max_explicit, AtomicSMax) _SPIRV_OP(fetch_and_explicit, AtomicAnd) _SPIRV_OP(fetch_or_explicit, AtomicOr) _SPIRV_OP(fetch_xor_explicit, AtomicXor) #undef _SPIRV_OP #define _SPIRV_OP(x, y) add(#x, Op##y); _SPIRV_OP(dot, Dot) _SPIRV_OP(async_work_group_copy, GroupAsyncCopy) _SPIRV_OP(async_work_group_strided_copy, GroupAsyncCopy) _SPIRV_OP(wait_group_events, GroupWaitEvents) _SPIRV_OP(isequal, FOrdEqual) _SPIRV_OP(isnotequal, FUnordNotEqual) _SPIRV_OP(isgreater, FOrdGreaterThan) _SPIRV_OP(isgreaterequal, FOrdGreaterThanEqual) _SPIRV_OP(isless, FOrdLessThan) _SPIRV_OP(islessequal, FOrdLessThanEqual) _SPIRV_OP(islessgreater, LessOrGreater) _SPIRV_OP(isordered, Ordered) _SPIRV_OP(isunordered, Unordered) _SPIRV_OP(isfinite, IsFinite) _SPIRV_OP(isinf, IsInf) _SPIRV_OP(isnan, IsNan) _SPIRV_OP(isnormal, IsNormal) _SPIRV_OP(signbit, SignBitSet) _SPIRV_OP(any, Any) _SPIRV_OP(all, All) _SPIRV_OP(popcount, BitCount) _SPIRV_OP(get_fence, GenericPtrMemSemantics) // CL 2.0 kernel enqueue builtins _SPIRV_OP(enqueue_marker, EnqueueMarker) _SPIRV_OP(enqueue_kernel, EnqueueKernel) _SPIRV_OP(get_kernel_sub_group_count_for_ndrange_impl, GetKernelNDrangeSubGroupCount) _SPIRV_OP(get_kernel_max_sub_group_size_for_ndrange_impl, GetKernelNDrangeMaxSubGroupSize) _SPIRV_OP(get_kernel_work_group_size_impl, GetKernelWorkGroupSize) _SPIRV_OP(get_kernel_preferred_work_group_size_multiple_impl, GetKernelPreferredWorkGroupSizeMultiple) _SPIRV_OP(retain_event, RetainEvent) _SPIRV_OP(release_event, ReleaseEvent) _SPIRV_OP(create_user_event, CreateUserEvent) _SPIRV_OP(is_valid_event, IsValidEvent) _SPIRV_OP(set_user_event_status, SetUserEventStatus) _SPIRV_OP(capture_event_profiling_info, CaptureEventProfilingInfo) _SPIRV_OP(get_default_queue, GetDefaultQueue) _SPIRV_OP(ndrange_1D, BuildNDRange) _SPIRV_OP(ndrange_2D, BuildNDRange) _SPIRV_OP(ndrange_3D, BuildNDRange) // Generic Address Space Casts _SPIRV_OP(to_global, GenericCastToPtrExplicit) _SPIRV_OP(to_local, GenericCastToPtrExplicit) _SPIRV_OP(to_private, GenericCastToPtrExplicit) // CL 2.0 pipe builtins _SPIRV_OP(read_pipe_2, ReadPipe) _SPIRV_OP(write_pipe_2, WritePipe) _SPIRV_OP(read_pipe_2_bl, ReadPipeBlockingINTEL) _SPIRV_OP(write_pipe_2_bl, WritePipeBlockingINTEL) _SPIRV_OP(read_pipe_4, ReservedReadPipe) _SPIRV_OP(write_pipe_4, ReservedWritePipe) _SPIRV_OP(reserve_read_pipe, ReserveReadPipePackets) _SPIRV_OP(reserve_write_pipe, ReserveWritePipePackets) _SPIRV_OP(commit_read_pipe, CommitReadPipe) _SPIRV_OP(commit_write_pipe, CommitWritePipe) _SPIRV_OP(is_valid_reserve_id, IsValidReserveId) _SPIRV_OP(group_reserve_read_pipe, GroupReserveReadPipePackets) _SPIRV_OP(group_reserve_write_pipe, GroupReserveWritePipePackets) _SPIRV_OP(group_commit_read_pipe, GroupCommitReadPipe) _SPIRV_OP(group_commit_write_pipe, GroupCommitWritePipe) _SPIRV_OP(get_pipe_num_packets_ro, GetNumPipePackets) _SPIRV_OP(get_pipe_num_packets_wo, GetNumPipePackets) _SPIRV_OP(get_pipe_max_packets_ro, GetMaxPipePackets) _SPIRV_OP(get_pipe_max_packets_wo, GetMaxPipePackets) // CL 2.0 workgroup builtins _SPIRV_OP(group_all, GroupAll) _SPIRV_OP(group_any, GroupAny) _SPIRV_OP(group_broadcast, GroupBroadcast) _SPIRV_OP(group_iadd, GroupIAdd) _SPIRV_OP(group_fadd, GroupFAdd) _SPIRV_OP(group_fmin, GroupFMin) _SPIRV_OP(group_umin, GroupUMin) _SPIRV_OP(group_smin, GroupSMin) _SPIRV_OP(group_fmax, GroupFMax) _SPIRV_OP(group_umax, GroupUMax) _SPIRV_OP(group_smax, GroupSMax) // CL image builtins _SPIRV_OP(SampledImage, SampledImage) _SPIRV_OP(ImageSampleExplicitLod, ImageSampleExplicitLod) _SPIRV_OP(read_image, ImageRead) _SPIRV_OP(write_image, ImageWrite) _SPIRV_OP(get_image_channel_data_type, ImageQueryFormat) _SPIRV_OP(get_image_channel_order, ImageQueryOrder) _SPIRV_OP(get_image_num_mip_levels, ImageQueryLevels) _SPIRV_OP(get_image_num_samples, ImageQuerySamples) // Intel Subgroups builtins _SPIRV_OP(intel_sub_group_shuffle, SubgroupShuffleINTEL) _SPIRV_OP(intel_sub_group_shuffle_down, SubgroupShuffleDownINTEL) _SPIRV_OP(intel_sub_group_shuffle_up, SubgroupShuffleUpINTEL) _SPIRV_OP(intel_sub_group_shuffle_xor, SubgroupShuffleXorINTEL) // Intel media_block_io builtins _SPIRV_OP(intel_sub_group_media_block_read, SubgroupImageMediaBlockReadINTEL) _SPIRV_OP(intel_sub_group_media_block_write, SubgroupImageMediaBlockWriteINTEL) #undef _SPIRV_OP } template <> inline void SPIRVMap::init() { #define _SPIRV_OP(x, y) add(#x, Op##y); _SPIRV_OP(add, AtomicIAdd) _SPIRV_OP(sub, AtomicISub) _SPIRV_OP(xchg, AtomicExchange) _SPIRV_OP(cmpxchg, AtomicCompareExchange) _SPIRV_OP(inc, AtomicIIncrement) _SPIRV_OP(dec, AtomicIDecrement) _SPIRV_OP(min, AtomicSMin) _SPIRV_OP(max, AtomicSMax) _SPIRV_OP(umin, AtomicUMin) _SPIRV_OP(umax, AtomicUMax) _SPIRV_OP(and, AtomicAnd) _SPIRV_OP(or, AtomicOr) _SPIRV_OP(xor, AtomicXor) #undef _SPIRV_OP } // SPV_INTEL_device_side_avc_motion_estimation extension builtins class SPIRVSubgroupsAVCIntelInst; template <> inline void SPIRVMap::init() { // Here is a workaround for a bug in the specification: // 'avc' missed in 'intel_sub_group_avc' prefix. add("intel_sub_group_ime_ref_window_size", OpSubgroupAvcImeRefWindowSizeINTEL); #define _SPIRV_OP(x, y) add("intel_sub_group_avc_" #x, OpSubgroupAvc##y##INTEL); // Initialization phase functions _SPIRV_OP(ime_initialize, ImeInitialize) _SPIRV_OP(fme_initialize, FmeInitialize) _SPIRV_OP(bme_initialize, BmeInitialize) _SPIRV_OP(sic_initialize, SicInitialize) // Result and payload types conversion functions _SPIRV_OP(mce_convert_to_ime_payload, MceConvertToImePayload) _SPIRV_OP(mce_convert_to_ime_result, MceConvertToImeResult) _SPIRV_OP(mce_convert_to_ref_payload, MceConvertToRefPayload) _SPIRV_OP(mce_convert_to_ref_result, MceConvertToRefResult) _SPIRV_OP(mce_convert_to_sic_payload, MceConvertToSicPayload) _SPIRV_OP(mce_convert_to_sic_result, MceConvertToSicResult) _SPIRV_OP(ime_convert_to_mce_payload, ImeConvertToMcePayload) _SPIRV_OP(ime_convert_to_mce_result, ImeConvertToMceResult) _SPIRV_OP(ref_convert_to_mce_payload, RefConvertToMcePayload) _SPIRV_OP(ref_convert_to_mce_result, RefConvertToMceResult) _SPIRV_OP(sic_convert_to_mce_payload, SicConvertToMcePayload) _SPIRV_OP(sic_convert_to_mce_result, SicConvertToMceResult) #undef _SPIRV_OP // MCE instructions #define _SPIRV_OP(x, y) \ add("intel_sub_group_avc_mce_" #x, OpSubgroupAvcMce##y##INTEL); _SPIRV_OP(get_default_inter_base_multi_reference_penalty, GetDefaultInterBaseMultiReferencePenalty) _SPIRV_OP(set_inter_base_multi_reference_penalty, SetInterBaseMultiReferencePenalty) _SPIRV_OP(get_default_inter_shape_penalty, GetDefaultInterShapePenalty) _SPIRV_OP(set_inter_shape_penalty, SetInterShapePenalty) _SPIRV_OP(get_default_inter_direction_penalty, GetDefaultInterDirectionPenalty) _SPIRV_OP(set_inter_direction_penalty, SetInterDirectionPenalty) _SPIRV_OP(get_default_intra_luma_shape_penalty, GetDefaultIntraLumaShapePenalty) _SPIRV_OP(get_default_inter_motion_vector_cost_table, GetDefaultInterMotionVectorCostTable) _SPIRV_OP(get_default_high_penalty_cost_table, GetDefaultHighPenaltyCostTable) _SPIRV_OP(get_default_medium_penalty_cost_table, GetDefaultMediumPenaltyCostTable) _SPIRV_OP(get_default_low_penalty_cost_table, GetDefaultLowPenaltyCostTable) _SPIRV_OP(set_motion_vector_cost_function, SetMotionVectorCostFunction) _SPIRV_OP(get_default_intra_luma_mode_penalty, GetDefaultIntraLumaModePenalty) _SPIRV_OP(get_default_non_dc_luma_intra_penalty, GetDefaultNonDcLumaIntraPenalty) _SPIRV_OP(get_default_intra_chroma_mode_base_penalty, GetDefaultIntraChromaModeBasePenalty) _SPIRV_OP(set_ac_only_haar, SetAcOnlyHaar) _SPIRV_OP(set_source_interlaced_field_polarity, SetSourceInterlacedFieldPolarity) _SPIRV_OP(set_single_reference_interlaced_field_polarity, SetSingleReferenceInterlacedFieldPolarity) _SPIRV_OP(set_dual_reference_interlaced_field_polarities, SetDualReferenceInterlacedFieldPolarities) _SPIRV_OP(get_motion_vectors, GetMotionVectors) _SPIRV_OP(get_inter_distortions, GetInterDistortions) _SPIRV_OP(get_best_inter_distortion, GetBestInterDistortions) _SPIRV_OP(get_inter_major_shape, GetInterMajorShape) _SPIRV_OP(get_inter_minor_shapes, GetInterMinorShape) _SPIRV_OP(get_inter_directions, GetInterDirections) _SPIRV_OP(get_inter_motion_vector_count, GetInterMotionVectorCount) _SPIRV_OP(get_inter_reference_ids, GetInterReferenceIds) _SPIRV_OP(get_inter_reference_interlaced_field_polarities, GetInterReferenceInterlacedFieldPolarities) #undef _SPIRV_OP // IME instructions #define _SPIRV_OP(x, y) \ add("intel_sub_group_avc_ime_" #x, OpSubgroupAvcIme##y##INTEL); _SPIRV_OP(set_single_reference, SetSingleReference) _SPIRV_OP(set_dual_reference, SetDualReference) _SPIRV_OP(ref_window_size, RefWindowSize) _SPIRV_OP(adjust_ref_offset, AdjustRefOffset) _SPIRV_OP(set_max_motion_vector_count, SetMaxMotionVectorCount) _SPIRV_OP(set_unidirectional_mix_disable, SetUnidirectionalMixDisable) _SPIRV_OP(set_early_search_termination_threshold, SetEarlySearchTerminationThreshold) _SPIRV_OP(set_weighted_sad, SetWeightedSad) _SPIRV_OP(evaluate_with_single_reference, EvaluateWithSingleReference) _SPIRV_OP(evaluate_with_dual_reference, EvaluateWithDualReference) _SPIRV_OP(evaluate_with_single_reference_streamin, EvaluateWithSingleReferenceStreamin) _SPIRV_OP(evaluate_with_dual_reference_streamin, EvaluateWithDualReferenceStreamin) _SPIRV_OP(evaluate_with_single_reference_streamout, EvaluateWithSingleReferenceStreamout) _SPIRV_OP(evaluate_with_dual_reference_streamout, EvaluateWithDualReferenceStreamout) _SPIRV_OP(evaluate_with_single_reference_streaminout, EvaluateWithSingleReferenceStreaminout) _SPIRV_OP(evaluate_with_dual_reference_streaminout, EvaluateWithDualReferenceStreaminout) _SPIRV_OP(get_single_reference_streamin, GetSingleReferenceStreamin) _SPIRV_OP(get_dual_reference_streamin, GetDualReferenceStreamin) _SPIRV_OP(strip_single_reference_streamout, StripSingleReferenceStreamout) _SPIRV_OP(strip_dual_reference_streamout, StripDualReferenceStreamout) _SPIRV_OP(get_border_reached, GetBorderReached) _SPIRV_OP(get_truncated_search_indication, GetTruncatedSearchIndication) _SPIRV_OP(get_unidirectional_early_search_termination, GetUnidirectionalEarlySearchTermination) _SPIRV_OP(get_weighting_pattern_minimum_motion_vector, GetWeightingPatternMinimumMotionVector) _SPIRV_OP(get_weighting_pattern_minimum_distortion, GetWeightingPatternMinimumDistortion) #undef _SPIRV_OP #define _SPIRV_OP(x, y) \ add("intel_sub_group_avc_ime_get_streamout_major_shape_" #x, \ OpSubgroupAvcImeGetStreamout##y##INTEL); _SPIRV_OP(motion_vectors_single_reference, SingleReferenceMajorShapeMotionVectors) _SPIRV_OP(distortions_single_reference, SingleReferenceMajorShapeDistortions) _SPIRV_OP(reference_ids_single_reference, SingleReferenceMajorShapeReferenceIds) _SPIRV_OP(motion_vectors_dual_reference, DualReferenceMajorShapeMotionVectors) _SPIRV_OP(distortions_dual_reference, DualReferenceMajorShapeDistortions) _SPIRV_OP(reference_ids_dual_reference, DualReferenceMajorShapeReferenceIds) #undef _SPIRV_OP // REF instructions #define _SPIRV_OP(x, y) \ add("intel_sub_group_avc_ref_" #x, OpSubgroupAvcRef##y##INTEL); _SPIRV_OP(set_bidirectional_mix_disable, SetBidirectionalMixDisable) _SPIRV_OP(set_bilinear_filter_enable, SetBilinearFilterEnable) _SPIRV_OP(evaluate_with_single_reference, EvaluateWithSingleReference) _SPIRV_OP(evaluate_with_dual_reference, EvaluateWithDualReference) _SPIRV_OP(evaluate_with_multi_reference, EvaluateWithMultiReference) _SPIRV_OP(evaluate_with_multi_reference_interlaced, EvaluateWithMultiReferenceInterlaced) #undef _SPIRV_OP // SIC instructions #define _SPIRV_OP(x, y) \ add("intel_sub_group_avc_sic_" #x, OpSubgroupAvcSic##y##INTEL); _SPIRV_OP(configure_skc, ConfigureSkc) _SPIRV_OP(configure_ipe_luma, ConfigureIpeLuma) _SPIRV_OP(configure_ipe_luma_chroma, ConfigureIpeLumaChroma) _SPIRV_OP(get_motion_vector_mask, GetMotionVectorMask) _SPIRV_OP(set_intra_luma_shape_penalty, SetIntraLumaShapePenalty) _SPIRV_OP(set_intra_luma_mode_cost_function, SetIntraLumaModeCostFunction) _SPIRV_OP(set_intra_chroma_mode_cost_function, SetIntraChromaModeCostFunction) _SPIRV_OP(set_skc_bilinear_filter_enable, SetBilinearFilterEnable) _SPIRV_OP(set_skc_forward_transform_enable, SetSkcForwardTransformEnable) _SPIRV_OP(set_block_based_raw_skip_sad, SetBlockBasedRawSkipSad) _SPIRV_OP(evaluate_ipe, EvaluateIpe) _SPIRV_OP(evaluate_with_single_reference, EvaluateWithSingleReference) _SPIRV_OP(evaluate_with_dual_reference, EvaluateWithDualReference) _SPIRV_OP(evaluate_with_multi_reference, EvaluateWithMultiReference) _SPIRV_OP(evaluate_with_multi_reference_interlaced, EvaluateWithMultiReferenceInterlaced) _SPIRV_OP(get_ipe_luma_shape, GetIpeLumaShape) _SPIRV_OP(get_best_ipe_luma_distortion, GetBestIpeLumaDistortion) _SPIRV_OP(get_best_ipe_chroma_distortion, GetBestIpeChromaDistortion) _SPIRV_OP(get_packed_ipe_luma_modes, GetPackedIpeLumaModes) _SPIRV_OP(get_ipe_chroma_mode, GetIpeChromaMode) _SPIRV_OP(get_packed_skc_luma_count_threshold, GetPackedSkcLumaCountThreshold) _SPIRV_OP(get_packed_skc_luma_sum_threshold, GetPackedSkcLumaSumThreshold) _SPIRV_OP(get_inter_raw_sads, GetInterRawSads) #undef _SPIRV_OP } typedef SPIRVMap OCLSPIRVSubgroupAVCIntelBuiltinMap; template <> inline void SPIRVMap::init() { add("opencl.event_t", OpTypeEvent); add("opencl.pipe_t", OpTypePipe); add("opencl.clk_event_t", OpTypeDeviceEvent); add("opencl.reserve_id_t", OpTypeReserveId); add("opencl.queue_t", OpTypeQueue); add("opencl.sampler_t", OpTypeSampler); } } // namespace SPIRV #endif // SPIRV_OCLUTIL_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/PreprocessMetadata.cpp000066400000000000000000000201041363521741200233360ustar00rootroot00000000000000//===- PreprocessMetadata.cpp - - C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// // // This file implements preprocessing of LLVM IR metadata in order to perform // further translation to SPIR-V. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "clmdtospv" #include "OCLUtil.h" #include "SPIRVInternal.h" #include "SPIRVMDBuilder.h" #include "SPIRVMDWalker.h" #include "llvm/ADT/Triple.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstVisitor.h" #include "llvm/IR/Verifier.h" #include "llvm/Pass.h" #include "llvm/PassSupport.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" using namespace llvm; using namespace SPIRV; using namespace OCLUtil; namespace SPIRV { cl::opt EraseOCLMD("spirv-erase-cl-md", cl::init(true), cl::desc("Erase OpenCL metadata")); class PreprocessMetadata : public ModulePass { public: PreprocessMetadata() : ModulePass(ID), M(nullptr), Ctx(nullptr) { initializePreprocessMetadataPass(*PassRegistry::getPassRegistry()); } bool runOnModule(Module &M) override; void visit(Module *M); static char ID; private: Module *M; LLVMContext *Ctx; }; char PreprocessMetadata::ID = 0; bool PreprocessMetadata::runOnModule(Module &Module) { M = &Module; Ctx = &M->getContext(); LLVM_DEBUG(dbgs() << "Enter PreprocessMetadata:\n"); visit(M); LLVM_DEBUG(dbgs() << "After PreprocessMetadata:\n" << *M); std::string Err; raw_string_ostream ErrorOS(Err); if (verifyModule(*M, &ErrorOS)) { LLVM_DEBUG(errs() << "Fails to verify module: " << ErrorOS.str()); } return true; } void PreprocessMetadata::visit(Module *M) { SPIRVMDBuilder B(*M); SPIRVMDWalker W(*M); unsigned CLVer = getOCLVersion(M, true); if (CLVer != 0) { // Preprocess OpenCL-specific metadata // !spirv.Source = !{!x} // !{x} = !{i32 3, i32 102000} B.addNamedMD(kSPIRVMD::Source) .addOp() .add(CLVer < kOCLVer::CL21 ? spv::SourceLanguageOpenCL_C : spv::SourceLanguageOpenCL_CPP) .add(CLVer) .done(); if (EraseOCLMD) B.eraseNamedMD(kSPIR2MD::OCLVer).eraseNamedMD(kSPIR2MD::SPIRVer); // !spirv.MemoryModel = !{!x} // !{x} = !{i32 1, i32 2} Triple TT(M->getTargetTriple()); assert(isSupportedTriple(TT) && "Invalid triple"); B.addNamedMD(kSPIRVMD::MemoryModel) .addOp() .add(TT.isArch32Bit() ? spv::AddressingModelPhysical32 : spv::AddressingModelPhysical64) .add(spv::MemoryModelOpenCL) .done(); // Add source extensions // !spirv.SourceExtension = !{!x, !y, ...} // !x = {!"cl_khr_..."} // !y = {!"cl_khr_..."} auto Exts = getNamedMDAsStringSet(M, kSPIR2MD::Extensions); if (!Exts.empty()) { auto N = B.addNamedMD(kSPIRVMD::SourceExtension); for (auto &I : Exts) N.addOp().add(I).done(); } if (EraseOCLMD) B.eraseNamedMD(kSPIR2MD::Extensions).eraseNamedMD(kSPIR2MD::OptFeatures); if (EraseOCLMD) B.eraseNamedMD(kSPIR2MD::FPContract); } // The rest of metadata might come not only from OpenCL // Create metadata representing (empty so far) list // of OpExecutionMode instructions auto EM = B.addNamedMD(kSPIRVMD::ExecutionMode); // !spirv.ExecutionMode = {} // Add execution modes for kernels. We take it from metadata attached to // the kernel functions. for (Function &Kernel : *M) { if (Kernel.getCallingConv() != CallingConv::SPIR_KERNEL) continue; // Specifing execution modes for the Kernel and adding it to the list // of ExecutionMode instructions. // !{void (i32 addrspace(1)*)* @kernel, i32 17, i32 X, i32 Y, i32 Z} if (MDNode *WGSize = Kernel.getMetadata(kSPIR2MD::WGSize)) { unsigned X, Y, Z; decodeMDNode(WGSize, X, Y, Z); EM.addOp() .add(&Kernel) .add(spv::ExecutionModeLocalSize) .add(X) .add(Y) .add(Z) .done(); } // !{void (i32 addrspace(1)*)* @kernel, i32 18, i32 X, i32 Y, i32 Z} if (MDNode *WGSizeHint = Kernel.getMetadata(kSPIR2MD::WGSizeHint)) { unsigned X, Y, Z; decodeMDNode(WGSizeHint, X, Y, Z); EM.addOp() .add(&Kernel) .add(spv::ExecutionModeLocalSizeHint) .add(X) .add(Y) .add(Z) .done(); } // !{void (i32 addrspace(1)*)* @kernel, i32 30, i32 hint} if (MDNode *VecTypeHint = Kernel.getMetadata(kSPIR2MD::VecTyHint)) { EM.addOp() .add(&Kernel) .add(spv::ExecutionModeVecTypeHint) .add(transVecTypeHint(VecTypeHint)) .done(); } // !{void (i32 addrspace(1)*)* @kernel, i32 35, i32 size} if (MDNode *ReqdSubgroupSize = Kernel.getMetadata(kSPIR2MD::SubgroupSize)) { EM.addOp() .add(&Kernel) .add(spv::ExecutionModeSubgroupSize) .add(getMDOperandAsInt(ReqdSubgroupSize, 0)) .done(); } // !{void (i32 addrspace(1)*)* @kernel, i32 max_work_group_size, i32 X, // i32 Y, i32 Z} if (MDNode *MaxWorkgroupSizeINTEL = Kernel.getMetadata(kSPIR2MD::MaxWGSize)) { unsigned X, Y, Z; decodeMDNode(MaxWorkgroupSizeINTEL, X, Y, Z); EM.addOp() .add(&Kernel) .add(spv::ExecutionModeMaxWorkgroupSizeINTEL) .add(X) .add(Y) .add(Z) .done(); } // !{void (i32 addrspace(1)*)* @kernel, i32 max_global_work_dim, i32 dim} if (MDNode *MaxWorkDimINTEL = Kernel.getMetadata(kSPIR2MD::MaxWGDim)) { EM.addOp() .add(&Kernel) .add(spv::ExecutionModeMaxWorkDimINTEL) .add(getMDOperandAsInt(MaxWorkDimINTEL, 0)) .done(); } // !{void (i32 addrspace(1)*)* @kernel, i32 num_simd_work_items, i32 num} if (MDNode *NumSIMDWorkitemsINTEL = Kernel.getMetadata(kSPIR2MD::NumSIMD)) { EM.addOp() .add(&Kernel) .add(spv::ExecutionModeNumSIMDWorkitemsINTEL) .add(getMDOperandAsInt(NumSIMDWorkitemsINTEL, 0)) .done(); } } } } // namespace SPIRV INITIALIZE_PASS(PreprocessMetadata, "preprocess-metadata", "Transform LLVM IR metadata to SPIR-V metadata format", false, false) ModulePass *llvm::createPreprocessMetadata() { return new PreprocessMetadata(); } SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVInternal.h000066400000000000000000001100361363521741200216210ustar00rootroot00000000000000//===- LLVMSPIRVInternal.h - SPIR-V internal header file -------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file declares classes and functions shared by SPIR-V reader/writer. /// //===----------------------------------------------------------------------===// #ifndef SPIRV_SPIRVINTERNAL_H #define SPIRV_SPIRVINTERNAL_H #include "NameMangleAPI.h" #include "libSPIRV/SPIRVEnum.h" #include "libSPIRV/SPIRVError.h" #include "libSPIRV/SPIRVNameMapEnum.h" #include "libSPIRV/SPIRVType.h" #include "libSPIRV/SPIRVUtil.h" #include "LLVMSPIRVLib.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" #include #include using namespace SPIRV; using namespace llvm; namespace SPIRV { /// The LLVM/SPIR-V translator version used to fill the lower 16 bits of the /// generator's magic number in the generated SPIR-V module. /// This number should be bumped up whenever the generated SPIR-V changes. const static unsigned short KTranslatorVer = 14; #define SPCV_TARGET_LLVM_IMAGE_TYPE_ENCODE_ACCESS_QUAL 0 // Workaround for SPIR 2 producer bug about kernel function calling convention. // This workaround checks metadata to determine if a function is kernel. #define SPCV_RELAX_KERNEL_CALLING_CONV 1 class SPIRVOpaqueType; typedef SPIRVMap SPIRVOpaqueTypeOpCodeMap; // Ad hoc function used by LLVM/SPIRV converter for type casting #define SPCV_CAST "spcv.cast" #define LLVM_MEMCPY "llvm.memcpy" // The name of function generated by Clang to initialize sampler(which is // opaqueue type) by 32-bit integer. The name is taken from // CodeGenModule::createOpenCLIntToSamplerConversion(). #define SAMPLER_INIT "__translate_sampler_initializer" template <> inline void SPIRVMap::init() { #define _SPIRV_OP(x, y) add(Instruction::x, Op##y); /* Casts */ _SPIRV_OP(ZExt, UConvert) _SPIRV_OP(SExt, SConvert) _SPIRV_OP(Trunc, UConvert) _SPIRV_OP(FPToUI, ConvertFToU) _SPIRV_OP(FPToSI, ConvertFToS) _SPIRV_OP(UIToFP, ConvertUToF) _SPIRV_OP(SIToFP, ConvertSToF) _SPIRV_OP(FPTrunc, FConvert) _SPIRV_OP(FPExt, FConvert) _SPIRV_OP(PtrToInt, ConvertPtrToU) _SPIRV_OP(IntToPtr, ConvertUToPtr) _SPIRV_OP(BitCast, Bitcast) _SPIRV_OP(AddrSpaceCast, GenericCastToPtr) _SPIRV_OP(GetElementPtr, AccessChain) _SPIRV_OP(FNeg, FNegate) /*Binary*/ _SPIRV_OP(And, BitwiseAnd) _SPIRV_OP(Or, BitwiseOr) _SPIRV_OP(Xor, BitwiseXor) _SPIRV_OP(Add, IAdd) _SPIRV_OP(FAdd, FAdd) _SPIRV_OP(Sub, ISub) _SPIRV_OP(FSub, FSub) _SPIRV_OP(Mul, IMul) _SPIRV_OP(FMul, FMul) _SPIRV_OP(UDiv, UDiv) _SPIRV_OP(SDiv, SDiv) _SPIRV_OP(FDiv, FDiv) _SPIRV_OP(SRem, SRem) _SPIRV_OP(FRem, FRem) _SPIRV_OP(URem, UMod) _SPIRV_OP(Shl, ShiftLeftLogical) _SPIRV_OP(LShr, ShiftRightLogical) _SPIRV_OP(AShr, ShiftRightArithmetic) #undef _SPIRV_OP } typedef SPIRVMap OpCodeMap; template <> inline void SPIRVMap::init() { #define _SPIRV_OP(x, y) add(CmpInst::x, Op##y); _SPIRV_OP(FCMP_OEQ, FOrdEqual) _SPIRV_OP(FCMP_OGT, FOrdGreaterThan) _SPIRV_OP(FCMP_OGE, FOrdGreaterThanEqual) _SPIRV_OP(FCMP_OLT, FOrdLessThan) _SPIRV_OP(FCMP_OLE, FOrdLessThanEqual) _SPIRV_OP(FCMP_ONE, FOrdNotEqual) _SPIRV_OP(FCMP_ORD, Ordered) _SPIRV_OP(FCMP_UNO, Unordered) _SPIRV_OP(FCMP_UEQ, FUnordEqual) _SPIRV_OP(FCMP_UGT, FUnordGreaterThan) _SPIRV_OP(FCMP_UGE, FUnordGreaterThanEqual) _SPIRV_OP(FCMP_ULT, FUnordLessThan) _SPIRV_OP(FCMP_ULE, FUnordLessThanEqual) _SPIRV_OP(FCMP_UNE, FUnordNotEqual) _SPIRV_OP(ICMP_EQ, IEqual) _SPIRV_OP(ICMP_NE, INotEqual) _SPIRV_OP(ICMP_UGT, UGreaterThan) _SPIRV_OP(ICMP_UGE, UGreaterThanEqual) _SPIRV_OP(ICMP_ULT, ULessThan) _SPIRV_OP(ICMP_ULE, ULessThanEqual) _SPIRV_OP(ICMP_SGT, SGreaterThan) _SPIRV_OP(ICMP_SGE, SGreaterThanEqual) _SPIRV_OP(ICMP_SLT, SLessThan) _SPIRV_OP(ICMP_SLE, SLessThanEqual) #undef _SPIRV_OP } typedef SPIRVMap CmpMap; class IntBoolOpMapId; template <> inline void SPIRVMap::init() { add(OpNot, OpLogicalNot); add(OpBitwiseAnd, OpLogicalAnd); add(OpBitwiseOr, OpLogicalOr); add(OpBitwiseXor, OpLogicalNotEqual); add(OpIEqual, OpLogicalEqual); add(OpINotEqual, OpLogicalNotEqual); } typedef SPIRVMap IntBoolOpMap; #define SPIR_TARGETTRIPLE32 "spir-unknown-unknown" #define SPIR_TARGETTRIPLE64 "spir64-unknown-unknown" #define SPIR_DATALAYOUT32 \ "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32" \ "-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32" \ "-v32:32:32-v48:64:64-v64:64:64-v96:128:128" \ "-v128:128:128-v192:256:256-v256:256:256" \ "-v512:512:512-v1024:1024:1024" #define SPIR_DATALAYOUT64 \ "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32" \ "-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32" \ "-v32:32:32-v48:64:64-v64:64:64-v96:128:128" \ "-v128:128:128-v192:256:256-v256:256:256" \ "-v512:512:512-v1024:1024:1024" enum SPIRAddressSpace { SPIRAS_Private, SPIRAS_Global, SPIRAS_Constant, SPIRAS_Local, SPIRAS_Generic, SPIRAS_Input, SPIRAS_Output, SPIRAS_Count, }; template <> inline void SPIRVMap::init() { add(SPIRAS_Private, "Private"); add(SPIRAS_Global, "Global"); add(SPIRAS_Constant, "Constant"); add(SPIRAS_Local, "Local"); add(SPIRAS_Generic, "Generic"); add(SPIRAS_Input, "Input"); } typedef SPIRVMap SPIRAddrSpaceCapitalizedNameMap; template <> inline void SPIRVMap::init() { add(SPIRAS_Private, StorageClassFunction); add(SPIRAS_Global, StorageClassCrossWorkgroup); add(SPIRAS_Constant, StorageClassUniformConstant); add(SPIRAS_Local, StorageClassWorkgroup); add(SPIRAS_Generic, StorageClassGeneric); add(SPIRAS_Input, StorageClassInput); } typedef SPIRVMap SPIRSPIRVAddrSpaceMap; // Maps OCL builtin function to SPIRV builtin variable. template <> inline void SPIRVMap::init() { add("read_only", AccessQualifierReadOnly); add("write_only", AccessQualifierWriteOnly); add("read_write", AccessQualifierReadWrite); } typedef SPIRVMap SPIRSPIRVAccessQualifierMap; template <> inline void SPIRVMap::init() { add(Attribute::ZExt, FunctionParameterAttributeZext); add(Attribute::SExt, FunctionParameterAttributeSext); add(Attribute::ByVal, FunctionParameterAttributeByVal); add(Attribute::StructRet, FunctionParameterAttributeSret); add(Attribute::NoAlias, FunctionParameterAttributeNoAlias); add(Attribute::NoCapture, FunctionParameterAttributeNoCapture); } typedef SPIRVMap SPIRSPIRVFuncParamAttrMap; template <> inline void SPIRVMap::init() { add(Attribute::ReadNone, FunctionControlPureMask); add(Attribute::ReadOnly, FunctionControlConstMask); add(Attribute::AlwaysInline, FunctionControlInlineMask); add(Attribute::NoInline, FunctionControlDontInlineMask); } typedef SPIRVMap SPIRSPIRVFuncCtlMaskMap; class SPIRVExtSetShortName; template <> inline void SPIRVMap::init() { add(SPIRVEIS_OpenCL, "ocl"); } typedef SPIRVMap SPIRVExtSetShortNameMap; #define SPIR_MD_COMPILER_OPTIONS "opencl.compiler.options" #define SPIR_MD_KERNEL_ARG_ADDR_SPACE "kernel_arg_addr_space" #define SPIR_MD_KERNEL_ARG_ACCESS_QUAL "kernel_arg_access_qual" #define SPIR_MD_KERNEL_ARG_TYPE "kernel_arg_type" #define SPIR_MD_KERNEL_ARG_BASE_TYPE "kernel_arg_base_type" #define SPIR_MD_KERNEL_ARG_TYPE_QUAL "kernel_arg_type_qual" #define SPIR_MD_KERNEL_ARG_NAME "kernel_arg_name" #define OCL_TYPE_NAME_SAMPLER_T "sampler_t" #define SPIR_TYPE_NAME_EVENT_T "opencl.event_t" #define SPIR_TYPE_NAME_CLK_EVENT_T "opencl.clk_event_t" #define SPIR_TYPE_NAME_BLOCK_T "opencl.block" #define SPIR_INTRINSIC_BLOCK_BIND "spir_block_bind" #define SPIR_INTRINSIC_GET_BLOCK_INVOKE "spir_get_block_invoke" #define SPIR_INTRINSIC_GET_BLOCK_CONTEXT "spir_get_block_context" #define SPIR_TEMP_NAME_PREFIX_BLOCK "block" #define SPIR_TEMP_NAME_PREFIX_CALL "call" namespace kLLVMTypeName { const static char StructPrefix[] = "struct."; } // namespace kLLVMTypeName namespace kSPIRVImageSampledTypeName { const static char Float[] = "float"; const static char Half[] = "half"; const static char Int[] = "int"; const static char UInt[] = "uint"; const static char Void[] = "void"; } // namespace kSPIRVImageSampledTypeName namespace kSPIRVTypeName { const static char Delimiter = '.'; const static char DeviceEvent[] = "DeviceEvent"; const static char Event[] = "Event"; const static char Image[] = "Image"; const static char Pipe[] = "Pipe"; const static char PostfixDelim = '_'; const static char Prefix[] = "spirv"; const static char PrefixAndDelim[] = "spirv."; const static char Queue[] = "Queue"; const static char ReserveId[] = "ReserveId"; const static char SampledImg[] = "SampledImage"; const static char Sampler[] = "Sampler"; const static char ConstantSampler[] = "ConstantSampler"; const static char PipeStorage[] = "PipeStorage"; const static char ConstantPipeStorage[] = "ConstantPipeStorage"; const static char VmeImageINTEL[] = "VmeImageINTEL"; } // namespace kSPIRVTypeName namespace kSPR2TypeName { const static char Delimiter = '.'; const static char OCLPrefix[] = "opencl."; const static char ImagePrefix[] = "opencl.image"; const static char PipeRO[] = "opencl.pipe_ro_t"; const static char PipeWO[] = "opencl.pipe_wo_t"; const static char Sampler[] = "opencl.sampler_t"; const static char Event[] = "opencl.event_t"; } // namespace kSPR2TypeName namespace kAccessQualName { const static char ReadOnly[] = "read_only"; const static char WriteOnly[] = "write_only"; const static char ReadWrite[] = "read_write"; } // namespace kAccessQualName namespace kMangledName { const static char Sampler[] = "11ocl_sampler"; const static char AtomicPrefixIncoming[] = "U7_Atomic"; const static char AtomicPrefixInternal[] = "atomic_"; } // namespace kMangledName namespace kSPIRVName { const static char GroupPrefix[] = "group_"; const static char Prefix[] = "__spirv_"; const static char Postfix[] = "__"; const static char ImageQuerySize[] = "ImageQuerySize"; const static char ImageQuerySizeLod[] = "ImageQuerySizeLod"; const static char ImageSampleExplicitLod[] = "ImageSampleExplicitLod"; const static char ReservedPrefix[] = "reserved_"; const static char SampledImage[] = "SampledImage"; const static char TempSampledImage[] = "TempSampledImage"; const static char TranslateOCLMemOrder[] = "__translate_ocl_memory_order"; const static char TranslateOCLMemScope[] = "__translate_ocl_memory_scope"; const static char TranslateSPIRVMemOrder[] = "__translate_spirv_memory_order"; const static char TranslateSPIRVMemScope[] = "__translate_spirv_memory_scope"; const static char TranslateSPIRVMemFence[] = "__translate_spirv_memory_fence"; } // namespace kSPIRVName namespace kSPIRVPostfix { const static char Sat[] = "sat"; const static char Rtz[] = "rtz"; const static char Rte[] = "rte"; const static char Rtp[] = "rtp"; const static char Rtn[] = "rtn"; const static char Rt[] = "rt"; const static char Return[] = "R"; const static char Divider[] = "_"; /// Divider between extended instruction name and postfix const static char ExtDivider[] = "__"; } // namespace kSPIRVPostfix namespace kSPIRVMD { const static char Capability[] = "spirv.Capability"; const static char EntryPoint[] = "spirv.EntryPoint"; const static char ExecutionMode[] = "spirv.ExecutionMode"; const static char Extension[] = "spirv.Extension"; const static char Generator[] = "spirv.Generator"; const static char Source[] = "spirv.Source"; const static char SourceExtension[] = "spirv.SourceExtension"; const static char MemoryModel[] = "spirv.MemoryModel"; } // namespace kSPIRVMD namespace kSPIR2MD { const static char Extensions[] = "opencl.used.extensions"; const static char FPContract[] = "opencl.enable.FP_CONTRACT"; const static char OCLVer[] = "opencl.ocl.version"; const static char OptFeatures[] = "opencl.used.optional.core.features"; const static char SPIRVer[] = "opencl.spir.version"; const static char VecTyHint[] = "vec_type_hint"; const static char WGSize[] = "reqd_work_group_size"; const static char WGSizeHint[] = "work_group_size_hint"; const static char SubgroupSize[] = "intel_reqd_sub_group_size"; const static char MaxWGSize[] = "max_work_group_size"; const static char MaxWGDim[] = "max_global_work_dim"; const static char NumSIMD[] = "num_simd_work_items"; } // namespace kSPIR2MD enum Spir2SamplerKind { CLK_ADDRESS_NONE = 0x0000, CLK_ADDRESS_CLAMP = 0x0004, CLK_ADDRESS_CLAMP_TO_EDGE = 0x0002, CLK_ADDRESS_REPEAT = 0x0006, CLK_ADDRESS_MIRRORED_REPEAT = 0x0008, CLK_NORMALIZED_COORDS_FALSE = 0x0000, CLK_NORMALIZED_COORDS_TRUE = 0x0001, CLK_FILTER_NEAREST = 0x0010, CLK_FILTER_LINEAR = 0x0020, }; /// Additional information for mangling a function argument type. struct BuiltinArgTypeMangleInfo { bool IsSigned; bool IsVoidPtr; bool IsEnum; bool IsSampler; bool IsAtomic; bool IsLocalArgBlock; SPIR::TypePrimitiveEnum Enum; unsigned Attr; BuiltinArgTypeMangleInfo() : IsSigned(true), IsVoidPtr(false), IsEnum(false), IsSampler(false), IsAtomic(false), IsLocalArgBlock(false), Enum(SPIR::PRIMITIVE_NONE), Attr(0) {} }; /// Information for mangling builtin function. class BuiltinFuncMangleInfo { public: /// Translate builtin function name and set /// argument attributes and unsigned args. BuiltinFuncMangleInfo(const std::string &UniqName = "") : LocalArgBlockIdx(-1), VarArgIdx(-1) { if (!UniqName.empty()) init(UniqName); } virtual ~BuiltinFuncMangleInfo() {} const std::string &getUnmangledName() const { return UnmangledName; } void addUnsignedArg(int Ndx) { UnsignedArgs.insert(Ndx); } void addUnsignedArgs(int StartNdx, int StopNdx) { assert(StartNdx < StopNdx && "wrong parameters"); for (int I = StartNdx; I <= StopNdx; ++I) addUnsignedArg(I); } void addVoidPtrArg(int Ndx) { VoidPtrArgs.insert(Ndx); } void addSamplerArg(int Ndx) { SamplerArgs.insert(Ndx); } void addAtomicArg(int Ndx) { AtomicArgs.insert(Ndx); } void setLocalArgBlock(int Ndx) { assert(0 <= Ndx && "it is not allowed to set less than zero index"); LocalArgBlockIdx = Ndx; } void setEnumArg(int Ndx, SPIR::TypePrimitiveEnum Enum) { EnumArgs[Ndx] = Enum; } void setArgAttr(int Ndx, unsigned Attr) { Attrs[Ndx] = Attr; } void setVarArg(int Ndx) { assert(0 <= Ndx && "it is not allowed to set less than zero index"); VarArgIdx = Ndx; } bool isArgUnsigned(int Ndx) { return UnsignedArgs.count(-1) || UnsignedArgs.count(Ndx); } bool isArgVoidPtr(int Ndx) { return VoidPtrArgs.count(-1) || VoidPtrArgs.count(Ndx); } bool isArgSampler(int Ndx) { return SamplerArgs.count(Ndx); } bool isArgAtomic(int Ndx) { return AtomicArgs.count(Ndx); } bool isLocalArgBlock(int Ndx) { return LocalArgBlockIdx == Ndx; } bool isArgEnum(int Ndx, SPIR::TypePrimitiveEnum *Enum = nullptr) { auto Loc = EnumArgs.find(Ndx); if (Loc == EnumArgs.end()) Loc = EnumArgs.find(-1); if (Loc == EnumArgs.end()) return false; if (Enum) *Enum = Loc->second; return true; } unsigned getArgAttr(int Ndx) { auto Loc = Attrs.find(Ndx); if (Loc == Attrs.end()) Loc = Attrs.find(-1); if (Loc == Attrs.end()) return 0; return Loc->second; } // get ellipsis index, single ellipsis at the end of the function is possible // only return value < 0 if none int getVarArg() const { return VarArgIdx; } BuiltinArgTypeMangleInfo getTypeMangleInfo(int Ndx) { BuiltinArgTypeMangleInfo Info; Info.IsSigned = !isArgUnsigned(Ndx); Info.IsVoidPtr = isArgVoidPtr(Ndx); Info.IsEnum = isArgEnum(Ndx, &Info.Enum); Info.IsSampler = isArgSampler(Ndx); Info.IsAtomic = isArgAtomic(Ndx); Info.IsLocalArgBlock = isLocalArgBlock(Ndx); Info.Attr = getArgAttr(Ndx); return Info; } virtual void init(const std::string &UniqUnmangledName) { UnmangledName = UniqUnmangledName; } protected: std::string UnmangledName; std::set UnsignedArgs; // unsigned arguments, or -1 if all are unsigned std::set VoidPtrArgs; // void pointer arguments, or -1 if all are void // pointer std::set SamplerArgs; // sampler arguments std::set AtomicArgs; // atomic arguments std::map EnumArgs; // enum arguments std::map Attrs; // argument attributes int LocalArgBlockIdx; // index of a block with local arguments, idx < 0 if // none int VarArgIdx; // index of ellipsis argument, idx < 0 if none }; /// \returns a vector of types for a collection of values. template std::vector getTypes(T V) { std::vector Tys; for (auto &I : V) Tys.push_back(I->getType()); return Tys; } /// Move elements of std::vector from [begin, end) to target. template void move(std::vector &V, size_t Begin, size_t End, size_t Target) { assert(Begin < End && End <= V.size() && Target <= V.size() && !(Begin < Target && Target < End)); if (Begin <= Target && Target <= End) return; auto B = V.begin() + Begin, E = V.begin() + End; if (Target > V.size()) Target = V.size(); if (Target > End) Target -= (End - Begin); std::vector Segment(B, E); V.erase(B, E); V.insert(V.begin() + Target, Segment.begin(), Segment.end()); } /// Find position of first pointer type value in a vector. inline size_t findFirstPtr(const std::vector &Args) { auto PtArg = std::find_if(Args.begin(), Args.end(), [](Value *V) { return V->getType()->isPointerTy(); }); return PtArg - Args.begin(); } bool isSupportedTriple(Triple T); void removeFnAttr(CallInst *Call, Attribute::AttrKind Attr); void addFnAttr(CallInst *Call, Attribute::AttrKind Attr); void saveLLVMModule(Module *M, const std::string &OutputFile); std::string mapSPIRVTypeToOCLType(SPIRVType *Ty, bool Signed); std::string mapLLVMTypeToOCLType(const Type *Ty, bool Signed); SPIRVDecorate *mapPostfixToDecorate(StringRef Postfix, SPIRVEntry *Target); /// Add decorations to a SPIR-V entry. /// \param Decs Each string is a postfix without _ at the beginning. SPIRVValue *addDecorations(SPIRVValue *Target, const SmallVectorImpl &Decs); PointerType *getOrCreateOpaquePtrType(Module *M, const std::string &Name, unsigned AddrSpace = SPIRAS_Global); PointerType *getSamplerType(Module *M); PointerType *getPipeStorageType(Module *M); void getFunctionTypeParameterTypes(llvm::FunctionType *FT, std::vector &ArgTys); Function *getOrCreateFunction(Module *M, Type *RetTy, ArrayRef ArgTypes, StringRef Name, BuiltinFuncMangleInfo *Mangle = nullptr, AttributeList *Attrs = nullptr, bool TakeName = true); PointerType *getOCLClkEventType(Module *M); PointerType *getOCLClkEventPtrType(Module *M); Constant *getOCLNullClkEventPtr(Module *M); /// Get function call arguments. /// \param Start Starting index. /// \param End Ending index. std::vector getArguments(CallInst *CI, unsigned Start = 0, unsigned End = 0); /// Get constant function call argument as an integer. /// \param I argument index. uint64_t getArgAsInt(CallInst *CI, unsigned I); /// Get constant function call argument as type \param T. /// \param I argument index. template T getArgAs(CallInst *CI, unsigned I) { return static_cast(getArgAsInt(CI, I)); } /// Get constant function call argument as a Scope enum. /// \param I argument index. Scope getArgAsScope(CallInst *CI, unsigned I); /// Get constant function call argument as a Decoration enum. /// \param I argument index. Decoration getArgAsDecoration(CallInst *CI, unsigned I); bool isPointerToOpaqueStructType(llvm::Type *Ty); bool isPointerToOpaqueStructType(llvm::Type *Ty, const std::string &Name); /// Check if a type is OCL image type. /// \return type name without "opencl." prefix. bool isOCLImageType(llvm::Type *Ty, StringRef *Name = nullptr); /// \param BaseTyName is the type name as in spirv.BaseTyName.Postfixes /// \param Postfix contains postfixes extracted from the SPIR-V image /// type name as spirv.BaseTyName.Postfixes. bool isSPIRVType(llvm::Type *Ty, StringRef BaseTyName, StringRef *Postfix = 0); /// Decorate a function name as __spirv_{Name}_ std::string decorateSPIRVFunction(const std::string &S); /// Remove prefix/postfix from __spirv_{Name}_ std::string undecorateSPIRVFunction(const std::string &S); /// Check if a function has decorated name as __spirv_{Name}_ /// and get the original name. bool isDecoratedSPIRVFunc(const Function *F, std::string *UndecName = nullptr); /// Get a canonical function name for a SPIR-V op code. std::string getSPIRVFuncName(Op OC, StringRef PostFix = ""); std::string getSPIRVFuncName(Op OC, const Type *PRetTy, bool IsSigned = false); /// Get a canonical function name for a SPIR-V extended instruction std::string getSPIRVExtFuncName(SPIRVExtInstSetKind Set, unsigned ExtOp, StringRef PostFix = ""); /// Get SPIR-V op code given the canonical function name. /// Assume \param Name is either IA64 mangled or unmangled, and the unmangled /// name takes the __spirv_{OpName}_{Postfixes} format. /// \return op code if the unmangled function name is a valid op code name, /// otherwise return OpNop. /// \param Dec contains decorations decoded from function name if it is /// not nullptr. Op getSPIRVFuncOC(const std::string &Name, SmallVectorImpl *Dec = nullptr); /// Get SPIR-V builtin variable enum given the canonical builtin name /// Assume \param Name is in format __spirv_BuiltIn{Name} /// \return false if \param Name is not a valid builtin name. bool getSPIRVBuiltin(const std::string &Name, spv::BuiltIn &Builtin); /// \param Name LLVM function name /// \param DemangledName demanged name of the OpenCL built-in function /// \returns true if Name is the name of the OpenCL built-in function, /// false for other functions bool oclIsBuiltin(const StringRef &Name, std::string *DemangledName = nullptr, bool IsCpp = false); /// Check if a function type is void(void). bool isVoidFuncTy(FunctionType *FT); /// \returns true if \p T is a function pointer type. bool isFunctionPointerType(Type *T); /// \returns true if function \p F has function pointer type argument. /// \param AI points to the function pointer type argument if returns true. bool hasFunctionPointerArg(Function *F, Function::arg_iterator &AI); /// \returns true if function \p F has array type argument. bool hasArrayArg(Function *F); /// Mutates function call instruction by changing the arguments. /// \param ArgMutate mutates the function arguments. /// \return mutated call instruction. CallInst *mutateCallInst( Module *M, CallInst *CI, std::function &)> ArgMutate, BuiltinFuncMangleInfo *Mangle = nullptr, AttributeList *Attrs = nullptr, bool TakeName = false); /// Mutates function call instruction by changing the arguments and return /// value. /// \param ArgMutate mutates the function arguments. /// \param RetMutate mutates the return value. /// \return mutated instruction. Instruction *mutateCallInst( Module *M, CallInst *CI, std::function &, Type *&RetTy)> ArgMutate, std::function RetMutate, BuiltinFuncMangleInfo *Mangle = nullptr, AttributeList *Attrs = nullptr, bool TakeName = false); /// Mutate call instruction to call SPIR-V builtin function. CallInst *mutateCallInstSPIRV( Module *M, CallInst *CI, std::function &)> ArgMutate, AttributeList *Attrs = nullptr); /// Mutate call instruction to call SPIR-V builtin function. Instruction *mutateCallInstSPIRV( Module *M, CallInst *CI, std::function &, Type *&RetTy)> ArgMutate, std::function RetMutate, AttributeList *Attrs = nullptr); /// Mutate function by change the arguments. /// \param ArgMutate mutates the function arguments. /// \param TakeName Take the original function's name if a new function with /// different type needs to be created. void mutateFunction( Function *F, std::function &)> ArgMutate, BuiltinFuncMangleInfo *Mangle = nullptr, AttributeList *Attrs = nullptr, bool TakeName = true); /// Add a call instruction at \p Pos. CallInst *addCallInst(Module *M, StringRef FuncName, Type *RetTy, ArrayRef Args, AttributeList *Attrs, Instruction *Pos, BuiltinFuncMangleInfo *Mangle = nullptr, StringRef InstName = SPIR_TEMP_NAME_PREFIX_CALL, bool TakeFuncName = true); /// Add a call instruction for SPIR-V builtin function. CallInst *addCallInstSPIRV(Module *M, StringRef FuncName, Type *RetTy, ArrayRef Args, AttributeList *Attrs, Instruction *Pos, StringRef InstName); /// Add a call of spir_block_bind function. CallInst *addBlockBind(Module *M, Function *InvokeFunc, Value *BlkCtx, Value *CtxLen, Value *CtxAlign, Instruction *InsPos, StringRef InstName = SPIR_TEMP_NAME_PREFIX_BLOCK); typedef std::pair::iterator, std::vector::iterator> ValueVecRange; /// Add a vector at \param InsPos. Value *addVector(Instruction *InsPos, ValueVecRange Range); /// Replace scalar values with a vector created at \param InsPos. void makeVector(Instruction *InsPos, std::vector &Ops, ValueVecRange Range); /// Expand a vector type value in \param Ops at index \param VecPos. /// Generate extract element instructions at \param InsPos and replace /// the vector type value with scalar type values. /// If the value to be expanded is not vector type, do nothing. void expandVector(Instruction *InsPos, std::vector &Ops, size_t VecPos); /// Get size_t type. IntegerType *getSizetType(Module *M); /// Get void(void) function type. Type *getVoidFuncType(Module *M); /// Get void(void) function pointer type. Type *getVoidFuncPtrType(Module *M, unsigned AddrSpace = 0); /// Get a 64 bit integer constant. ConstantInt *getInt64(Module *M, int64_t Value); /// Get a 32 bit integer constant. ConstantInt *getInt32(Module *M, int Value); /// Get a 32 bit unsigned integer constant. ConstantInt *getUInt32(Module *M, unsigned Value); /// Get 32 bit integer constant if the value fits in 32 bits, /// return 64 bit integer constant otherwise ConstantInt *getInt(Module *M, int64_t Value); /// Get 32 bit unsigned integer constant if the value fits in 32 bits, /// return 64 bit unsigned integer constant otherwise ConstantInt *getUInt(Module *M, uint64_t Value); /// Get a 16 bit unsigned integer constant. ConstantInt *getUInt16(Module *M, unsigned short Value); // Get a 32 bit floating point constant. Constant *getFloat32(Module *M, float Value); /// Get a 32 bit integer constant vector. std::vector getInt32(Module *M, const std::vector &Value); /// Get a size_t type constant. ConstantInt *getSizet(Module *M, uint64_t Value); /// Get metadata operand as int. int getMDOperandAsInt(MDNode *N, unsigned I); /// Get metadata operand as string. std::string getMDOperandAsString(MDNode *N, unsigned I); /// Get metadata operand as another metadata node MDNode *getMDOperandAsMDNode(MDNode *N, unsigned I); /// Get metadata operand as type. Type *getMDOperandAsType(MDNode *N, unsigned I); /// Get a named metadata as a set of string. /// Assume the named metadata has one or more operands each of which might /// contain set of strings. For instance: /// !opencl.used.optional.core.features = !{!0} /// !0 = !{!"cl_doubles", !"cl_images"} /// or if we linked two modules we may have /// !opencl.used.optional.core.features = !{!0, !1} /// !0 = !{!"cl_doubles"} /// !1 = !{!"cl_images"} std::set getNamedMDAsStringSet(Module *M, const std::string &MDName); /// Get SPIR-V language by SPIR-V metadata spirv.Source std::tuple getSPIRVSource(Module *M); /// Map an unsigned integer constant by applying a function. ConstantInt *mapUInt(Module *M, ConstantInt *I, std::function F); /// Map a signed integer constant by applying a function. ConstantInt *mapSInt(Module *M, ConstantInt *I, std::function F); /// Get postfix for given decoration. /// The returned postfix does not include "_" at the beginning. std::string getPostfix(Decoration Dec, unsigned Value = 0); /// Get postfix _R{ReturnType} for return type /// The returned postfix does not includ "_" at the beginning std::string getPostfixForReturnType(CallInst *CI, bool IsSigned = false); std::string getPostfixForReturnType(const Type *PRetTy, bool IsSigned = false); Constant *getScalarOrVectorConstantInt(Type *T, uint64_t V, bool IsSigned = false); /// Get a constant int or a constant int array. /// \param T is the type of the constant. It should be an integer type or // an integer pointer type. /// \param Len is the length of the array. /// \param V is the value to fill the array. Value *getScalarOrArrayConstantInt(Instruction *P, Type *T, unsigned Len, uint64_t V, bool IsSigned = false); /// Get the array from GEP. /// \param V is a GEP whose pointer operand is a pointer to an array of size /// \param Size. Value *getScalarOrArray(Value *V, unsigned Size, Instruction *Pos); void dumpUsers(Value *V, StringRef Prompt = ""); /// Get SPIR-V type name as spirv.BaseTyName.Postfixes. std::string getSPIRVTypeName(StringRef BaseTyName, StringRef Postfixes = ""); /// Checks if given type name is either ConstantSampler or ConsantPipeStorage. bool isSPIRVConstantName(StringRef TyName); /// Get SPIR-V type by changing the type name from spirv.OldName.Postfixes /// to spirv.NewName.Postfixes. Type *getSPIRVTypeByChangeBaseTypeName(Module *M, Type *T, StringRef OldName, StringRef NewName); /// Get the postfixes of SPIR-V image type name as in spirv.Image.postfixes. std::string getSPIRVImageTypePostfixes(StringRef SampledType, SPIRVTypeImageDescriptor Desc, SPIRVAccessQualifierKind Acc); /// Get the sampled type name used in postfix of image type in SPIR-V /// friendly LLVM IR. std::string getSPIRVImageSampledTypeName(SPIRVType *Ty); /// Translates OpenCL image type names to SPIR-V. /// E.g. %opencl.image1d_rw_t -> %spirv.Image._void_0_0_0_0_0_0_2 Type *getSPIRVImageTypeFromOCL(Module *M, Type *T); /// Get LLVM type for sampled type of SPIR-V image type by postfix. Type *getLLVMTypeForSPIRVImageSampledTypePostfix(StringRef Postfix, LLVMContext &Ctx); /// Return the unqualified and unsuffixed base name of an image type. /// E.g. opencl.image2d_ro_t.3 -> image2d_t std::string getImageBaseTypeName(StringRef Name); /// Map OpenCL opaque type name to SPIR-V type name. std::string mapOCLTypeNameToSPIRV(StringRef Name, StringRef Acc = ""); /// Check if access qualifier is encoded in the type name. bool hasAccessQualifiedName(StringRef TyName); /// Get access qualifier from the type name. StringRef getAccessQualifier(StringRef TyName); bool eraseUselessFunctions(Module *M); /// Erase a function if it is declaration, has internal linkage and has no use. bool eraseIfNoUse(Function *F); void eraseIfNoUse(Value *V); // Check if a mangled type name is unsigned bool isMangledTypeUnsigned(char Mangled); // Check if a mangled type name is signed bool isMangledTypeSigned(char Mangled); // Check if a mangled type name is floating point (except half) bool isMangledTypeFP(char Mangled); // Check if a mangled type name is half bool isMangledTypeHalf(std::string Mangled); // Check if \param I is valid vector size: 2, 3, 4, 8, 16. bool isValidVectorSize(unsigned I); enum class ParamType { FLOAT = 0, SIGNED = 1, UNSIGNED = 2, UNKNOWN = 3 }; ParamType lastFuncParamType(const std::string &MangledName); // Check if the last function parameter is signed bool isLastFuncParamSigned(const std::string &MangledName); // Check if a mangled function name contains unsigned atomic type bool containsUnsignedAtomicType(StringRef Name); /// Mangle builtin function name. /// \return \param UniqName if \param BtnInfo is null pointer, otherwise /// return IA64 mangled name. std::string mangleBuiltin(const std::string &UniqName, ArrayRef ArgTypes, BuiltinFuncMangleInfo *BtnInfo); /// Remove cast from a value. Value *removeCast(Value *V); /// Cast a function to a void(void) funtion pointer. Constant *castToVoidFuncPtr(Function *F); /// Get i8* with the same address space. PointerType *getInt8PtrTy(PointerType *T); /// Cast a value to a i8* by inserting a cast instruction. Value *castToInt8Ptr(Value *V, Instruction *Pos); template <> inline void SPIRVMap::init() { add(kSPIRVTypeName::DeviceEvent, OpTypeDeviceEvent); add(kSPIRVTypeName::Event, OpTypeEvent); add(kSPIRVTypeName::Image, OpTypeImage); add(kSPIRVTypeName::Pipe, OpTypePipe); add(kSPIRVTypeName::Queue, OpTypeQueue); add(kSPIRVTypeName::ReserveId, OpTypeReserveId); add(kSPIRVTypeName::Sampler, OpTypeSampler); add(kSPIRVTypeName::SampledImg, OpTypeSampledImage); } // Check if the module contains llvm.loop.* metadata bool hasLoopMetadata(const Module *M); } // namespace SPIRV #endif // SPIRV_SPIRVINTERNAL_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVLowerBool.cpp000066400000000000000000000116041363521741200223050ustar00rootroot00000000000000//===- SPIRVLowerBool.cpp - Lower instructions with bool operands ---------===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// // // This file implements lowering instructions with bool operands. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "spvbool" #include "SPIRVInternal.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstVisitor.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Verifier.h" #include "llvm/Pass.h" #include "llvm/PassSupport.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" using namespace llvm; using namespace SPIRV; namespace SPIRV { cl::opt SPIRVLowerBoolValidate( "spvbool-validate", cl::desc("Validate module after lowering boolean instructions for SPIR-V")); class SPIRVLowerBool : public ModulePass, public InstVisitor { public: SPIRVLowerBool() : ModulePass(ID), Context(nullptr) { initializeSPIRVLowerBoolPass(*PassRegistry::getPassRegistry()); } void replace(Instruction *I, Instruction *NewI) { NewI->takeName(I); I->replaceAllUsesWith(NewI); I->dropAllReferences(); I->eraseFromParent(); } bool isBoolType(Type *Ty) { if (Ty->isIntegerTy(1)) return true; if (auto VT = dyn_cast(Ty)) return isBoolType(VT->getElementType()); return false; } virtual void visitTruncInst(TruncInst &I) { if (isBoolType(I.getType())) { auto Op = I.getOperand(0); auto Zero = getScalarOrVectorConstantInt(Op->getType(), 0, false); auto Cmp = new ICmpInst(&I, CmpInst::ICMP_NE, Op, Zero); replace(&I, Cmp); } } virtual void visitZExtInst(ZExtInst &I) { auto Op = I.getOperand(0); if (isBoolType(Op->getType())) { auto Ty = I.getType(); auto Zero = getScalarOrVectorConstantInt(Ty, 0, false); auto One = getScalarOrVectorConstantInt(Ty, 1, false); assert(Zero && One && "Couldn't create constant int"); auto Sel = SelectInst::Create(Op, One, Zero, "", &I); replace(&I, Sel); } } virtual void visitSExtInst(SExtInst &I) { auto Op = I.getOperand(0); if (isBoolType(Op->getType())) { auto Ty = I.getType(); auto Zero = getScalarOrVectorConstantInt(Ty, 0, false); auto One = getScalarOrVectorConstantInt(Ty, ~0, false); assert(Zero && One && "Couldn't create constant int"); auto Sel = SelectInst::Create(Op, One, Zero, "", &I); replace(&I, Sel); } } bool runOnModule(Module &M) override { Context = &M.getContext(); visit(M); if (SPIRVLowerBoolValidate) { LLVM_DEBUG(dbgs() << "After SPIRVLowerBool:\n" << M); std::string Err; raw_string_ostream ErrorOS(Err); if (verifyModule(M, &ErrorOS)) { Err = std::string("Fails to verify module: ") + Err; report_fatal_error(Err.c_str(), false); } } return true; } static char ID; private: LLVMContext *Context; }; char SPIRVLowerBool::ID = 0; } // namespace SPIRV INITIALIZE_PASS(SPIRVLowerBool, "spvbool", "Lower instructions with bool operands", false, false) ModulePass *llvm::createSPIRVLowerBool() { return new SPIRVLowerBool(); } SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVLowerConstExpr.cpp000066400000000000000000000134531363521741200233430ustar00rootroot00000000000000//===- SPIRVLowerConstExpr.cpp - Regularize LLVM for SPIR-V ------- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// // // This file implements regularization of LLVM moduel for SPIR-V. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "spv-lower-const-expr" #include "OCLUtil.h" #include "SPIRVInternal.h" #include "SPIRVMDBuilder.h" #include "SPIRVMDWalker.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstVisitor.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Verifier.h" #include "llvm/Pass.h" #include "llvm/PassSupport.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include #include using namespace llvm; using namespace SPIRV; using namespace OCLUtil; namespace SPIRV { cl::opt SPIRVLowerConst( "spirv-lower-const-expr", cl::init(true), cl::desc("LLVM/SPIR-V translation enable lowering constant expression")); class SPIRVLowerConstExpr : public ModulePass { public: SPIRVLowerConstExpr() : ModulePass(ID), M(nullptr), Ctx(nullptr) { initializeSPIRVLowerConstExprPass(*PassRegistry::getPassRegistry()); } bool runOnModule(Module &M) override; void visit(Module *M); static char ID; private: Module *M; LLVMContext *Ctx; }; char SPIRVLowerConstExpr::ID = 0; bool SPIRVLowerConstExpr::runOnModule(Module &Module) { if (!SPIRVLowerConst) return false; M = &Module; Ctx = &M->getContext(); LLVM_DEBUG(dbgs() << "Enter SPIRVLowerConstExpr:\n"); visit(M); LLVM_DEBUG(dbgs() << "After SPIRVLowerConstExpr:\n" << *M); std::string Err; raw_string_ostream ErrorOS(Err); if (verifyModule(*M, &ErrorOS)) { LLVM_DEBUG(errs() << "Fails to verify module: " << ErrorOS.str()); } return true; } /// Since SPIR-V cannot represent constant expression, constant expressions /// in LLVM needs to be lowered to instructions. /// For each function, the constant expressions used by instructions of the /// function are replaced by instructions placed in the entry block since it /// dominates all other BB's. Each constant expression only needs to be lowered /// once in each function and all uses of it by instructions in that function /// is replaced by one instruction. /// ToDo: remove redundant instructions for common subexpression void SPIRVLowerConstExpr::visit(Module *M) { for (auto &I : M->functions()) { std::map CMap; std::list WorkList; for (auto &BI : I) { for (auto &II : BI) { WorkList.push_back(&II); } } auto FBegin = I.begin(); while (!WorkList.empty()) { auto II = WorkList.front(); WorkList.pop_front(); for (unsigned OI = 0, OE = II->getNumOperands(); OI != OE; ++OI) { auto Op = II->getOperand(OI); if (auto CE = dyn_cast(Op)) { SPIRVDBG(dbgs() << "[lowerConstantExpressions] " << *CE;) auto ReplInst = CE->getAsInstruction(); auto InsPoint = II->getParent() == &*FBegin ? II : &FBegin->back(); ReplInst->insertBefore(InsPoint); SPIRVDBG(dbgs() << " -> " << *ReplInst << '\n';) WorkList.push_front(ReplInst); std::vector Users; // Do not replace use during iteration of use. Do it in another loop for (auto U : CE->users()) { SPIRVDBG(dbgs() << "[lowerConstantExpressions] Use: " << *U << '\n';) if (auto InstUser = dyn_cast(U)) { // Only replace users in scope of current function if (InstUser->getParent()->getParent() == &I) Users.push_back(InstUser); } } for (auto &User : Users) User->replaceUsesOfWith(CE, ReplInst); } } } } } } // namespace SPIRV INITIALIZE_PASS(SPIRVLowerConstExpr, "spv-lower-const-expr", "Regularize LLVM for SPIR-V", false, false) ModulePass *llvm::createSPIRVLowerConstExpr() { return new SPIRVLowerConstExpr(); } SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVLowerMemmove.cpp000066400000000000000000000126761363521741200230310ustar00rootroot00000000000000//===- SPIRVLowerMemmove.cpp - Lower llvm.memmove to llvm.memcpys ---------===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// // // This file implements lowering llvm.memmove into several llvm.memcpys. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "spvmemmove" #include "SPIRVInternal.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstVisitor.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" #include "llvm/Pass.h" #include "llvm/PassSupport.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" using namespace llvm; using namespace SPIRV; namespace SPIRV { cl::opt SPIRVLowerMemmoveValidate( "spvmemmove-validate", cl::desc("Validate module after lowering llvm.memmove instructions into " "llvm.memcpy")); class SPIRVLowerMemmove : public ModulePass, public InstVisitor { public: SPIRVLowerMemmove() : ModulePass(ID), Context(nullptr) { initializeSPIRVLowerMemmovePass(*PassRegistry::getPassRegistry()); } virtual void visitMemMoveInst(MemMoveInst &I) { IRBuilder<> Builder(I.getParent()); Builder.SetInsertPoint(&I); auto *Dest = I.getRawDest(); auto *Src = I.getRawSource(); auto *SrcTy = Src->getType(); if (!isa(I.getLength())) // ToDo: for non-constant length, could use a loop to copy a // fixed length chunk at a time. For now simply fail report_fatal_error("llvm.memmove of non-constant length not supported", false); auto *Length = cast(I.getLength()); if (isa(Src)) // The source could be bit-cast from another type, // need the original type for the allocation of the temporary variable SrcTy = cast(Src)->getOperand(0)->getType(); MaybeAlign Align = I.getSourceAlign(); auto Volatile = I.isVolatile(); Value *NumElements = nullptr; uint64_t ElementsCount = 1; if (SrcTy->isArrayTy()) { NumElements = Builder.getInt32(SrcTy->getArrayNumElements()); ElementsCount = SrcTy->getArrayNumElements(); } if (Mod->getDataLayout().getTypeSizeInBits(SrcTy->getPointerElementType()) * ElementsCount != Length->getZExtValue() * 8) report_fatal_error("Size of the memcpy should match the allocated memory", false); auto *Alloca = Builder.CreateAlloca(SrcTy->getPointerElementType(), NumElements); Alloca->setAlignment(Align); Builder.CreateLifetimeStart(Alloca); Builder.CreateMemCpy(Alloca, Align, Src, Align, Length, Volatile); auto *SecondCpy = Builder.CreateMemCpy(Dest, I.getDestAlign(), Alloca, Align, Length, Volatile); Builder.CreateLifetimeEnd(Alloca); SecondCpy->takeName(&I); I.replaceAllUsesWith(SecondCpy); I.dropAllReferences(); I.eraseFromParent(); } bool runOnModule(Module &M) override { Context = &M.getContext(); Mod = &M; visit(M); if (SPIRVLowerMemmoveValidate) { LLVM_DEBUG(dbgs() << "After SPIRVLowerMemmove:\n" << M); std::string Err; raw_string_ostream ErrorOS(Err); if (verifyModule(M, &ErrorOS)) { Err = std::string("Fails to verify module: ") + Err; report_fatal_error(Err.c_str(), false); } } return true; } static char ID; private: LLVMContext *Context; Module *Mod; }; char SPIRVLowerMemmove::ID = 0; } // namespace SPIRV INITIALIZE_PASS(SPIRVLowerMemmove, "spvmemmove", "Lower llvm.memmove into llvm.memcpy", false, false) ModulePass *llvm::createSPIRVLowerMemmove() { return new SPIRVLowerMemmove(); } SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVLowerOCLBlocks.cpp000066400000000000000000000102771363521741200231720ustar00rootroot00000000000000//===- SPIRVLowerOCLBlocks.cpp - OCL Utilities ----------------------------===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2018 Intel Corporation. All rights reserved. // // 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 Intel Corporation, 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. // //===----------------------------------------------------------------------===// // // SPIR-V specification doesn't allow function pointers, so SPIR-V translator // is designed to fail if a value with function type (except calls) is occured. // Currently there is only two cases, when function pointers are generating in // LLVM IR in OpenCL - block calls and device side enqueue built-in calls. // // In both cases values with function type used as intermediate representation // for block literal structure. // // In LLVM IR produced by clang, blocks are represented with the following // structure: // %struct.__opencl_block_literal_generic = type { i32, i32, i8 addrspace(4)* } // Pointers to block invoke functions are stored in the third field. Clang // replaces inderect function calls in all cases except if block is passed as a // function argument. Note that it is somewhat unclear if the OpenCL C spec // should allow passing blocks as function argumernts. This pass is not supposed // to work correctly with such functions. // Clang though has to store function pointers to this structure. Purpose of // this pass is to replace store of function pointers(not allowed in SPIR-V) // with null pointers. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "spv-lower-ocl-blocks" #include "SPIRVInternal.h" #include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/Support/Regex.h" using namespace llvm; namespace { static bool isBlockInvoke(Function &F) { static Regex BlockInvokeRegex("_block_invoke_?[0-9]*$"); return BlockInvokeRegex.match(F.getName()); } class SPIRVLowerOCLBlocks : public ModulePass { public: SPIRVLowerOCLBlocks() : ModulePass(ID) {} bool runOnModule(Module &M) { bool Changed = false; for (Function &F : M) { if (!isBlockInvoke(F)) continue; for (User *U : F.users()) { if (!isa(U)) continue; Constant *Null = Constant::getNullValue(U->getType()); if (U != Null) { U->replaceAllUsesWith(Null); Changed = true; } } } return Changed; } static char ID; }; char SPIRVLowerOCLBlocks::ID = 0; } // namespace INITIALIZE_PASS( SPIRVLowerOCLBlocks, "spv-lower-ocl-blocks", "Remove function pointers occured in case of using OpenCL blocks", false, false) llvm::ModulePass *llvm::createSPIRVLowerOCLBlocks() { return new SPIRVLowerOCLBlocks(); } SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVLowerSPIRBlocks.cpp000066400000000000000000000530351363521741200233310ustar00rootroot00000000000000//===- SPIRVLowerSPIRBlocks.cpp - Lower SPIR 2.0 blocks ---------*- C++ -*-===// // // The LLVM/SPIR-V Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file implements lowering of SPIR 2.0 blocks to functions. /// //===----------------------------------------------------------------------===// #include "OCLUtil.h" #include "SPIRVInternal.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SetVector.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/CallGraph.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/IR/Verifier.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" #include "llvm/PassSupport.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/GlobalStatus.h" #include #include #include #include #include #include #define DEBUG_TYPE "spv-lower-spir-blocks" using namespace llvm; using namespace SPIRV; using namespace OCLUtil; namespace SPIRV { /// Lower SPIR2 blocks to function calls. /// /// SPIR2 representation of blocks: /// /// block = spir_block_bind(bitcast(block_func), context_len, context_align, /// context) /// block_func_ptr = bitcast(spir_get_block_invoke(block)) /// context_ptr = spir_get_block_context(block) /// ret = block_func_ptr(context_ptr, args) /// /// Propagates block_func to each spir_get_block_invoke through def-use chain of /// spir_block_bind, so that /// ret = block_func(context, args) class SPIRVLowerSPIRBlocks : public ModulePass { public: SPIRVLowerSPIRBlocks() : ModulePass(ID), M(nullptr) { initializeSPIRVLowerSPIRBlocksPass(*PassRegistry::getPassRegistry()); } void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired(); AU.addRequired(); AU.addRequired(); } bool runOnModule(Module &Module) override { M = &Module; if (!lowerBlockBind()) { // There are no SPIR2 blocks in the module. return false; } lowerGetBlockInvoke(); lowerGetBlockContext(); eraseUselessGlobalVars(); eliminateDeadArgs(); erase(M->getFunction(SPIR_INTRINSIC_GET_BLOCK_INVOKE)); erase(M->getFunction(SPIR_INTRINSIC_GET_BLOCK_CONTEXT)); erase(M->getFunction(SPIR_INTRINSIC_BLOCK_BIND)); LLVM_DEBUG(dbgs() << "------- After OCLLowerBlocks ------------\n" << *M << '\n'); return true; } static char ID; private: const static int MaxIter = 1000; Module *M; bool lowerBlockBind() { auto F = M->getFunction(SPIR_INTRINSIC_BLOCK_BIND); if (!F) return false; int Iter = MaxIter; while (lowerBlockBind(F) && Iter > 0) { Iter--; LLVM_DEBUG(dbgs() << "-------------- after iteration " << MaxIter - Iter << " --------------\n" << *M << '\n'); } assert(Iter > 0 && "Too many iterations"); return true; } bool eraseUselessFunctions() { bool Changed = false; for (auto I = M->begin(), E = M->end(); I != E;) { Function *F = &(*I++); if (!GlobalValue::isInternalLinkage(F->getLinkage()) && !F->isDeclaration()) continue; dumpUsers(F, "[eraseUselessFunctions] "); for (auto UI = F->user_begin(), UE = F->user_end(); UI != UE;) { auto U = *UI++; if (auto CE = dyn_cast(U)) { if (CE->use_empty()) { CE->dropAllReferences(); Changed = true; } } } if (!F->use_empty()) { continue; } auto &CG = getAnalysis().getCallGraph(); CallGraphNode *CGN = CG[F]; if (CGN->getNumReferences() != 0) { continue; } erase(F); Changed = true; } return Changed; } void lowerGetBlockInvoke() { if (auto F = M->getFunction(SPIR_INTRINSIC_GET_BLOCK_INVOKE)) { for (auto UI = F->user_begin(), UE = F->user_end(); UI != UE;) { auto CI = dyn_cast(*UI++); assert(CI && "Invalid usage of spir_get_block_invoke"); lowerGetBlockInvoke(CI); } } } void lowerGetBlockContext() { if (auto F = M->getFunction(SPIR_INTRINSIC_GET_BLOCK_CONTEXT)) { for (auto UI = F->user_begin(), UE = F->user_end(); UI != UE;) { auto CI = dyn_cast(*UI++); assert(CI && "Invalid usage of spir_get_block_context"); lowerGetBlockContext(CI); } } } /// Lower calls of spir_block_bind. /// Return true if the Module is changed. bool lowerBlockBind(Function *BlockBindFunc) { bool Changed = false; for (auto I = BlockBindFunc->user_begin(), E = BlockBindFunc->user_end(); I != E;) { LLVM_DEBUG(dbgs() << "[lowerBlockBind] " << **I << '\n'); // Handle spir_block_bind(bitcast(block_func), context_len, // context_align, context) auto CallBlkBind = cast(*I++); Function *InvF = nullptr; Value *Ctx = nullptr; Value *CtxLen = nullptr; Value *CtxAlign = nullptr; getBlockInvokeFuncAndContext(CallBlkBind, &InvF, &Ctx, &CtxLen, &CtxAlign); for (auto II = CallBlkBind->user_begin(), EE = CallBlkBind->user_end(); II != EE;) { auto BlkUser = *II++; SPIRVDBG(dbgs() << " Block user: " << *BlkUser << '\n'); if (auto Ret = dyn_cast(BlkUser)) { bool Inlined = false; Changed |= lowerReturnBlock(Ret, CallBlkBind, Inlined); if (Inlined) return true; } else if (auto CI = dyn_cast(BlkUser)) { auto CallBindF = CI->getCalledFunction(); auto Name = CallBindF->getName(); std::string DemangledName; if (Name == SPIR_INTRINSIC_GET_BLOCK_INVOKE) { assert(CI->getArgOperand(0) == CallBlkBind); Changed |= lowerGetBlockInvoke(CI, cast(InvF)); } else if (Name == SPIR_INTRINSIC_GET_BLOCK_CONTEXT) { assert(CI->getArgOperand(0) == CallBlkBind); // Handle context_ptr = spir_get_block_context(block) lowerGetBlockContext(CI, Ctx); Changed = true; } else if (oclIsBuiltin(Name, &DemangledName)) { lowerBlockBuiltin(CI, InvF, Ctx, CtxLen, CtxAlign, DemangledName); Changed = true; } else llvm_unreachable("Invalid block user"); } } erase(CallBlkBind); } Changed |= eraseUselessFunctions(); return Changed; } void lowerGetBlockContext(CallInst *CallGetBlkCtx, Value *Ctx = nullptr) { if (!Ctx) getBlockInvokeFuncAndContext(CallGetBlkCtx->getArgOperand(0), nullptr, &Ctx); CallGetBlkCtx->replaceAllUsesWith(Ctx); LLVM_DEBUG(dbgs() << " [lowerGetBlockContext] " << *CallGetBlkCtx << " => " << *Ctx << "\n\n"); erase(CallGetBlkCtx); } bool lowerGetBlockInvoke(CallInst *CallGetBlkInvoke, Function *InvokeF = nullptr) { bool Changed = false; for (auto UI = CallGetBlkInvoke->user_begin(), UE = CallGetBlkInvoke->user_end(); UI != UE;) { // Handle block_func_ptr = bitcast(spir_get_block_invoke(block)) auto CallInv = cast(*UI++); auto Cast = dyn_cast(CallInv); if (Cast) CallInv = dyn_cast(*CallInv->user_begin()); LLVM_DEBUG(dbgs() << "[lowerGetBlockInvoke] " << *CallInv); // Handle ret = block_func_ptr(context_ptr, args) auto CI = cast(CallInv); auto F = CI->getCalledValue(); if (InvokeF == nullptr) { getBlockInvokeFuncAndContext(CallGetBlkInvoke->getArgOperand(0), &InvokeF, nullptr); assert(InvokeF); } assert(F->getType() == InvokeF->getType()); CI->replaceUsesOfWith(F, InvokeF); LLVM_DEBUG(dbgs() << " => " << *CI << "\n\n"); erase(Cast); Changed = true; } erase(CallGetBlkInvoke); return Changed; } void lowerBlockBuiltin(CallInst *CI, Function *InvF, Value *Ctx, Value *CtxLen, Value *CtxAlign, const std::string &DemangledName) { mutateCallInstSPIRV(M, CI, [=](CallInst *CI, std::vector &Args) { size_t I = 0; size_t E = Args.size(); for (; I != E; ++I) { if (isPointerToOpaqueStructType(Args[I]->getType(), SPIR_TYPE_NAME_BLOCK_T)) { break; } } assert(I < E); Args[I] = castToVoidFuncPtr(InvF); if (I + 1 == E) { Args.push_back(Ctx); Args.push_back(CtxLen); Args.push_back(CtxAlign); } else { Args.insert(Args.begin() + I + 1, CtxAlign); Args.insert(Args.begin() + I + 1, CtxLen); Args.insert(Args.begin() + I + 1, Ctx); } if (DemangledName == kOCLBuiltinName::EnqueueKernel) { // Insert event arguments if there are not. if (!isa(Args[3]->getType())) { Args.insert(Args.begin() + 3, getInt32(M, 0)); Args.insert(Args.begin() + 4, getOCLNullClkEventPtr()); } if (!isOCLClkEventPtrType(Args[5]->getType())) Args.insert(Args.begin() + 5, getOCLNullClkEventPtr()); } return getSPIRVFuncName(OCLSPIRVBuiltinMap::map(DemangledName)); }); } /// Transform return of a block. /// The function returning a block is inlined since the context cannot be /// passed to another function. /// Returns true of module is changed. bool lowerReturnBlock(ReturnInst *Ret, Value *CallBlkBind, bool &Inlined) { auto F = Ret->getParent()->getParent(); auto Changed = false; for (auto UI = F->user_begin(), UE = F->user_end(); UI != UE;) { auto U = *UI++; dumpUsers(U); auto Inst = dyn_cast(U); if (Inst && Inst->use_empty()) { erase(Inst); Changed = true; continue; } auto CI = dyn_cast(U); if (!CI || CI->getCalledFunction() != F) continue; LLVM_DEBUG(dbgs() << "[lowerReturnBlock] inline " << F->getName() << '\n'); auto CG = &getAnalysis().getCallGraph(); auto ACT = &getAnalysis(); std::function GetAssumptionCache = [&](Function &F) -> AssumptionCache & { return ACT->getAssumptionCache(F); }; InlineFunctionInfo IFI(CG, &GetAssumptionCache); InlineFunction(CI, IFI); Inlined = true; } return Changed || Inlined; } /// Looking for a global variables initialized by opencl.block*. If found, /// check /// its users. If users are trivially dead, erase them. If the global variable /// has no users left after that, erase it too. void eraseUselessGlobalVars() { std::vector GlobalVarsToDelete; for (GlobalVariable &G : M->globals()) { if (!G.hasInitializer()) continue; Type *T = G.getInitializer()->getType(); if (!T->isPointerTy()) continue; T = cast(T)->getElementType(); if (!T->isStructTy()) continue; StringRef STName = cast(T)->getName(); if (STName != "opencl.block") continue; std::vector UsersToDelete; for (User *U : G.users()) if (U->use_empty()) UsersToDelete.push_back(U); for (User *U : UsersToDelete) erase(dyn_cast(U)); if (G.use_empty()) { GlobalVarsToDelete.push_back(&G); } } for (GlobalVariable *G : GlobalVarsToDelete) { if (G->hasInitializer()) { Constant *Init = G->getInitializer(); G->setInitializer(nullptr); if (llvm::isSafeToDestroyConstant(Init)) Init->destroyConstant(); } M->getGlobalList().erase(G); } } /// This method identifies F as an enqueued function iff: /// 1. F is bitcasted to a pointer, and /// 2. is passed to a function call of _Z21__spirv_EnqueueKernel /// Returns true if F is enqueued function, false otherwise. bool isEnqueuedFunction(Function &F) const { for (User *U : F.users()) { if (ConstantExpr *CE = dyn_cast(U)) { if (CE->getOpcode() != Instruction::BitCast) continue; if (!CE->getType()->isPointerTy()) continue; // lowerBlockBind() should already have substituted last argument // of enqueue_kernel() call with arguments of spir_block_bind(). for (User *UU : CE->users()) if (CallInst *C = dyn_cast(UU)) if (Function *CF = C->getCalledFunction()) if (CF->getName().startswith("_Z21__spirv_EnqueueKernel")) return true; } } return false; } /// Looking for functions which first argument is i8* %.block_descriptor /// If users of this argument are dead, erase them. /// After that clone the found function, removing its first argument /// Then adjust all users/callers of the function with new arguments /// Implementation of this function is based on /// the dead argument elimination pass. void eliminateDeadArgs() { std::vector FunctionsToDelete; for (Function &F : M->functions()) { if (F.arg_size() < 1) continue; auto FirstArg = F.arg_begin(); if (FirstArg->getName() != ".block_descriptor") continue; // Skip the function if it is an enqueued kernel, because per SPIR-V spec, // function invoked with OpEnqueueKernel must have at least one argument // of type i8* if (isEnqueuedFunction(F)) continue; std::vector UsersToDelete; for (User *U : FirstArg->users()) if (U->use_empty()) UsersToDelete.push_back(U); for (User *U : UsersToDelete) erase(dyn_cast(U)); UsersToDelete.clear(); if (!FirstArg->use_empty()) continue; // Create new function without block descriptor argument. ValueToValueMapTy VMap; // If any of the arguments to the function are in the VMap, // the arguments are deleted from the resultant function. VMap[&*FirstArg] = llvm::UndefValue::get(FirstArg->getType()); Function *NF = CloneFunction(&F, VMap); NF->takeName(&F); // Redirect all users of the old function to the new one. for (User *U : F.users()) { ConstantExpr *CE = dyn_cast(U); CallSite CS(U); if (CE && CE->getOpcode() == Instruction::BitCast) { Constant *NewCE = ConstantExpr::getBitCast(NF, CE->getType()); U->replaceAllUsesWith(NewCE); } else if (CS) { assert(isa(CS.getInstruction()) && "Call instruction is expected"); CallInst *Call = cast(CS.getInstruction()); std::vector Args; auto I = CS.arg_begin(); Args.assign(++I, CS.arg_end()); // Skip first argument. CallInst *New = CallInst::Create(NF, Args, "", Call); assert(New->getType() == Call->getType()); New->setCallingConv(CS.getCallingConv()); New->setAttributes(NF->getAttributes()); if (Call->isTailCall()) New->setTailCall(); New->setDebugLoc(Call->getDebugLoc()); New->takeName(Call); Call->replaceAllUsesWith(New); UsersToDelete.push_back(Call); } else { llvm_unreachable("Unexpected user of function"); } } for (User *U : UsersToDelete) erase(cast(U)); UsersToDelete.clear(); FunctionsToDelete.push_back(&F); } // iteration over module's functions. for (Function *F : FunctionsToDelete) erase(F); } void getBlockInvokeFuncAndContext(Value *Blk, Function **PInvF, Value **PCtx, Value **PCtxLen = nullptr, Value **PCtxAlign = nullptr) { Function *InvF = nullptr; Value *Ctx = nullptr; Value *CtxLen = nullptr; Value *CtxAlign = nullptr; if (auto CallBlkBind = dyn_cast(Blk)) { assert(CallBlkBind->getCalledFunction()->getName() == SPIR_INTRINSIC_BLOCK_BIND && "Invalid block"); InvF = dyn_cast( CallBlkBind->getArgOperand(0)->stripPointerCasts()); CtxLen = CallBlkBind->getArgOperand(1); CtxAlign = CallBlkBind->getArgOperand(2); Ctx = CallBlkBind->getArgOperand(3); } else if (auto F = dyn_cast(Blk->stripPointerCasts())) { InvF = F; Ctx = Constant::getNullValue(IntegerType::getInt8PtrTy(M->getContext())); } else if (auto Load = dyn_cast(Blk)) { auto Op = Load->getPointerOperand(); if (auto GV = dyn_cast(Op)) { if (GV->isConstant()) { InvF = cast(GV->getInitializer()->stripPointerCasts()); Ctx = Constant::getNullValue( IntegerType::getInt8PtrTy(M->getContext())); } else { llvm_unreachable("load non-constant block?"); } } else { llvm_unreachable("Loading block from non global?"); } } else { llvm_unreachable("Invalid block"); } LLVM_DEBUG(dbgs() << " Block invocation func: " << InvF->getName() << '\n' << " Block context: " << *Ctx << '\n'); assert(InvF && Ctx && "Invalid block"); if (PInvF) *PInvF = InvF; if (PCtx) *PCtx = Ctx; if (PCtxLen) *PCtxLen = CtxLen; if (PCtxAlign) *PCtxAlign = CtxAlign; } void erase(Instruction *I) { if (!I) return; if (I->use_empty()) { I->dropAllReferences(); I->eraseFromParent(); } else dumpUsers(I); } void erase(ConstantExpr *I) { if (!I) return; if (I->use_empty()) { I->dropAllReferences(); I->destroyConstant(); } else dumpUsers(I); } void erase(Function *F) { if (!F) return; if (!F->use_empty()) { dumpUsers(F); return; } F->dropAllReferences(); auto &CG = getAnalysis().getCallGraph(); CallGraphNode *CGN = CG[F]; if (CGN->getNumReferences() != 0) { return; } CGN->removeAllCalledFunctions(); delete CG.removeFunctionFromModule(CGN); } llvm::PointerType *getOCLClkEventType() { return getOrCreateOpaquePtrType(M, SPIR_TYPE_NAME_CLK_EVENT_T, SPIRAS_Global); } llvm::PointerType *getOCLClkEventPtrType() { return PointerType::get(getOCLClkEventType(), SPIRAS_Generic); } bool isOCLClkEventPtrType(Type *T) { if (auto PT = dyn_cast(T)) return isPointerToOpaqueStructType(PT->getElementType(), SPIR_TYPE_NAME_CLK_EVENT_T); return false; } llvm::Constant *getOCLNullClkEventPtr() { return Constant::getNullValue(getOCLClkEventPtrType()); } void dumpGetBlockInvokeUsers(StringRef Prompt) { LLVM_DEBUG(dbgs() << Prompt); dumpUsers(M->getFunction(SPIR_INTRINSIC_GET_BLOCK_INVOKE)); } }; char SPIRVLowerSPIRBlocks::ID = 0; } // namespace SPIRV INITIALIZE_PASS_BEGIN(SPIRVLowerSPIRBlocks, "spv-lower-spir-blocks", "SPIR-V lower SPIR blocks", false, false) INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) INITIALIZE_PASS_END(SPIRVLowerSPIRBlocks, "spv-lower-spir-blocks", "SPIR-V lower SPIR blocks", false, false) ModulePass *llvm::createSPIRVLowerSPIRBlocks() { return new SPIRVLowerSPIRBlocks(); } SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVMDBuilder.h000066400000000000000000000106751363521741200216640ustar00rootroot00000000000000//===- SPIRVMDBuilder.h - SPIR-V metadata builder header file --*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file declares classes for creating SPIR-V metadata. /// //===----------------------------------------------------------------------===// #ifndef SPIRV_SPIRVMDBUILDER_H #define SPIRV_SPIRVMDBUILDER_H #include "SPIRVInternal.h" #include "llvm/IR/Metadata.h" #include using namespace llvm; namespace SPIRV { class SPIRVMDBuilder { public: template struct MDWrapper; struct NamedMDWrapper { NamedMDWrapper(NamedMDNode &Named, SPIRVMDBuilder &BB) : NMD(Named), B(BB) {} MDWrapper addOp() { return MDWrapper(*this, B); } NamedMDWrapper &addOp(MDWrapper &MD) { NMD.addOperand(MD.M); return *this; } NamedMDNode &NMD; SPIRVMDBuilder &B; }; template struct MDWrapper { MDWrapper(ParentT &Parent, SPIRVMDBuilder &Builder) : M(nullptr), P(Parent), B(Builder) {} MDWrapper &add(unsigned I) { V.push_back(ConstantAsMetadata::get(getUInt32(&B.M, I))); return *this; } MDWrapper &addU16(unsigned short I) { V.push_back(ConstantAsMetadata::get(getUInt16(&B.M, I))); return *this; } MDWrapper &add(StringRef S) { V.push_back(MDString::get(B.C, S)); return *this; } MDWrapper &add(Function *F) { V.push_back(ConstantAsMetadata::get(F)); return *this; } MDWrapper &add(SmallVectorImpl &S) { for (auto &I : S) add(I); return *this; } MDWrapper &addOp(MDNode *Node) { V.push_back(Node); return *this; } MDWrapper addOp() { return MDWrapper(*this, B); } MDWrapper &addOp(MDWrapper &MD) { V.push_back(MD.M); return *this; } /// Generate the scheduled MDNode and return the parent. /// If \param Ptr is not nullptr, save the generated MDNode. ParentT &done(MDNode **Ptr = nullptr) { M = MDNode::get(B.C, V); if (Ptr) *Ptr = M; return P.addOp(*this); } MDNode *M; ParentT &P; SPIRVMDBuilder &B; SmallVector V; }; explicit SPIRVMDBuilder(Module &Mod) : M(Mod), C(Mod.getContext()) {} NamedMDWrapper addNamedMD(StringRef Name) { return NamedMDWrapper(*M.getOrInsertNamedMetadata(Name), *this); } SPIRVMDBuilder &eraseNamedMD(StringRef Name) { if (auto N = M.getNamedMetadata(Name)) M.eraseNamedMetadata(N); return *this; } friend struct NamedMDWrapper; private: Module &M; LLVMContext &C; }; } /* namespace SPIRV */ #endif // SPIRV_SPIRVMDBUILDER_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVMDWalker.h000066400000000000000000000120651363521741200215160ustar00rootroot00000000000000//===- SPIRVMDWalker.h - SPIR-V metadata walker header file ----*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file declares classes for walking SPIR-V metadata. /// //===----------------------------------------------------------------------===// #ifndef SPIRV_SPIRVMDWALKER_H #define SPIRV_SPIRVMDWALKER_H #include "SPIRVInternal.h" #include "llvm/IR/Metadata.h" #include using namespace llvm; namespace SPIRV { class SPIRVMDWalker { public: template struct MDWrapper; struct NamedMDWrapper { NamedMDWrapper(NamedMDNode *Named, SPIRVMDWalker &WW) : NMD(Named), W(WW), I(0), Q(true) { E = Named ? Named->getNumOperands() : 0; } operator bool() const { return NMD; } bool atEnd() const { return !(NMD && I < E); } MDWrapper nextOp() { if (!Q) assert(I < E && "out of bound"); return MDWrapper( (NMD && I < E) ? NMD->getOperand(I++) : nullptr, *this, W); } NamedMDWrapper &setQuiet(bool Quiet) { Q = Quiet; return *this; } NamedMDNode *NMD; SPIRVMDWalker &W; unsigned I; unsigned E; bool Q; // Quiet }; template struct MDWrapper { MDWrapper(MDNode *Node, ParentT &Parent, SPIRVMDWalker &Walker) : M(Node), P(Parent), W(Walker), I(0), Q(false) { E = Node ? Node->getNumOperands() : 0; } operator bool() const { return M; } bool atEnd() const { return !(M && I < E); } template MDWrapper &get(T &V) { if (!Q) assert(I < E && "out of bound"); if (atEnd()) return *this; V = mdconst::dyn_extract(M->getOperand(I++))->getZExtValue(); return *this; } MDWrapper &get(std::string &S) { if (!Q) assert(I < E && "out of bound"); if (atEnd()) return *this; Metadata *Op = M->getOperand(I++); if (!Op) S = ""; else if (auto Str = dyn_cast(Op)) S = Str->getString().str(); else S = ""; return *this; } MDWrapper &get(Function *&F) { if (!Q) assert(I < E && "out of bound"); if (atEnd()) return *this; F = mdconst::dyn_extract(M->getOperand(I++)); return *this; } MDWrapper &get(SmallVectorImpl &SV) { if (atEnd()) return *this; while (I < E) { std::string S; get(S); SV.push_back(S); } return *this; } MDWrapper nextOp() { if (!Q) assert(I < E && "out of bound"); return MDWrapper( (M && I < E) ? dyn_cast(M->getOperand(I++)) : nullptr, *this, W); } ParentT &done() { return P; } MDWrapper &setQuiet(bool Quiet) { Q = Quiet; return *this; } MDNode *M; ParentT &P; SPIRVMDWalker &W; SmallVector V; unsigned I; unsigned E; bool Q; // Quiet }; explicit SPIRVMDWalker(Module &Mod) : M(Mod), C(Mod.getContext()) {} NamedMDWrapper getNamedMD(StringRef Name) { return NamedMDWrapper(M.getNamedMetadata(Name), *this); } friend struct NamedMDWrapper; private: Module &M; LLVMContext &C; }; } /* namespace SPIRV */ #endif // SPIRV_SPIRVMDWALKER_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVReader.cpp000066400000000000000000004160571363521741200216160ustar00rootroot00000000000000//===- SPIRVReader.cpp - Converts SPIR-V to LLVM ----------------*- C++ -*-===// // // The LLVM/SPIR-V Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file implements conversion of SPIR-V binary to LLVM IR. /// //===----------------------------------------------------------------------===// #include "SPIRVReader.h" #include "OCLUtil.h" #include "SPIRVAsm.h" #include "SPIRVBasicBlock.h" #include "SPIRVExtInst.h" #include "SPIRVFunction.h" #include "SPIRVInstruction.h" #include "SPIRVInternal.h" #include "SPIRVMDBuilder.h" #include "SPIRVModule.h" #include "SPIRVToLLVMDbgTran.h" #include "SPIRVType.h" #include "SPIRVUtil.h" #include "SPIRVValue.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" #include #include #include #include #include #include #include #include #include #include #define DEBUG_TYPE "spirv" using namespace std; using namespace llvm; using namespace SPIRV; using namespace OCLUtil; namespace SPIRV { cl::opt SPIRVEnableStepExpansion( "spirv-expand-step", cl::init(true), cl::desc("Enable expansion of OpenCL step and smoothstep function")); // Prefix for placeholder global variable name. const char *KPlaceholderPrefix = "placeholder."; // Save the translated LLVM before validation for debugging purpose. static bool DbgSaveTmpLLVM = false; static const char *DbgTmpLLVMFileName = "_tmp_llvmbil.ll"; namespace kOCLTypeQualifierName { const static char *Const = "const"; const static char *Volatile = "volatile"; const static char *Restrict = "restrict"; const static char *Pipe = "pipe"; } // namespace kOCLTypeQualifierName static bool isOpenCLKernel(SPIRVFunction *BF) { return BF->getModule()->isEntryPoint(ExecutionModelKernel, BF->getId()); } static void dumpLLVM(Module *M, const std::string &FName) { std::error_code EC; raw_fd_ostream FS(FName, EC, sys::fs::F_None); if (EC) { FS << *M; FS.close(); } } static MDNode *getMDNodeStringIntVec(LLVMContext *Context, const std::vector &IntVals) { std::vector ValueVec; for (auto &I : IntVals) ValueVec.push_back(ConstantAsMetadata::get( ConstantInt::get(Type::getInt32Ty(*Context), I))); return MDNode::get(*Context, ValueVec); } static MDNode *getMDTwoInt(LLVMContext *Context, unsigned Int1, unsigned Int2) { std::vector ValueVec; ValueVec.push_back(ConstantAsMetadata::get( ConstantInt::get(Type::getInt32Ty(*Context), Int1))); ValueVec.push_back(ConstantAsMetadata::get( ConstantInt::get(Type::getInt32Ty(*Context), Int2))); return MDNode::get(*Context, ValueVec); } static void addOCLVersionMetadata(LLVMContext *Context, Module *M, const std::string &MDName, unsigned Major, unsigned Minor) { NamedMDNode *NamedMD = M->getOrInsertNamedMetadata(MDName); NamedMD->addOperand(getMDTwoInt(Context, Major, Minor)); } static void addNamedMetadataStringSet(LLVMContext *Context, Module *M, const std::string &MDName, const std::set &StrSet) { NamedMDNode *NamedMD = M->getOrInsertNamedMetadata(MDName); std::vector ValueVec; for (auto &&Str : StrSet) { ValueVec.push_back(MDString::get(*Context, Str)); } NamedMD->addOperand(MDNode::get(*Context, ValueVec)); } static void addOCLKernelArgumentMetadata( LLVMContext *Context, const std::string &MDName, SPIRVFunction *BF, llvm::Function *Fn, std::function Func) { std::vector ValueVec; BF->foreachArgument( [&](SPIRVFunctionParameter *Arg) { ValueVec.push_back(Func(Arg)); }); Fn->setMetadata(MDName, MDNode::get(*Context, ValueVec)); } Value *SPIRVToLLVM::getTranslatedValue(SPIRVValue *BV) { auto Loc = ValueMap.find(BV); if (Loc != ValueMap.end()) return Loc->second; return nullptr; } IntrinsicInst *SPIRVToLLVM::getLifetimeStartIntrinsic(Instruction *I) { auto II = dyn_cast(I); if (II && II->getIntrinsicID() == Intrinsic::lifetime_start) return II; // Bitcast might be inserted during translation of OpLifetimeStart auto BC = dyn_cast(I); if (BC) { for (const auto &U : BC->users()) { II = dyn_cast(U); if (II && II->getIntrinsicID() == Intrinsic::lifetime_start) return II; ; } } return nullptr; } SPIRVErrorLog &SPIRVToLLVM::getErrorLog() { return BM->getErrorLog(); } void SPIRVToLLVM::setCallingConv(CallInst *Call) { Function *F = Call->getCalledFunction(); assert(F && "Function pointers are not allowed in SPIRV"); Call->setCallingConv(F->getCallingConv()); } void SPIRVToLLVM::setAttrByCalledFunc(CallInst *Call) { Function *F = Call->getCalledFunction(); assert(F); if (F->isIntrinsic()) { return; } Call->setCallingConv(F->getCallingConv()); Call->setAttributes(F->getAttributes()); } bool SPIRVToLLVM::transOCLBuiltinsFromVariables() { std::vector WorkList; for (auto I = M->global_begin(), E = M->global_end(); I != E; ++I) { SPIRVBuiltinVariableKind Kind; if (!isSPIRVBuiltinVariable(&(*I), &Kind)) continue; if (!transOCLBuiltinFromVariable(&(*I), Kind)) return false; WorkList.push_back(&(*I)); } for (auto &I : WorkList) { I->eraseFromParent(); } return true; } // For integer types shorter than 32 bit, unsigned/signedness can be inferred // from zext/sext attribute. MDString *SPIRVToLLVM::transOCLKernelArgTypeName(SPIRVFunctionParameter *Arg) { auto Ty = Arg->isByVal() ? Arg->getType()->getPointerElementType() : Arg->getType(); return MDString::get(*Context, transTypeToOCLTypeName(Ty, !Arg->isZext())); } Value *SPIRVToLLVM::mapFunction(SPIRVFunction *BF, Function *F) { SPIRVDBG(spvdbgs() << "[mapFunction] " << *BF << " -> "; dbgs() << *F << '\n';) FuncMap[BF] = F; return F; } // Variable like GlobalInvolcationId[x] -> get_global_id(x). // Variable like WorkDim -> get_work_dim(). bool SPIRVToLLVM::transOCLBuiltinFromVariable(GlobalVariable *GV, SPIRVBuiltinVariableKind Kind) { std::string FuncName = SPIRSPIRVBuiltinVariableMap::rmap(Kind); std::string MangledName; Type *ReturnTy = GV->getType()->getPointerElementType(); bool IsVec = ReturnTy->isVectorTy(); if (IsVec) ReturnTy = cast(ReturnTy)->getElementType(); std::vector ArgTy; if (IsVec) ArgTy.push_back(Type::getInt32Ty(*Context)); mangleOpenClBuiltin(FuncName, ArgTy, MangledName); Function *Func = M->getFunction(MangledName); if (!Func) { FunctionType *FT = FunctionType::get(ReturnTy, ArgTy, false); Func = Function::Create(FT, GlobalValue::ExternalLinkage, MangledName, M); Func->setCallingConv(CallingConv::SPIR_FUNC); Func->addFnAttr(Attribute::NoUnwind); Func->addFnAttr(Attribute::ReadNone); } std::vector Deletes; std::vector Uses; for (auto UI = GV->user_begin(), UE = GV->user_end(); UI != UE; ++UI) { LoadInst *LD = nullptr; AddrSpaceCastInst *ASCast = dyn_cast(*UI); if (ASCast) { LD = cast(*ASCast->user_begin()); } else { LD = cast(*UI); } if (!IsVec) { Uses.push_back(LD); Deletes.push_back(LD); if (ASCast) Deletes.push_back(ASCast); continue; } for (auto LDUI = LD->user_begin(), LDUE = LD->user_end(); LDUI != LDUE; ++LDUI) { assert(isa(*LDUI) && "Unsupported use"); auto EEI = dyn_cast(*LDUI); Uses.push_back(EEI); Deletes.push_back(EEI); } Deletes.push_back(LD); if (ASCast) Deletes.push_back(ASCast); } for (auto &I : Uses) { std::vector Arg; if (auto EEI = dyn_cast(I)) Arg.push_back(EEI->getIndexOperand()); auto Call = CallInst::Create(Func, Arg, "", I); Call->takeName(I); setAttrByCalledFunc(Call); SPIRVDBG(dbgs() << "[transOCLBuiltinFromVariable] " << *I << " -> " << *Call << '\n';) I->replaceAllUsesWith(Call); } for (auto &I : Deletes) { I->eraseFromParent(); } return true; } Type *SPIRVToLLVM::transFPType(SPIRVType *T) { switch (T->getFloatBitWidth()) { case 16: return Type::getHalfTy(*Context); case 32: return Type::getFloatTy(*Context); case 64: return Type::getDoubleTy(*Context); default: llvm_unreachable("Invalid type"); return nullptr; } } std::string SPIRVToLLVM::transOCLImageTypeName(SPIRV::SPIRVTypeImage *ST) { std::string Name = std::string(kSPR2TypeName::OCLPrefix) + rmap(ST->getDescriptor()); SPIRVToLLVM::insertImageNameAccessQualifier(ST, Name); return Name; } std::string SPIRVToLLVM::transOCLSampledImageTypeName(SPIRV::SPIRVTypeSampledImage *ST) { return getSPIRVTypeName( kSPIRVTypeName::SampledImg, getSPIRVImageTypePostfixes( getSPIRVImageSampledTypeName(ST->getImageType()->getSampledType()), ST->getImageType()->getDescriptor(), ST->getImageType()->hasAccessQualifier() ? ST->getImageType()->getAccessQualifier() : AccessQualifierReadOnly)); } std::string SPIRVToLLVM::transOCLPipeTypeName(SPIRV::SPIRVTypePipe *PT, bool UseSPIRVFriendlyFormat, SPIRVAccessQualifierKind PipeAccess) { assert((PipeAccess == AccessQualifierReadOnly || PipeAccess == AccessQualifierWriteOnly) && "Invalid access qualifier"); if (!UseSPIRVFriendlyFormat) return PipeAccess == AccessQualifierWriteOnly ? kSPR2TypeName::PipeWO : kSPR2TypeName::PipeRO; else return std::string(kSPIRVTypeName::PrefixAndDelim) + kSPIRVTypeName::Pipe + kSPIRVTypeName::Delimiter + kSPIRVTypeName::PostfixDelim + PipeAccess; } std::string SPIRVToLLVM::transOCLPipeStorageTypeName(SPIRV::SPIRVTypePipeStorage *PST) { return std::string(kSPIRVTypeName::PrefixAndDelim) + kSPIRVTypeName::PipeStorage; } Type *SPIRVToLLVM::transType(SPIRVType *T, bool IsClassMember) { auto Loc = TypeMap.find(T); if (Loc != TypeMap.end()) return Loc->second; SPIRVDBG(spvdbgs() << "[transType] " << *T << " -> ";) T->validate(); switch (T->getOpCode()) { case OpTypeVoid: return mapType(T, Type::getVoidTy(*Context)); case OpTypeBool: return mapType(T, Type::getInt1Ty(*Context)); case OpTypeInt: return mapType(T, Type::getIntNTy(*Context, T->getIntegerBitWidth())); case OpTypeFloat: return mapType(T, transFPType(T)); case OpTypeArray: return mapType(T, ArrayType::get(transType(T->getArrayElementType()), T->getArrayLength())); case OpTypePointer: return mapType( T, PointerType::get( transType(T->getPointerElementType(), IsClassMember), SPIRSPIRVAddrSpaceMap::rmap(T->getPointerStorageClass()))); case OpTypeVector: return mapType(T, VectorType::get(transType(T->getVectorComponentType()), T->getVectorComponentCount())); case OpTypeMatrix: return mapType(T, ArrayType::get(transType(T->getMatrixColumnType()), T->getMatrixColumnCount())); case OpTypeOpaque: return mapType(T, StructType::create(*Context, T->getName())); case OpTypeFunction: { auto FT = static_cast(T); auto RT = transType(FT->getReturnType()); std::vector PT; for (size_t I = 0, E = FT->getNumParameters(); I != E; ++I) PT.push_back(transType(FT->getParameterType(I))); return mapType(T, FunctionType::get(RT, PT, false)); } case OpTypeImage: { auto ST = static_cast(T); if (ST->isOCLImage()) return mapType(T, getOrCreateOpaquePtrType(M, transOCLImageTypeName(ST))); else llvm_unreachable("Unsupported image type"); return nullptr; } case OpTypeSampledImage: { auto ST = static_cast(T); return mapType( T, getOrCreateOpaquePtrType(M, transOCLSampledImageTypeName(ST))); } case OpTypeStruct: { auto ST = static_cast(T); auto Name = ST->getName(); if (!Name.empty()) { if (auto OldST = M->getTypeByName(Name)) OldST->setName(""); } else { Name = "structtype"; } auto *StructTy = StructType::create(*Context, Name); mapType(ST, StructTy); SmallVector MT; for (size_t I = 0, E = ST->getMemberCount(); I != E; ++I) MT.push_back(transType(ST->getMemberType(I), true)); StructTy->setBody(MT, ST->isPacked()); return StructTy; } case OpTypePipe: { auto PT = static_cast(T); return mapType(T, getOrCreateOpaquePtrType( M, transOCLPipeTypeName(PT, IsClassMember, PT->getAccessQualifier()), getOCLOpaqueTypeAddrSpace(T->getOpCode()))); } case OpTypePipeStorage: { auto PST = static_cast(T); return mapType( T, getOrCreateOpaquePtrType(M, transOCLPipeStorageTypeName(PST), getOCLOpaqueTypeAddrSpace(T->getOpCode()))); } // OpenCL Compiler does not use this instruction case OpTypeVmeImageINTEL: return nullptr; default: { auto OC = T->getOpCode(); if (isOpaqueGenericTypeOpCode(OC) || isSubgroupAvcINTELTypeOpCode(OC)) { auto Name = isSubgroupAvcINTELTypeOpCode(OC) ? OCLSubgroupINTELTypeOpCodeMap::rmap(OC) : OCLOpaqueTypeOpCodeMap::rmap(OC); return mapType( T, getOrCreateOpaquePtrType(M, Name, getOCLOpaqueTypeAddrSpace(OC))); } llvm_unreachable("Not implemented"); } } return 0; } std::string SPIRVToLLVM::transTypeToOCLTypeName(SPIRVType *T, bool IsSigned) { switch (T->getOpCode()) { case OpTypeVoid: return "void"; case OpTypeBool: return "bool"; case OpTypeInt: { std::string Prefix = IsSigned ? "" : "u"; switch (T->getIntegerBitWidth()) { case 8: return Prefix + "char"; case 16: return Prefix + "short"; case 32: return Prefix + "int"; case 64: return Prefix + "long"; default: llvm_unreachable("invalid integer size"); return Prefix + std::string("int") + T->getIntegerBitWidth() + "_t"; } } break; case OpTypeFloat: switch (T->getFloatBitWidth()) { case 16: return "half"; case 32: return "float"; case 64: return "double"; default: llvm_unreachable("invalid floating pointer bitwidth"); return std::string("float") + T->getFloatBitWidth() + "_t"; } break; case OpTypeArray: return "array"; case OpTypePointer: { SPIRVType *ET = T->getPointerElementType(); if (isa(ET)) { SPIRVTypeFunction *TF = static_cast(ET); std::string name = transTypeToOCLTypeName(TF->getReturnType()); name += " (*)("; for (unsigned I = 0, E = TF->getNumParameters(); I < E; ++I) name += transTypeToOCLTypeName(TF->getParameterType(I)) + ','; name.back() = ')'; // replace the last comma with a closing brace. return name; } return transTypeToOCLTypeName(ET) + "*"; } case OpTypeVector: return transTypeToOCLTypeName(T->getVectorComponentType()) + T->getVectorComponentCount(); case OpTypeMatrix: return transTypeToOCLTypeName(T->getMatrixColumnType()) + T->getMatrixColumnCount(); case OpTypeOpaque: return T->getName(); case OpTypeFunction: llvm_unreachable("Unsupported"); return "function"; case OpTypeStruct: { auto Name = T->getName(); if (Name.find("struct.") == 0) Name[6] = ' '; else if (Name.find("union.") == 0) Name[5] = ' '; return Name; } case OpTypePipe: return "pipe"; case OpTypeSampler: return "sampler_t"; case OpTypeImage: { std::string Name; Name = rmap(static_cast(T)->getDescriptor()); return Name; } default: if (isOpaqueGenericTypeOpCode(T->getOpCode())) { return OCLOpaqueTypeOpCodeMap::rmap(T->getOpCode()); } llvm_unreachable("Not implemented"); return "unknown"; } } std::vector SPIRVToLLVM::transTypeVector(const std::vector &BT) { std::vector T; for (auto I : BT) T.push_back(transType(I)); return T; } std::vector SPIRVToLLVM::transValue(const std::vector &BV, Function *F, BasicBlock *BB) { std::vector V; for (auto I : BV) V.push_back(transValue(I, F, BB)); return V; } bool SPIRVToLLVM::isSPIRVCmpInstTransToLLVMInst(SPIRVInstruction *BI) const { auto OC = BI->getOpCode(); return isCmpOpCode(OC) && !(OC >= OpLessOrGreater && OC <= OpUnordered); } bool SPIRVToLLVM::isDirectlyTranslatedToOCL(Op OpCode) const { // Not every spirv opcode which is placed in OCLSPIRVBuiltinMap is // translated directly to OCL builtin. Some of them are translated // to LLVM representation without any modifications (SPIRV format of // instruction is represented in LLVM) and then its translated to // clang-consistent format in SPIRVToOCL pass. if (isSubgroupAvcINTELInstructionOpCode(OpCode) || isIntelSubgroupOpCode(OpCode)) return true; if (OCLSPIRVBuiltinMap::rfind(OpCode, nullptr)) { // everything except atomics, groups, pipes and media_block_io_intel is // directly translated return !(isAtomicOpCode(OpCode) || isGroupOpCode(OpCode) || isPipeOpCode(OpCode) || isMediaBlockINTELOpcode(OpCode)); } return false; } void SPIRVToLLVM::setName(llvm::Value *V, SPIRVValue *BV) { auto Name = BV->getName(); if (!Name.empty() && (!V->hasName() || Name != V->getName())) V->setName(Name); } inline llvm::Metadata *SPIRVToLLVM::getMetadataFromName(std::string Name) { return llvm::MDNode::get(*Context, llvm::MDString::get(*Context, Name)); } inline std::vector SPIRVToLLVM::getMetadataFromNameAndParameter(std::string Name, SPIRVWord Parameter) { return {MDString::get(*Context, Name), ConstantAsMetadata::get( ConstantInt::get(Type::getInt32Ty(*Context), Parameter))}; } template void SPIRVToLLVM::setLLVMLoopMetadata(const LoopInstType *LM, const Loop *LoopObj) { if (!LM) return; auto Temp = MDNode::getTemporary(*Context, None); auto Self = MDNode::get(*Context, Temp.get()); Self->replaceOperandWith(0, Self); SPIRVWord LC = LM->getLoopControl(); if (LC == LoopControlMaskNone) { LoopObj->setLoopID(Self); return; } unsigned NumParam = 0; std::vector Metadata; std::vector LoopControlParameters = LM->getLoopControlParameters(); Metadata.push_back(llvm::MDNode::get(*Context, Self)); // To correctly decode loop control parameters, order of checks for loop // control masks must match with the order given in the spec (see 3.23), // i.e. check smaller-numbered bits first. // Unroll and UnrollCount loop controls can't be applied simultaneously with // DontUnroll loop control. if (LC & LoopControlUnrollMask) Metadata.push_back(getMetadataFromName("llvm.loop.unroll.enable")); else if (LC & LoopControlDontUnrollMask) Metadata.push_back(getMetadataFromName("llvm.loop.unroll.disable")); if (LC & LoopControlDependencyInfiniteMask) Metadata.push_back(getMetadataFromName("llvm.loop.ivdep.enable")); if (LC & LoopControlDependencyLengthMask) { if (!LoopControlParameters.empty()) { Metadata.push_back(llvm::MDNode::get( *Context, getMetadataFromNameAndParameter("llvm.loop.ivdep.safelen", LoopControlParameters[NumParam]))); ++NumParam; // TODO: Fix the increment/assertion logic in all of the conditions assert(NumParam <= LoopControlParameters.size() && "Missing loop control parameter!"); } } // Placeholder for LoopControls added in SPIR-V 1.4 spec (see 3.23) if (LC & LoopControlMinIterationsMask) { ++NumParam; assert(NumParam <= LoopControlParameters.size() && "Missing loop control parameter!"); } if (LC & LoopControlMaxIterationsMask) { ++NumParam; assert(NumParam <= LoopControlParameters.size() && "Missing loop control parameter!"); } if (LC & LoopControlIterationMultipleMask) { ++NumParam; assert(NumParam <= LoopControlParameters.size() && "Missing loop control parameter!"); } if (LC & LoopControlPeelCountMask) { ++NumParam; assert(NumParam <= LoopControlParameters.size() && "Missing loop control parameter!"); } if (LC & LoopControlPartialCountMask && !(LC & LoopControlDontUnrollMask)) { // If unroll factor is set as '1' - disable loop unrolling if (1 == LoopControlParameters[NumParam]) Metadata.push_back(getMetadataFromName("llvm.loop.unroll.disable")); else Metadata.push_back(llvm::MDNode::get( *Context, getMetadataFromNameAndParameter("llvm.loop.unroll.count", LoopControlParameters[NumParam]))); ++NumParam; assert(NumParam <= LoopControlParameters.size() && "Missing loop control parameter!"); } if (LC & InitiationIntervalINTEL) { Metadata.push_back(llvm::MDNode::get( *Context, getMetadataFromNameAndParameter( "llvm.loop.ii.count", LoopControlParameters[NumParam]))); ++NumParam; assert(NumParam <= LoopControlParameters.size() && "Missing loop control parameter!"); } if (LC & MaxConcurrencyINTEL) { Metadata.push_back(llvm::MDNode::get( *Context, getMetadataFromNameAndParameter("llvm.loop.max_concurrency.count", LoopControlParameters[NumParam]))); ++NumParam; assert(NumParam <= LoopControlParameters.size() && "Missing loop control parameter!"); } if (LC & DependencyArrayINTEL) { // Collect array variable <-> safelen information std::map ArraySflnMap; unsigned NumOperandPairs = LoopControlParameters[NumParam]; unsigned OperandsEndIndex = NumParam + NumOperandPairs * 2; assert(OperandsEndIndex <= LoopControlParameters.size() && "Missing loop control parameter!"); SPIRVModule *M = LM->getModule(); while (NumParam < OperandsEndIndex) { SPIRVId ArraySPIRVId = LoopControlParameters[++NumParam]; Value *ArrayVar = ValueMap[M->getValue(ArraySPIRVId)]; unsigned Safelen = LoopControlParameters[++NumParam]; ArraySflnMap.emplace(ArrayVar, Safelen); } // A single run over the loop to retrieve all GetElementPtr instructions // that access relevant array variables std::map> ArrayGEPMap; for (const auto &BB : LoopObj->blocks()) { for (Instruction &I : *BB) { auto *GEP = dyn_cast(&I); if (!GEP) continue; Value *AccessedArray = GEP->getPointerOperand(); auto ArraySflnIt = ArraySflnMap.find(AccessedArray); if (ArraySflnIt != ArraySflnMap.end()) ArrayGEPMap[AccessedArray].push_back(GEP); } } // Create index group metadata nodes - one per each array // variables. Mark each GEP accessing a particular array variable // into a corresponding index group std::map> SafelenIdxGroupMap; for (auto &ArrayGEPIt : ArrayGEPMap) { // Emit a distinct index group that will be referenced from // llvm.loop.parallel_access_indices metadata auto *CurrentDepthIdxGroup = llvm::MDNode::getDistinct(*Context, None); unsigned Safelen = ArraySflnMap.find(ArrayGEPIt.first)->second; SafelenIdxGroupMap[Safelen].push_back(CurrentDepthIdxGroup); for (auto *GEP : ArrayGEPIt.second) { StringRef IdxGroupMDName("llvm.index.group"); llvm::MDNode *PreviousIdxGroup = GEP->getMetadata(IdxGroupMDName); if (!PreviousIdxGroup) { GEP->setMetadata(IdxGroupMDName, CurrentDepthIdxGroup); continue; } // If we're dealing with an embedded loop, it may be the case // that GEP instructions for some of the arrays were already // marked by the algorithm when it went over the outer level loops. // In order to retain the IVDep information for each "loop // dimension", we will mark such GEP's into a separate joined node // that will refer to the previous levels' index groups AND to the // index group specific to the current loop. std::vector CurrentDepthOperands( PreviousIdxGroup->op_begin(), PreviousIdxGroup->op_end()); if (CurrentDepthOperands.empty()) CurrentDepthOperands.push_back(PreviousIdxGroup); CurrentDepthOperands.push_back(CurrentDepthIdxGroup); auto *JointIdxGroup = llvm::MDNode::get(*Context, CurrentDepthOperands); GEP->setMetadata(IdxGroupMDName, JointIdxGroup); } } for (auto &SflnIdxGroupIt : SafelenIdxGroupMap) { auto *Name = MDString::get(*Context, "llvm.loop.parallel_access_indices"); unsigned SflnValue = SflnIdxGroupIt.first; llvm::Metadata *SafelenMDOp = SflnValue ? ConstantAsMetadata::get(ConstantInt::get( Type::getInt32Ty(*Context), SflnValue)) : nullptr; std::vector Parameters{Name}; for (auto *Node : SflnIdxGroupIt.second) Parameters.push_back(Node); if (SafelenMDOp) Parameters.push_back(SafelenMDOp); Metadata.push_back(llvm::MDNode::get(*Context, Parameters)); } } llvm::MDNode *Node = llvm::MDNode::get(*Context, Metadata); // Set the first operand to refer itself Node->replaceOperandWith(0, Node); LoopObj->setLoopID(Node); } void SPIRVToLLVM::transLLVMLoopMetadata(const Function *F) { assert(F); if (FuncLoopMetadataMap.empty()) return; DominatorTree DomTree(*(const_cast(F))); LoopInfo LI(DomTree); // In SPIRV loop metadata is linked to a header basic block of a loop // whilst in LLVM IR it is linked to a latch basic block (the one // whose back edge goes to a header basic block) of the loop. // To ensure consistent behaviour, we can rely on the `llvm::Loop` // class to handle the metadata placement for (const auto *LoopObj : LI.getLoopsInPreorder()) { // Check that loop header BB contains loop metadata. const auto LMDItr = FuncLoopMetadataMap.find(LoopObj->getHeader()); if (LMDItr == FuncLoopMetadataMap.end()) continue; const auto *LMD = LMDItr->second; if (LMD->getOpCode() == OpLoopMerge) { const auto *LM = static_cast(LMD); setLLVMLoopMetadata(LM, LoopObj); } else if (LMD->getOpCode() == OpLoopControlINTEL) { const auto *LCI = static_cast(LMD); setLLVMLoopMetadata(LCI, LoopObj); } FuncLoopMetadataMap.erase(LMDItr); } } void SPIRVToLLVM::insertImageNameAccessQualifier(SPIRV::SPIRVTypeImage *ST, std::string &Name) { SPIRVAccessQualifierKind Acc = ST->hasAccessQualifier() ? ST->getAccessQualifier() : AccessQualifierReadOnly; std::string QName = rmap(Acc); // transform: read_only -> ro, write_only -> wo, read_write -> rw QName = QName.substr(0, 1) + QName.substr(QName.find("_") + 1, 1) + "_"; assert(!Name.empty() && "image name should not be empty"); Name.insert(Name.size() - 1, QName); } Value *SPIRVToLLVM::transValue(SPIRVValue *BV, Function *F, BasicBlock *BB, bool CreatePlaceHolder) { SPIRVToLLVMValueMap::iterator Loc = ValueMap.find(BV); if (Loc != ValueMap.end() && (!PlaceholderMap.count(BV) || CreatePlaceHolder)) return Loc->second; SPIRVDBG(spvdbgs() << "[transValue] " << *BV << " -> ";) BV->validate(); auto V = transValueWithoutDecoration(BV, F, BB, CreatePlaceHolder); if (!V) { SPIRVDBG(dbgs() << " Warning ! nullptr\n";) return nullptr; } setName(V, BV); if (!transDecoration(BV, V)) { assert(0 && "trans decoration fail"); return nullptr; } SPIRVDBG(dbgs() << *V << '\n';) return V; } Value *SPIRVToLLVM::transDeviceEvent(SPIRVValue *BV, Function *F, BasicBlock *BB) { auto Val = transValue(BV, F, BB, false); auto Ty = dyn_cast(Val->getType()); assert(Ty && "Invalid Device Event"); if (Ty->getAddressSpace() == SPIRAS_Generic) return Val; IRBuilder<> Builder(BB); auto EventTy = PointerType::get(Ty->getElementType(), SPIRAS_Generic); return Builder.CreateAddrSpaceCast(Val, EventTy); } Value *SPIRVToLLVM::transConvertInst(SPIRVValue *BV, Function *F, BasicBlock *BB) { SPIRVUnary *BC = static_cast(BV); auto Src = transValue(BC->getOperand(0), F, BB, BB ? true : false); auto Dst = transType(BC->getType()); CastInst::CastOps CO = Instruction::BitCast; bool IsExt = Dst->getScalarSizeInBits() > Src->getType()->getScalarSizeInBits(); switch (BC->getOpCode()) { case OpPtrCastToGeneric: case OpGenericCastToPtr: CO = Instruction::AddrSpaceCast; break; case OpSConvert: CO = IsExt ? Instruction::SExt : Instruction::Trunc; break; case OpUConvert: CO = IsExt ? Instruction::ZExt : Instruction::Trunc; break; case OpFConvert: CO = IsExt ? Instruction::FPExt : Instruction::FPTrunc; break; default: CO = static_cast(OpCodeMap::rmap(BC->getOpCode())); } assert(CastInst::isCast(CO) && "Invalid cast op code"); SPIRVDBG(if (!CastInst::castIsValid(CO, Src, Dst)) { spvdbgs() << "Invalid cast: " << *BV << " -> "; dbgs() << "Op = " << CO << ", Src = " << *Src << " Dst = " << *Dst << '\n'; }) if (BB) return CastInst::Create(CO, Src, Dst, BV->getName(), BB); return ConstantExpr::getCast(CO, dyn_cast(Src), Dst); } static void applyNoIntegerWrapDecorations(const SPIRVValue *BV, Instruction *Inst) { if (BV->hasDecorate(DecorationNoSignedWrap)) { Inst->setHasNoSignedWrap(true); } if (BV->hasDecorate(DecorationNoUnsignedWrap)) { Inst->setHasNoUnsignedWrap(true); } } static void applyFPFastMathModeDecorations(const SPIRVValue *BV, Instruction *Inst) { SPIRVWord V; FastMathFlags FMF; if (BV->hasDecorate(DecorationFPFastMathMode, 0, &V)) { if (V & FPFastMathModeNotNaNMask) FMF.setNoNaNs(); if (V & FPFastMathModeNotInfMask) FMF.setNoInfs(); if (V & FPFastMathModeNSZMask) FMF.setNoSignedZeros(); if (V & FPFastMathModeAllowRecipMask) FMF.setAllowReciprocal(); if (V & FPFastMathModeFastMask) FMF.setFast(); Inst->setFastMathFlags(FMF); } } BinaryOperator *SPIRVToLLVM::transShiftLogicalBitwiseInst(SPIRVValue *BV, BasicBlock *BB, Function *F) { SPIRVBinary *BBN = static_cast(BV); assert(BB && "Invalid BB"); Instruction::BinaryOps BO; auto OP = BBN->getOpCode(); if (isLogicalOpCode(OP)) OP = IntBoolOpMap::rmap(OP); BO = static_cast(OpCodeMap::rmap(OP)); auto Inst = BinaryOperator::Create(BO, transValue(BBN->getOperand(0), F, BB), transValue(BBN->getOperand(1), F, BB), BV->getName(), BB); applyNoIntegerWrapDecorations(BV, Inst); applyFPFastMathModeDecorations(BV, Inst); return Inst; } Instruction *SPIRVToLLVM::transCmpInst(SPIRVValue *BV, BasicBlock *BB, Function *F) { SPIRVCompare *BC = static_cast(BV); assert(BB && "Invalid BB"); SPIRVType *BT = BC->getOperand(0)->getType(); Instruction *Inst = nullptr; auto OP = BC->getOpCode(); if (isLogicalOpCode(OP)) OP = IntBoolOpMap::rmap(OP); if (BT->isTypeVectorOrScalarInt() || BT->isTypeVectorOrScalarBool() || BT->isTypePointer()) Inst = new ICmpInst(*BB, CmpMap::rmap(OP), transValue(BC->getOperand(0), F, BB), transValue(BC->getOperand(1), F, BB)); else if (BT->isTypeVectorOrScalarFloat()) Inst = new FCmpInst(*BB, CmpMap::rmap(OP), transValue(BC->getOperand(0), F, BB), transValue(BC->getOperand(1), F, BB)); assert(Inst && "not implemented"); return Inst; } bool SPIRVToLLVM::postProcessOCL() { std::string DemangledName; SPIRVWord SrcLangVer = 0; BM->getSourceLanguage(&SrcLangVer); bool IsCpp = SrcLangVer == kOCLVer::CL21; for (auto I = M->begin(), E = M->end(); I != E;) { auto F = I++; if (F->hasName() && F->isDeclaration()) { LLVM_DEBUG(dbgs() << "[postProcessOCL sret] " << *F << '\n'); if (F->getReturnType()->isStructTy() && oclIsBuiltin(F->getName(), &DemangledName, IsCpp)) { if (!postProcessOCLBuiltinReturnStruct(&(*F))) return false; } } } for (auto I = M->begin(), E = M->end(); I != E;) { auto F = I++; if (F->hasName() && F->isDeclaration()) { LLVM_DEBUG(dbgs() << "[postProcessOCL array arg] " << *F << '\n'); if (hasArrayArg(&(*F)) && oclIsBuiltin(F->getName(), &DemangledName, IsCpp)) if (!postProcessOCLBuiltinWithArrayArguments(&(*F), DemangledName)) return false; } } return true; } bool SPIRVToLLVM::postProcessOCLBuiltinReturnStruct(Function *F) { std::string Name = F->getName(); F->setName(Name + ".old"); for (auto I = F->user_begin(), E = F->user_end(); I != E;) { if (auto CI = dyn_cast(*I++)) { auto ST = dyn_cast(*(CI->user_begin())); assert(ST); std::vector ArgTys; getFunctionTypeParameterTypes(F->getFunctionType(), ArgTys); ArgTys.insert(ArgTys.begin(), PointerType::get(F->getReturnType(), SPIRAS_Private)); auto NewF = getOrCreateFunction(M, Type::getVoidTy(*Context), ArgTys, Name); NewF->setCallingConv(F->getCallingConv()); auto Args = getArguments(CI); Args.insert(Args.begin(), ST->getPointerOperand()); auto NewCI = CallInst::Create(NewF, Args, CI->getName(), CI); NewCI->setCallingConv(CI->getCallingConv()); ST->eraseFromParent(); CI->eraseFromParent(); } } F->eraseFromParent(); return true; } bool SPIRVToLLVM::postProcessOCLBuiltinWithArrayArguments( Function *F, const std::string &DemangledName) { LLVM_DEBUG(dbgs() << "[postProcessOCLBuiltinWithArrayArguments] " << *F << '\n'); auto Attrs = F->getAttributes(); auto Name = F->getName(); mutateFunction( F, [=](CallInst *CI, std::vector &Args) { auto FBegin = CI->getParent()->getParent()->begin()->getFirstInsertionPt(); for (auto &I : Args) { auto T = I->getType(); if (!T->isArrayTy()) continue; auto Alloca = new AllocaInst(T, 0, "", &(*FBegin)); new StoreInst(I, Alloca, false, CI); auto Zero = ConstantInt::getNullValue(Type::getInt32Ty(T->getContext())); Value *Index[] = {Zero, Zero}; I = GetElementPtrInst::CreateInBounds(Alloca, Index, "", CI); } return Name; }, nullptr, &Attrs); return true; } static char getTypeSuffix(Type *T) { char Suffix; Type *ST = T->getScalarType(); if (ST->isHalfTy()) Suffix = 'h'; else if (ST->isFloatTy()) Suffix = 'f'; else Suffix = 'i'; return Suffix; } // ToDo: Handle unsigned integer return type. May need spec change. Instruction *SPIRVToLLVM::postProcessOCLReadImage(SPIRVInstruction *BI, CallInst *CI, const std::string &FuncName) { assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); StringRef ImageTypeName; bool IsDepthImage = false; if (isOCLImageType( (cast(CI->getOperand(0)))->getArgOperand(0)->getType(), &ImageTypeName)) IsDepthImage = ImageTypeName.contains("_depth_"); return mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args, llvm::Type *&RetTy) { CallInst *CallSampledImg = cast(Args[0]); auto Img = CallSampledImg->getArgOperand(0); assert(isOCLImageType(Img->getType())); auto Sampler = CallSampledImg->getArgOperand(1); Args[0] = Img; Args.insert(Args.begin() + 1, Sampler); if (Args.size() > 4) { ConstantInt *ImOp = dyn_cast(Args[3]); ConstantFP *LodVal = dyn_cast(Args[4]); // Drop "Image Operands" argument. Args.erase(Args.begin() + 3, Args.begin() + 4); // If the image operand is LOD and its value is zero, drop it too. if (ImOp && LodVal && LodVal->isNullValue() && ImOp->getZExtValue() == ImageOperandsMask::ImageOperandsLodMask) Args.erase(Args.begin() + 3, Args.end()); } if (CallSampledImg->hasOneUse()) { CallSampledImg->replaceAllUsesWith( UndefValue::get(CallSampledImg->getType())); CallSampledImg->dropAllReferences(); CallSampledImg->eraseFromParent(); } Type *T = CI->getType(); if (auto VT = dyn_cast(T)) T = VT->getElementType(); RetTy = IsDepthImage ? T : CI->getType(); return std::string(kOCLBuiltinName::SampledReadImage) + getTypeSuffix(T); }, [=](CallInst *NewCI) -> Instruction * { if (IsDepthImage) return InsertElementInst::Create( UndefValue::get(VectorType::get(NewCI->getType(), 4)), NewCI, getSizet(M, 0), "", NewCI->getParent()); return NewCI; }, &Attrs); } CallInst * SPIRVToLLVM::postProcessOCLWriteImage(SPIRVInstruction *BI, CallInst *CI, const std::string &DemangledName) { assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); return mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args) { llvm::Type *T = Args[2]->getType(); if (Args.size() > 4) { ConstantInt *ImOp = dyn_cast(Args[3]); ConstantFP *LodVal = dyn_cast(Args[4]); // Drop "Image Operands" argument. Args.erase(Args.begin() + 3, Args.begin() + 4); // If the image operand is LOD and its value is zero, drop it too. if (ImOp && LodVal && LodVal->isNullValue() && ImOp->getZExtValue() == ImageOperandsMask::ImageOperandsLodMask) Args.erase(Args.begin() + 3, Args.end()); else std::swap(Args[2], Args[3]); } return std::string(kOCLBuiltinName::WriteImage) + getTypeSuffix(T); }, &Attrs); } CallInst *SPIRVToLLVM::postProcessOCLBuildNDRange(SPIRVInstruction *BI, CallInst *CI, const std::string &FuncName) { assert(CI->getNumArgOperands() == 3); auto GWS = CI->getArgOperand(0); auto LWS = CI->getArgOperand(1); auto GWO = CI->getArgOperand(2); CI->setArgOperand(0, GWO); CI->setArgOperand(1, GWS); CI->setArgOperand(2, LWS); return CI; } Instruction * SPIRVToLLVM::postProcessGroupAllAny(CallInst *CI, const std::string &DemangledName) { assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); return mutateCallInstSPIRV( M, CI, [=](CallInst *, std::vector &Args, llvm::Type *&RetTy) { Type *Int32Ty = Type::getInt32Ty(*Context); RetTy = Int32Ty; Args[1] = CastInst::CreateZExtOrBitCast(Args[1], Int32Ty, "", CI); return DemangledName; }, [=](CallInst *NewCI) -> Instruction * { Type *RetTy = Type::getInt1Ty(*Context); return CastInst::CreateTruncOrBitCast(NewCI, RetTy, "", NewCI->getNextNode()); }, &Attrs); } Type *SPIRVToLLVM::mapType(SPIRVType *BT, Type *T) { SPIRVDBG(dbgs() << *T << '\n';) TypeMap[BT] = T; return T; } Value *SPIRVToLLVM::mapValue(SPIRVValue *BV, Value *V) { auto Loc = ValueMap.find(BV); if (Loc != ValueMap.end()) { if (Loc->second == V) return V; auto LD = dyn_cast(Loc->second); auto Placeholder = dyn_cast(LD->getPointerOperand()); assert(LD && Placeholder && Placeholder->getName().startswith(KPlaceholderPrefix) && "A value is translated twice"); // Replaces placeholders for PHI nodes LD->replaceAllUsesWith(V); LD->eraseFromParent(); Placeholder->eraseFromParent(); } ValueMap[BV] = V; return V; } bool SPIRVToLLVM::isSPIRVBuiltinVariable(GlobalVariable *GV, SPIRVBuiltinVariableKind *Kind) { auto Loc = BuiltinGVMap.find(GV); if (Loc == BuiltinGVMap.end()) return false; if (Kind) *Kind = Loc->second; return true; } CallInst * SPIRVToLLVM::expandOCLBuiltinWithScalarArg(CallInst *CI, const std::string &FuncName) { assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); if (!CI->getOperand(0)->getType()->isVectorTy() && CI->getOperand(1)->getType()->isVectorTy()) { return mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args) { unsigned VecSize = CI->getOperand(1)->getType()->getVectorNumElements(); Value *NewVec = nullptr; if (auto CA = dyn_cast(Args[0])) NewVec = ConstantVector::getSplat(VecSize, CA); else { NewVec = ConstantVector::getSplat( VecSize, Constant::getNullValue(Args[0]->getType())); NewVec = InsertElementInst::Create(NewVec, Args[0], getInt32(M, 0), "", CI); NewVec = new ShuffleVectorInst( NewVec, NewVec, ConstantVector::getSplat(VecSize, getInt32(M, 0)), "", CI); } NewVec->takeName(Args[0]); Args[0] = NewVec; return FuncName; }, &Attrs); } return CI; } std::string SPIRVToLLVM::transOCLPipeTypeAccessQualifier(SPIRV::SPIRVTypePipe *ST) { return SPIRSPIRVAccessQualifierMap::rmap(ST->getAccessQualifier()); } void SPIRVToLLVM::transGeneratorMD() { SPIRVMDBuilder B(*M); B.addNamedMD(kSPIRVMD::Generator) .addOp() .addU16(BM->getGeneratorId()) .addU16(BM->getGeneratorVer()) .done(); } Value *SPIRVToLLVM::oclTransConstantSampler(SPIRV::SPIRVConstantSampler *BCS, BasicBlock *BB) { auto *SamplerT = getOrCreateOpaquePtrType(M, OCLOpaqueTypeOpCodeMap::rmap(OpTypeSampler), getOCLOpaqueTypeAddrSpace(BCS->getOpCode())); auto *I32Ty = IntegerType::getInt32Ty(*Context); auto *FTy = FunctionType::get(SamplerT, {I32Ty}, false); FunctionCallee Func = M->getOrInsertFunction(SAMPLER_INIT, FTy); auto Lit = (BCS->getAddrMode() << 1) | BCS->getNormalized() | ((BCS->getFilterMode() + 1) << 4); return CallInst::Create(Func, {ConstantInt::get(I32Ty, Lit)}, "", BB); } Value *SPIRVToLLVM::oclTransConstantPipeStorage( SPIRV::SPIRVConstantPipeStorage *BCPS) { string CPSName = string(kSPIRVTypeName::PrefixAndDelim) + kSPIRVTypeName::ConstantPipeStorage; auto Int32Ty = IntegerType::getInt32Ty(*Context); auto CPSTy = M->getTypeByName(CPSName); if (!CPSTy) { Type *CPSElemsTy[] = {Int32Ty, Int32Ty, Int32Ty}; CPSTy = StructType::create(*Context, CPSElemsTy, CPSName); } assert(CPSTy != nullptr && "Could not create spirv.ConstantPipeStorage"); Constant *CPSElems[] = {ConstantInt::get(Int32Ty, BCPS->getPacketSize()), ConstantInt::get(Int32Ty, BCPS->getPacketAlign()), ConstantInt::get(Int32Ty, BCPS->getCapacity())}; return new GlobalVariable(*M, CPSTy, false, GlobalValue::LinkOnceODRLinkage, ConstantStruct::get(CPSTy, CPSElems), BCPS->getName(), nullptr, GlobalValue::NotThreadLocal, SPIRAS_Global); } /// For instructions, this function assumes they are created in order /// and appended to the given basic block. An instruction may use a /// instruction from another BB which has not been translated. Such /// instructions should be translated to place holders at the point /// of first use, then replaced by real instructions when they are /// created. /// /// When CreatePlaceHolder is true, create a load instruction of a /// global variable as placeholder for SPIRV instruction. Otherwise, /// create instruction and replace placeholder if there is one. Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F, BasicBlock *BB, bool CreatePlaceHolder) { auto OC = BV->getOpCode(); IntBoolOpMap::rfind(OC, &OC); // Translation of non-instruction values switch (OC) { case OpConstant: case OpSpecConstant: { SPIRVConstant *BConst = static_cast(BV); SPIRVType *BT = BV->getType(); Type *LT = transType(BT); uint64_t ConstValue = BConst->getZExtIntValue(); SPIRVWord SpecId = 0; if (OC == OpSpecConstant && BV->hasDecorate(DecorationSpecId, 0, &SpecId)) { // Update the value with possibly provided external specialization. if (BM->getSpecializationConstant(SpecId, ConstValue)) { assert( (BT->getBitWidth() == 64 || (ConstValue >> BT->getBitWidth()) == 0) && "Size of externally provided specialization constant value doesn't" "fit into the specialization constant type"); } } switch (BT->getOpCode()) { case OpTypeBool: case OpTypeInt: return mapValue( BV, ConstantInt::get(LT, ConstValue, static_cast(BT)->isSigned())); case OpTypeFloat: { const llvm::fltSemantics *FS = nullptr; switch (BT->getFloatBitWidth()) { case 16: FS = &APFloat::IEEEhalf(); break; case 32: FS = &APFloat::IEEEsingle(); break; case 64: FS = &APFloat::IEEEdouble(); break; default: llvm_unreachable("invalid floating-point type"); } APFloat FPConstValue(*FS, APInt(BT->getFloatBitWidth(), ConstValue)); return mapValue(BV, ConstantFP::get(*Context, FPConstValue)); } default: llvm_unreachable("Not implemented"); return nullptr; } } case OpConstantTrue: return mapValue(BV, ConstantInt::getTrue(*Context)); case OpConstantFalse: return mapValue(BV, ConstantInt::getFalse(*Context)); case OpSpecConstantTrue: case OpSpecConstantFalse: { bool IsTrue = OC == OpSpecConstantTrue; SPIRVWord SpecId = 0; if (BV->hasDecorate(DecorationSpecId, 0, &SpecId)) { uint64_t ConstValue = 0; if (BM->getSpecializationConstant(SpecId, ConstValue)) { IsTrue = ConstValue; } } return mapValue(BV, IsTrue ? ConstantInt::getTrue(*Context) : ConstantInt::getFalse(*Context)); } case OpConstantNull: { auto LT = transType(BV->getType()); return mapValue(BV, Constant::getNullValue(LT)); } case OpConstantComposite: case OpSpecConstantComposite: { auto BCC = static_cast(BV); std::vector CV; for (auto &I : BCC->getElements()) CV.push_back(dyn_cast(transValue(I, F, BB))); switch (BV->getType()->getOpCode()) { case OpTypeVector: return mapValue(BV, ConstantVector::get(CV)); case OpTypeMatrix: case OpTypeArray: return mapValue( BV, ConstantArray::get(dyn_cast(transType(BCC->getType())), CV)); case OpTypeStruct: { auto BCCTy = dyn_cast(transType(BCC->getType())); auto Members = BCCTy->getNumElements(); auto Constants = CV.size(); // if we try to initialize constant TypeStruct, add bitcasts // if src and dst types are both pointers but to different types if (Members == Constants) { for (unsigned I = 0; I < Members; ++I) { if (CV[I]->getType() == BCCTy->getElementType(I)) continue; if (!CV[I]->getType()->isPointerTy() || !BCCTy->getElementType(I)->isPointerTy()) continue; CV[I] = ConstantExpr::getBitCast(CV[I], BCCTy->getElementType(I)); } } return mapValue(BV, ConstantStruct::get( dyn_cast(transType(BCC->getType())), CV)); } default: llvm_unreachable("not implemented"); return nullptr; } } case OpConstantSampler: { auto BCS = static_cast(BV); return mapValue(BV, oclTransConstantSampler(BCS, BB)); } case OpConstantPipeStorage: { auto BCPS = static_cast(BV); return mapValue(BV, oclTransConstantPipeStorage(BCPS)); } case OpSpecConstantOp: { auto BI = createInstFromSpecConstantOp(static_cast(BV)); return mapValue(BV, transValue(BI, nullptr, nullptr, false)); } case OpUndef: return mapValue(BV, UndefValue::get(transType(BV->getType()))); case OpVariable: { auto BVar = static_cast(BV); auto Ty = transType(BVar->getType()->getPointerElementType()); bool IsConst = BVar->isConstant(); llvm::GlobalValue::LinkageTypes LinkageTy = transLinkageType(BVar); Constant *Initializer = nullptr; SPIRVValue *Init = BVar->getInitializer(); if (Init) Initializer = dyn_cast(transValue(Init, F, BB, false)); else if (LinkageTy == GlobalValue::CommonLinkage) // In LLVM variables with common linkage type must be initilized by 0 Initializer = Constant::getNullValue(Ty); else if (BVar->getStorageClass() == SPIRVStorageClassKind::StorageClassWorkgroup) Initializer = dyn_cast(UndefValue::get(Ty)); SPIRVStorageClassKind BS = BVar->getStorageClass(); if (BS == StorageClassFunction && !Init) { assert(BB && "Invalid BB"); return mapValue(BV, new AllocaInst(Ty, 0, BV->getName(), BB)); } auto AddrSpace = SPIRSPIRVAddrSpaceMap::rmap(BS); auto LVar = new GlobalVariable(*M, Ty, IsConst, LinkageTy, Initializer, BV->getName(), 0, GlobalVariable::NotThreadLocal, AddrSpace); LVar->setUnnamedAddr((IsConst && Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy(8)) ? GlobalValue::UnnamedAddr::Global : GlobalValue::UnnamedAddr::None); SPIRVBuiltinVariableKind BVKind; if (BVar->isBuiltin(&BVKind)) BuiltinGVMap[LVar] = BVKind; return mapValue(BV, LVar); } case OpFunctionParameter: { auto BA = static_cast(BV); assert(F && "Invalid function"); unsigned ArgNo = 0; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I, ++ArgNo) { if (ArgNo == BA->getArgNo()) return mapValue(BV, &(*I)); } llvm_unreachable("Invalid argument"); return nullptr; } case OpFunction: return mapValue(BV, transFunction(static_cast(BV))); case OpAsmINTEL: return mapValue(BV, transAsmINTEL(static_cast(BV))); case OpLabel: return mapValue(BV, BasicBlock::Create(*Context, BV->getName(), F)); default: // do nothing break; } // During translation of OpSpecConstantOp we create an instruction // corresponding to the Opcode operand and then translate this instruction. // For such instruction BB and F should be nullptr, because it is a constant // expression declared out of scope of any basic block or function. // All other values require valid BB pointer. assert(((isSpecConstantOpAllowedOp(OC) && !F && !BB) || BB) && "Invalid BB"); // Creation of place holder if (CreatePlaceHolder) { auto GV = new GlobalVariable( *M, transType(BV->getType()), false, GlobalValue::PrivateLinkage, nullptr, std::string(KPlaceholderPrefix) + BV->getName(), 0, GlobalVariable::NotThreadLocal, 0); auto LD = new LoadInst(GV, BV->getName(), BB); PlaceholderMap[BV] = LD; return mapValue(BV, LD); } // Translation of instructions switch (BV->getOpCode()) { case OpBranch: { auto *BR = static_cast(BV); auto *BI = BranchInst::Create( cast(transValue(BR->getTargetLabel(), F, BB)), BB); // Loop metadata will be translated in the end of function translation. return mapValue(BV, BI); } case OpBranchConditional: { auto *BR = static_cast(BV); auto *BC = BranchInst::Create( cast(transValue(BR->getTrueLabel(), F, BB)), cast(transValue(BR->getFalseLabel(), F, BB)), transValue(BR->getCondition(), F, BB), BB); // Loop metadata will be translated in the end of function translation. return mapValue(BV, BC); } case OpPhi: { auto Phi = static_cast(BV); auto LPhi = dyn_cast(mapValue( BV, PHINode::Create(transType(Phi->getType()), Phi->getPairs().size() / 2, Phi->getName(), BB))); Phi->foreachPair([&](SPIRVValue *IncomingV, SPIRVBasicBlock *IncomingBB, size_t Index) { auto Translated = transValue(IncomingV, F, BB); LPhi->addIncoming(Translated, dyn_cast(transValue(IncomingBB, F, BB))); }); return LPhi; } case OpUnreachable: return mapValue(BV, new UnreachableInst(*Context, BB)); case OpReturn: return mapValue(BV, ReturnInst::Create(*Context, BB)); case OpReturnValue: { auto RV = static_cast(BV); return mapValue( BV, ReturnInst::Create(*Context, transValue(RV->getReturnValue(), F, BB), BB)); } case OpLifetimeStart: { SPIRVLifetimeStart *LTStart = static_cast(BV); IRBuilder<> Builder(BB); SPIRVWord Size = LTStart->getSize(); ConstantInt *S = nullptr; if (Size) S = Builder.getInt64(Size); Value *Var = transValue(LTStart->getObject(), F, BB); CallInst *Start = Builder.CreateLifetimeStart(Var, S); return mapValue(BV, Start); } case OpLifetimeStop: { SPIRVLifetimeStop *LTStop = static_cast(BV); IRBuilder<> Builder(BB); SPIRVWord Size = LTStop->getSize(); ConstantInt *S = nullptr; if (Size) S = Builder.getInt64(Size); auto Var = transValue(LTStop->getObject(), F, BB); for (const auto &I : Var->users()) if (auto II = getLifetimeStartIntrinsic(dyn_cast(I))) return mapValue(BV, Builder.CreateLifetimeEnd(II->getOperand(1), S)); return mapValue(BV, Builder.CreateLifetimeEnd(Var, S)); } case OpStore: { SPIRVStore *BS = static_cast(BV); StoreInst *SI = new StoreInst( transValue(BS->getSrc(), F, BB), transValue(BS->getDst(), F, BB), BS->SPIRVMemoryAccess::isVolatile(), MaybeAlign(BS->SPIRVMemoryAccess::getAlignment()), BB); if (BS->SPIRVMemoryAccess::isNonTemporal()) transNonTemporalMetadata(SI); return mapValue(BV, SI); } case OpLoad: { SPIRVLoad *BL = static_cast(BV); LoadInst *LI = new LoadInst(transValue(BL->getSrc(), F, BB), BV->getName(), BL->SPIRVMemoryAccess::isVolatile(), MaybeAlign(BL->SPIRVMemoryAccess::getAlignment()), BB); if (BL->SPIRVMemoryAccess::isNonTemporal()) transNonTemporalMetadata(LI); return mapValue(BV, LI); } case OpCopyMemorySized: { SPIRVCopyMemorySized *BC = static_cast(BV); CallInst *CI = nullptr; llvm::Value *Dst = transValue(BC->getTarget(), F, BB); MaybeAlign Align(BC->getAlignment()); llvm::Value *Size = transValue(BC->getSize(), F, BB); bool IsVolatile = BC->SPIRVMemoryAccess::isVolatile(); IRBuilder<> Builder(BB); // If we copy from zero-initialized array, we can optimize it to llvm.memset if (BC->getSource()->getOpCode() == OpBitcast) { SPIRVValue *Source = static_cast(BC->getSource())->getOperand(0); if (Source->isVariable()) { auto *Init = static_cast(Source)->getInitializer(); if (isa(Init)) { SPIRVType *Ty = static_cast(Init)->getType(); if (isa(Ty)) { Type *Int8Ty = Type::getInt8Ty(Dst->getContext()); llvm::Value *Src = ConstantInt::get(Int8Ty, 0); llvm::Value *NewDst = Dst; if (!Dst->getType()->getPointerElementType()->isIntegerTy(8)) { Type *Int8PointerTy = Type::getInt8PtrTy( Dst->getContext(), Dst->getType()->getPointerAddressSpace()); NewDst = llvm::BitCastInst::CreatePointerCast(Dst, Int8PointerTy, "", BB); } CI = Builder.CreateMemSet(NewDst, Src, Size, Align, IsVolatile); } } } } if (!CI) { llvm::Value *Src = transValue(BC->getSource(), F, BB); CI = Builder.CreateMemCpy(Dst, Align, Src, Align, Size, IsVolatile); } if (isFuncNoUnwind()) CI->getFunction()->addFnAttr(Attribute::NoUnwind); return mapValue(BV, CI); } case OpSelect: { SPIRVSelect *BS = static_cast(BV); return mapValue(BV, SelectInst::Create(transValue(BS->getCondition(), F, BB), transValue(BS->getTrueValue(), F, BB), transValue(BS->getFalseValue(), F, BB), BV->getName(), BB)); } case OpVmeImageINTEL: case OpLine: case OpSelectionMerge: // OpenCL Compiler does not use this instruction return nullptr; case OpLoopMerge: // Will be translated after all other function's case OpLoopControlINTEL: // instructions are translated. FuncLoopMetadataMap[BB] = BV; return nullptr; case OpSwitch: { auto BS = static_cast(BV); auto Select = transValue(BS->getSelect(), F, BB); auto LS = SwitchInst::Create( Select, dyn_cast(transValue(BS->getDefault(), F, BB)), BS->getNumPairs(), BB); BS->foreachPair( [&](SPIRVSwitch::LiteralTy Literals, SPIRVBasicBlock *Label) { assert(!Literals.empty() && "Literals should not be empty"); assert(Literals.size() <= 2 && "Number of literals should not be more then two"); uint64_t Literal = uint64_t(Literals.at(0)); if (Literals.size() == 2) { Literal += uint64_t(Literals.at(1)) << 32; } LS->addCase( ConstantInt::get(cast(Select->getType()), Literal), cast(transValue(Label, F, BB))); }); return mapValue(BV, LS); } case OpVectorTimesScalar: { auto VTS = static_cast(BV); IRBuilder<> Builder(BB); auto Scalar = transValue(VTS->getScalar(), F, BB); auto Vector = transValue(VTS->getVector(), F, BB); assert(Vector->getType()->isVectorTy() && "Invalid type"); unsigned VecSize = Vector->getType()->getVectorNumElements(); auto NewVec = Builder.CreateVectorSplat(VecSize, Scalar, Scalar->getName()); NewVec->takeName(Scalar); auto Scale = Builder.CreateFMul(Vector, NewVec, "scale"); return mapValue(BV, Scale); } case OpVectorTimesMatrix: { auto *VTM = static_cast(BV); IRBuilder<> Builder(BB); Value *Mat = transValue(VTM->getMatrix(), F, BB); Value *Vec = transValue(VTM->getVector(), F, BB); // Vec is of N elements. // Mat is of M columns and N rows. // Mat consists of vectors: V_1, V_2, ..., V_M // // The product is: // // |------- M ----------| // Result = sum ( {Vec_1, Vec_1, ..., Vec_1} * {V_1_1, V_2_1, ..., V_M_1}, // {Vec_2, Vec_2, ..., Vec_2} * {V_1_2, V_2_2, ..., V_M_2}, // ... // {Vec_N, Vec_N, ..., Vec_N} * {V_1_N, V_2_N, ..., V_M_N}); unsigned M = Mat->getType()->getArrayNumElements(); VectorType *VTy = VectorType::get(Vec->getType()->getVectorElementType(), M); auto ETy = VTy->getElementType(); unsigned N = Vec->getType()->getVectorNumElements(); Value *V = Builder.CreateVectorSplat(M, ConstantFP::get(ETy, 0.0)); for (unsigned Idx = 0; Idx != N; ++Idx) { Value *S = Builder.CreateExtractElement(Vec, Builder.getInt32(Idx)); Value *Lhs = Builder.CreateVectorSplat(M, S); Value *Rhs = UndefValue::get(VTy); for (unsigned Idx2 = 0; Idx2 != M; ++Idx2) { Value *Vx = Builder.CreateExtractValue(Mat, Idx2); Value *Vxi = Builder.CreateExtractElement(Vx, Builder.getInt32(Idx)); Rhs = Builder.CreateInsertElement(Rhs, Vxi, Builder.getInt32(Idx2)); } Value *Mul = Builder.CreateFMul(Lhs, Rhs); V = Builder.CreateFAdd(V, Mul); } return mapValue(BV, V); } case OpMatrixTimesScalar: { auto MTS = static_cast(BV); IRBuilder<> Builder(BB); auto Scalar = transValue(MTS->getScalar(), F, BB); auto Matrix = transValue(MTS->getMatrix(), F, BB); uint64_t ColNum = Matrix->getType()->getArrayNumElements(); auto ColType = cast(Matrix->getType())->getElementType(); auto VecSize = ColType->getVectorNumElements(); auto NewVec = Builder.CreateVectorSplat(VecSize, Scalar, Scalar->getName()); NewVec->takeName(Scalar); Value *V = UndefValue::get(Matrix->getType()); for (uint64_t Idx = 0; Idx != ColNum; Idx++) { auto Col = Builder.CreateExtractValue(Matrix, Idx); auto I = Builder.CreateFMul(Col, NewVec); V = Builder.CreateInsertValue(V, I, Idx); } return mapValue(BV, V); } case OpMatrixTimesVector: { auto *MTV = static_cast(BV); IRBuilder<> Builder(BB); Value *Mat = transValue(MTV->getMatrix(), F, BB); Value *Vec = transValue(MTV->getVector(), F, BB); // Result is similar to Matrix * Matrix // Mat is of M columns and N rows. // Mat consists of vectors: V_1, V_2, ..., V_M // where each vector is of size N. // // Vec is of size M. // The product is a vector of size N. // // |------- N ----------| // Result = sum ( {Vec_1, Vec_1, ..., Vec_1} * V_1, // {Vec_2, Vec_2, ..., Vec_2} * V_2, // ... // {Vec_M, Vec_M, ..., Vec_M} * V_N ); // // where sum is defined as vector sum. unsigned M = Mat->getType()->getArrayNumElements(); VectorType *VTy = cast(cast(Mat->getType())->getElementType()); unsigned N = VTy->getVectorNumElements(); auto ETy = VTy->getElementType(); Value *V = Builder.CreateVectorSplat(N, ConstantFP::get(ETy, 0.0)); for (unsigned Idx = 0; Idx != M; ++Idx) { Value *S = Builder.CreateExtractElement(Vec, Builder.getInt32(Idx)); Value *Lhs = Builder.CreateVectorSplat(N, S); Value *Vx = Builder.CreateExtractValue(Mat, Idx); Value *Mul = Builder.CreateFMul(Lhs, Vx); V = Builder.CreateFAdd(V, Mul); } return mapValue(BV, V); } case OpMatrixTimesMatrix: { auto *MTM = static_cast(BV); IRBuilder<> Builder(BB); Value *M1 = transValue(MTM->getLeftMatrix(), F, BB); Value *M2 = transValue(MTM->getRightMatrix(), F, BB); // Each matrix consists of a list of columns. // M1 (the left matrix) is of C1 columns and R1 rows. // M1 consists of a list of vectors: V_1, V_2, ..., V_C1 // where V_x are vectors of size R1. // // M2 (the right matrix) is of C2 columns and R2 rows. // M2 consists of a list of vectors: U_1, U_2, ..., U_C2 // where U_x are vectors of size R2. // // Now M1 * M2 requires C1 == R2. // The result is a matrix of C2 columns and R1 rows. // That is, consists of C2 vectors of size R1. // // M1 * M2 algorithm is as below: // // Result = { dot_product(U_1, M1), // dot_product(U_2, M1), // ... // dot_product(U_C2, M1) }; // where // dot_product (U, M) is defined as: // // |-------- C1 ------| // Result = sum ( {U[1], U[1], ..., U[1]} * V_1, // {U[2], U[2], ..., U[2]} * V_2, // ... // {U[R2], U[R2], ..., U[R2]} * V_C1 ); // Note that C1 == R2 // sum is defined as vector sum. unsigned C1 = M1->getType()->getArrayNumElements(); unsigned C2 = M2->getType()->getArrayNumElements(); VectorType *V1Ty = cast(cast(M1->getType())->getElementType()); VectorType *V2Ty = cast(cast(M2->getType())->getElementType()); unsigned R1 = V1Ty->getVectorNumElements(); unsigned R2 = V2Ty->getVectorNumElements(); auto ETy = V1Ty->getElementType(); (void)C1; assert(C1 == R2 && "Unmatched matrix"); auto VTy = VectorType::get(ETy, R1); auto ResultTy = ArrayType::get(VTy, C2); Value *Res = UndefValue::get(ResultTy); for (unsigned Idx = 0; Idx != C2; ++Idx) { Value *U = Builder.CreateExtractValue(M2, Idx); // Calculate dot_product(U, M1) Value *Dot = Builder.CreateVectorSplat(R1, ConstantFP::get(ETy, 0.0)); for (unsigned Idx2 = 0; Idx2 != R2; ++Idx2) { Value *Ux = Builder.CreateExtractElement(U, Builder.getInt32(Idx2)); Value *Lhs = Builder.CreateVectorSplat(R1, Ux); Value *Rhs = Builder.CreateExtractValue(M1, Idx2); Value *Mul = Builder.CreateFMul(Lhs, Rhs); Dot = Builder.CreateFAdd(Dot, Mul); } Res = Builder.CreateInsertValue(Res, Dot, Idx); } return mapValue(BV, Res); } case OpTranspose: { auto TR = static_cast(BV); IRBuilder<> Builder(BB); auto Matrix = transValue(TR->getMatrix(), F, BB); unsigned ColNum = Matrix->getType()->getArrayNumElements(); VectorType *ColTy = cast(cast(Matrix->getType())->getElementType()); unsigned RowNum = ColTy->getVectorNumElements(); auto VTy = VectorType::get(ColTy->getElementType(), ColNum); auto ResultTy = ArrayType::get(VTy, RowNum); Value *V = UndefValue::get(ResultTy); SmallVector MCache; MCache.reserve(ColNum); for (unsigned Idx = 0; Idx != ColNum; ++Idx) MCache.push_back(Builder.CreateExtractValue(Matrix, Idx)); if (ColNum == RowNum) { // Fastpath switch (ColNum) { case 2: { Value *V1 = Builder.CreateShuffleVector(MCache[0], MCache[1], {0, 2}); V = Builder.CreateInsertValue(V, V1, 0); Value *V2 = Builder.CreateShuffleVector(MCache[0], MCache[1], {1, 3}); V = Builder.CreateInsertValue(V, V2, 1); return mapValue(BV, V); } case 4: { for (unsigned Idx = 0; Idx < 4; ++Idx) { Value *V1 = Builder.CreateShuffleVector(MCache[0], MCache[1], {Idx, Idx + 4}); Value *V2 = Builder.CreateShuffleVector(MCache[2], MCache[3], {Idx, Idx + 4}); Value *V3 = Builder.CreateShuffleVector(V1, V2, {0, 1, 2, 3}); V = Builder.CreateInsertValue(V, V3, Idx); } return mapValue(BV, V); } default: break; } } // Slowpath for (unsigned Idx = 0; Idx != RowNum; ++Idx) { Value *Vec = UndefValue::get(VTy); for (unsigned Idx2 = 0; Idx2 != ColNum; ++Idx2) { Value *S = Builder.CreateExtractElement(MCache[Idx2], Builder.getInt32(Idx)); Vec = Builder.CreateInsertElement(Vec, S, Idx2); } V = Builder.CreateInsertValue(V, Vec, Idx); } return mapValue(BV, V); } case OpCopyObject: { SPIRVCopyObject *CO = static_cast(BV); AllocaInst *AI = new AllocaInst(transType(CO->getOperand()->getType()), 0, "", BB); new StoreInst(transValue(CO->getOperand(), F, BB), AI, BB); LoadInst *LI = new LoadInst(AI, "", BB); return mapValue(BV, LI); } case OpAccessChain: case OpInBoundsAccessChain: case OpPtrAccessChain: case OpInBoundsPtrAccessChain: { auto AC = static_cast(BV); auto Base = transValue(AC->getBase(), F, BB); auto Index = transValue(AC->getIndices(), F, BB); if (!AC->hasPtrIndex()) Index.insert(Index.begin(), getInt32(M, 0)); auto IsInbound = AC->isInBounds(); Value *V = nullptr; if (BB) { auto GEP = GetElementPtrInst::Create(nullptr, Base, Index, BV->getName(), BB); GEP->setIsInBounds(IsInbound); V = GEP; } else { V = ConstantExpr::getGetElementPtr(nullptr, dyn_cast(Base), Index, IsInbound); } return mapValue(BV, V); } case OpCompositeConstruct: { auto CC = static_cast(BV); auto Constituents = transValue(CC->getConstituents(), F, BB); std::vector CV; for (const auto &I : Constituents) { CV.push_back(dyn_cast(I)); } switch (BV->getType()->getOpCode()) { case OpTypeVector: return mapValue(BV, ConstantVector::get(CV)); case OpTypeArray: return mapValue( BV, ConstantArray::get(dyn_cast(transType(CC->getType())), CV)); case OpTypeStruct: return mapValue(BV, ConstantStruct::get( dyn_cast(transType(CC->getType())), CV)); default: llvm_unreachable("Unhandled type!"); } } case OpCompositeExtract: { SPIRVCompositeExtract *CE = static_cast(BV); if (CE->getComposite()->getType()->isTypeVector()) { assert(CE->getIndices().size() == 1 && "Invalid index"); return mapValue( BV, ExtractElementInst::Create( transValue(CE->getComposite(), F, BB), ConstantInt::get(*Context, APInt(32, CE->getIndices()[0])), BV->getName(), BB)); } return mapValue( BV, ExtractValueInst::Create(transValue(CE->getComposite(), F, BB), CE->getIndices(), BV->getName(), BB)); } case OpVectorExtractDynamic: { auto CE = static_cast(BV); return mapValue( BV, ExtractElementInst::Create(transValue(CE->getVector(), F, BB), transValue(CE->getIndex(), F, BB), BV->getName(), BB)); } case OpCompositeInsert: { auto CI = static_cast(BV); if (CI->getComposite()->getType()->isTypeVector()) { assert(CI->getIndices().size() == 1 && "Invalid index"); return mapValue( BV, InsertElementInst::Create( transValue(CI->getComposite(), F, BB), transValue(CI->getObject(), F, BB), ConstantInt::get(*Context, APInt(32, CI->getIndices()[0])), BV->getName(), BB)); } return mapValue( BV, InsertValueInst::Create(transValue(CI->getComposite(), F, BB), transValue(CI->getObject(), F, BB), CI->getIndices(), BV->getName(), BB)); } case OpVectorInsertDynamic: { auto CI = static_cast(BV); return mapValue( BV, InsertElementInst::Create(transValue(CI->getVector(), F, BB), transValue(CI->getComponent(), F, BB), transValue(CI->getIndex(), F, BB), BV->getName(), BB)); } case OpVectorShuffle: { auto VS = static_cast(BV); std::vector Components; IntegerType *Int32Ty = IntegerType::get(*Context, 32); for (auto I : VS->getComponents()) { if (I == static_cast(-1)) Components.push_back(UndefValue::get(Int32Ty)); else Components.push_back(ConstantInt::get(Int32Ty, I)); } return mapValue(BV, new ShuffleVectorInst(transValue(VS->getVector1(), F, BB), transValue(VS->getVector2(), F, BB), ConstantVector::get(Components), BV->getName(), BB)); } case OpBitReverse: { auto *BR = static_cast(BV); auto Ty = transType(BV->getType()); Function *intr = Intrinsic::getDeclaration(M, llvm::Intrinsic::bitreverse, Ty); auto *Call = CallInst::Create(intr, transValue(BR->getOperand(0), F, BB), BR->getName(), BB); return mapValue(BV, Call); } case OpFunctionCall: { SPIRVFunctionCall *BC = static_cast(BV); auto Call = CallInst::Create(transFunction(BC->getFunction()), transValue(BC->getArgumentValues(), F, BB), BC->getName(), BB); setCallingConv(Call); setAttrByCalledFunc(Call); return mapValue(BV, Call); } case OpAsmCallINTEL: return mapValue( BV, transAsmCallINTEL(static_cast(BV), F, BB)); case OpFunctionPointerCallINTEL: { SPIRVFunctionPointerCallINTEL *BC = static_cast(BV); auto Call = CallInst::Create(transValue(BC->getCalledValue(), F, BB), transValue(BC->getArgumentValues(), F, BB), BC->getName(), BB); // Assuming we are calling a regular device function Call->setCallingConv(CallingConv::SPIR_FUNC); // Don't set attributes, because at translation time we don't know which // function exactly we are calling. return mapValue(BV, Call); } case OpFunctionPointerINTEL: { SPIRVFunctionPointerINTEL *BC = static_cast(BV); SPIRVFunction *F = BC->getFunction(); BV->setName(F->getName()); return mapValue(BV, transFunction(F)); } case OpExtInst: { auto *ExtInst = static_cast(BV); switch (ExtInst->getExtSetKind()) { case SPIRVEIS_OpenCL: return mapValue(BV, transOCLBuiltinFromExtInst(ExtInst, BB)); case SPIRVEIS_Debug: return mapValue(BV, DbgTran->transDebugIntrinsic(ExtInst, BB)); default: llvm_unreachable("Unknown extended instruction set!"); } } case OpSNegate: { SPIRVUnary *BC = static_cast(BV); auto Neg = BinaryOperator::CreateNeg(transValue(BC->getOperand(0), F, BB), BV->getName(), BB); applyNoIntegerWrapDecorations(BV, Neg); return mapValue(BV, Neg); } case OpFMod: { // translate OpFMod(a, b) to: // r = frem(a, b) // c = copysign(r, b) // needs_fixing = islessgreater(r, c) // result = needs_fixing ? r + b : c IRBuilder<> Builder(BB); SPIRVFMod *FMod = static_cast(BV); auto Dividend = transValue(FMod->getDividend(), F, BB); auto Divisor = transValue(FMod->getDivisor(), F, BB); auto FRem = Builder.CreateFRem(Dividend, Divisor, "frem.res"); auto CopySign = Builder.CreateBinaryIntrinsic( llvm::Intrinsic::copysign, FRem, Divisor, nullptr, "copysign.res"); auto FAdd = Builder.CreateFAdd(FRem, Divisor, "fadd.res"); auto Cmp = Builder.CreateFCmpONE(FRem, CopySign, "cmp.res"); auto Select = Builder.CreateSelect(Cmp, FAdd, CopySign); return mapValue(BV, Select); } case OpSMod: { // translate OpSMod(a, b) to: // r = srem(a, b) // needs_fixing = ((a < 0) != (b < 0) && r != 0) // result = needs_fixing ? r + b : r IRBuilder<> Builder(BB); SPIRVSMod *SMod = static_cast(BV); auto Dividend = transValue(SMod->getDividend(), F, BB); auto Divisor = transValue(SMod->getDivisor(), F, BB); auto SRem = Builder.CreateSRem(Dividend, Divisor, "srem.res"); auto Xor = Builder.CreateXor(Dividend, Divisor, "xor.res"); auto Zero = ConstantInt::getNullValue(Dividend->getType()); auto CmpSign = Builder.CreateICmpSLT(Xor, Zero, "cmpsign.res"); auto CmpSRem = Builder.CreateICmpNE(SRem, Zero, "cmpsrem.res"); auto Add = Builder.CreateNSWAdd(SRem, Divisor, "add.res"); auto Cmp = Builder.CreateAnd(CmpSign, CmpSRem, "cmp.res"); auto Select = Builder.CreateSelect(Cmp, Add, SRem); return mapValue(BV, Select); } case OpFNegate: { SPIRVUnary *BC = static_cast(BV); auto Neg = BinaryOperator::CreateFNeg(transValue(BC->getOperand(0), F, BB), BV->getName(), BB); applyFPFastMathModeDecorations(BV, Neg); return mapValue(BV, Neg); } case OpNot: case OpLogicalNot: { SPIRVUnary *BC = static_cast(BV); return mapValue( BV, BinaryOperator::CreateNot(transValue(BC->getOperand(0), F, BB), BV->getName(), BB)); } case OpAll: case OpAny: return mapValue(BV, transOCLAllAny(static_cast(BV), BB)); case OpIsFinite: case OpIsInf: case OpIsNan: case OpIsNormal: case OpSignBitSet: return mapValue( BV, transOCLRelational(static_cast(BV), BB)); case OpEnqueueKernel: return mapValue( BV, transEnqueueKernelBI(static_cast(BV), BB)); case OpGetKernelWorkGroupSize: case OpGetKernelPreferredWorkGroupSizeMultiple: return mapValue( BV, transWGSizeQueryBI(static_cast(BV), BB)); case OpGetKernelNDrangeMaxSubGroupSize: case OpGetKernelNDrangeSubGroupCount: return mapValue( BV, transSGSizeQueryBI(static_cast(BV), BB)); case OpFPGARegINTEL: { IRBuilder<> Builder(BB); SPIRVFPGARegINTELInstBase *BC = static_cast(BV); PointerType *Int8PtrTyPrivate = Type::getInt8PtrTy(*Context, SPIRAS_Private); IntegerType *Int32Ty = Type::getInt32Ty(*Context); Value *UndefInt8Ptr = UndefValue::get(Int8PtrTyPrivate); Value *UndefInt32 = UndefValue::get(Int32Ty); Constant *GS = Builder.CreateGlobalStringPtr(kOCLBuiltinName::FPGARegIntel); Type *Ty = transType(BC->getType()); Value *Val = transValue(BC->getOperand(0), F, BB); Value *ValAsArg = Val; Type *RetTy = Ty; auto IID = Intrinsic::annotation; if (!isa(Ty)) { // All scalar types can be bitcasted to a same-sized integer if (!isa(Ty) && !isa(Ty)) { RetTy = IntegerType::get(*Context, Ty->getPrimitiveSizeInBits()); ValAsArg = Builder.CreateBitCast(Val, RetTy); } // If pointer type or struct type else { IID = Intrinsic::ptr_annotation; auto *PtrTy = dyn_cast(Ty); if (PtrTy && isa(PtrTy->getElementType())) RetTy = PtrTy; // Whether a struct or a pointer to some other type, // bitcast to i8* else { RetTy = Int8PtrTyPrivate; ValAsArg = Builder.CreateBitCast(Val, Int8PtrTyPrivate); } } } Value *Args[] = {ValAsArg, GS, UndefInt8Ptr, UndefInt32}; auto *IntrinsicCall = Builder.CreateIntrinsic(IID, RetTy, Args); return mapValue(BV, IntrinsicCall); } default: { auto OC = BV->getOpCode(); if (isSPIRVCmpInstTransToLLVMInst(static_cast(BV))) { return mapValue(BV, transCmpInst(BV, BB, F)); } else if (isDirectlyTranslatedToOCL(OC)) { return mapValue( BV, transOCLBuiltinFromInst(static_cast(BV), BB)); } else if (isBinaryShiftLogicalBitwiseOpCode(OC) || isLogicalOpCode(OC)) { return mapValue(BV, transShiftLogicalBitwiseInst(BV, BB, F)); } else if (isCvtOpCode(OC)) { auto BI = static_cast(BV); Value *Inst = nullptr; if (BI->hasFPRoundingMode() || BI->isSaturatedConversion()) Inst = transOCLBuiltinFromInst(BI, BB); else Inst = transConvertInst(BV, F, BB); return mapValue(BV, Inst); } return mapValue( BV, transSPIRVBuiltinFromInst(static_cast(BV), BB)); } } } template bool SPIRVToLLVM::foreachFuncCtlMask(SourceTy Source, FuncTy Func) { SPIRVWord FCM = Source->getFuncCtlMask(); SPIRSPIRVFuncCtlMaskMap::foreach ( [&](Attribute::AttrKind Attr, SPIRVFunctionControlMaskKind Mask) { if (FCM & Mask) Func(Attr); }); return true; } Function *SPIRVToLLVM::transFunction(SPIRVFunction *BF) { auto Loc = FuncMap.find(BF); if (Loc != FuncMap.end()) return Loc->second; auto IsKernel = BM->isEntryPoint(ExecutionModelKernel, BF->getId()); auto Linkage = IsKernel ? GlobalValue::ExternalLinkage : transLinkageType(BF); FunctionType *FT = dyn_cast(transType(BF->getFunctionType())); Function *F = cast( mapValue(BF, Function::Create(FT, Linkage, BF->getName(), M))); mapFunction(BF, F); if (BF->hasDecorate(DecorationReferencedIndirectlyINTEL)) F->addFnAttr("referenced-indirectly"); if (!F->isIntrinsic()) { F->setCallingConv(IsKernel ? CallingConv::SPIR_KERNEL : CallingConv::SPIR_FUNC); if (isFuncNoUnwind()) F->addFnAttr(Attribute::NoUnwind); foreachFuncCtlMask(BF, [&](Attribute::AttrKind Attr) { F->addFnAttr(Attr); }); } for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) { auto BA = BF->getArgument(I->getArgNo()); mapValue(BA, &(*I)); setName(&(*I), BA); BA->foreachAttr([&](SPIRVFuncParamAttrKind Kind) { if (Kind == FunctionParameterAttributeNoWrite) return; F->addAttribute(I->getArgNo() + 1, SPIRSPIRVFuncParamAttrMap::rmap(Kind)); }); SPIRVWord MaxOffset = 0; if (BA->hasDecorate(DecorationMaxByteOffset, 0, &MaxOffset)) { AttrBuilder Builder; Builder.addDereferenceableAttr(MaxOffset); I->addAttrs(Builder); } } BF->foreachReturnValueAttr([&](SPIRVFuncParamAttrKind Kind) { if (Kind == FunctionParameterAttributeNoWrite) return; F->addAttribute(AttributeList::ReturnIndex, SPIRSPIRVFuncParamAttrMap::rmap(Kind)); }); // Creating all basic blocks before creating instructions. for (size_t I = 0, E = BF->getNumBasicBlock(); I != E; ++I) { transValue(BF->getBasicBlock(I), F, nullptr); } for (size_t I = 0, E = BF->getNumBasicBlock(); I != E; ++I) { SPIRVBasicBlock *BBB = BF->getBasicBlock(I); BasicBlock *BB = dyn_cast(transValue(BBB, F, nullptr)); for (size_t BI = 0, BE = BBB->getNumInst(); BI != BE; ++BI) { SPIRVInstruction *BInst = BBB->getInst(BI); transValue(BInst, F, BB, false); } } transLLVMLoopMetadata(F); return F; } Value *SPIRVToLLVM::transAsmINTEL(SPIRVAsmINTEL *BA) { assert(BA); bool HasSideEffect = BA->hasDecorate(DecorationSideEffectsINTEL); return InlineAsm::get( cast(transType(BA->getFunctionType())), BA->getInstructions(), BA->getConstraints(), HasSideEffect, /* IsAlignStack */ false, InlineAsm::AsmDialect::AD_ATT); } CallInst *SPIRVToLLVM::transAsmCallINTEL(SPIRVAsmCallINTEL *BI, Function *F, BasicBlock *BB) { assert(BI); auto *IA = cast(transValue(BI->getAsm(), F, BB)); auto Args = transValue(BM->getValues(BI->getArguments()), F, BB); return CallInst::Create(cast(IA->getFunctionType()), IA, Args, BI->getName(), BB); } /// LLVM convert builtin functions is translated to two instructions: /// y = i32 islessgreater(float x, float z) -> /// y = i32 ZExt(bool LessOrGreater(float x, float z)) /// When translating back, for simplicity, a trunc instruction is inserted /// w = bool LessOrGreater(float x, float z) -> /// w = bool Trunc(i32 islessgreater(float x, float z)) /// Optimizer should be able to remove the redundant trunc/zext void SPIRVToLLVM::transOCLBuiltinFromInstPreproc( SPIRVInstruction *BI, Type *&RetTy, std::vector &Args) { if (!BI->hasType()) return; auto BT = BI->getType(); auto OC = BI->getOpCode(); if (isCmpOpCode(BI->getOpCode())) { if (BT->isTypeBool()) RetTy = IntegerType::getInt32Ty(*Context); else if (BT->isTypeVectorBool()) RetTy = VectorType::get( IntegerType::get( *Context, Args[0]->getType()->getVectorComponentType()->getBitWidth()), BT->getVectorComponentCount()); else llvm_unreachable("invalid compare instruction"); } else if (OC == OpGenericCastToPtrExplicit) Args.pop_back(); else if (OC == OpImageRead && Args.size() > 2) { // Drop "Image operands" argument Args.erase(Args.begin() + 2); } else if (isSubgroupAvcINTELEvaluateOpcode(OC)) { // There are three types of AVC Intel Evaluate opcodes: // 1. With multi reference images - does not use OpVmeImageINTEL opcode for // reference images // 2. With dual reference images - uses two OpVmeImageINTEL opcodes for // reference image // 3. With single reference image - uses one OpVmeImageINTEL opcode for // reference image int NumImages = std::count_if(Args.begin(), Args.end(), [](SPIRVValue *Arg) { return static_cast(Arg)->getOpCode() == OpVmeImageINTEL; }); if (NumImages) { SPIRVInstruction *SrcImage = static_cast(Args[0]); assert(SrcImage && "Src image operand not found in avc evaluate instruction"); if (NumImages == 1) { // Multi reference opcode - remove src image OpVmeImageINTEL opcode // and replace it with corresponding OpImage and OpSampler arguments size_t SamplerPos = Args.size() - 1; Args.erase(Args.begin(), Args.begin() + 1); Args.insert(Args.begin(), SrcImage->getOperands()[0]); Args.insert(Args.begin() + SamplerPos, SrcImage->getOperands()[1]); } else { SPIRVInstruction *FwdRefImage = static_cast(Args[1]); SPIRVInstruction *BwdRefImage = static_cast(Args[2]); assert(FwdRefImage && "invalid avc evaluate instruction"); // Single reference opcode - remove src and ref image OpVmeImageINTEL // opcodes and replace them with src and ref OpImage opcodes and // OpSampler Args.erase(Args.begin(), Args.begin() + NumImages); // insert source OpImage and OpSampler auto SrcOps = SrcImage->getOperands(); Args.insert(Args.begin(), SrcOps.begin(), SrcOps.end()); // insert reference OpImage Args.insert(Args.begin() + 1, FwdRefImage->getOperands()[0]); if (NumImages == 3) { // Dual reference opcode - insert second reference OpImage argument assert(BwdRefImage && "invalid avc evaluate instruction"); Args.insert(Args.begin() + 2, BwdRefImage->getOperands()[0]); } } } else llvm_unreachable("invalid avc instruction"); } } Instruction * SPIRVToLLVM::transOCLBuiltinPostproc(SPIRVInstruction *BI, CallInst *CI, BasicBlock *BB, const std::string &DemangledName) { auto OC = BI->getOpCode(); if (isCmpOpCode(OC) && BI->getType()->isTypeVectorOrScalarBool()) { return CastInst::Create(Instruction::Trunc, CI, transType(BI->getType()), "cvt", BB); } if (OC == OpImageSampleExplicitLod) return postProcessOCLReadImage(BI, CI, DemangledName); if (OC == OpImageWrite) { return postProcessOCLWriteImage(BI, CI, DemangledName); } if (OC == OpGenericPtrMemSemantics) return BinaryOperator::CreateShl(CI, getInt32(M, 8), "", BB); if (OC == OpImageQueryFormat) return BinaryOperator::CreateSub( CI, getInt32(M, OCLImageChannelDataTypeOffset), "", BB); if (OC == OpImageQueryOrder) return BinaryOperator::CreateSub( CI, getInt32(M, OCLImageChannelOrderOffset), "", BB); if (OC == OpBuildNDRange) return postProcessOCLBuildNDRange(BI, CI, DemangledName); if (OC == OpGroupAll || OC == OpGroupAny) return postProcessGroupAllAny(CI, DemangledName); if (SPIRVEnableStepExpansion && (DemangledName == "smoothstep" || DemangledName == "step")) return expandOCLBuiltinWithScalarArg(CI, DemangledName); return CI; } Value *SPIRVToLLVM::transBlockInvoke(SPIRVValue *Invoke, BasicBlock *BB) { auto *TranslatedInvoke = transFunction(static_cast(Invoke)); auto *Int8PtrTyGen = Type::getInt8PtrTy(*Context, SPIRAS_Generic); return CastInst::CreatePointerBitCastOrAddrSpaceCast(TranslatedInvoke, Int8PtrTyGen, "", BB); } Instruction *SPIRVToLLVM::transEnqueueKernelBI(SPIRVInstruction *BI, BasicBlock *BB) { Type *Int32Ty = Type::getInt32Ty(*Context); Type *Int64Ty = Type::getInt64Ty(*Context); Type *IntTy = M->getDataLayout().getPointerSizeInBits(0) == 32 ? Int32Ty : Int64Ty; // Find or create enqueue kernel BI declaration auto Ops = BI->getOperands(); bool HasVaargs = Ops.size() > 10; bool HasEvents = true; SPIRVValue *EventRet = Ops[5]; if (EventRet->getOpCode() == OpConstantNull) { SPIRVValue *NumEvents = Ops[3]; if (NumEvents->getOpCode() == OpConstant) { SPIRVConstant *NE = static_cast(NumEvents); HasEvents = NE->getZExtIntValue() != 0; } else if (NumEvents->getOpCode() == OpConstantNull) HasEvents = false; } std::string FName = ""; if (!HasVaargs && !HasEvents) FName = "__enqueue_kernel_basic"; else if (!HasVaargs && HasEvents) FName = "__enqueue_kernel_basic_events"; else if (HasVaargs && !HasEvents) FName = "__enqueue_kernel_varargs"; else FName = "__enqueue_kernel_events_varargs"; Function *F = M->getFunction(FName); if (!F) { SmallVector Tys = { transType(Ops[0]->getType()), // queue Int32Ty, // flags transType(Ops[2]->getType()), // ndrange }; if (HasEvents) { Type *EventTy = PointerType::get(getOrCreateOpaquePtrType( M, SPIR_TYPE_NAME_CLK_EVENT_T, getOCLOpaqueTypeAddrSpace(OpTypeDeviceEvent)), SPIRAS_Generic); Tys.push_back(Int32Ty); Tys.push_back(EventTy); Tys.push_back(EventTy); } Tys.push_back(Type::getInt8PtrTy(*Context, SPIRAS_Generic)); Tys.push_back(Type::getInt8PtrTy(*Context, SPIRAS_Generic)); if (HasVaargs) { // Number of block invoke arguments (local arguments) Tys.push_back(Int32Ty); // Array of sizes of block invoke arguments Tys.push_back(PointerType::get(IntTy, SPIRAS_Private)); } FunctionType *FT = FunctionType::get(Int32Ty, Tys, false); F = Function::Create(FT, GlobalValue::ExternalLinkage, FName, M); if (isFuncNoUnwind()) F->addFnAttr(Attribute::NoUnwind); } // Create call to enqueue kernel BI SmallVector Args = { transValue(Ops[0], F, BB, false), // queue transValue(Ops[1], F, BB, false), // flags transValue(Ops[2], F, BB, false), // ndrange }; if (HasEvents) { Args.push_back(transValue(Ops[3], F, BB, false)); // events number Args.push_back(transDeviceEvent(Ops[4], F, BB)); // event_wait_list Args.push_back(transDeviceEvent(Ops[5], F, BB)); // event_ret } Args.push_back(transBlockInvoke(Ops[6], BB)); // block_invoke Args.push_back(transValue(Ops[7], F, BB, false)); // block_literal if (HasVaargs) { // Number of local arguments Args.push_back(ConstantInt::get(Int32Ty, Ops.size() - 10)); // GEP to array of sizes of local arguments if (Ops[10]->getOpCode() == OpPtrAccessChain) Args.push_back(transValue(Ops[10], F, BB, false)); else llvm_unreachable("Not implemented"); } auto Call = CallInst::Create(F, Args, "", BB); setName(Call, BI); setAttrByCalledFunc(Call); return Call; } Instruction *SPIRVToLLVM::transWGSizeQueryBI(SPIRVInstruction *BI, BasicBlock *BB) { std::string FName = (BI->getOpCode() == OpGetKernelWorkGroupSize) ? "__get_kernel_work_group_size_impl" : "__get_kernel_preferred_work_group_size_multiple_impl"; Function *F = M->getFunction(FName); if (!F) { auto Int8PtrTyGen = Type::getInt8PtrTy(*Context, SPIRAS_Generic); FunctionType *FT = FunctionType::get(Type::getInt32Ty(*Context), {Int8PtrTyGen, Int8PtrTyGen}, false); F = Function::Create(FT, GlobalValue::ExternalLinkage, FName, M); if (isFuncNoUnwind()) F->addFnAttr(Attribute::NoUnwind); } auto Ops = BI->getOperands(); SmallVector Args = {transBlockInvoke(Ops[0], BB), transValue(Ops[1], F, BB, false)}; auto Call = CallInst::Create(F, Args, "", BB); setName(Call, BI); setAttrByCalledFunc(Call); return Call; } Instruction *SPIRVToLLVM::transSGSizeQueryBI(SPIRVInstruction *BI, BasicBlock *BB) { std::string FName = (BI->getOpCode() == OpGetKernelNDrangeMaxSubGroupSize) ? "__get_kernel_max_sub_group_size_for_ndrange_impl" : "__get_kernel_sub_group_count_for_ndrange_impl"; auto Ops = BI->getOperands(); Function *F = M->getFunction(FName); if (!F) { auto Int8PtrTyGen = Type::getInt8PtrTy(*Context, SPIRAS_Generic); SmallVector Tys = { transType(Ops[0]->getType()), // ndrange Int8PtrTyGen, // block_invoke Int8PtrTyGen // block_literal }; auto *FT = FunctionType::get(Type::getInt32Ty(*Context), Tys, false); F = Function::Create(FT, GlobalValue::ExternalLinkage, FName, M); if (isFuncNoUnwind()) F->addFnAttr(Attribute::NoUnwind); } SmallVector Args = { transValue(Ops[0], F, BB, false), // ndrange transBlockInvoke(Ops[1], BB), // block_invoke transValue(Ops[2], F, BB, false) // block_literal }; auto Call = CallInst::Create(F, Args, "", BB); setName(Call, BI); setAttrByCalledFunc(Call); return Call; } Instruction *SPIRVToLLVM::transBuiltinFromInst(const std::string &FuncName, SPIRVInstruction *BI, BasicBlock *BB) { std::string MangledName; auto Ops = BI->getOperands(); Type *RetTy = BI->hasType() ? transType(BI->getType()) : Type::getVoidTy(*Context); transOCLBuiltinFromInstPreproc(BI, RetTy, Ops); std::vector ArgTys = transTypeVector(SPIRVInstruction::getOperandTypes(Ops)); bool HasFuncPtrArg = false; for (auto &I : ArgTys) { if (isa(I)) { I = PointerType::get(I, SPIRAS_Private); HasFuncPtrArg = true; } } if (!HasFuncPtrArg) mangleOpenClBuiltin(FuncName, ArgTys, MangledName); else MangledName = decorateSPIRVFunction(FuncName); Function *Func = M->getFunction(MangledName); FunctionType *FT = FunctionType::get(RetTy, ArgTys, false); // ToDo: Some intermediate functions have duplicate names with // different function types. This is OK if the function name // is used internally and finally translated to unique function // names. However it is better to have a way to differentiate // between intermidiate functions and final functions and make // sure final functions have unique names. SPIRVDBG(if (!HasFuncPtrArg && Func && Func->getFunctionType() != FT) { dbgs() << "Warning: Function name conflict:\n" << *Func << '\n' << " => " << *FT << '\n'; }) if (!Func || Func->getFunctionType() != FT) { LLVM_DEBUG(for (auto &I : ArgTys) { dbgs() << *I << '\n'; }); Func = Function::Create(FT, GlobalValue::ExternalLinkage, MangledName, M); Func->setCallingConv(CallingConv::SPIR_FUNC); if (isFuncNoUnwind()) Func->addFnAttr(Attribute::NoUnwind); } auto Call = CallInst::Create(Func, transValue(Ops, BB->getParent(), BB), "", BB); setName(Call, BI); setAttrByCalledFunc(Call); SPIRVDBG(spvdbgs() << "[transInstToBuiltinCall] " << *BI << " -> "; dbgs() << *Call << '\n';) Instruction *Inst = transOCLBuiltinPostproc(BI, Call, BB, FuncName); return Inst; } SPIRVToLLVM::SPIRVToLLVM(Module *LLVMModule, SPIRVModule *TheSPIRVModule) : M(LLVMModule), BM(TheSPIRVModule) { assert(M && "Initialization without an LLVM module is not allowed"); Context = &M->getContext(); DbgTran.reset(new SPIRVToLLVMDbgTran(TheSPIRVModule, LLVMModule, this)); } std::string SPIRVToLLVM::getOCLBuiltinName(SPIRVInstruction *BI) { auto OC = BI->getOpCode(); if (OC == OpGenericCastToPtrExplicit) return getOCLGenericCastToPtrName(BI); if (isCvtOpCode(OC)) return getOCLConvertBuiltinName(BI); if (OC == OpBuildNDRange) { auto NDRangeInst = static_cast(BI); auto EleTy = ((NDRangeInst->getOperands())[0])->getType(); int Dim = EleTy->isTypeArray() ? EleTy->getArrayLength() : 1; // cygwin does not have std::to_string ostringstream OS; OS << Dim; assert((EleTy->isTypeInt() && Dim == 1) || (EleTy->isTypeArray() && Dim >= 2 && Dim <= 3)); return std::string(kOCLBuiltinName::NDRangePrefix) + OS.str() + "D"; } if (isIntelSubgroupOpCode(OC)) { std::stringstream Name; SPIRVType *DataTy = nullptr; switch (OC) { case OpSubgroupBlockReadINTEL: case OpSubgroupImageBlockReadINTEL: Name << "intel_sub_group_block_read"; DataTy = BI->getType(); break; case OpSubgroupBlockWriteINTEL: Name << "intel_sub_group_block_write"; DataTy = BI->getOperands()[1]->getType(); break; case OpSubgroupImageBlockWriteINTEL: Name << "intel_sub_group_block_write"; DataTy = BI->getOperands()[2]->getType(); break; default: return OCLSPIRVBuiltinMap::rmap(OC); } if (DataTy) { if (DataTy->getBitWidth() == 16) Name << "_us"; if (DataTy->isTypeVector()) { if (unsigned ComponentCount = DataTy->getVectorComponentCount()) Name << ComponentCount; } } return Name.str(); } if (isSubgroupAvcINTELInstructionOpCode(OC)) return OCLSPIRVSubgroupAVCIntelBuiltinMap::rmap(OC); auto Name = OCLSPIRVBuiltinMap::rmap(OC); SPIRVType *T = nullptr; switch (OC) { case OpImageRead: T = BI->getType(); break; case OpImageWrite: T = BI->getOperands()[2]->getType(); break; default: // do nothing break; } if (T && T->isTypeVector()) T = T->getVectorComponentType(); if (T) { if (T->isTypeFloat(16)) Name += 'h'; else if (T->isTypeFloat(32)) Name += 'f'; else Name += 'i'; } return Name; } Instruction *SPIRVToLLVM::transOCLBuiltinFromInst(SPIRVInstruction *BI, BasicBlock *BB) { assert(BB && "Invalid BB"); auto FuncName = getOCLBuiltinName(BI); return transBuiltinFromInst(FuncName, BI, BB); } Instruction *SPIRVToLLVM::transSPIRVBuiltinFromInst(SPIRVInstruction *BI, BasicBlock *BB) { assert(BB && "Invalid BB"); string Suffix = ""; if (BI->getOpCode() == OpCreatePipeFromPipeStorage) { auto CPFPS = static_cast(BI); assert(CPFPS->getType()->isTypePipe() && "Invalid type of CreatePipeFromStorage"); auto PipeType = static_cast(CPFPS->getType()); switch (PipeType->getAccessQualifier()) { default: case AccessQualifierReadOnly: Suffix = "_read"; break; case AccessQualifierWriteOnly: Suffix = "_write"; break; case AccessQualifierReadWrite: Suffix = "_read_write"; break; } } return transBuiltinFromInst(getSPIRVFuncName(BI->getOpCode(), Suffix), BI, BB); } bool SPIRVToLLVM::translate() { if (!transAddressingModel()) return false; for (unsigned I = 0, E = BM->getNumVariables(); I != E; ++I) { auto BV = BM->getVariable(I); if (BV->getStorageClass() != StorageClassFunction) transValue(BV, nullptr, nullptr); } transGlobalAnnotations(); // Compile unit might be needed during translation of debug intrinsics. for (SPIRVExtInst *EI : BM->getDebugInstVec()) { // Translate Compile Unit first. // It shuldn't be far from the beginig of the vector if (EI->getExtOp() == SPIRVDebug::CompilationUnit) { DbgTran->transDebugInst(EI); // Fixme: there might be more then one Compile Unit. break; } } // Then translate all debug instructions. for (SPIRVExtInst *EI : BM->getDebugInstVec()) { DbgTran->transDebugInst(EI); } for (unsigned I = 0, E = BM->getNumFunctions(); I != E; ++I) { transFunction(BM->getFunction(I)); } if (!transKernelMetadata()) return false; if (!transFPContractMetadata()) return false; if (!transSourceLanguage()) return false; if (!transSourceExtension()) return false; transGeneratorMD(); if (!transOCLBuiltinsFromVariables()) return false; if (!postProcessOCL()) return false; eraseUselessFunctions(M); DbgTran->addDbgInfoVersion(); DbgTran->finalize(); return true; } bool SPIRVToLLVM::transAddressingModel() { switch (BM->getAddressingModel()) { case AddressingModelPhysical64: M->setTargetTriple(SPIR_TARGETTRIPLE64); M->setDataLayout(SPIR_DATALAYOUT64); break; case AddressingModelPhysical32: M->setTargetTriple(SPIR_TARGETTRIPLE32); M->setDataLayout(SPIR_DATALAYOUT32); break; case AddressingModelLogical: // Do not set target triple and data layout break; default: SPIRVCKRT(0, InvalidAddressingModel, "Actual addressing mode is " + std::to_string(BM->getAddressingModel())); } return true; } void generateIntelFPGAAnnotation(const SPIRVEntry *E, llvm::SmallString<256> &AnnotStr) { llvm::raw_svector_ostream Out(AnnotStr); if (E->hasDecorate(DecorationRegisterINTEL)) Out << "{register:1}"; SPIRVWord Result = 0; if (E->hasDecorate(DecorationMemoryINTEL)) Out << "{memory:" << E->getDecorationStringLiteral(DecorationMemoryINTEL).front() << '}'; if (E->hasDecorate(DecorationBankwidthINTEL, 0, &Result)) Out << "{bankwidth:" << Result << '}'; if (E->hasDecorate(DecorationNumbanksINTEL, 0, &Result)) Out << "{numbanks:" << Result << '}'; if (E->hasDecorate(DecorationMaxPrivateCopiesINTEL, 0, &Result)) Out << "{private_copies:" << Result << '}'; if (E->hasDecorate(DecorationSinglepumpINTEL)) Out << "{pump:1}"; if (E->hasDecorate(DecorationDoublepumpINTEL)) Out << "{pump:2}"; if (E->hasDecorate(DecorationMaxReplicatesINTEL, 0, &Result)) Out << "{max_replicates:" << Result << '}'; if (E->hasDecorate(DecorationSimpleDualPortINTEL)) Out << "{simple_dual_port:1}"; if (E->hasDecorate(DecorationMergeINTEL)) { Out << "{merge"; for (auto Str : E->getDecorationStringLiteral(DecorationMergeINTEL)) Out << ":" << Str; Out << '}'; } if (E->hasDecorate(DecorationBankBitsINTEL)) { Out << "{bank_bits:"; auto Literals = E->getDecorationLiterals(DecorationBankBitsINTEL); for (size_t I = 0; I < Literals.size() - 1; ++I) Out << Literals[I] << ","; Out << Literals.back() << '}'; } if (E->hasDecorate(DecorationUserSemantic)) Out << E->getDecorationStringLiteral(DecorationUserSemantic).front(); } void generateIntelFPGAAnnotationForStructMember( const SPIRVEntry *E, SPIRVWord MemberNumber, llvm::SmallString<256> &AnnotStr) { llvm::raw_svector_ostream Out(AnnotStr); if (E->hasMemberDecorate(DecorationRegisterINTEL, 0, MemberNumber)) Out << "{register:1}"; SPIRVWord Result = 0; if (E->hasMemberDecorate(DecorationMemoryINTEL, 0, MemberNumber, &Result)) Out << "{memory:" << E->getMemberDecorationStringLiteral(DecorationMemoryINTEL, MemberNumber) .front() << '}'; if (E->hasMemberDecorate(DecorationBankwidthINTEL, 0, MemberNumber, &Result)) Out << "{bankwidth:" << Result << '}'; if (E->hasMemberDecorate(DecorationNumbanksINTEL, 0, MemberNumber, &Result)) Out << "{numbanks:" << Result << '}'; if (E->hasMemberDecorate(DecorationMaxPrivateCopiesINTEL, 0, MemberNumber, &Result)) Out << "{private_copies:" << Result << '}'; if (E->hasMemberDecorate(DecorationSinglepumpINTEL, 0, MemberNumber)) Out << "{pump:1}"; if (E->hasMemberDecorate(DecorationDoublepumpINTEL, 0, MemberNumber)) Out << "{pump:2}"; if (E->hasMemberDecorate(DecorationMaxReplicatesINTEL, 0, MemberNumber, &Result)) Out << "{max_replicates:" << Result << '}'; if (E->hasMemberDecorate(DecorationSimpleDualPortINTEL, 0, MemberNumber)) Out << "{simple_dual_port:1}"; if (E->hasMemberDecorate(DecorationMergeINTEL, 0, MemberNumber)) { Out << "{merge"; for (auto Str : E->getMemberDecorationStringLiteral(DecorationMergeINTEL, MemberNumber)) Out << ":" << Str; Out << '}'; } if (E->hasMemberDecorate(DecorationBankBitsINTEL, 0, MemberNumber)) { Out << "{bank_bits:"; auto Literals = E->getMemberDecorationLiterals(DecorationBankBitsINTEL, MemberNumber); for (size_t I = 0; I < Literals.size() - 1; ++I) Out << Literals[I] << ","; Out << Literals.back() << '}'; } if (E->hasMemberDecorate(DecorationUserSemantic, 0, MemberNumber)) Out << E->getMemberDecorationStringLiteral(DecorationUserSemantic, MemberNumber) .front(); } void SPIRVToLLVM::transIntelFPGADecorations(SPIRVValue *BV, Value *V) { if (!BV->isVariable()) return; if (auto AL = dyn_cast(V)) { IRBuilder<> Builder(AL->getParent()); SPIRVType *ST = BV->getType()->getPointerElementType(); Type *Int8PtrTyPrivate = Type::getInt8PtrTy(*Context, SPIRAS_Private); IntegerType *Int32Ty = IntegerType::get(*Context, 32); Value *UndefInt8Ptr = UndefValue::get(Int8PtrTyPrivate); Value *UndefInt32 = UndefValue::get(Int32Ty); if (ST->isTypeStruct()) { SPIRVTypeStruct *STS = static_cast(ST); for (SPIRVWord I = 0; I < STS->getMemberCount(); ++I) { SmallString<256> AnnotStr; generateIntelFPGAAnnotationForStructMember(ST, I, AnnotStr); if (!AnnotStr.empty()) { auto *GS = Builder.CreateGlobalStringPtr(AnnotStr); auto GEP = Builder.CreateConstInBoundsGEP2_32(AL->getAllocatedType(), AL, 0, I); Type *IntTy = GEP->getType()->getPointerElementType()->isIntegerTy() ? GEP->getType() : Int8PtrTyPrivate; auto AnnotationFn = llvm::Intrinsic::getDeclaration( M, Intrinsic::ptr_annotation, IntTy); llvm::Value *Args[] = { Builder.CreateBitCast(GEP, IntTy, GEP->getName()), Builder.CreateBitCast(GS, Int8PtrTyPrivate), UndefInt8Ptr, UndefInt32}; Builder.CreateCall(AnnotationFn, Args); } } } SmallString<256> AnnotStr; generateIntelFPGAAnnotation(BV, AnnotStr); if (!AnnotStr.empty()) { auto *GS = Builder.CreateGlobalStringPtr(AnnotStr); auto AnnotationFn = llvm::Intrinsic::getDeclaration(M, Intrinsic::var_annotation); llvm::Value *Args[] = { Builder.CreateBitCast(V, Int8PtrTyPrivate, V->getName()), Builder.CreateBitCast(GS, Int8PtrTyPrivate), UndefInt8Ptr, UndefInt32}; Builder.CreateCall(AnnotationFn, Args); } } else if (auto *GV = dyn_cast(V)) { SmallString<256> AnnotStr; generateIntelFPGAAnnotation(BV, AnnotStr); if (AnnotStr.empty()) return; Constant *StrConstant = ConstantDataArray::getString(*Context, StringRef(AnnotStr)); auto *GS = new GlobalVariable(*GV->getParent(), StrConstant->getType(), /*IsConstant*/ true, GlobalValue::PrivateLinkage, StrConstant, ""); GS->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); GS->setSection("llvm.metadata"); Type *ResType = PointerType::getInt8PtrTy( GV->getContext(), GV->getType()->getPointerAddressSpace()); Constant *C = ConstantExpr::getPointerBitCastOrAddrSpaceCast(GV, ResType); Type *Int8PtrTyPrivate = Type::getInt8PtrTy(*Context, SPIRAS_Private); IntegerType *Int32Ty = Type::getInt32Ty(*Context); llvm::Constant *Fields[4] = { C, ConstantExpr::getBitCast(GS, Int8PtrTyPrivate), UndefValue::get(Int8PtrTyPrivate), UndefValue::get(Int32Ty)}; GlobalAnnotations.push_back(ConstantStruct::getAnon(Fields)); } } void SPIRVToLLVM::transGlobalAnnotations() { if (!GlobalAnnotations.empty()) { Constant *Array = ConstantArray::get(ArrayType::get(GlobalAnnotations[0]->getType(), GlobalAnnotations.size()), GlobalAnnotations); auto *GV = new GlobalVariable(*M, Array->getType(), /*IsConstant*/ false, GlobalValue::AppendingLinkage, Array, "llvm.global.annotations"); GV->setSection("llvm.metadata"); } } bool SPIRVToLLVM::transDecoration(SPIRVValue *BV, Value *V) { if (!transAlign(BV, V)) return false; transIntelFPGADecorations(BV, V); DbgTran->transDbgInfo(BV, V); return true; } bool SPIRVToLLVM::transFPContractMetadata() { bool ContractOff = false; for (unsigned I = 0, E = BM->getNumFunctions(); I != E; ++I) { SPIRVFunction *BF = BM->getFunction(I); if (!isOpenCLKernel(BF)) continue; if (BF->getExecutionMode(ExecutionModeContractionOff)) { ContractOff = true; break; } } if (!ContractOff) M->getOrInsertNamedMetadata(kSPIR2MD::FPContract); return true; } std::string SPIRVToLLVM::transOCLImageTypeAccessQualifier(SPIRV::SPIRVTypeImage *ST) { return SPIRSPIRVAccessQualifierMap::rmap(ST->hasAccessQualifier() ? ST->getAccessQualifier() : AccessQualifierReadOnly); } bool SPIRVToLLVM::transNonTemporalMetadata(Instruction *I) { Constant *One = ConstantInt::get(Type::getInt32Ty(*Context), 1); MDNode *Node = MDNode::get(*Context, ConstantAsMetadata::get(One)); I->setMetadata(M->getMDKindID("nontemporal"), Node); return true; } // Information of types of kernel arguments may be additionally stored in // 'OpString "kernel_arg_type.%kernel_name%.type1,type2,type3,..' instruction. // Try to find such instruction and generate metadata based on it. // Return 'true' if 'OpString' was found and 'kernel_arg_type' metadata // generated and 'false' otherwise. static bool transKernelArgTypeMedataFromString(LLVMContext *Ctx, SPIRVModule *BM, Function *Kernel) { std::string ArgTypePrefix = std::string(SPIR_MD_KERNEL_ARG_TYPE) + "." + Kernel->getName().str() + "."; auto ArgTypeStrIt = std::find_if( BM->getStringVec().begin(), BM->getStringVec().end(), [=](SPIRVString *S) { return S->getStr().find(ArgTypePrefix) == 0; }); if (ArgTypeStrIt == BM->getStringVec().end()) return false; std::string ArgTypeStr = (*ArgTypeStrIt)->getStr().substr(ArgTypePrefix.size()); std::vector TypeMDs; int CountBraces = 0; std::string::size_type Start = 0; for (std::string::size_type I = 0; I < ArgTypeStr.length(); I++) { switch (ArgTypeStr[I]) { case '<': CountBraces++; break; case '>': CountBraces--; break; case ',': if (CountBraces == 0) { TypeMDs.push_back( MDString::get(*Ctx, ArgTypeStr.substr(Start, I - Start))); Start = I + 1; } } } Kernel->setMetadata(SPIR_MD_KERNEL_ARG_TYPE, MDNode::get(*Ctx, TypeMDs)); return true; } bool SPIRVToLLVM::transKernelMetadata() { for (unsigned I = 0, E = BM->getNumFunctions(); I != E; ++I) { SPIRVFunction *BF = BM->getFunction(I); Function *F = static_cast(getTranslatedValue(BF)); assert(F && "Invalid translated function"); if (F->getCallingConv() != CallingConv::SPIR_KERNEL) continue; // Generate metadata for kernel_arg_address_spaces addOCLKernelArgumentMetadata( Context, SPIR_MD_KERNEL_ARG_ADDR_SPACE, BF, F, [=](SPIRVFunctionParameter *Arg) { SPIRVType *ArgTy = Arg->getType(); SPIRAddressSpace AS = SPIRAS_Private; if (ArgTy->isTypePointer()) AS = SPIRSPIRVAddrSpaceMap::rmap(ArgTy->getPointerStorageClass()); else if (ArgTy->isTypeOCLImage() || ArgTy->isTypePipe()) AS = SPIRAS_Global; return ConstantAsMetadata::get( ConstantInt::get(Type::getInt32Ty(*Context), AS)); }); // Generate metadata for kernel_arg_access_qual addOCLKernelArgumentMetadata(Context, SPIR_MD_KERNEL_ARG_ACCESS_QUAL, BF, F, [=](SPIRVFunctionParameter *Arg) { std::string Qual; auto T = Arg->getType(); if (T->isTypeOCLImage()) { auto ST = static_cast(T); Qual = transOCLImageTypeAccessQualifier(ST); } else if (T->isTypePipe()) { auto PT = static_cast(T); Qual = transOCLPipeTypeAccessQualifier(PT); } else Qual = "none"; return MDString::get(*Context, Qual); }); // Generate metadata for kernel_arg_type if (!transKernelArgTypeMedataFromString(Context, BM, F)) addOCLKernelArgumentMetadata(Context, SPIR_MD_KERNEL_ARG_TYPE, BF, F, [=](SPIRVFunctionParameter *Arg) { return transOCLKernelArgTypeName(Arg); }); // Generate metadata for kernel_arg_type_qual addOCLKernelArgumentMetadata( Context, SPIR_MD_KERNEL_ARG_TYPE_QUAL, BF, F, [=](SPIRVFunctionParameter *Arg) { std::string Qual; if (Arg->hasDecorate(DecorationVolatile)) Qual = kOCLTypeQualifierName::Volatile; Arg->foreachAttr([&](SPIRVFuncParamAttrKind Kind) { Qual += Qual.empty() ? "" : " "; switch (Kind) { case FunctionParameterAttributeNoAlias: Qual += kOCLTypeQualifierName::Restrict; break; case FunctionParameterAttributeNoWrite: Qual += kOCLTypeQualifierName::Const; break; default: // do nothing. break; } }); if (Arg->getType()->isTypePipe()) { Qual += Qual.empty() ? "" : " "; Qual += kOCLTypeQualifierName::Pipe; } return MDString::get(*Context, Qual); }); // Generate metadata for kernel_arg_base_type addOCLKernelArgumentMetadata(Context, SPIR_MD_KERNEL_ARG_BASE_TYPE, BF, F, [=](SPIRVFunctionParameter *Arg) { return transOCLKernelArgTypeName(Arg); }); // Generate metadata for kernel_arg_name if (BM->isGenArgNameMDEnabled()) { addOCLKernelArgumentMetadata(Context, SPIR_MD_KERNEL_ARG_NAME, BF, F, [=](SPIRVFunctionParameter *Arg) { return MDString::get(*Context, Arg->getName()); }); } // Generate metadata for reqd_work_group_size if (auto EM = BF->getExecutionMode(ExecutionModeLocalSize)) { F->setMetadata(kSPIR2MD::WGSize, getMDNodeStringIntVec(Context, EM->getLiterals())); } // Generate metadata for work_group_size_hint if (auto EM = BF->getExecutionMode(ExecutionModeLocalSizeHint)) { F->setMetadata(kSPIR2MD::WGSizeHint, getMDNodeStringIntVec(Context, EM->getLiterals())); } // Generate metadata for vec_type_hint if (auto EM = BF->getExecutionMode(ExecutionModeVecTypeHint)) { std::vector MetadataVec; Type *VecHintTy = decodeVecTypeHint(*Context, EM->getLiterals()[0]); assert(VecHintTy); MetadataVec.push_back(ValueAsMetadata::get(UndefValue::get(VecHintTy))); MetadataVec.push_back(ConstantAsMetadata::get( ConstantInt::get(Type::getInt32Ty(*Context), 1))); F->setMetadata(kSPIR2MD::VecTyHint, MDNode::get(*Context, MetadataVec)); } // Generate metadata for intel_reqd_sub_group_size if (auto *EM = BF->getExecutionMode(ExecutionModeSubgroupSize)) { auto SizeMD = ConstantAsMetadata::get(getUInt32(M, EM->getLiterals()[0])); F->setMetadata(kSPIR2MD::SubgroupSize, MDNode::get(*Context, SizeMD)); } // Generate metadata for max_work_group_size if (auto EM = BF->getExecutionMode(ExecutionModeMaxWorkgroupSizeINTEL)) { F->setMetadata(kSPIR2MD::MaxWGSize, getMDNodeStringIntVec(Context, EM->getLiterals())); } // Generate metadata for max_global_work_dim if (auto EM = BF->getExecutionMode(ExecutionModeMaxWorkDimINTEL)) { F->setMetadata(kSPIR2MD::MaxWGDim, getMDNodeStringIntVec(Context, EM->getLiterals())); } // Generate metadata for num_simd_work_items if (auto EM = BF->getExecutionMode(ExecutionModeNumSIMDWorkitemsINTEL)) { F->setMetadata(kSPIR2MD::NumSIMD, getMDNodeStringIntVec(Context, EM->getLiterals())); } } return true; } bool SPIRVToLLVM::transAlign(SPIRVValue *BV, Value *V) { if (auto AL = dyn_cast(V)) { SPIRVWord Align = 0; if (BV->hasAlignment(&Align)) AL->setAlignment(MaybeAlign(Align)); return true; } if (auto GV = dyn_cast(V)) { SPIRVWord Align = 0; if (BV->hasAlignment(&Align)) GV->setAlignment(MaybeAlign(Align)); return true; } return true; } void SPIRVToLLVM::transOCLVectorLoadStore(std::string &UnmangledName, std::vector &BArgs) { if (UnmangledName.find("vload") == 0 && UnmangledName.find("n") != std::string::npos) { if (BArgs.back() != 1) { std::stringstream SS; SS << BArgs.back(); UnmangledName.replace(UnmangledName.find("n"), 1, SS.str()); } else { UnmangledName.erase(UnmangledName.find("n"), 1); } BArgs.pop_back(); } else if (UnmangledName.find("vstore") == 0) { if (UnmangledName.find("n") != std::string::npos) { auto T = BM->getValueType(BArgs[0]); if (T->isTypeVector()) { auto W = T->getVectorComponentCount(); std::stringstream SS; SS << W; UnmangledName.replace(UnmangledName.find("n"), 1, SS.str()); } else { UnmangledName.erase(UnmangledName.find("n"), 1); } } if (UnmangledName.find("_r") != std::string::npos) { UnmangledName.replace( UnmangledName.find("_r"), 2, std::string("_") + SPIRSPIRVFPRoundingModeMap::rmap( static_cast(BArgs.back()))); BArgs.pop_back(); } } } // printf is not mangled. The function type should have just one argument. // read_image*: the second argument should be mangled as sampler. Instruction *SPIRVToLLVM::transOCLBuiltinFromExtInst(SPIRVExtInst *BC, BasicBlock *BB) { assert(BB && "Invalid BB"); std::string MangledName; SPIRVWord EntryPoint = BC->getExtOp(); bool IsVarArg = false; bool IsPrintf = false; std::string UnmangledName; auto BArgs = BC->getArguments(); assert(BM->getBuiltinSet(BC->getExtSetId()) == SPIRVEIS_OpenCL && "Not OpenCL extended instruction"); if (EntryPoint == OpenCLLIB::Printf) IsPrintf = true; else { UnmangledName = OCLExtOpMap::map(static_cast(EntryPoint)); } SPIRVDBG(spvdbgs() << "[transOCLBuiltinFromExtInst] OrigUnmangledName: " << UnmangledName << '\n'); transOCLVectorLoadStore(UnmangledName, BArgs); std::vector ArgTypes = transTypeVector(BC->getValueTypes(BArgs)); if (IsPrintf) { MangledName = "printf"; IsVarArg = true; ArgTypes.resize(1); } else if (UnmangledName.find("read_image") == 0) { auto ModifiedArgTypes = ArgTypes; ModifiedArgTypes[1] = getOrCreateOpaquePtrType(M, "opencl.sampler_t"); mangleOpenClBuiltin(UnmangledName, ModifiedArgTypes, MangledName); } else { mangleOpenClBuiltin(UnmangledName, ArgTypes, MangledName); } SPIRVDBG(spvdbgs() << "[transOCLBuiltinFromExtInst] ModifiedUnmangledName: " << UnmangledName << " MangledName: " << MangledName << '\n'); FunctionType *FT = FunctionType::get(transType(BC->getType()), ArgTypes, IsVarArg); Function *F = M->getFunction(MangledName); if (!F) { F = Function::Create(FT, GlobalValue::ExternalLinkage, MangledName, M); F->setCallingConv(CallingConv::SPIR_FUNC); if (isFuncNoUnwind()) F->addFnAttr(Attribute::NoUnwind); } auto Args = transValue(BC->getValues(BArgs), F, BB); SPIRVDBG(dbgs() << "[transOCLBuiltinFromExtInst] Function: " << *F << ", Args: "; for (auto &I : Args) dbgs() << *I << ", "; dbgs() << '\n'); CallInst *Call = CallInst::Create(F, Args, BC->getName(), BB); setCallingConv(Call); addFnAttr(Call, Attribute::NoUnwind); return transOCLBuiltinPostproc(BC, Call, BB, UnmangledName); } // SPIR-V only contains language version. Use OpenCL language version as // SPIR version. bool SPIRVToLLVM::transSourceLanguage() { SPIRVWord Ver = 0; SourceLanguage Lang = BM->getSourceLanguage(&Ver); assert((Lang == SourceLanguageUnknown || // Allow unknown for debug info test Lang == SourceLanguageOpenCL_C || Lang == SourceLanguageOpenCL_CPP) && "Unsupported source language"); unsigned short Major = 0; unsigned char Minor = 0; unsigned char Rev = 0; std::tie(Major, Minor, Rev) = decodeOCLVer(Ver); SPIRVMDBuilder Builder(*M); Builder.addNamedMD(kSPIRVMD::Source).addOp().add(Lang).add(Ver).done(); // ToDo: Phasing out usage of old SPIR metadata if (Ver <= kOCLVer::CL12) addOCLVersionMetadata(Context, M, kSPIR2MD::SPIRVer, 1, 2); else addOCLVersionMetadata(Context, M, kSPIR2MD::SPIRVer, 2, 0); addOCLVersionMetadata(Context, M, kSPIR2MD::OCLVer, Major, Minor); return true; } bool SPIRVToLLVM::transSourceExtension() { auto ExtSet = rmap(BM->getExtension()); auto CapSet = rmap(BM->getCapability()); ExtSet.insert(CapSet.begin(), CapSet.end()); auto OCLExtensions = map(ExtSet); std::set OCLOptionalCoreFeatures; static const char *OCLOptCoreFeatureNames[] = { "cl_images", "cl_doubles", }; for (auto &I : OCLOptCoreFeatureNames) { auto Loc = OCLExtensions.find(I); if (Loc != OCLExtensions.end()) { OCLExtensions.erase(Loc); OCLOptionalCoreFeatures.insert(I); } } addNamedMetadataStringSet(Context, M, kSPIR2MD::Extensions, OCLExtensions); addNamedMetadataStringSet(Context, M, kSPIR2MD::OptFeatures, OCLOptionalCoreFeatures); return true; } // If the argument is unsigned return uconvert*, otherwise return convert*. std::string SPIRVToLLVM::getOCLConvertBuiltinName(SPIRVInstruction *BI) { auto OC = BI->getOpCode(); assert(isCvtOpCode(OC) && "Not convert instruction"); auto U = static_cast(BI); std::string Name; if (isCvtFromUnsignedOpCode(OC)) Name = "u"; Name += "convert_"; Name += mapSPIRVTypeToOCLType(U->getType(), !isCvtToUnsignedOpCode(OC)); SPIRVFPRoundingModeKind Rounding; if (U->isSaturatedConversion()) Name += "_sat"; if (U->hasFPRoundingMode(&Rounding)) { Name += "_"; Name += SPIRSPIRVFPRoundingModeMap::rmap(Rounding); } return Name; } // Check Address Space of the Pointer Type std::string SPIRVToLLVM::getOCLGenericCastToPtrName(SPIRVInstruction *BI) { auto GenericCastToPtrInst = BI->getType()->getPointerStorageClass(); switch (GenericCastToPtrInst) { case StorageClassCrossWorkgroup: return std::string(kOCLBuiltinName::ToGlobal); case StorageClassWorkgroup: return std::string(kOCLBuiltinName::ToLocal); case StorageClassFunction: return std::string(kOCLBuiltinName::ToPrivate); default: llvm_unreachable("Invalid address space"); return ""; } } llvm::GlobalValue::LinkageTypes SPIRVToLLVM::transLinkageType(const SPIRVValue *V) { if (V->getLinkageType() == LinkageTypeInternal) { return GlobalValue::InternalLinkage; } else if (V->getLinkageType() == LinkageTypeImport) { // Function declaration if (V->getOpCode() == OpFunction) { if (static_cast(V)->getNumBasicBlock() == 0) return GlobalValue::ExternalLinkage; } // Variable declaration if (V->getOpCode() == OpVariable) { if (static_cast(V)->getInitializer() == 0) return GlobalValue::ExternalLinkage; } // Definition return GlobalValue::AvailableExternallyLinkage; } else { // LinkageTypeExport if (V->getOpCode() == OpVariable) { if (static_cast(V)->getInitializer() == 0) // Tentative definition return GlobalValue::CommonLinkage; } return GlobalValue::ExternalLinkage; } } Instruction *SPIRVToLLVM::transOCLAllAny(SPIRVInstruction *I, BasicBlock *BB) { CallInst *CI = cast(transSPIRVBuiltinFromInst(I, BB)); assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); return cast(mapValue( I, mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args, llvm::Type *&RetTy) { Type *Int32Ty = Type::getInt32Ty(*Context); auto OldArg = CI->getOperand(0); auto NewArgTy = VectorType::get( Int32Ty, OldArg->getType()->getVectorNumElements()); auto NewArg = CastInst::CreateSExtOrBitCast(OldArg, NewArgTy, "", CI); Args[0] = NewArg; RetTy = Int32Ty; return CI->getCalledFunction()->getName(); }, [=](CallInst *NewCI) -> Instruction * { return CastInst::CreateTruncOrBitCast( NewCI, Type::getInt1Ty(*Context), "", NewCI->getNextNode()); }, &Attrs))); } Instruction *SPIRVToLLVM::transOCLRelational(SPIRVInstruction *I, BasicBlock *BB) { CallInst *CI = cast(transSPIRVBuiltinFromInst(I, BB)); assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); return cast(mapValue( I, mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args, llvm::Type *&RetTy) { Type *IntTy = Type::getInt32Ty(*Context); RetTy = IntTy; if (CI->getType()->isVectorTy()) { if (cast(CI->getOperand(0)->getType()) ->getElementType() ->isDoubleTy()) IntTy = Type::getInt64Ty(*Context); if (cast(CI->getOperand(0)->getType()) ->getElementType() ->isHalfTy()) IntTy = Type::getInt16Ty(*Context); RetTy = VectorType::get(IntTy, CI->getType()->getVectorNumElements()); } return CI->getCalledFunction()->getName(); }, [=](CallInst *NewCI) -> Instruction * { Type *RetTy = Type::getInt1Ty(*Context); if (NewCI->getType()->isVectorTy()) RetTy = VectorType::get(Type::getInt1Ty(*Context), NewCI->getType()->getVectorNumElements()); return CastInst::CreateTruncOrBitCast(NewCI, RetTy, "", NewCI->getNextNode()); }, &Attrs))); } std::unique_ptr readSpirvModule(std::istream &IS, const SPIRV::TranslatorOpts &Opts, std::string &ErrMsg) { std::unique_ptr BM(SPIRVModule::createSPIRVModule(Opts)); IS >> *BM; if (!BM->isModuleValid()) { BM->getError(ErrMsg); return nullptr; } return BM; } std::unique_ptr readSpirvModule(std::istream &IS, std::string &ErrMsg) { SPIRV::TranslatorOpts DefaultOpts; return readSpirvModule(IS, DefaultOpts, ErrMsg); } } // namespace SPIRV std::unique_ptr llvm::convertSpirvToLLVM(LLVMContext &C, SPIRVModule &BM, std::string &ErrMsg) { std::unique_ptr M(new Module("", C)); SPIRVToLLVM BTL(M.get(), &BM); if (!BTL.translate()) { BM.getError(ErrMsg); return nullptr; } llvm::legacy::PassManager PassMgr; PassMgr.add(createSPIRVToOCL(*M)); PassMgr.run(*M); return M; } bool llvm::readSpirv(LLVMContext &C, std::istream &IS, Module *&M, std::string &ErrMsg) { SPIRV::TranslatorOpts DefaultOpts; // As it is stated in the documentation, the translator accepts all SPIR-V // extensions by default DefaultOpts.enableAllExtensions(); return llvm::readSpirv(C, DefaultOpts, IS, M, ErrMsg); } bool llvm::readSpirv(LLVMContext &C, const SPIRV::TranslatorOpts &Opts, std::istream &IS, Module *&M, std::string &ErrMsg) { std::unique_ptr BM(readSpirvModule(IS, Opts, ErrMsg)); if (!BM) return false; M = convertSpirvToLLVM(C, *BM, ErrMsg).release(); if (!M) return false; if (DbgSaveTmpLLVM) dumpLLVM(M, DbgTmpLLVMFileName); return true; } void llvm::getSpecConstInfo(std::istream &IS, std::vector &SpecConstInfo) { std::unique_ptr BM(SPIRVModule::createSPIRVModule()); BM->setAutoAddExtensions(false); SPIRVDecoder D(IS, *BM); SPIRVWord Magic; D >> Magic; if (!BM->getErrorLog().checkError(Magic == MagicNumber, SPIRVEC_InvalidModule, "invalid magic number")) { return; } // Skip the rest of the header D.ignore(4); // According to the logical layout of SPIRV module (p2.4 of the spec), // all constant instructions must appear before function declarations. while (D.OpCode != OpFunction && D.getWordCountAndOpCode()) { switch (D.OpCode) { case OpDecorate: // The decoration is added to the module in scope of SPIRVDecorate::decode D.getEntry(); break; case OpTypeBool: case OpTypeInt: case OpTypeFloat: BM->addEntry(D.getEntry()); break; case OpSpecConstant: case OpSpecConstantTrue: case OpSpecConstantFalse: { auto *C = BM->addConstant(static_cast(D.getEntry())); SPIRVWord SpecConstIdLiteral = 0; if (C->hasDecorate(DecorationSpecId, 0, &SpecConstIdLiteral)) { SPIRVType *Ty = C->getType(); uint32_t SpecConstSize = Ty->isTypeBool() ? 1 : Ty->getBitWidth() / 8; SpecConstInfo.emplace_back(SpecConstIdLiteral, SpecConstSize); } break; } default: D.ignoreInstruction(); } } } SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVReader.h000066400000000000000000000306431363521741200212540ustar00rootroot00000000000000//===- SPIRVReader.h - Converts SPIR-V to LLVM ------------------*- C++ -*-===// // // The LLVM/SPIR-V Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file contains declaration of SPIRVToLLVM class which implements /// conversion of SPIR-V binary to LLVM IR. /// //===----------------------------------------------------------------------===// #ifndef SPIRVREADER_H #define SPIRVREADER_H #include "SPIRVModule.h" #include "llvm/ADT/DenseMap.h" #include "llvm/IR/GlobalValue.h" // llvm::GlobalValue::LinkageTypes #include "llvm/IR/Metadata.h" // llvm::Metadata namespace llvm { class Module; class Type; class Instruction; class CallInst; class BasicBlock; class Loop; class Function; class GlobalVariable; class LLVMContext; class MDString; class IntrinsicInst; class LoadInst; class BranchInst; class BinaryOperator; class Value; } // namespace llvm using namespace llvm; namespace SPIRV { class SPIRVFunctionParameter; class SPIRVConstantSampler; class SPIRVConstantPipeStorage; class SPIRVLoopMerge; class SPIRVToLLVMDbgTran; class SPIRVToLLVM { public: SPIRVToLLVM(Module *LLVMModule, SPIRVModule *TheSPIRVModule); std::string getOCLBuiltinName(SPIRVInstruction *BI); std::string getOCLConvertBuiltinName(SPIRVInstruction *BI); std::string getOCLGenericCastToPtrName(SPIRVInstruction *BI); Type *transType(SPIRVType *BT, bool IsClassMember = false); std::string transTypeToOCLTypeName(SPIRVType *BT, bool IsSigned = true); std::vector transTypeVector(const std::vector &); bool translate(); bool transAddressingModel(); Value *transValue(SPIRVValue *, Function *F, BasicBlock *, bool CreatePlaceHolder = true); Value *transValueWithoutDecoration(SPIRVValue *, Function *F, BasicBlock *, bool CreatePlaceHolder = true); Value *transDeviceEvent(SPIRVValue *BV, Function *F, BasicBlock *BB); bool transDecoration(SPIRVValue *, Value *); bool transAlign(SPIRVValue *, Value *); Instruction *transOCLBuiltinFromExtInst(SPIRVExtInst *BC, BasicBlock *BB); std::vector transValue(const std::vector &, Function *F, BasicBlock *); Function *transFunction(SPIRVFunction *F); Value *transBlockInvoke(SPIRVValue *Invoke, BasicBlock *BB); Instruction *transEnqueueKernelBI(SPIRVInstruction *BI, BasicBlock *BB); Instruction *transWGSizeQueryBI(SPIRVInstruction *BI, BasicBlock *BB); Instruction *transSGSizeQueryBI(SPIRVInstruction *BI, BasicBlock *BB); bool transFPContractMetadata(); bool transKernelMetadata(); Value *transAsmINTEL(SPIRVAsmINTEL *BA); CallInst *transAsmCallINTEL(SPIRVAsmCallINTEL *BI, Function *F, BasicBlock *BB); bool transNonTemporalMetadata(Instruction *I); bool transSourceLanguage(); bool transSourceExtension(); void transGeneratorMD(); Value *transConvertInst(SPIRVValue *BV, Function *F, BasicBlock *BB); Instruction *transBuiltinFromInst(const std::string &FuncName, SPIRVInstruction *BI, BasicBlock *BB); Instruction *transOCLBuiltinFromInst(SPIRVInstruction *BI, BasicBlock *BB); Instruction *transSPIRVBuiltinFromInst(SPIRVInstruction *BI, BasicBlock *BB); void transOCLVectorLoadStore(std::string &UnmangledName, std::vector &BArgs); /// Post-process translated LLVM module for OpenCL. bool postProcessOCL(); /// \brief Post-process OpenCL builtin functions returning struct type. /// /// Some OpenCL builtin functions are translated to SPIR-V instructions with /// struct type result, e.g. NDRange creation functions. Such functions /// need to be post-processed to return the struct through sret argument. bool postProcessOCLBuiltinReturnStruct(Function *F); /// \brief Post-process OpenCL builtin functions having array argument. /// /// These functions are translated to functions with array type argument /// first, then post-processed to have pointer arguments. bool postProcessOCLBuiltinWithArrayArguments(Function *F, const std::string &DemangledName); /// \brief Post-process OpImageSampleExplicitLod. /// sampled_image = __spirv_SampledImage__(image, sampler); /// return __spirv_ImageSampleExplicitLod__(sampled_image, image_operands, /// ...); /// => /// read_image(image, sampler, ...) /// \return transformed call instruction. Instruction *postProcessOCLReadImage(SPIRVInstruction *BI, CallInst *CI, const std::string &DemangledName); /// \brief Post-process OpImageWrite. /// return write_image(image, coord, color, image_operands, ...); /// => /// write_image(image, coord, ..., color) /// \return transformed call instruction. CallInst *postProcessOCLWriteImage(SPIRVInstruction *BI, CallInst *CI, const std::string &DemangledName); /// \brief Post-process OpBuildNDRange. /// OpBuildNDRange GlobalWorkSize, LocalWorkSize, GlobalWorkOffset /// => /// call ndrange_XD(GlobalWorkOffset, GlobalWorkSize, LocalWorkSize) /// \return transformed call instruction. CallInst *postProcessOCLBuildNDRange(SPIRVInstruction *BI, CallInst *CI, const std::string &DemangledName); /// \brief Expand OCL builtin functions with scalar argument, e.g. /// step, smoothstep. /// gentype func (fp edge, gentype x) /// => /// gentype func (gentype edge, gentype x) /// \return transformed call instruction. CallInst *expandOCLBuiltinWithScalarArg(CallInst *CI, const std::string &FuncName); /// \brief Post-process OpGroupAll and OpGroupAny instructions translation. /// i1 func ( arg) /// => /// i32 func ( arg) /// \return transformed call instruction. Instruction *postProcessGroupAllAny(CallInst *CI, const std::string &DemangledName); typedef DenseMap SPIRVToLLVMTypeMap; typedef DenseMap SPIRVToLLVMValueMap; typedef DenseMap SPIRVBlockToLLVMStructMap; typedef DenseMap SPIRVToLLVMFunctionMap; typedef DenseMap BuiltinVarMap; // A SPIRV value may be translated to a load instruction of a placeholder // global variable. This map records load instruction of these placeholders // which are supposed to be replaced by the real values later. typedef std::map SPIRVToLLVMPlaceholderMap; typedef std::map SPIRVToLLVMLoopMetadataMap; private: Module *M; BuiltinVarMap BuiltinGVMap; LLVMContext *Context; SPIRVModule *BM; SPIRVToLLVMTypeMap TypeMap; SPIRVToLLVMValueMap ValueMap; SPIRVToLLVMFunctionMap FuncMap; SPIRVBlockToLLVMStructMap BlockMap; SPIRVToLLVMPlaceholderMap PlaceholderMap; std::unique_ptr DbgTran; std::vector GlobalAnnotations; // Loops metadata is translated in the end of a function translation. // This storage contains pairs of translated loop header basic block and loop // metadata SPIR-V instruction in SPIR-V representation of this basic block. SPIRVToLLVMLoopMetadataMap FuncLoopMetadataMap; Type *mapType(SPIRVType *BT, Type *T); // If a value is mapped twice, the existing mapped value is a placeholder, // which must be a load instruction of a global variable whose name starts // with kPlaceholderPrefix. Value *mapValue(SPIRVValue *BV, Value *V); bool isSPIRVBuiltinVariable(GlobalVariable *GV, SPIRVBuiltinVariableKind *Kind = nullptr); // OpenCL function always has NoUnwind attribute. // Change this if it is no longer true. bool isFuncNoUnwind() const { return true; } bool isSPIRVCmpInstTransToLLVMInst(SPIRVInstruction *BI) const; bool isDirectlyTranslatedToOCL(Op OpCode) const; bool transOCLBuiltinsFromVariables(); bool transOCLBuiltinFromVariable(GlobalVariable *GV, SPIRVBuiltinVariableKind Kind); MDString *transOCLKernelArgTypeName(SPIRVFunctionParameter *); Value *mapFunction(SPIRVFunction *BF, Function *F); Value *getTranslatedValue(SPIRVValue *BV); IntrinsicInst *getLifetimeStartIntrinsic(Instruction *I); SPIRVErrorLog &getErrorLog(); void setCallingConv(CallInst *Call); void setAttrByCalledFunc(CallInst *Call); Type *transFPType(SPIRVType *T); BinaryOperator *transShiftLogicalBitwiseInst(SPIRVValue *BV, BasicBlock *BB, Function *F); Instruction *transCmpInst(SPIRVValue *BV, BasicBlock *BB, Function *F); void transOCLBuiltinFromInstPreproc(SPIRVInstruction *BI, Type *&RetTy, std::vector &Args); Instruction *transOCLBuiltinPostproc(SPIRVInstruction *BI, CallInst *CI, BasicBlock *BB, const std::string &DemangledName); std::string transOCLImageTypeName(SPIRV::SPIRVTypeImage *ST); std::string transOCLSampledImageTypeName(SPIRV::SPIRVTypeSampledImage *ST); std::string transOCLPipeTypeName( SPIRV::SPIRVTypePipe *ST, bool UseSPIRVFriendlyFormat = false, SPIRVAccessQualifierKind PipeAccess = AccessQualifierReadOnly); std::string transOCLPipeStorageTypeName(SPIRV::SPIRVTypePipeStorage *PST); std::string transOCLImageTypeAccessQualifier(SPIRV::SPIRVTypeImage *ST); std::string transOCLPipeTypeAccessQualifier(SPIRV::SPIRVTypePipe *ST); Value *oclTransConstantSampler(SPIRV::SPIRVConstantSampler *BCS, BasicBlock *BB); Value *oclTransConstantPipeStorage(SPIRV::SPIRVConstantPipeStorage *BCPS); void setName(llvm::Value *V, SPIRVValue *BV); template void setLLVMLoopMetadata(const LoopInstType *LM, const Loop *LoopObj); void transLLVMLoopMetadata(const Function *F); inline llvm::Metadata *getMetadataFromName(std::string Name); inline std::vector getMetadataFromNameAndParameter(std::string Name, SPIRVWord Parameter); void insertImageNameAccessQualifier(SPIRV::SPIRVTypeImage *ST, std::string &Name); template bool foreachFuncCtlMask(Source, Func); llvm::GlobalValue::LinkageTypes transLinkageType(const SPIRVValue *V); Instruction *transOCLAllAny(SPIRVInstruction *BI, BasicBlock *BB); Instruction *transOCLRelational(SPIRVInstruction *BI, BasicBlock *BB); void transGlobalAnnotations(); void transIntelFPGADecorations(SPIRVValue *BV, Value *V); }; // class SPIRVToLLVM } // namespace SPIRV #endif // SPIRVREADER_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVRegularizeLLVM.cpp000066400000000000000000000146231363521741200232110ustar00rootroot00000000000000//===- SPIRVRegularizeLLVM.cpp - Regularize LLVM for SPIR-V ------- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// // // This file implements regularization of LLVM module for SPIR-V. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "spvregular" #include "OCLUtil.h" #include "SPIRVInternal.h" #include "llvm/IR/InstVisitor.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Operator.h" #include "llvm/IR/Verifier.h" #include "llvm/Pass.h" #include "llvm/PassSupport.h" #include "llvm/Support/Debug.h" #include using namespace llvm; using namespace SPIRV; using namespace OCLUtil; namespace SPIRV { static bool SPIRVDbgSaveRegularizedModule = false; static std::string RegularizedModuleTmpFile = "regularized.bc"; class SPIRVRegularizeLLVM : public ModulePass { public: SPIRVRegularizeLLVM() : ModulePass(ID), M(nullptr), Ctx(nullptr) { initializeSPIRVRegularizeLLVMPass(*PassRegistry::getPassRegistry()); } bool runOnModule(Module &M) override; // Lower functions bool regularize(); /// Erase cast inst of function and replace with the function. /// Assuming F is a SPIR-V builtin function with op code \param OC. void lowerFuncPtr(Function *F, Op OC); void lowerFuncPtr(Module *M); static char ID; private: Module *M; LLVMContext *Ctx; }; char SPIRVRegularizeLLVM::ID = 0; bool SPIRVRegularizeLLVM::runOnModule(Module &Module) { M = &Module; Ctx = &M->getContext(); LLVM_DEBUG(dbgs() << "Enter SPIRVRegularizeLLVM:\n"); regularize(); LLVM_DEBUG(dbgs() << "After SPIRVRegularizeLLVM:\n" << *M); std::string Err; raw_string_ostream ErrorOS(Err); if (verifyModule(*M, &ErrorOS)) { LLVM_DEBUG(errs() << "Fails to verify module: " << ErrorOS.str()); } return true; } /// Remove entities not representable by SPIR-V bool SPIRVRegularizeLLVM::regularize() { eraseUselessFunctions(M); lowerFuncPtr(M); for (auto I = M->begin(), E = M->end(); I != E;) { Function *F = &(*I++); if (F->isDeclaration() && F->use_empty()) { F->eraseFromParent(); continue; } for (auto BI = F->begin(), BE = F->end(); BI != BE; ++BI) { for (auto II = BI->begin(), IE = BI->end(); II != IE; ++II) { if (auto Call = dyn_cast(II)) { Call->setTailCall(false); Function *CF = Call->getCalledFunction(); if (CF && CF->isIntrinsic()) removeFnAttr(Call, Attribute::NoUnwind); } // Remove optimization info not supported by SPIRV if (auto BO = dyn_cast(II)) { if (isa(BO) && BO->isExact()) BO->setIsExact(false); } // Remove metadata not supported by SPIRV static const char *MDs[] = { "fpmath", "tbaa", "range", }; for (auto &MDName : MDs) { if (II->getMetadata(MDName)) { II->setMetadata(MDName, nullptr); } } } } } std::string Err; raw_string_ostream ErrorOS(Err); if (verifyModule(*M, &ErrorOS)) { SPIRVDBG(errs() << "Fails to verify module: " << ErrorOS.str();) return false; } if (SPIRVDbgSaveRegularizedModule) saveLLVMModule(M, RegularizedModuleTmpFile); return true; } // Assume F is a SPIR-V builtin function with a function pointer argument which // is a bitcast instruction casting a function to a void(void) function pointer. void SPIRVRegularizeLLVM::lowerFuncPtr(Function *F, Op OC) { LLVM_DEBUG(dbgs() << "[lowerFuncPtr] " << *F << '\n'); auto Name = decorateSPIRVFunction(getName(OC)); std::set InvokeFuncPtrs; auto Attrs = F->getAttributes(); mutateFunction( F, [=, &InvokeFuncPtrs](CallInst *CI, std::vector &Args) { for (auto &I : Args) { if (isFunctionPointerType(I->getType())) { InvokeFuncPtrs.insert(I); I = removeCast(I); } } return Name; }, nullptr, &Attrs, false); for (auto &I : InvokeFuncPtrs) eraseIfNoUse(I); } void SPIRVRegularizeLLVM::lowerFuncPtr(Module *M) { std::vector> Work; for (auto &F : *M) { auto AI = F.arg_begin(); if (hasFunctionPointerArg(&F, AI)) { auto OC = getSPIRVFuncOC(F.getName()); if (OC != OpNop) // builtin with a function pointer argument Work.push_back(std::make_pair(&F, OC)); } } for (auto &I : Work) lowerFuncPtr(I.first, I.second); } } // namespace SPIRV INITIALIZE_PASS(SPIRVRegularizeLLVM, "spvregular", "Regularize LLVM for SPIR-V", false, false) ModulePass *llvm::createSPIRVRegularizeLLVM() { return new SPIRVRegularizeLLVM(); } SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVToLLVMDbgTran.cpp000066400000000000000000001206261363521741200227250ustar00rootroot00000000000000//===- SPIRVToLLVMDbgTran.cpp - Converts debug info to LLVM -----*- C++ -*-===// // // The LLVM/SPIR-V Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2018 Intel Corporation. All rights reserved. // // 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 Intel Corporation, 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. // //===----------------------------------------------------------------------===// // // This file implements translation of debug info from SPIR-V to LLVM metadata // //===----------------------------------------------------------------------===// #include "SPIRVToLLVMDbgTran.h" #include "SPIRVEntry.h" #include "SPIRVFunction.h" #include "SPIRVInstruction.h" #include "SPIRVInternal.h" #include "SPIRVReader.h" #include "SPIRVType.h" #include "llvm/IR/DIBuilder.h" #include "llvm/IR/Module.h" using namespace std; using namespace SPIRVDebug::Operand; namespace SPIRV { SPIRVToLLVMDbgTran::SPIRVToLLVMDbgTran(SPIRVModule *TBM, Module *TM, SPIRVToLLVM *Reader) : BM(TBM), M(TM), Builder(*M), SPIRVReader(Reader) { Enable = BM->hasDebugInfo(); } void SPIRVToLLVMDbgTran::addDbgInfoVersion() { if (!Enable) return; M->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION); } DIFile *SPIRVToLLVMDbgTran::getDIFile(const string &FileName) { return getOrInsert(FileMap, FileName, [=]() { SplitFileName Split(FileName); if (!Split.BaseName.empty()) return Builder.createFile(Split.BaseName, Split.Path); return static_cast(nullptr); }); } SPIRVExtInst *SPIRVToLLVMDbgTran::getDbgInst(const SPIRVId Id) { SPIRVEntry *E = BM->getEntry(Id); if (isa(E)) { SPIRVExtInst *EI = static_cast(E); if (EI->getExtSetKind() == SPIRV::SPIRVEIS_Debug) return EI; } return nullptr; } StringRef SPIRVToLLVMDbgTran::getString(const SPIRVId Id) { SPIRVString *String = BM->get(Id); assert(String && "Invalid string"); return String->getStr(); } void SPIRVToLLVMDbgTran::transDbgInfo(const SPIRVValue *SV, Value *V) { // A constant sampler does not have a corresponding SPIRVInstruction. if (SV->getOpCode() == OpConstantSampler) return; if (Instruction *I = dyn_cast(V)) { const SPIRVInstruction *SI = static_cast(SV); I->setDebugLoc(transDebugScope(SI)); } } DIScope *SPIRVToLLVMDbgTran::getScope(const SPIRVEntry *ScopeInst) { if (ScopeInst->getOpCode() == OpString) return getDIFile(static_cast(ScopeInst)->getStr()); return transDebugInst(static_cast(ScopeInst)); } DICompileUnit * SPIRVToLLVMDbgTran::transCompileUnit(const SPIRVExtInst *DebugInst) { const SPIRVWordVec &Ops = DebugInst->getArguments(); using namespace SPIRVDebug::Operand::CompilationUnit; assert(Ops.size() == OperandCount && "Invalid number of operands"); M->addModuleFlag(llvm::Module::Warning, "Dwarf Version", Ops[DWARFVersionIdx]); SPIRVExtInst *Source = BM->get(Ops[SourceIdx]); SPIRVId FileId = Source->getArguments()[SPIRVDebug::Operand::Source::FileIdx]; std::string File = getString(FileId); unsigned SourceLang = Ops[LanguageIdx]; CU = Builder.createCompileUnit(SourceLang, getDIFile(File), "spirv", false, "", 0); return CU; } DIBasicType *SPIRVToLLVMDbgTran::transTypeBasic(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::TypeBasic; const SPIRVWordVec &Ops = DebugInst->getArguments(); assert(Ops.size() == OperandCount && "Invalid number of operands"); StringRef Name = getString(Ops[NameIdx]); auto Tag = static_cast(Ops[EncodingIdx]); unsigned Encoding = SPIRV::DbgEncodingMap::rmap(Tag); if (Encoding == 0) return Builder.createUnspecifiedType(Name); uint64_t Size = BM->get(Ops[SizeIdx])->getZExtIntValue(); return Builder.createBasicType(Name, Size, Encoding); } DIDerivedType * SPIRVToLLVMDbgTran::transTypeQualifier(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::TypeQualifier; const SPIRVWordVec &Ops = DebugInst->getArguments(); assert(Ops.size() == OperandCount && "Invalid number of operands"); DIType *BaseTy = transDebugInst(BM->get(Ops[BaseTypeIdx])); unsigned Tag = SPIRV::DbgTypeQulifierMap::rmap( static_cast(Ops[QualifierIdx])); return Builder.createQualifiedType(Tag, BaseTy); } DIType *SPIRVToLLVMDbgTran::transTypePointer(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::TypePointer; const SPIRVWordVec &Ops = DebugInst->getArguments(); assert(Ops.size() == OperandCount && "Invalid number of operands"); DIType *PointeeTy = nullptr; if (BM->getEntry(Ops[BaseTypeIdx])->getOpCode() != OpTypeVoid) PointeeTy = transDebugInst(BM->get(Ops[BaseTypeIdx])); Optional AS; if (Ops[StorageClassIdx] != ~0U) { auto SC = static_cast(Ops[StorageClassIdx]); AS = SPIRSPIRVAddrSpaceMap::rmap(SC); } DIType *Ty; SPIRVWord Flags = Ops[FlagsIdx]; if (Flags & SPIRVDebug::FlagIsLValueReference) Ty = Builder.createReferenceType(dwarf::DW_TAG_reference_type, PointeeTy, 0, 0, AS); else if (Flags & SPIRVDebug::FlagIsRValueReference) Ty = Builder.createReferenceType(dwarf::DW_TAG_rvalue_reference_type, PointeeTy, 0, 0, AS); else Ty = Builder.createPointerType(PointeeTy, BM->getAddressingModel() * 32, 0, AS); if (Flags & SPIRVDebug::FlagIsObjectPointer) Ty = Builder.createObjectPointerType(Ty); else if (Flags & SPIRVDebug::FlagIsArtificial) Ty = Builder.createArtificialType(Ty); return Ty; } DICompositeType * SPIRVToLLVMDbgTran::transTypeArray(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::TypeArray; const SPIRVWordVec &Ops = DebugInst->getArguments(); assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); DIType *BaseTy = transDebugInst(BM->get(Ops[BaseTypeIdx])); size_t TotalCount = 1; SmallVector Subscripts; for (size_t I = ComponentCountIdx, E = Ops.size(); I < E; ++I) { SPIRVConstant *C = BM->get(Ops[I]); int64_t Count = static_cast(C->getZExtIntValue()); Subscripts.push_back(Builder.getOrCreateSubrange(0, Count)); TotalCount *= static_cast(Count); } DINodeArray SubscriptArray = Builder.getOrCreateArray(Subscripts); size_t Size = BaseTy->getSizeInBits() * TotalCount; return Builder.createArrayType(Size, 0 /*align*/, BaseTy, SubscriptArray); } DICompositeType * SPIRVToLLVMDbgTran::transTypeVector(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::TypeVector; const SPIRVWordVec &Ops = DebugInst->getArguments(); assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); DIType *BaseTy = transDebugInst(BM->get(Ops[BaseTypeIdx])); SPIRVWord Count = Ops[ComponentCountIdx]; uint64_t Size = BaseTy->getSizeInBits() * Count; SmallVector Subscripts; Subscripts.push_back(Builder.getOrCreateSubrange(0, Count)); DINodeArray SubscriptArray = Builder.getOrCreateArray(Subscripts); return Builder.createVectorType(Size, 0 /*align*/, BaseTy, SubscriptArray); } DICompositeType * SPIRVToLLVMDbgTran::transTypeComposite(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::TypeComposite; const SPIRVWordVec &Ops = DebugInst->getArguments(); assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); StringRef Name = getString(Ops[NameIdx]); DIFile *File = getFile(Ops[SourceIdx]); unsigned LineNo = Ops[LineIdx]; DIScope *ParentScope = getScope(BM->getEntry(Ops[ParentIdx])); uint64_t Size = BM->get(Ops[SizeIdx])->getZExtIntValue(); uint64_t Align = 0; DIType *DerivedFrom = nullptr; StringRef Identifier; SPIRVEntry *UniqId = BM->get(Ops[LinkageNameIdx]); if (UniqId->getOpCode() == OpString) Identifier = static_cast(UniqId)->getStr(); DINode::DIFlags Flags = DINode::FlagZero; if (Ops[FlagsIdx] & SPIRVDebug::FlagIsFwdDecl) Flags |= DINode::FlagFwdDecl; if (Ops[FlagsIdx] & SPIRVDebug::FlagTypePassByValue) Flags |= DINode::FlagTypePassByValue; if (Ops[FlagsIdx] & SPIRVDebug::FlagTypePassByReference) Flags |= DINode::FlagTypePassByReference; DICompositeType *CT = nullptr; switch (Ops[TagIdx]) { case SPIRVDebug::Class: CT = Builder.createClassType( ParentScope, Name, File, LineNo, Size, Align, 0, Flags, DerivedFrom, DINodeArray() /*elements*/, nullptr /*VTableHolder*/, nullptr /*TemplateParams*/, Identifier); break; case SPIRVDebug::Structure: CT = Builder.createStructType(ParentScope, Name, File, LineNo, Size, Align, Flags, DerivedFrom, DINodeArray() /*elements*/, 0 /*RunTimeLang*/, nullptr /*VTableHolder*/, Identifier); break; case SPIRVDebug::Union: CT = Builder.createUnionType(ParentScope, Name, File, LineNo, Size, Align, Flags, DINodeArray(), 0 /*RuntimrLang*/, Identifier); break; default: llvm_unreachable("Unexpected composite type"); break; } DebugInstCache[DebugInst] = CT; SmallVector EltTys; for (size_t I = FirstMemberIdx; I < Ops.size(); ++I) { EltTys.push_back(transDebugInst(BM->get(Ops[I]))); } DINodeArray Elements = Builder.getOrCreateArray(EltTys); Builder.replaceArrays(CT, Elements); assert(CT && "Composite type translation failed."); return CT; } DINode *SPIRVToLLVMDbgTran::transTypeMember(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::TypeMember; const SPIRVWordVec &Ops = DebugInst->getArguments(); assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); DIFile *File = getFile(Ops[SourceIdx]); unsigned LineNo = Ops[LineIdx]; StringRef Name = getString(Ops[NameIdx]); DIScope *Scope = getScope(BM->getEntry(Ops[ParentIdx])); DIType *BaseType = transDebugInst(BM->get(Ops[TypeIdx])); uint64_t OffsetInBits = BM->get(Ops[OffsetIdx])->getZExtIntValue(); unsigned SPIRVFlags = Ops[FlagsIdx]; DINode::DIFlags Flags = DINode::FlagZero; if ((SPIRVDebug::FlagAccess & SPIRVFlags) == SPIRVDebug::FlagIsPublic) { Flags |= DINode::FlagPublic; } else if (SPIRVFlags & SPIRVDebug::FlagIsProtected) { Flags |= DINode::FlagProtected; } else if (SPIRVFlags & SPIRVDebug::FlagIsPrivate) { Flags |= DINode::FlagPrivate; } if (SPIRVFlags & SPIRVDebug::FlagIsStaticMember) Flags |= DINode::FlagStaticMember; if (Flags & DINode::FlagStaticMember && Ops.size() > MinOperandCount) { SPIRVValue *ConstVal = BM->get(Ops[ValueIdx]); assert(isConstantOpCode(ConstVal->getOpCode()) && "Static member must be a constant"); llvm::Value *Val = SPIRVReader->transValue(ConstVal, nullptr, nullptr); return Builder.createStaticMemberType(Scope, Name, File, LineNo, BaseType, Flags, cast(Val)); } uint64_t Size = BM->get(Ops[SizeIdx])->getZExtIntValue(); uint64_t Alignment = 0; return Builder.createMemberType(Scope, Name, File, LineNo, Size, Alignment, OffsetInBits, Flags, BaseType); } DINode *SPIRVToLLVMDbgTran::transTypeEnum(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::TypeEnum; const SPIRVWordVec &Ops = DebugInst->getArguments(); assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); StringRef Name = getString(Ops[NameIdx]); DIFile *File = getFile(Ops[SourceIdx]); unsigned LineNo = Ops[LineIdx]; DIScope *Scope = getScope(BM->getEntry(Ops[ParentIdx])); uint64_t SizeInBits = BM->get(Ops[SizeIdx])->getZExtIntValue(); unsigned AlignInBits = 0; SPIRVWord Flags = Ops[FlagsIdx]; if (Flags & SPIRVDebug::FlagIsFwdDecl) { return Builder.createForwardDecl(dwarf::DW_TAG_enumeration_type, Name, Scope, File, LineNo, AlignInBits, SizeInBits); } else { SmallVector Elts; for (size_t I = FirstEnumeratorIdx, E = Ops.size(); I < E; I += 2) { uint64_t Val = BM->get(Ops[I])->getZExtIntValue(); StringRef Name = getString(Ops[I + 1]); Elts.push_back(Builder.createEnumerator(Name, Val)); } DINodeArray Enumerators = Builder.getOrCreateArray(Elts); DIType *UnderlyingType = nullptr; SPIRVEntry *E = BM->getEntry(Ops[UnderlyingTypeIdx]); if (!isa(E)) UnderlyingType = transDebugInst(static_cast(E)); return Builder.createEnumerationType(Scope, Name, File, LineNo, SizeInBits, AlignInBits, Enumerators, UnderlyingType, "", UnderlyingType); } } DINode *SPIRVToLLVMDbgTran::transTypeFunction(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::TypeFunction; const SPIRVWordVec &Ops = DebugInst->getArguments(); assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); SPIRVWord SPIRVFlags = Ops[FlagsIdx]; DINode::DIFlags Flags = DINode::FlagZero; if (SPIRVFlags & SPIRVDebug::FlagIsLValueReference) Flags |= llvm::DINode::FlagLValueReference; if (SPIRVFlags & SPIRVDebug::FlagIsRValueReference) Flags |= llvm::DINode::FlagRValueReference; SPIRVEntry *E = BM->getEntry(Ops[ReturnTypeIdx]); MDNode *RT = isa(E) ? nullptr : transDebugInst(BM->get(Ops[ReturnTypeIdx])); SmallVector Elements{RT}; for (size_t I = FirstParameterIdx, E = Ops.size(); I < E; ++I) { SPIRVEntry *P = BM->getEntry(Ops[I]); MDNode *Param = isa(P) ? nullptr : transDebugInst(BM->get(Ops[I])); Elements.push_back(Param); } DITypeRefArray ArgTypes = Builder.getOrCreateTypeArray(Elements); return Builder.createSubroutineType(ArgTypes, Flags); } DINode * SPIRVToLLVMDbgTran::transTypePtrToMember(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::PtrToMember; const SPIRVWordVec &Ops = DebugInst->getArguments(); assert(Ops.size() >= OperandCount && "Invalid number of operands"); SPIRVExtInst *Member = BM->get(Ops[MemberTypeIdx]); DIType *PointeeTy = transDebugInst(Member); SPIRVExtInst *ContainingTy = BM->get(Ops[ParentIdx]); DIType *BaseTy = transDebugInst(ContainingTy); return Builder.createMemberPointerType(PointeeTy, BaseTy, 0); } DINode *SPIRVToLLVMDbgTran::transLexicalBlock(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::LexicalBlock; const SPIRVWordVec &Ops = DebugInst->getArguments(); DIScope *ParentScope = getScope(BM->getEntry(Ops[ParentIdx])); DIFile *File = getFile(Ops[SourceIdx]); unsigned LineNo = Ops[LineIdx]; if (Ops.size() > NameIdx) { StringRef Name = getString(Ops[NameIdx]); return Builder.createNameSpace(ParentScope, Name, false /*inlined namespace*/); } unsigned Column = Ops[ColumnIdx]; return Builder.createLexicalBlock(ParentScope, File, LineNo, Column); } DINode *SPIRVToLLVMDbgTran::transLexicalBlockDiscriminator( const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::LexicalBlockDiscriminator; const SPIRVWordVec &Ops = DebugInst->getArguments(); DIFile *File = getFile(Ops[SourceIdx]); unsigned Disc = Ops[DiscriminatorIdx]; DIScope *ParentScope = getScope(BM->getEntry(Ops[ParentIdx])); return Builder.createLexicalBlockFile(ParentScope, File, Disc); } DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::Function; const SPIRVWordVec &Ops = DebugInst->getArguments(); assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); StringRef Name = getString(Ops[NameIdx]); DISubroutineType *Ty = transDebugInst(BM->get(Ops[TypeIdx])); DIFile *File = getFile(Ops[SourceIdx]); unsigned LineNo = Ops[LineIdx]; DIScope *Scope = getScope(BM->getEntry(Ops[ParentIdx])); StringRef LinkageName = getString(Ops[LinkageNameIdx]); SPIRVWord SPIRVDebugFlags = Ops[FlagsIdx]; DINode::DIFlags Flags = DINode::FlagZero; if (SPIRVDebugFlags & SPIRVDebug::FlagIsArtificial) Flags |= llvm::DINode::FlagArtificial; if (SPIRVDebugFlags & SPIRVDebug::FlagIsExplicit) Flags |= llvm::DINode::FlagExplicit; if (SPIRVDebugFlags & SPIRVDebug::FlagIsPrototyped) Flags |= llvm::DINode::FlagPrototyped; if (SPIRVDebugFlags & SPIRVDebug::FlagIsLValueReference) Flags |= llvm::DINode::FlagLValueReference; if (SPIRVDebugFlags & SPIRVDebug::FlagIsRValueReference) Flags |= llvm::DINode::FlagRValueReference; if ((SPIRVDebugFlags & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsPublic) Flags |= llvm::DINode::FlagPublic; if (SPIRVDebugFlags & SPIRVDebug::FlagIsProtected) Flags |= llvm::DINode::FlagProtected; if (SPIRVDebugFlags & SPIRVDebug::FlagIsPrivate) Flags |= llvm::DINode::FlagPrivate; bool IsDefinition = SPIRVDebugFlags & SPIRVDebug::FlagIsDefinition; bool IsOptimized = SPIRVDebugFlags & SPIRVDebug::FlagIsOptimized; bool IsLocal = SPIRVDebugFlags & SPIRVDebug::FlagIsLocal; bool IsMainSubprogram = BM->isEntryPoint(spv::ExecutionModelKernel, Ops[FunctionIdIdx]); DISubprogram::DISPFlags SPFlags = DISubprogram::toSPFlags(IsLocal, IsDefinition, IsOptimized, DISubprogram::SPFlagNonvirtual, IsMainSubprogram); unsigned ScopeLine = Ops[ScopeLineIdx]; // Function declaration descriptor DISubprogram *FD = nullptr; if (Ops.size() > DeclarationIdx) { FD = transDebugInst( BM->get(Ops[DeclarationIdx])); } // Here we create fake array of template parameters. If it was plain nullptr, // the template parameter operand would be removed in DISubprogram::getImpl. // But we want it to be there, because if there is DebugTemplate instruction // refering to this function, TransTemplate method must be able to replace the // template parameter operand, thus it must be in the operands list. SmallVector Elts; DINodeArray TParams = Builder.getOrCreateArray(Elts); llvm::DITemplateParameterArray TParamsArray = TParams.get(); DISubprogram *DIS = nullptr; if ((isa(Scope) || isa(Scope)) && !IsDefinition) DIS = Builder.createMethod(Scope, Name, LinkageName, File, LineNo, Ty, 0, 0, nullptr, Flags, SPFlags, TParamsArray); else DIS = Builder.createFunction(Scope, Name, LinkageName, File, LineNo, Ty, ScopeLine, Flags, SPFlags, TParamsArray, FD); DebugInstCache[DebugInst] = DIS; SPIRVId RealFuncId = Ops[FunctionIdIdx]; FuncMap[RealFuncId] = DIS; // Function. SPIRVEntry *E = BM->getEntry(Ops[FunctionIdIdx]); if (E->getOpCode() == OpFunction) { SPIRVFunction *BF = static_cast(E); llvm::Function *F = SPIRVReader->transFunction(BF); assert(F && "Translation of function failed!"); if (!F->hasMetadata()) F->setMetadata("dbg", DIS); } return DIS; } DINode *SPIRVToLLVMDbgTran::transFunctionDecl(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::FunctionDeclaration; const SPIRVWordVec &Ops = DebugInst->getArguments(); assert(Ops.size() == OperandCount && "Invalid number of operands"); // Scope DIScope *Scope = getScope(BM->getEntry(Ops[ParentIdx])); StringRef Name = getString(Ops[NameIdx]); StringRef LinkageName = getString(Ops[LinkageNameIdx]); DIFile *File = getFile(Ops[SourceIdx]); unsigned LineNo = Ops[LineIdx]; DISubroutineType *Ty = transDebugInst(BM->get(Ops[TypeIdx])); SPIRVWord SPIRVDebugFlags = Ops[FlagsIdx]; bool IsDefinition = SPIRVDebugFlags & SPIRVDebug::FlagIsDefinition; bool IsOptimized = SPIRVDebugFlags & SPIRVDebug::FlagIsOptimized; bool IsLocal = SPIRVDebugFlags & SPIRVDebug::FlagIsLocal; DINode::DIFlags Flags = DINode::FlagZero; if (SPIRVDebugFlags & SPIRVDebug::FlagIsArtificial) Flags |= llvm::DINode::FlagArtificial; if (SPIRVDebugFlags & SPIRVDebug::FlagIsExplicit) Flags |= llvm::DINode::FlagExplicit; if (SPIRVDebugFlags & SPIRVDebug::FlagIsPrototyped) Flags |= llvm::DINode::FlagPrototyped; if (SPIRVDebugFlags & SPIRVDebug::FlagIsLValueReference) Flags |= llvm::DINode::FlagLValueReference; if (SPIRVDebugFlags & SPIRVDebug::FlagIsRValueReference) Flags |= llvm::DINode::FlagRValueReference; if ((SPIRVDebugFlags & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsPublic) Flags |= llvm::DINode::FlagPublic; if (SPIRVDebugFlags & SPIRVDebug::FlagIsProtected) Flags |= llvm::DINode::FlagProtected; if (SPIRVDebugFlags & SPIRVDebug::FlagIsPrivate) Flags |= llvm::DINode::FlagPrivate; // Here we create fake array of template parameters. If it was plain nullptr, // the template parameter operand would be removed in DISubprogram::getImpl. // But we want it to be there, because if there is DebugTemplate instruction // refering to this function, TransTemplate method must be able to replace the // template parameter operand, thus it must be in the operands list. SmallVector Elts; DINodeArray TParams = Builder.getOrCreateArray(Elts); llvm::DITemplateParameterArray TParamsArray = TParams.get(); DISubprogram *DIS = nullptr; DISubprogram::DISPFlags SPFlags = DISubprogram::toSPFlags(IsLocal, IsDefinition, IsOptimized); if (isa(Scope) || isa(Scope)) DIS = Builder.createMethod(Scope, Name, LinkageName, File, LineNo, Ty, 0, 0, nullptr, Flags, SPFlags, TParamsArray); else { // Since a function declaration doesn't have any retained nodes, resolve // the temporary placeholder for them immediately. DIS = Builder.createTempFunctionFwdDecl(Scope, Name, LinkageName, File, LineNo, Ty, 0, Flags, SPFlags, TParamsArray); llvm::TempMDNode FwdDecl(cast(DIS)); DIS = Builder.replaceTemporary(std::move(FwdDecl), DIS); } DebugInstCache[DebugInst] = DIS; return DIS; } MDNode *SPIRVToLLVMDbgTran::transGlobalVariable(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::GlobalVariable; const SPIRVWordVec &Ops = DebugInst->getArguments(); assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); StringRef Name = getString(Ops[NameIdx]); DIType *Ty = transDebugInst(BM->get(Ops[TypeIdx])); DIFile *File = getFile(Ops[SourceIdx]); unsigned LineNo = Ops[LineIdx]; DIScope *Parent = getScope(BM->getEntry(Ops[ParentIdx])); StringRef LinkageName = getString(Ops[LinkageNameIdx]); DIDerivedType *StaticMemberDecl = nullptr; if (Ops.size() > MinOperandCount) { StaticMemberDecl = transDebugInst( BM->get(Ops[StaticMemberDeclarationIdx])); } bool IsLocal = Ops[FlagsIdx] & SPIRVDebug::FlagIsLocal; bool IsDefinition = Ops[FlagsIdx] & SPIRVDebug::FlagIsDefinition; MDNode *VarDecl = nullptr; if (IsDefinition) { VarDecl = Builder.createGlobalVariableExpression( Parent, Name, LinkageName, File, LineNo, Ty, IsLocal, IsDefinition, nullptr, StaticMemberDecl); } else { VarDecl = Builder.createTempGlobalVariableFwdDecl( Parent, Name, LinkageName, File, LineNo, Ty, IsLocal, StaticMemberDecl); // replaceAllUsesWith call makes VarDecl non-temp. // Otherwise DIBuilder will crash at finalization. llvm::TempMDNode TMP(VarDecl); Builder.replaceTemporary(std::move(TMP), VarDecl); } // If the variable has no initializer Ops[VariableIdx] is OpDebugInfoNone. // Otherwise Ops[VariableIdx] may be a global variable or a constant(C++ // static const). if (VarDecl && !getDbgInst(Ops[VariableIdx])) { SPIRVValue *V = BM->get(Ops[VariableIdx]); Value *Var = SPIRVReader->transValue(V, nullptr, nullptr); llvm::GlobalVariable *GV = dyn_cast_or_null(Var); if (GV && !GV->hasMetadata()) GV->addMetadata("dbg", *VarDecl); } return VarDecl; } DINode *SPIRVToLLVMDbgTran::transLocalVariable(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::LocalVariable; const SPIRVWordVec &Ops = DebugInst->getArguments(); assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); DIScope *Scope = getScope(BM->getEntry(Ops[ParentIdx])); StringRef Name = getString(Ops[NameIdx]); DIFile *File = getFile(Ops[SourceIdx]); unsigned LineNo = Ops[LineIdx]; DIType *Ty = transDebugInst(BM->get(Ops[TypeIdx])); DINode::DIFlags Flags = DINode::FlagZero; if (Ops[FlagsIdx] & SPIRVDebug::FlagIsArtificial) Flags |= DINode::FlagArtificial; if (Ops[FlagsIdx] & SPIRVDebug::FlagIsObjectPointer) Flags |= DINode::FlagObjectPointer; if (Ops.size() > ArgNumberIdx) return Builder.createParameterVariable(Scope, Name, Ops[ArgNumberIdx], File, LineNo, Ty, true, Flags); return Builder.createAutoVariable(Scope, Name, File, LineNo, Ty, true, Flags); } DINode *SPIRVToLLVMDbgTran::transTypedef(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::Typedef; const SPIRVWordVec &Ops = DebugInst->getArguments(); assert(Ops.size() >= OperandCount && "Invalid number of operands"); DIFile *File = getFile(Ops[SourceIdx]); unsigned LineNo = Ops[LineIdx]; StringRef Alias = getString(Ops[NameIdx]); SPIRVEntry *TypeInst = BM->getEntry(Ops[BaseTypeIdx]); DIType *Ty = transDebugInst(static_cast(TypeInst)); DIScope *Scope = getScope(BM->getEntry(Ops[ParentIdx])); assert(Scope && "Typedef should have a parent scope"); return Builder.createTypedef(Ty, Alias, File, LineNo, Scope); } DINode *SPIRVToLLVMDbgTran::transInheritance(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::TypeInheritance; const SPIRVWordVec &Ops = DebugInst->getArguments(); assert(Ops.size() >= OperandCount && "Invalid number of operands"); DIType *Parent = transDebugInst(BM->get(Ops[ParentIdx])); DIType *Child = transDebugInst(BM->get(Ops[ChildIdx])); DINode::DIFlags Flags = DINode::FlagZero; if ((Ops[FlagsIdx] & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsPublic) Flags |= llvm::DINode::FlagPublic; if ((Ops[FlagsIdx] & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsProtected) Flags |= llvm::DINode::FlagProtected; if ((Ops[FlagsIdx] & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsPrivate) Flags |= llvm::DINode::FlagPrivate; uint64_t Offset = BM->get(Ops[OffsetIdx])->getZExtIntValue(); return Builder.createInheritance(Child, Parent, Offset, 0, Flags); } DINode * SPIRVToLLVMDbgTran::transTemplateParameter(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::TemplateParameter; const SPIRVWordVec &Ops = DebugInst->getArguments(); assert(Ops.size() >= OperandCount && "Invalid number of operands"); StringRef Name = getString(Ops[NameIdx]); SPIRVEntry *ActualType = BM->getEntry(Ops[TypeIdx]); DIType *Ty = nullptr; if (!isa(ActualType)) Ty = transDebugInst(static_cast(ActualType)); DIScope *Context = nullptr; if (!getDbgInst(Ops[ValueIdx])) { SPIRVValue *Val = BM->get(Ops[ValueIdx]); Value *V = SPIRVReader->transValue(Val, nullptr, nullptr); return Builder.createTemplateValueParameter(Context, Name, Ty, cast(V)); } return Builder.createTemplateTypeParameter(Context, Name, Ty); } DINode *SPIRVToLLVMDbgTran::transTemplateTemplateParameter( const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::TemplateTemplateParameter; const SPIRVWordVec &Ops = DebugInst->getArguments(); assert(Ops.size() >= OperandCount && "Invalid number of operands"); StringRef Name = getString(Ops[NameIdx]); StringRef TemplName = getString(Ops[TemplateNameIdx]); DIScope *Context = nullptr; return Builder.createTemplateTemplateParameter(Context, Name, nullptr, TemplName); } DINode * SPIRVToLLVMDbgTran::transTemplateParameterPack(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::TemplateParameterPack; const SPIRVWordVec &Ops = DebugInst->getArguments(); assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); StringRef Name = getString(Ops[NameIdx]); SmallVector Elts; for (size_t I = FirstParameterIdx, E = Ops.size(); I < E; ++I) { Elts.push_back(transDebugInst(BM->get(Ops[I]))); } DINodeArray Pack = Builder.getOrCreateArray(Elts); DIScope *Context = nullptr; return Builder.createTemplateParameterPack(Context, Name, nullptr, Pack); } MDNode *SPIRVToLLVMDbgTran::transTemplate(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::Template; const SPIRVWordVec &Ops = DebugInst->getArguments(); const size_t NumOps = Ops.size(); assert(NumOps >= MinOperandCount && "Invalid number of operands"); auto *Templ = BM->get(Ops[TargetIdx]); MDNode *D = transDebugInst(Templ); SmallVector Elts; for (size_t I = FirstParameterIdx; I < NumOps; ++I) { Elts.push_back(transDebugInst(BM->get(Ops[I]))); } DINodeArray TParams = Builder.getOrCreateArray(Elts); if (DICompositeType *Comp = dyn_cast(D)) { Builder.replaceArrays(Comp, Comp->getElements(), TParams); return Comp; } if (isa(D)) { // This constant matches with one used in // DISubprogram::getRawTemplateParams() const unsigned TemplateParamsIndex = 9; D->replaceOperandWith(TemplateParamsIndex, TParams.get()); return D; } llvm_unreachable("Invalid template"); } DINode *SPIRVToLLVMDbgTran::transImportedEntry(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::ImportedEntity; const SPIRVWordVec &Ops = DebugInst->getArguments(); assert(Ops.size() >= OperandCount && "Invalid number of operands"); DIScope *Scope = getScope(BM->getEntry(Ops[ParentIdx])); unsigned Line = Ops[LineIdx]; DIFile *File = getFile(Ops[SourceIdx]); auto *Entity = transDebugInst(BM->get(Ops[EntityIdx])); if (Ops[TagIdx] == SPIRVDebug::ImportedModule) { if (DIImportedEntity *IE = dyn_cast(Entity)) return Builder.createImportedModule(Scope, IE, File, Line); if (DINamespace *NS = dyn_cast(Entity)) return Builder.createImportedModule(Scope, NS, File, Line); } if (Ops[TagIdx] == SPIRVDebug::ImportedDeclaration) { StringRef Name = getString(Ops[NameIdx]); if (DIGlobalVariableExpression *GVE = dyn_cast(Entity)) return Builder.createImportedDeclaration(Scope, GVE->getVariable(), File, Line, Name); return Builder.createImportedDeclaration(Scope, Entity, File, Line, Name); } llvm_unreachable("Unexpected kind of imported entity!"); } MDNode *SPIRVToLLVMDbgTran::transExpression(const SPIRVExtInst *DebugInst) { const SPIRVWordVec &Args = DebugInst->getArguments(); std::vector Ops; for (SPIRVId A : Args) { SPIRVExtInst *O = BM->get(A); const SPIRVWordVec &Operands = O->getArguments(); auto OpCode = static_cast(Operands[0]); Ops.push_back(SPIRV::DbgExpressionOpCodeMap::rmap(OpCode)); for (unsigned I = 1, E = Operands.size(); I < E; ++I) { Ops.push_back(Operands[I]); } } ArrayRef Addr(Ops.data(), Ops.size()); return Builder.createExpression(Addr); } MDNode *SPIRVToLLVMDbgTran::transDebugInstImpl(const SPIRVExtInst *DebugInst) { switch (DebugInst->getExtOp()) { case SPIRVDebug::DebugInfoNone: return nullptr; case SPIRVDebug::CompilationUnit: return transCompileUnit(DebugInst); case SPIRVDebug::TypeBasic: return transTypeBasic(DebugInst); case SPIRVDebug::TypeQualifier: return transTypeQualifier(DebugInst); case SPIRVDebug::TypePointer: return transTypePointer(DebugInst); case SPIRVDebug::TypeArray: return transTypeArray(DebugInst); case SPIRVDebug::TypeVector: return transTypeVector(DebugInst); case SPIRVDebug::TypeComposite: return transTypeComposite(DebugInst); case SPIRVDebug::TypeMember: return transTypeMember(DebugInst); case SPIRVDebug::TypePtrToMember: return transTypePtrToMember(DebugInst); case SPIRVDebug::TypeEnum: return transTypeEnum(DebugInst); case SPIRVDebug::TypeFunction: return transTypeFunction(DebugInst); case SPIRVDebug::LexicalBlock: return transLexicalBlock(DebugInst); case SPIRVDebug::LexicalBlockDiscriminator: return transLexicalBlockDiscriminator(DebugInst); case SPIRVDebug::Function: return transFunction(DebugInst); case SPIRVDebug::FunctionDecl: return transFunctionDecl(DebugInst); case SPIRVDebug::GlobalVariable: return transGlobalVariable(DebugInst); case SPIRVDebug::LocalVariable: return transLocalVariable(DebugInst); case SPIRVDebug::Typedef: return transTypedef(DebugInst); case SPIRVDebug::InlinedAt: return transDebugInlined(DebugInst); case SPIRVDebug::Inheritance: return transInheritance(DebugInst); case SPIRVDebug::TypeTemplateParameter: return transTemplateParameter(DebugInst); case SPIRVDebug::TypeTemplateTemplateParameter: return transTemplateTemplateParameter(DebugInst); case SPIRVDebug::TypeTemplateParameterPack: return transTemplateParameterPack(DebugInst); case SPIRVDebug::TypeTemplate: return transTemplate(DebugInst); case SPIRVDebug::ImportedEntity: return transImportedEntry(DebugInst); case SPIRVDebug::Operation: // To be translated with transExpression case SPIRVDebug::Source: // To be used by other instructions return nullptr; case SPIRVDebug::Expression: return transExpression(DebugInst); default: llvm_unreachable("Not implemented SPIR-V debug instruction!"); } } Instruction * SPIRVToLLVMDbgTran::transDebugIntrinsic(const SPIRVExtInst *DebugInst, BasicBlock *BB) { auto GetLocalVar = [&](SPIRVId Id) -> std::pair { auto *LV = transDebugInst(BM->get(Id)); DebugLoc DL = DebugLoc::get(LV->getLine(), 0, LV->getScope()); return std::make_pair(LV, DL); }; auto GetValue = [&](SPIRVId Id) -> Value * { auto *V = BM->get(Id); return SPIRVReader->transValue(V, BB->getParent(), BB); }; auto GetExpression = [&](SPIRVId Id) -> DIExpression * { return transDebugInst(BM->get(Id)); }; SPIRVWordVec Ops = DebugInst->getArguments(); switch (DebugInst->getExtOp()) { case SPIRVDebug::Scope: case SPIRVDebug::NoScope: return nullptr; case SPIRVDebug::Declare: { using namespace SPIRVDebug::Operand::DebugDeclare; auto LocalVar = GetLocalVar(Ops[DebugLocalVarIdx]); if (getDbgInst(Ops[VariableIdx])) { // If we don't have the variable(e.g. alloca might be promoted by mem2reg) // we should generate the following IR: // call void @llvm.dbg.declare(metadata !4, metadata !14, metadata !5) // !4 = !{} // DIBuilder::insertDeclare doesn't allow to pass nullptr for the Storage // parameter. To work around this limitation we create a dummy temp // alloca, use it to create llvm.dbg.declare, and then remove the alloca. auto *AI = new AllocaInst(Type::getInt8Ty(M->getContext()), 0, "tmp", BB); auto *DbgDeclare = Builder.insertDeclare( AI, LocalVar.first, GetExpression(Ops[ExpressionIdx]), LocalVar.second, BB); AI->eraseFromParent(); return DbgDeclare; } return Builder.insertDeclare(GetValue(Ops[VariableIdx]), LocalVar.first, GetExpression(Ops[ExpressionIdx]), LocalVar.second, BB); } case SPIRVDebug::Value: { using namespace SPIRVDebug::Operand::DebugValue; auto LocalVar = GetLocalVar(Ops[DebugLocalVarIdx]); return Builder.insertDbgValueIntrinsic( GetValue(Ops[ValueIdx]), LocalVar.first, GetExpression(Ops[ExpressionIdx]), LocalVar.second, BB); } default: llvm_unreachable("Unknown debug intrinsic!"); } } DebugLoc SPIRVToLLVMDbgTran::transDebugScope(const SPIRVInstruction *Inst) { unsigned Line = 0; unsigned Col = 0; MDNode *Scope = nullptr; MDNode *InlinedAt = nullptr; if (auto L = Inst->getLine()) { Line = L->getLine(); Col = L->getColumn(); } if (SPIRVEntry *S = Inst->getDebugScope()) { using namespace SPIRVDebug::Operand::Scope; SPIRVExtInst *DbgScope = static_cast(S); SPIRVWordVec Ops = DbgScope->getArguments(); Scope = getScope(BM->getEntry(Ops[ScopeIdx])); if (Ops.size() > InlinedAtIdx) InlinedAt = transDebugInst(BM->get(Ops[InlinedAtIdx])); } return DebugLoc::get(Line, Col, Scope, InlinedAt); } MDNode *SPIRVToLLVMDbgTran::transDebugInlined(const SPIRVExtInst *Inst) { using namespace SPIRVDebug::Operand::InlinedAt; SPIRVWordVec Ops = Inst->getArguments(); assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); unsigned Line = Ops[LineIdx]; unsigned Col = 0; // DebugInlinedAt instruction has no column operand DILocalScope *Scope = cast(getScope(BM->getEntry(Ops[ScopeIdx]))); DILocation *InlinedAt = nullptr; if (Ops.size() > InlinedIdx) { InlinedAt = transDebugInst(BM->get(Ops[InlinedIdx])); } return DILocation::getDistinct(M->getContext(), Line, Col, Scope, InlinedAt); } void SPIRVToLLVMDbgTran::finalize() { if (!Enable) return; Builder.finalize(); } DIFile *SPIRVToLLVMDbgTran::getFile(const SPIRVId SourceId) { using namespace SPIRVDebug::Operand::Source; SPIRVExtInst *Source = BM->get(SourceId); assert(Source->getExtOp() == SPIRVDebug::Source && "DebugSource instruction is expected"); SPIRVWordVec SourceArgs = Source->getArguments(); assert(SourceArgs.size() == OperandCount && "Invalid number of operands"); return getDIFile(getString(SourceArgs[FileIdx])); } SPIRVToLLVMDbgTran::SplitFileName::SplitFileName(const string &FileName) { auto Loc = FileName.find_last_of("/\\"); if (Loc != std::string::npos) { BaseName = FileName.substr(Loc + 1); Path = FileName.substr(0, Loc); } else { BaseName = FileName; Path = "."; } } } // namespace SPIRV SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVToLLVMDbgTran.h000066400000000000000000000140041363521741200223620ustar00rootroot00000000000000//===- SPIRVToLLVMDbgTran.h - Converts SPIR-V DebugInfo to LLVM -*- C++ -*-===// // // The LLVM/SPIR-V Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2018 Intel Corporation. All rights reserved. // // 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 Intel Corporation, 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. // //===----------------------------------------------------------------------===// // // This file implements translation of debug info from SPIR-V to LLVM metadata // //===----------------------------------------------------------------------===// #ifndef SPIRVTOLLVMDBGTRAN_H #define SPIRVTOLLVMDBGTRAN_H #include "SPIRVInstruction.h" #include "SPIRVModule.h" #include "llvm/IR/DIBuilder.h" #include "llvm/IR/DebugLoc.h" #include namespace llvm { class Module; class Value; class Instruction; class Type; } // namespace llvm using namespace llvm; namespace SPIRV { class SPIRVToLLVM; class SPIRVEntry; class SPIRVFunction; class SPIRVValue; class SPIRVToLLVMDbgTran { public: typedef std::vector SPIRVWordVec; SPIRVToLLVMDbgTran(SPIRVModule *TBM, Module *TM, SPIRVToLLVM *Reader); void addDbgInfoVersion(); void transDbgInfo(const SPIRVValue *SV, Value *V); template T *transDebugInst(const SPIRVExtInst *DebugInst) { assert(DebugInst->getExtSetKind() == SPIRVEIS_Debug && "Unexpected extended instruction set"); auto It = DebugInstCache.find(DebugInst); if (It != DebugInstCache.end()) return static_cast(It->second); MDNode *Res = transDebugInstImpl(DebugInst); DebugInstCache[DebugInst] = Res; return static_cast(Res); } Instruction *transDebugIntrinsic(const SPIRVExtInst *DebugInst, BasicBlock *BB); void finalize(); private: DIFile *getFile(const SPIRVId SourceId); DIFile *getDIFile(const std::string &FileName); DIFile *getDIFile(const SPIRVEntry *E); unsigned getLineNo(const SPIRVEntry *E); MDNode *transDebugInstImpl(const SPIRVExtInst *DebugInst); llvm::DebugLoc transDebugLocation(const SPIRVExtInst *DebugInst); llvm::DebugLoc transDebugScope(const SPIRVInstruction *Inst); MDNode *transDebugInlined(const SPIRVExtInst *Inst); DICompileUnit *transCompileUnit(const SPIRVExtInst *DebugInst); DIBasicType *transTypeBasic(const SPIRVExtInst *DebugInst); DIDerivedType *transTypeQualifier(const SPIRVExtInst *DebugInst); DIType *transTypePointer(const SPIRVExtInst *DebugInst); DICompositeType *transTypeArray(const SPIRVExtInst *DebugInst); DICompositeType *transTypeVector(const SPIRVExtInst *DebugInst); DICompositeType *transTypeComposite(const SPIRVExtInst *DebugInst); DINode *transTypeMember(const SPIRVExtInst *DebugInst); DINode *transTypeEnum(const SPIRVExtInst *DebugInst); DINode *transTemplateParameter(const SPIRVExtInst *DebugInst); DINode *transTemplateTemplateParameter(const SPIRVExtInst *DebugInst); DINode *transTemplateParameterPack(const SPIRVExtInst *DebugInst); MDNode *transTemplate(const SPIRVExtInst *DebugInst); DINode *transTypeFunction(const SPIRVExtInst *DebugInst); DINode *transTypePtrToMember(const SPIRVExtInst *DebugInst); DINode *transLexicalBlock(const SPIRVExtInst *DebugInst); DINode *transLexicalBlockDiscriminator(const SPIRVExtInst *DebugInst); DINode *transFunction(const SPIRVExtInst *DebugInst); DINode *transFunctionDecl(const SPIRVExtInst *DebugInst); MDNode *transGlobalVariable(const SPIRVExtInst *DebugInst); DINode *transLocalVariable(const SPIRVExtInst *DebugInst); DINode *transTypedef(const SPIRVExtInst *DebugInst); DINode *transInheritance(const SPIRVExtInst *DebugInst); DINode *transImportedEntry(const SPIRVExtInst *DebugInst); MDNode *transExpression(const SPIRVExtInst *DebugInst); SPIRVModule *BM; Module *M; DIBuilder Builder; SPIRVToLLVM *SPIRVReader; DICompileUnit *CU; bool Enable; std::unordered_map FileMap; std::unordered_map FuncMap; std::unordered_map DebugInstCache; struct SplitFileName { SplitFileName(const std::string &FileName); std::string BaseName; std::string Path; }; DIScope *getScope(const SPIRVEntry *ScopeInst); SPIRVExtInst *getDbgInst(const SPIRVId Id); template SPIRVExtInst *getDbgInst(const SPIRVId Id) { if (SPIRVExtInst *DI = getDbgInst(Id)) { if (DI->getExtOp() == OpCode) { return DI; } } return nullptr; } StringRef getString(const SPIRVId Id); }; } // namespace SPIRV #endif // SPIRVTOLLVMDBGTRAN_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVToOCL.cpp000066400000000000000000000406421363521741200213250ustar00rootroot00000000000000//===- SPIRVToOCL.cpp - Transform SPIR-V builtins to OCL builtins------===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// // // This file implements common transform of SPIR-V builtins to OCL builtins. // // Some of the visit functions are translations to OCL2.0 builtins, but they // are currently used also for OCL1.2, so theirs implementations are placed // in this pass as a common functionality for both versions. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "spvtocl" #include "SPIRVToOCL.h" #include "llvm/IR/Verifier.h" #include "llvm/Support/CommandLine.h" namespace SPIRV { static cl::opt MangledAtomicTypeNamePrefix("spirv-atomic-prefix", cl::desc("Mangled atomic type name prefix"), cl::init("U7_Atomic")); static cl::opt OCLBuiltinsVersion("spirv-ocl-builtins-version", cl::desc("Specify version of OCL builtins to translate " "to (CL1.2, CL2.0, CL2.1)")); void SPIRVToOCL::visitCallInst(CallInst &CI) { LLVM_DEBUG(dbgs() << "[visistCallInst] " << CI << '\n'); auto F = CI.getCalledFunction(); if (!F) return; auto MangledName = F->getName(); std::string DemangledName; Op OC = OpNop; if (!oclIsBuiltin(MangledName, &DemangledName) || (OC = getSPIRVFuncOC(DemangledName)) == OpNop) return; LLVM_DEBUG(dbgs() << "DemangledName = " << DemangledName.c_str() << '\n' << "OpCode = " << OC << '\n'); if (OC == OpImageQuerySize || OC == OpImageQuerySizeLod) { visitCallSPRIVImageQuerySize(&CI); return; } if (OC == OpMemoryBarrier) { visitCallSPIRVMemoryBarrier(&CI); return; } if (OC == OpControlBarrier) { visitCallSPIRVControlBarrier(&CI); } if (isAtomicOpCode(OC)) { visitCallSPIRVAtomicBuiltin(&CI, OC); return; } if (isGroupOpCode(OC)) { visitCallSPIRVGroupBuiltin(&CI, OC); return; } if (isPipeOpCode(OC)) { visitCallSPIRVPipeBuiltin(&CI, OC); return; } if (isMediaBlockINTELOpcode(OC)) { visitCallSPIRVImageMediaBlockBuiltin(&CI, OC); return; } if (OCLSPIRVBuiltinMap::rfind(OC)) visitCallSPIRVBuiltin(&CI, OC); } void SPIRVToOCL::visitCastInst(CastInst &Cast) { if (!isa(Cast) && !isa(Cast) && !isa(Cast) && !isa(Cast) && !isa(Cast) && !isa(Cast) && !isa(Cast) && !isa(Cast) && !isa(Cast)) return; Type const *SrcTy = Cast.getSrcTy(); Type *DstVecTy = Cast.getDestTy(); // Leave scalar casts as is. Skip boolean vector casts becase there // are no suitable OCL built-ins. if (!DstVecTy->isVectorTy() || SrcTy->getScalarSizeInBits() == 1 || DstVecTy->getScalarSizeInBits() == 1) return; // Assemble built-in name -> convert_gentypeN std::string CastBuiltInName(kOCLBuiltinName::ConvertPrefix); // Check if this is 'floating point -> unsigned integer' cast CastBuiltInName += mapLLVMTypeToOCLType(DstVecTy, !isa(Cast)); // Replace LLVM conversion instruction with call to conversion built-in BuiltinFuncMangleInfo Mangle; // It does matter if the source is unsigned integer or not. SExt is for // signed source, ZExt and UIToFPInst are for unsigned source. if (isa(Cast) || isa(Cast)) Mangle.addUnsignedArg(0); AttributeList Attributes; CallInst *Call = addCallInst(M, CastBuiltInName, DstVecTy, Cast.getOperand(0), &Attributes, &Cast, &Mangle, Cast.getName(), false); Cast.replaceAllUsesWith(Call); Cast.eraseFromParent(); } void SPIRVToOCL::visitCallSPRIVImageQuerySize(CallInst *CI) { Function *Func = CI->getCalledFunction(); // Get image type Type *ArgTy = Func->getFunctionType()->getParamType(0); assert(ArgTy->isPointerTy() && "argument must be a pointer to opaque structure"); StructType *ImgTy = cast(ArgTy->getPointerElementType()); assert(ImgTy->isOpaque() && "image type must be an opaque structure"); StringRef ImgTyName = ImgTy->getName(); assert(ImgTyName.startswith("opencl.image") && "not an OCL image type"); unsigned ImgDim = 0; bool ImgArray = false; if (ImgTyName.startswith("opencl.image1d")) { ImgDim = 1; } else if (ImgTyName.startswith("opencl.image2d")) { ImgDim = 2; } else if (ImgTyName.startswith("opencl.image3d")) { ImgDim = 3; } assert(ImgDim != 0 && "unexpected image dimensionality"); if (ImgTyName.count("_array_") != 0) { ImgArray = true; } AttributeList Attributes = CI->getCalledFunction()->getAttributes(); BuiltinFuncMangleInfo Mangle; Type *Int32Ty = Type::getInt32Ty(*Ctx); Instruction *GetImageSize = nullptr; if (ImgDim == 1) { // OpImageQuerySize from non-arrayed 1d image is always translated // into get_image_width returning scalar argument GetImageSize = addCallInst(M, kOCLBuiltinName::GetImageWidth, Int32Ty, CI->getArgOperand(0), &Attributes, CI, &Mangle, CI->getName(), false); // The width of integer type returning by OpImageQuerySize[Lod] may // differ from i32 if (CI->getType()->getScalarType() != Int32Ty) { GetImageSize = CastInst::CreateIntegerCast(GetImageSize, CI->getType()->getScalarType(), false, CI->getName(), CI); } } else { assert((ImgDim == 2 || ImgDim == 3) && "invalid image type"); assert(CI->getType()->isVectorTy() && "this code can handle vector result type only"); // get_image_dim returns int2 and int4 for 2d and 3d images respecitvely. const unsigned ImgDimRetEls = ImgDim == 2 ? 2 : 4; VectorType *RetTy = VectorType::get(Int32Ty, ImgDimRetEls); GetImageSize = addCallInst(M, kOCLBuiltinName::GetImageDim, RetTy, CI->getArgOperand(0), &Attributes, CI, &Mangle, CI->getName(), false); // The width of integer type returning by OpImageQuerySize[Lod] may // differ from i32 if (CI->getType()->getScalarType() != Int32Ty) { GetImageSize = CastInst::CreateIntegerCast( GetImageSize, VectorType::get(CI->getType()->getScalarType(), GetImageSize->getType()->getVectorNumElements()), false, CI->getName(), CI); } } if (ImgArray || ImgDim == 3) { assert( CI->getType()->isVectorTy() && "OpImageQuerySize[Lod] must return vector for arrayed and 3d images"); const unsigned ImgQuerySizeRetEls = CI->getType()->getVectorNumElements(); if (ImgDim == 1) { // get_image_width returns scalar result while OpImageQuerySize // for image1d_array_t returns <2 x i32> vector. assert(ImgQuerySizeRetEls == 2 && "OpImageQuerySize[Lod] must return <2 x iN> vector type"); GetImageSize = InsertElementInst::Create( UndefValue::get(CI->getType()), GetImageSize, ConstantInt::get(Int32Ty, 0), CI->getName(), CI); } else { // get_image_dim and OpImageQuerySize returns different vector // types for arrayed and 3d images. SmallVector MaskEls; for (unsigned Idx = 0; Idx < ImgQuerySizeRetEls; ++Idx) MaskEls.push_back(ConstantInt::get(Int32Ty, Idx)); Constant *Mask = ConstantVector::get(MaskEls); GetImageSize = new ShuffleVectorInst( GetImageSize, UndefValue::get(GetImageSize->getType()), Mask, CI->getName(), CI); } } if (ImgArray) { assert((ImgDim == 1 || ImgDim == 2) && "invalid image array type"); // Insert get_image_array_size to the last position of the resulting vector. Type *SizeTy = Type::getIntNTy(*Ctx, M->getDataLayout().getPointerSizeInBits(0)); Instruction *GetImageArraySize = addCallInst( M, kOCLBuiltinName::GetImageArraySize, SizeTy, CI->getArgOperand(0), &Attributes, CI, &Mangle, CI->getName(), false); // The width of integer type returning by OpImageQuerySize[Lod] may // differ from size_t which is returned by get_image_array_size if (GetImageArraySize->getType() != CI->getType()->getScalarType()) { GetImageArraySize = CastInst::CreateIntegerCast( GetImageArraySize, CI->getType()->getScalarType(), false, CI->getName(), CI); } GetImageSize = InsertElementInst::Create( GetImageSize, GetImageArraySize, ConstantInt::get(Int32Ty, CI->getType()->getVectorNumElements() - 1), CI->getName(), CI); } assert(GetImageSize && "must not be null"); CI->replaceAllUsesWith(GetImageSize); CI->eraseFromParent(); } void SPIRVToOCL::visitCallSPIRVGroupBuiltin(CallInst *CI, Op OC) { auto DemangledName = OCLSPIRVBuiltinMap::rmap(OC); assert(DemangledName.find(kSPIRVName::GroupPrefix) == 0); std::string Prefix = getGroupBuiltinPrefix(CI); bool HasGroupOperation = hasGroupOperation(OC); if (!HasGroupOperation) { DemangledName = Prefix + DemangledName; } else { auto GO = getArgAs(CI, 1); StringRef Op = DemangledName; Op = Op.drop_front(strlen(kSPIRVName::GroupPrefix)); bool Unsigned = Op.front() == 'u'; if (!Unsigned) Op = Op.drop_front(1); DemangledName = Prefix + kSPIRVName::GroupPrefix + SPIRSPIRVGroupOperationMap::rmap(GO) + '_' + Op.str(); } assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args) { Args.erase(Args.begin(), Args.begin() + (HasGroupOperation ? 2 : 1)); if (OC == OpGroupBroadcast) expandVector(CI, Args, 1); return DemangledName; }, &Attrs); } void SPIRVToOCL::visitCallSPIRVPipeBuiltin(CallInst *CI, Op OC) { auto DemangledName = OCLSPIRVBuiltinMap::rmap(OC); bool HasScope = DemangledName.find(kSPIRVName::GroupPrefix) == 0; if (HasScope) DemangledName = getGroupBuiltinPrefix(CI) + DemangledName; assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args) { if (HasScope) Args.erase(Args.begin(), Args.begin() + 1); if (!(OC == OpReadPipe || OC == OpWritePipe || OC == OpReservedReadPipe || OC == OpReservedWritePipe || OC == OpReadPipeBlockingINTEL || OC == OpWritePipeBlockingINTEL)) return DemangledName; auto &P = Args[Args.size() - 3]; auto T = P->getType(); assert(isa(T)); auto ET = T->getPointerElementType(); if (!ET->isIntegerTy(8) || T->getPointerAddressSpace() != SPIRAS_Generic) { auto NewTy = PointerType::getInt8PtrTy(*Ctx, SPIRAS_Generic); P = CastInst::CreatePointerBitCastOrAddrSpaceCast(P, NewTy, "", CI); } return DemangledName; }, &Attrs); } void SPIRVToOCL::visitCallSPIRVImageMediaBlockBuiltin(CallInst *CI, Op OC) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args) { // Moving the first argument to the end. std::rotate(Args.rbegin(), Args.rend() - 1, Args.rend()); Type *RetType = CI->getType(); if (OC == OpSubgroupImageMediaBlockWriteINTEL) { assert(Args.size() >= 4 && "Wrong media block write signature"); RetType = Args.at(3)->getType(); // texel type } unsigned int BitWidth = RetType->getScalarSizeInBits(); std::string FuncPostfix; if (BitWidth == 8) FuncPostfix = "_uc"; else if (BitWidth == 16) FuncPostfix = "_us"; else if (BitWidth == 32) FuncPostfix = "_ui"; else assert(0 && "Unsupported texel type!"); if (RetType->isVectorTy()) { unsigned int NumEl = RetType->getVectorNumElements(); assert((NumEl == 2 || NumEl == 4 || NumEl == 8 || NumEl == 16) && "Wrong function type!"); FuncPostfix += std::to_string(NumEl); } return OCLSPIRVBuiltinMap::rmap(OC) + FuncPostfix; }, &Attrs); } void SPIRVToOCL::visitCallSPIRVBuiltin(CallInst *CI, Op OC) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args) { return OCLSPIRVBuiltinMap::rmap(OC); }, &Attrs); } void SPIRVToOCL::translateMangledAtomicTypeName() { for (auto &I : M->functions()) { if (!I.hasName()) continue; std::string MangledName = I.getName(); std::string DemangledName; if (!oclIsBuiltin(MangledName, &DemangledName) || DemangledName.find(kOCLBuiltinName::AtomPrefix) != 0) continue; auto Loc = MangledName.find(kOCLBuiltinName::AtomPrefix); Loc = MangledName.find(kMangledName::AtomicPrefixInternal, Loc); MangledName.replace(Loc, strlen(kMangledName::AtomicPrefixInternal), MangledAtomicTypeNamePrefix); I.setName(MangledName); } } std::string SPIRVToOCL::getGroupBuiltinPrefix(CallInst *CI) { std::string Prefix; auto ES = getArgAsScope(CI, 0); switch (ES) { case ScopeWorkgroup: Prefix = kOCLBuiltinName::WorkPrefix; break; case ScopeSubgroup: Prefix = kOCLBuiltinName::SubPrefix; break; default: llvm_unreachable("Invalid execution scope"); } return Prefix; } } // namespace SPIRV ModulePass *llvm::createSPIRVToOCL(Module &M) { if (OCLBuiltinsVersion.getNumOccurrences() > 0) { if (OCLBuiltinsVersion.getValue() == "CL1.2") return createSPIRVToOCL12(); else if (OCLBuiltinsVersion.getValue() == "CL2.0" || OCLBuiltinsVersion.getValue() == "CL2.1") return createSPIRVToOCL20(); else { assert(0 && "Invalid spirv-ocl-builtins-version value"); return nullptr; } } // Below part of code is here just temporarily (to not broke existing // projects based on translator), because ocl builtins versions shouldn't has // a dependency on OpSource spirv opcode. OpSource spec: "This has no semantic // impact and can safely be removed from a module." After some time it can be // removed, then only factor impacting version of ocl builtins will be // spirv-ocl-builtins-version command option. unsigned OCLVersion = getOCLVersion(&M); if (OCLVersion <= kOCLVer::CL12) return createSPIRVToOCL12(); else if (OCLVersion >= kOCLVer::CL20) return createSPIRVToOCL20(); else { assert(0 && "Invalid ocl version in llvm module"); return nullptr; } } SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVToOCL.h000066400000000000000000000141241363521741200207660ustar00rootroot00000000000000//===- SPIRVToOCL.h - Converts SPIR-V to LLVM ------------------*- C++ -*-===// // // The LLVM/SPIR-V Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file contains declaration of SPIRVToOCL class which implements /// common transform of SPIR-V builtins to OCL builtins. /// //===----------------------------------------------------------------------===// #include "OCLUtil.h" #include "SPIRVInternal.h" #include "llvm/IR/InstVisitor.h" #include "llvm/Pass.h" #include "llvm/PassSupport.h" #include namespace SPIRV { class SPIRVToOCL : public ModulePass, public InstVisitor { protected: SPIRVToOCL(char &ID) : ModulePass(ID), M(nullptr), Ctx(nullptr) {} public: virtual bool runOnModule(Module &M) = 0; void visitCallInst(CallInst &CI); // SPIR-V reader should translate vector casts into OCL built-ins because // such conversions are not defined neither by OpenCL C/C++ nor // by SPIR 1.2/2.0 standards. So, it is safer to convert such casts into // appropriate calls to conversion built-ins defined by the standards. void visitCastInst(CastInst &CI); /// Transform __spirv_ImageQuerySize[Lod] into vector of the same length /// containing {[get_image_width | get_image_dim], get_image_array_size} /// for all images except image1d_t which is always converted into /// get_image_width returning scalar result. void visitCallSPRIVImageQuerySize(CallInst *CI); /// Transform __spirv_Group* to {work_group|sub_group}_*. /// /// Special handling of work_group_broadcast. /// __spirv_GroupBroadcast(a, vec3(x, y, z)) /// => /// work_group_broadcast(a, x, y, z) /// /// Transform OpenCL group builtin function names from group_ /// to workgroup_ and sub_group_. /// Insert group operation part: reduce_/inclusive_scan_/exclusive_scan_ /// Transform the operation part: /// fadd/iadd/sadd => add /// fmax/smax => max /// fmin/smin => min /// Keep umax/umin unchanged. void visitCallSPIRVGroupBuiltin(CallInst *CI, Op OC); /// Transform __spirv_{PipeOpName} to OCL pipe builtin functions. void visitCallSPIRVPipeBuiltin(CallInst *CI, Op OC); /// Transform __spirv_OpOpSubgroupImageMediaBlockReadINTEL => /// intel_sub_group_media_block_read /// __spirv_OpSubgroupImageMediaBlockWriteINTEL => /// intel_sub_group_media_block_write void visitCallSPIRVImageMediaBlockBuiltin(CallInst *CI, Op OC); /// Transform __spirv_* builtins to OCL 2.0 builtins. /// No change with arguments. void visitCallSPIRVBuiltin(CallInst *CI, Op OC); /// Translate mangled atomic type name: "atomic_" => /// MangledAtomicTypeNamePrefix void translateMangledAtomicTypeName(); /// Get prefix work_/sub_ for OCL group builtin functions. /// Assuming the first argument of \param CI is a constant integer for /// workgroup/subgroup scope enums. std::string getGroupBuiltinPrefix(CallInst *CI); /// Transform __spirv_OpAtomicCompareExchange and /// __spirv_OpAtomicCompareExchangeWeak virtual Instruction *visitCallSPIRVAtomicCmpExchg(CallInst *CI, Op OC) = 0; /// Transform __spirv_OpAtomicIIncrement/OpAtomicIDecrement to: /// - OCL2.0: atomic_fetch_add_explicit/atomic_fetch_sub_explicit /// - OCL1.2: atomic_inc/atomic_dec virtual Instruction *visitCallSPIRVAtomicIncDec(CallInst *CI, Op OC) = 0; /// Transform __spirv_Atomic* to atomic_*. /// __spirv_Atomic*(atomic_op, scope, sema, ops, ...) => /// atomic_*(atomic_op, ops, ..., order(sema), map(scope)) virtual Instruction *visitCallSPIRVAtomicBuiltin(CallInst *CI, Op OC) = 0; /// Transform __spirv_MemoryBarrier to: /// - OCL2.0: atomic_work_item_fence.__spirv_MemoryBarrier(scope, sema) => /// atomic_work_item_fence(flag(sema), order(sema), map(scope)) /// - OCL1.2: mem_fence virtual void visitCallSPIRVMemoryBarrier(CallInst *CI) = 0; /// Transform __spirv_ControlBarrier to: /// - OCL2.0: work_group_barrier or sub_group barrier /// - OCL1.2: barrier virtual void visitCallSPIRVControlBarrier(CallInst *CI) = 0; /// Conduct generic mutations for all atomic builtins virtual CallInst *mutateCommonAtomicArguments(CallInst *CI, Op OC) = 0; /// Transform __spirv_Opcode to ocl-version specific builtin name /// using separate maps for OpenCL 1.2 and OpenCL 2.0 virtual Instruction *mutateAtomicName(CallInst *CI, Op OC) = 0; protected: Module *M; LLVMContext *Ctx; }; } // namespace SPIRV SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVToOCL12.cpp000066400000000000000000000335031363521741200214660ustar00rootroot00000000000000//===- SPIRVToOCL12.cpp - Transform SPIR-V builtins to OCL 1.2 // builtins------===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// // // This file implements transform of SPIR-V builtins to OCL 1.2 builtins. // //===----------------------------------------------------------------------===// #include "SPIRVToOCL.h" #include "llvm/IR/Verifier.h" #define DEBUG_TYPE "spvtocl12" namespace SPIRV { class SPIRVToOCL12 : public SPIRVToOCL { public: SPIRVToOCL12() : SPIRVToOCL(ID) { initializeSPIRVToOCL12Pass(*PassRegistry::getPassRegistry()); } bool runOnModule(Module &M) override; /// Transform __spirv_MemoryBarrier to atomic_work_item_fence. /// __spirv_MemoryBarrier(scope, sema) => /// atomic_work_item_fence(flag(sema), order(sema), map(scope)) void visitCallSPIRVMemoryBarrier(CallInst *CI) override; /// Transform __spirv_ControlBarrier to barrier. /// __spirv_ControlBarrier(execScope, memScope, sema) => /// barrier(flag(sema)) void visitCallSPIRVControlBarrier(CallInst *CI) override; /// Transform __spirv_OpAtomic functions. It firstly conduct generic /// mutations for all builtins and then mutate some of them seperately Instruction *visitCallSPIRVAtomicBuiltin(CallInst *CI, Op OC) override; /// Transform __spirv_OpAtomicIIncrement / OpAtomicIDecrement to /// atomic_inc / atomic_dec Instruction *visitCallSPIRVAtomicIncDec(CallInst *CI, Op OC) override; /// Transform __spirv_OpAtomicUMin/SMin/UMax/SMax into /// atomic_min/atomic_max, as there is no distinction in OpenCL 1.2 /// between signed and unsigned version of those functions Instruction *visitCallSPIRVAtomicUMinUMax(CallInst *CI, Op OC); /// Transform __spirv_OpAtomicLoad to atomic_add(*ptr, 0) Instruction *visitCallSPIRVAtomicLoad(CallInst *CI); /// Transform __spirv_OpAtomicStore to atomic_xchg(*ptr, value) Instruction *visitCallSPIRVAtomicStore(CallInst *CI); /// Transform __spirv_OpAtomicFlagClear to atomic_xchg(*ptr, 0) /// with ignoring the result Instruction *visitCallSPIRVAtomicFlagClear(CallInst *CI); /// Transform __spirv_OpAtomicFlagTestAndTest to /// (bool)atomic_xchg(*ptr, 1) Instruction *visitCallSPIRVAtomicFlagTestAndSet(CallInst *CI); /// Transform __spirv_OpAtomicCompareExchange and /// __spirv_OpAtomicCompareExchangeWeak into atomic_cmpxchg. There is no /// weak version of function in OpenCL 1.2 Instruction *visitCallSPIRVAtomicCmpExchg(CallInst *CI, Op OC) override; /// Conduct generic mutations for all atomic builtins CallInst *mutateCommonAtomicArguments(CallInst *CI, Op OC) override; /// Transform atomic builtin name into correct ocl-dependent name Instruction *mutateAtomicName(CallInst *CI, Op OC) override; /// Transform SPIR-V atomic instruction opcode into OpenCL 1.2 builtin name. /// Depending on the type, the return name starts with "atomic_" for 32-bit /// types or with "atom_" for 64-bit types, as specified by /// cl_khr_int64_base_atomics and cl_khr_int64_extended_atomics extensions. std::string mapAtomicName(Op OC, Type *Ty); static char ID; }; char SPIRVToOCL12::ID = 0; bool SPIRVToOCL12::runOnModule(Module &Module) { M = &Module; Ctx = &M->getContext(); visit(*M); eraseUselessFunctions(&Module); LLVM_DEBUG(dbgs() << "After SPIRVToOCL12:\n" << *M); std::string Err; raw_string_ostream ErrorOS(Err); if (verifyModule(*M, &ErrorOS)) { LLVM_DEBUG(errs() << "Fails to verify module: " << ErrorOS.str()); } return true; } void SPIRVToOCL12::visitCallSPIRVMemoryBarrier(CallInst *CI) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args) { if (auto Arg = dyn_cast(Args[1])) { auto Sema = mapSPIRVMemSemanticToOCL(Arg->getZExtValue()); Args.resize(1); Args[0] = getInt32(M, Sema.first); } else { CallInst *TransCall = dyn_cast(Args[1]); Function *F = TransCall ? TransCall->getCalledFunction() : nullptr; if (F && F->getName().equals(kSPIRVName::TranslateOCLMemScope)) { Args[0] = TransCall->getArgOperand(0); } else { int ClMemFenceMask = MemorySemanticsWorkgroupMemoryMask | MemorySemanticsCrossWorkgroupMemoryMask | MemorySemanticsImageMemoryMask; Args[0] = getOrCreateSwitchFunc( kSPIRVName::TranslateSPIRVMemFence, Args[1], OCLMemFenceExtendedMap::getRMap(), true /*IsReverse*/, None, CI, M, ClMemFenceMask); } Args.resize(1); } return kOCLBuiltinName::MemFence; }, &Attrs); } void SPIRVToOCL12::visitCallSPIRVControlBarrier(CallInst *CI) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); Attrs = Attrs.addAttribute(CI->getContext(), AttributeList::FunctionIndex, Attribute::Convergent); mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args) { if (auto Arg = dyn_cast(Args[2])) { auto Sema = mapSPIRVMemSemanticToOCL(Arg->getZExtValue()); Args.resize(1); Args[0] = getInt32(M, Sema.first); } else { CallInst *TransCall = dyn_cast(Args[2]); Function *F = TransCall ? TransCall->getCalledFunction() : nullptr; if (F && F->getName().equals(kSPIRVName::TranslateOCLMemScope)) { Args[0] = TransCall->getArgOperand(0); } else { int ClMemFenceMask = MemorySemanticsWorkgroupMemoryMask | MemorySemanticsCrossWorkgroupMemoryMask | MemorySemanticsImageMemoryMask; Args[0] = getOrCreateSwitchFunc( kSPIRVName::TranslateSPIRVMemFence, Args[2], OCLMemFenceExtendedMap::getRMap(), true /*IsReverse*/, None, CI, M, ClMemFenceMask); } Args.resize(1); } return kOCLBuiltinName::Barrier; }, &Attrs); } Instruction *SPIRVToOCL12::visitCallSPIRVAtomicIncDec(CallInst *CI, Op OC) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); return mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args) { Args.resize(1); return mapAtomicName(OC, CI->getType()); }, &Attrs); } CallInst *SPIRVToOCL12::mutateCommonAtomicArguments(CallInst *CI, Op OC) { assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); return mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args) { auto Ptr = findFirstPtr(Args); auto NumOrder = getSPIRVAtomicBuiltinNumMemoryOrderArgs(OC); auto ArgsToRemove = NumOrder + 1; // OpenCL1.2 builtins does not use // scope and memory order arguments auto StartIdx = Ptr + 1; auto StopIdx = StartIdx + ArgsToRemove; Args.erase(Args.begin() + StartIdx, Args.begin() + StopIdx); return mapAtomicName(OC, CI->getType()); }, &Attrs); } Instruction *SPIRVToOCL12::visitCallSPIRVAtomicUMinUMax(CallInst *CI, Op OC) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); return mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args) { std::swap(Args[1], Args[3]); Args.resize(2); return mapAtomicName(OC, CI->getType()); }, &Attrs); } Instruction *SPIRVToOCL12::visitCallSPIRVAtomicLoad(CallInst *CI) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); return mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args) { Args.resize(1); // There is no atomic_load in OpenCL 1.2 spec. // Emit this builtin via call of atomic_add(*p, 0). Type *ptrElemTy = Args[0]->getType()->getPointerElementType(); Args.push_back(Constant::getNullValue(ptrElemTy)); return mapAtomicName(OpAtomicIAdd, ptrElemTy); }, &Attrs); } Instruction *SPIRVToOCL12::visitCallSPIRVAtomicStore(CallInst *CI) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); return mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args, Type *&RetTy) { std::swap(Args[1], Args[3]); Args.resize(2); // The type of the value pointed to by Pointer (1st argument) // must be the same as Result Type. RetTy = Args[0]->getType()->getPointerElementType(); return mapAtomicName(OpAtomicExchange, RetTy); }, [=](CallInst *CI) -> Instruction * { return CI; }, &Attrs); } Instruction *SPIRVToOCL12::visitCallSPIRVAtomicFlagClear(CallInst *CI) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); return mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args, Type *&RetTy) { Args.resize(1); Args.push_back(getInt32(M, 0)); RetTy = Type::getInt32Ty(M->getContext()); return mapAtomicName(OpAtomicExchange, RetTy); }, [=](CallInst *CI) -> Instruction * { return CI; }, &Attrs); } Instruction *SPIRVToOCL12::visitCallSPIRVAtomicFlagTestAndSet(CallInst *CI) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); return mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args, Type *&RetTy) { Args.resize(1); Args.push_back(getInt32(M, 1)); RetTy = Type::getInt32Ty(M->getContext()); return mapAtomicName(OpAtomicExchange, RetTy); }, [=](CallInst *CI) -> Instruction * { return BitCastInst::Create(Instruction::Trunc, CI, Type::getInt1Ty(CI->getContext()), "", CI->getNextNode()); }, &Attrs); } Instruction *SPIRVToOCL12::visitCallSPIRVAtomicCmpExchg(CallInst *CI, Op OC) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); return mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args) { Args.erase(Args.begin() + 1, Args.begin() + 4); // SPIRV OpAtomicCompareExchange and OpAtomicCompareExchangeWeak // has Value and Comparator in different order than ocl functions // both of them are translated into atomic_cmpxchg std::swap(Args[1], Args[2]); // Type of return value, pointee of the pointer operand, other operands, // all match, and should be integer scalar types. return mapAtomicName(OpAtomicCompareExchange, CI->getType()); }, &Attrs); } Instruction *SPIRVToOCL12::visitCallSPIRVAtomicBuiltin(CallInst *CI, Op OC) { Instruction *NewCI = nullptr; switch (OC) { case OpAtomicLoad: NewCI = visitCallSPIRVAtomicLoad(CI); break; case OpAtomicStore: NewCI = visitCallSPIRVAtomicStore(CI); break; case OpAtomicFlagClear: NewCI = visitCallSPIRVAtomicFlagClear(CI); break; case OpAtomicFlagTestAndSet: NewCI = visitCallSPIRVAtomicFlagTestAndSet(CI); break; case OpAtomicUMin: case OpAtomicUMax: NewCI = visitCallSPIRVAtomicUMinUMax(CI, OC); break; case OpAtomicCompareExchange: case OpAtomicCompareExchangeWeak: NewCI = visitCallSPIRVAtomicCmpExchg(CI, OC); break; default: NewCI = mutateCommonAtomicArguments(CI, OC); } return NewCI; } Instruction *SPIRVToOCL12::mutateAtomicName(CallInst *CI, Op OC) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); return mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args) { return OCL12SPIRVBuiltinMap::rmap(OC); }, &Attrs); } std::string SPIRVToOCL12::mapAtomicName(Op OC, Type *Ty) { std::string Prefix = Ty->isIntegerTy(64) ? kOCLBuiltinName::AtomPrefix : kOCLBuiltinName::AtomicPrefix; return Prefix += OCL12SPIRVBuiltinMap::rmap(OC); } } // namespace SPIRV INITIALIZE_PASS(SPIRVToOCL12, "spvtoocl12", "Translate SPIR-V builtins to OCL 1.2 builtins", false, false) ModulePass *llvm::createSPIRVToOCL12() { return new SPIRVToOCL12(); } SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVToOCL20.cpp000066400000000000000000000325441363521741200214710ustar00rootroot00000000000000//===- SPIRVToOCL20.cpp - Transform SPIR-V builtins to OCL20 builtins------===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// // // This file implements transform SPIR-V builtins to OCL 2.0 builtins. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "spvtocl20" #include "SPIRVToOCL.h" #include "llvm/IR/Verifier.h" namespace SPIRV { class SPIRVToOCL20 : public SPIRVToOCL { public: SPIRVToOCL20() : SPIRVToOCL(ID) { initializeSPIRVToOCL20Pass(*PassRegistry::getPassRegistry()); } bool runOnModule(Module &M) override; /// Transform __spirv_MemoryBarrier to atomic_work_item_fence. /// __spirv_MemoryBarrier(scope, sema) => /// atomic_work_item_fence(flag(sema), order(sema), map(scope)) void visitCallSPIRVMemoryBarrier(CallInst *CI) override; /// Transform __spirv_ControlBarrier to work_group_barrier/sub_group_barrier. /// If execution scope is ScopeWorkgroup: /// __spirv_ControlBarrier(execScope, memScope, sema) => /// work_group_barrier(flag(sema), map(memScope)) /// Otherwise: /// __spirv_ControlBarrier(execScope, memScope, sema) => /// sub_group_barrier(flag(sema), map(memScope)) void visitCallSPIRVControlBarrier(CallInst *CI) override; /// Transform __spirv_Atomic* to atomic_*. /// __spirv_Atomic*(atomic_op, scope, sema, ops, ...) => /// atomic_*(generic atomic_op, ops, ..., order(sema), map(scope)) Instruction *visitCallSPIRVAtomicBuiltin(CallInst *CI, Op OC) override; /// Transform __spirv_OpAtomicIIncrement / OpAtomicIDecrement to /// atomic_fetch_add_explicit / atomic_fetch_sub_explicit Instruction *visitCallSPIRVAtomicIncDec(CallInst *CI, Op OC) override; /// Conduct generic mutations for all atomic builtins CallInst *mutateCommonAtomicArguments(CallInst *CI, Op OC) override; /// Transform atomic builtin name into correct ocl-dependent name Instruction *mutateAtomicName(CallInst *CI, Op OC) override; /// Transform __spirv_OpAtomicCompareExchange/Weak into /// compare_exchange_strong/weak_explicit Instruction *visitCallSPIRVAtomicCmpExchg(CallInst *CI, Op OC) override; static char ID; }; char SPIRVToOCL20::ID = 0; bool SPIRVToOCL20::runOnModule(Module &Module) { M = &Module; Ctx = &M->getContext(); visit(*M); translateMangledAtomicTypeName(); eraseUselessFunctions(&Module); LLVM_DEBUG(dbgs() << "After SPIRVToOCL20:\n" << *M); std::string Err; raw_string_ostream ErrorOS(Err); if (verifyModule(*M, &ErrorOS)) { LLVM_DEBUG(errs() << "Fails to verify module: " << ErrorOS.str()); } return true; } void SPIRVToOCL20::visitCallSPIRVMemoryBarrier(CallInst *CI) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); mutateCallInstOCL(M, CI, [=](CallInst *, std::vector &Args) { auto GetArg = [=](unsigned I) { return cast(Args[I])->getZExtValue(); }; auto MScope = static_cast(GetArg(0)); auto Sema = mapSPIRVMemSemanticToOCL(GetArg(1)); Args.resize(3); Args[0] = getInt32(M, Sema.first); Args[1] = getInt32(M, Sema.second); Args[2] = getInt32(M, rmap(MScope)); return kOCLBuiltinName::AtomicWorkItemFence; }, &Attrs); } void SPIRVToOCL20::visitCallSPIRVControlBarrier(CallInst *CI) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); Attrs = Attrs.addAttribute(CI->getContext(), AttributeList::FunctionIndex, Attribute::Convergent); mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args) { auto GetArg = [=](unsigned I) { return cast(Args[I])->getZExtValue(); }; auto ExecScope = static_cast(GetArg(0)); auto MScope = static_cast(GetArg(1)); auto Sema = mapSPIRVMemSemanticToOCL(GetArg(2)); Args.resize(2); Args[0] = getInt32(M, Sema.first); Args[1] = getInt32(M, rmap(MScope)); return (ExecScope == ScopeWorkgroup) ? kOCLBuiltinName::WorkGroupBarrier : kOCLBuiltinName::SubGroupBarrier; }, &Attrs); } Instruction *SPIRVToOCL20::mutateAtomicName(CallInst *CI, Op OC) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); return mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args) { return OCLSPIRVBuiltinMap::rmap(OC); }, &Attrs); } Instruction *SPIRVToOCL20::visitCallSPIRVAtomicBuiltin(CallInst *CI, Op OC) { CallInst *CIG = mutateCommonAtomicArguments(CI, OC); Instruction *NewCI = nullptr; switch (OC) { case OpAtomicIIncrement: case OpAtomicIDecrement: NewCI = visitCallSPIRVAtomicIncDec(CIG, OC); break; case OpAtomicCompareExchange: case OpAtomicCompareExchangeWeak: NewCI = visitCallSPIRVAtomicCmpExchg(CIG, OC); break; default: NewCI = mutateAtomicName(CIG, OC); } return NewCI; } Instruction *SPIRVToOCL20::visitCallSPIRVAtomicIncDec(CallInst *CI, Op OC) { AttributeList Attrs = CI->getCalledFunction()->getAttributes(); return mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args) { // Since OpenCL 2.0 doesn't have atomic_inc and atomic_dec builtins, // we translate these instructions to atomic_fetch_add_explicit and // atomic_fetch_sub_explicit OpenCL 2.0 builtins with "operand" argument // = 1. auto Name = OCLSPIRVBuiltinMap::rmap( OC == OpAtomicIIncrement ? OpAtomicIAdd : OpAtomicISub); auto Ptr = findFirstPtr(Args); Type *ValueTy = cast(Args[Ptr]->getType())->getElementType(); assert(ValueTy->isIntegerTy()); Args.insert(Args.begin() + 1, llvm::ConstantInt::get(ValueTy, 1)); return Name; }, &Attrs); } CallInst *SPIRVToOCL20::mutateCommonAtomicArguments(CallInst *CI, Op OC) { assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); return mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args) { for (size_t I = 0; I < Args.size(); ++I) { Value *PtrArg = Args[I]; Type *PtrArgTy = PtrArg->getType(); if (PtrArgTy->isPointerTy()) { if (PtrArgTy->getPointerAddressSpace() != SPIRAS_Generic) { Type *FixedPtr = PtrArgTy->getPointerElementType()->getPointerTo( SPIRAS_Generic); Args[I] = CastInst::CreatePointerBitCastOrAddrSpaceCast( PtrArg, FixedPtr, PtrArg->getName() + ".as", CI); } } } auto Ptr = findFirstPtr(Args); auto Name = OCLSPIRVBuiltinMap::rmap(OC); auto NumOrder = getSPIRVAtomicBuiltinNumMemoryOrderArgs(OC); auto ScopeIdx = Ptr + 1; auto OrderIdx = Ptr + 2; if (auto *ScopeInt = dyn_cast_or_null(Args[ScopeIdx])) { Args[ScopeIdx] = mapUInt(M, ScopeInt, [](unsigned I) { return rmap(static_cast(I)); }); } else { CallInst *TransCall = dyn_cast(Args[ScopeIdx]); Function *F = TransCall ? TransCall->getCalledFunction() : nullptr; if (F && F->getName().equals(kSPIRVName::TranslateOCLMemScope)) { // In case the SPIR-V module was created from an OpenCL program by // *this* SPIR-V generator, we know that the value passed to // __translate_ocl_memory_scope is what we should pass to the OpenCL // builtin now. Args[ScopeIdx] = TransCall->getArgOperand(0); } else { Args[ScopeIdx] = getOrCreateSwitchFunc( kSPIRVName::TranslateSPIRVMemScope, Args[ScopeIdx], OCLMemScopeMap::getRMap(), true /*IsReverse*/, None, CI, M); } } for (size_t I = 0; I < NumOrder; ++I) { if (auto OrderInt = dyn_cast_or_null(Args[OrderIdx + I])) { Args[OrderIdx + I] = mapUInt(M, OrderInt, [](unsigned Ord) { return mapSPIRVMemOrderToOCL(Ord); }); } else { CallInst *TransCall = dyn_cast(Args[OrderIdx + I]); Function *F = TransCall ? TransCall->getCalledFunction() : nullptr; if (F && F->getName().equals(kSPIRVName::TranslateOCLMemOrder)) { // In case the SPIR-V module was created from an OpenCL program by // *this* SPIR-V generator, we know that the value passed to // __translate_ocl_memory_order is what we should pass to the // OpenCL builtin now. Args[OrderIdx + I] = TransCall->getArgOperand(0); } else { Args[OrderIdx + I] = getOrCreateSwitchFunc( kSPIRVName::TranslateSPIRVMemOrder, Args[OrderIdx + I], OCLMemOrderMap::getRMap(), true /*IsReverse*/, None, CI, M); } } } std::swap(Args[ScopeIdx], Args.back()); return Name; }, &Attrs); } Instruction *SPIRVToOCL20::visitCallSPIRVAtomicCmpExchg(CallInst *CI, Op OC) { assert(CI->getCalledFunction() && "Unexpected indirect call"); AttributeList Attrs = CI->getCalledFunction()->getAttributes(); Instruction *PInsertBefore = CI; return mutateCallInstOCL( M, CI, [=](CallInst *, std::vector &Args, Type *&RetTy) { // OpAtomicCompareExchange[Weak] semantics is different from // atomic_compare_exchange_[strong|weak] semantics as well as // arguments order. // OCL built-ins returns boolean value and stores a new/original // value by pointer passed as 2nd argument (aka expected) while SPIR-V // instructions returns this new/original value as a resulting value. AllocaInst *PExpected = new AllocaInst(CI->getType(), 0, "expected", &(*PInsertBefore->getParent() ->getParent() ->getEntryBlock() .getFirstInsertionPt())); PExpected->setAlignment( MaybeAlign(CI->getType()->getScalarSizeInBits() / 8)); new StoreInst(Args[1], PExpected, PInsertBefore); unsigned AddrSpc = SPIRAS_Generic; Type *PtrTyAS = PExpected->getType()->getElementType()->getPointerTo(AddrSpc); Args[1] = CastInst::CreatePointerBitCastOrAddrSpaceCast( PExpected, PtrTyAS, PExpected->getName() + ".as", PInsertBefore); std::swap(Args[3], Args[4]); std::swap(Args[2], Args[3]); RetTy = Type::getInt1Ty(*Ctx); return OCLSPIRVBuiltinMap::rmap(OC); }, [=](CallInst *CI) -> Instruction * { // OCL built-ins atomic_compare_exchange_[strong|weak] return boolean // value. So, to obtain the same value as SPIR-V instruction is // returning it has to be loaded from the memory where 'expected' // value is stored. This memory must contain the needed value after a // call to OCL built-in is completed. return new LoadInst(CI->getArgOperand(1), "original", PInsertBefore); }, &Attrs); } } // namespace SPIRV INITIALIZE_PASS(SPIRVToOCL20, "spvtoocl20", "Translate SPIR-V builtins to OCL 2.0 builtins", false, false) ModulePass *llvm::createSPIRVToOCL20() { return new SPIRVToOCL20(); } SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVUtil.cpp000066400000000000000000001503371363521741200213250ustar00rootroot00000000000000//===- SPIRVUtil.cpp - SPIR-V Utilities -------------------------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines utility classes and functions shared by SPIR-V /// reader/writer. /// //===----------------------------------------------------------------------===// #include "FunctionDescriptor.h" #include "ManglingUtils.h" #include "NameMangleAPI.h" #include "OCLUtil.h" #include "ParameterType.h" #include "SPIRVInternal.h" #include "SPIRVMDWalker.h" #include "libSPIRV/SPIRVDecorate.h" #include "libSPIRV/SPIRVValue.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/IR/IRBuilder.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/ToolOutputFile.h" #include #include #define DEBUG_TYPE "spirv" namespace SPIRV { #ifdef _SPIRV_SUPPORT_TEXT_FMT cl::opt UseTextFormat("spirv-text", cl::desc("Use text format for SPIR-V for debugging purpose"), cl::location(SPIRVUseTextFormat)); #endif #ifdef _SPIRVDBG cl::opt EnableDbgOutput("spirv-debug", cl::desc("Enable SPIR-V debug output"), cl::location(SPIRVDbgEnable)); #endif bool isSupportedTriple(Triple T) { return T.isSPIR(); } void addFnAttr(CallInst *Call, Attribute::AttrKind Attr) { Call->addAttribute(AttributeList::FunctionIndex, Attr); } void removeFnAttr(CallInst *Call, Attribute::AttrKind Attr) { Call->removeAttribute(AttributeList::FunctionIndex, Attr); } Value *removeCast(Value *V) { auto Cast = dyn_cast(V); if (Cast && Cast->isCast()) { return removeCast(Cast->getOperand(0)); } if (auto Cast = dyn_cast(V)) return removeCast(Cast->getOperand(0)); return V; } void saveLLVMModule(Module *M, const std::string &OutputFile) { std::error_code EC; ToolOutputFile Out(OutputFile.c_str(), EC, sys::fs::F_None); if (EC) { SPIRVDBG(errs() << "Fails to open output file: " << EC.message();) return; } WriteBitcodeToFile(*M, Out.os()); Out.keep(); } std::string mapLLVMTypeToOCLType(const Type *Ty, bool Signed) { if (Ty->isHalfTy()) return "half"; if (Ty->isFloatTy()) return "float"; if (Ty->isDoubleTy()) return "double"; if (auto IntTy = dyn_cast(Ty)) { std::string SignPrefix; std::string Stem; if (!Signed) SignPrefix = "u"; switch (IntTy->getIntegerBitWidth()) { case 8: Stem = "char"; break; case 16: Stem = "short"; break; case 32: Stem = "int"; break; case 64: Stem = "long"; break; default: Stem = "invalid_type"; break; } return SignPrefix + Stem; } if (auto VecTy = dyn_cast(Ty)) { Type *EleTy = VecTy->getElementType(); unsigned Size = VecTy->getVectorNumElements(); std::stringstream Ss; Ss << mapLLVMTypeToOCLType(EleTy, Signed) << Size; return Ss.str(); } return "invalid_type"; } std::string mapSPIRVTypeToOCLType(SPIRVType *Ty, bool Signed) { if (Ty->isTypeFloat()) { auto W = Ty->getBitWidth(); switch (W) { case 16: return "half"; case 32: return "float"; case 64: return "double"; default: assert(0 && "Invalid floating pointer type"); return std::string("float") + W + "_t"; } } if (Ty->isTypeInt()) { std::string SignPrefix; std::string Stem; if (!Signed) SignPrefix = "u"; auto W = Ty->getBitWidth(); switch (W) { case 8: Stem = "char"; break; case 16: Stem = "short"; break; case 32: Stem = "int"; break; case 64: Stem = "long"; break; default: llvm_unreachable("Invalid integer type"); Stem = std::string("int") + W + "_t"; break; } return SignPrefix + Stem; } if (Ty->isTypeVector()) { auto EleTy = Ty->getVectorComponentType(); auto Size = Ty->getVectorComponentCount(); std::stringstream Ss; Ss << mapSPIRVTypeToOCLType(EleTy, Signed) << Size; return Ss.str(); } llvm_unreachable("Invalid type"); return "unknown_type"; } PointerType *getOrCreateOpaquePtrType(Module *M, const std::string &Name, unsigned AddrSpace) { auto OpaqueType = M->getTypeByName(Name); if (!OpaqueType) OpaqueType = StructType::create(M->getContext(), Name); return PointerType::get(OpaqueType, AddrSpace); } PointerType *getSamplerType(Module *M) { return getOrCreateOpaquePtrType(M, getSPIRVTypeName(kSPIRVTypeName::Sampler), SPIRAS_Constant); } PointerType *getPipeStorageType(Module *M) { return getOrCreateOpaquePtrType( M, getSPIRVTypeName(kSPIRVTypeName::PipeStorage), SPIRAS_Constant); } void getFunctionTypeParameterTypes(llvm::FunctionType *FT, std::vector &ArgTys) { for (auto I = FT->param_begin(), E = FT->param_end(); I != E; ++I) { ArgTys.push_back(*I); } } bool isVoidFuncTy(FunctionType *FT) { return FT->getReturnType()->isVoidTy() && FT->getNumParams() == 0; } bool isPointerToOpaqueStructType(llvm::Type *Ty) { if (auto PT = dyn_cast(Ty)) if (auto ST = dyn_cast(PT->getElementType())) if (ST->isOpaque()) return true; return false; } bool isPointerToOpaqueStructType(llvm::Type *Ty, const std::string &Name) { if (auto PT = dyn_cast(Ty)) if (auto ST = dyn_cast(PT->getElementType())) if (ST->isOpaque() && ST->getName() == Name) return true; return false; } bool isOCLImageType(llvm::Type *Ty, StringRef *Name) { if (auto PT = dyn_cast(Ty)) if (auto ST = dyn_cast(PT->getElementType())) if (ST->isOpaque()) { auto FullName = ST->getName(); if (FullName.find(kSPR2TypeName::ImagePrefix) == 0) { if (Name) *Name = FullName.drop_front(strlen(kSPR2TypeName::OCLPrefix)); return true; } } return false; } /// \param BaseTyName is the type Name as in spirv.BaseTyName.Postfixes /// \param Postfix contains postfixes extracted from the SPIR-V image /// type Name as spirv.BaseTyName.Postfixes. bool isSPIRVType(llvm::Type *Ty, StringRef BaseTyName, StringRef *Postfix) { if (auto PT = dyn_cast(Ty)) if (auto ST = dyn_cast(PT->getElementType())) if (ST->isOpaque()) { auto FullName = ST->getName(); std::string N = std::string(kSPIRVTypeName::PrefixAndDelim) + BaseTyName.str(); if (FullName != N) N = N + kSPIRVTypeName::Delimiter; if (FullName.startswith(N)) { if (Postfix) *Postfix = FullName.drop_front(N.size()); return true; } } return false; } Function *getOrCreateFunction(Module *M, Type *RetTy, ArrayRef ArgTypes, StringRef Name, BuiltinFuncMangleInfo *Mangle, AttributeList *Attrs, bool TakeName) { std::string MangledName = Name; bool IsVarArg = false; if (Mangle) { MangledName = mangleBuiltin(Name, ArgTypes, Mangle); IsVarArg = 0 <= Mangle->getVarArg(); if (IsVarArg) ArgTypes = ArgTypes.slice(0, Mangle->getVarArg()); } FunctionType *FT = FunctionType::get(RetTy, ArgTypes, IsVarArg); Function *F = M->getFunction(MangledName); if (!TakeName && F && F->getFunctionType() != FT && Mangle != nullptr) { std::string S; raw_string_ostream SS(S); SS << "Error: Attempt to redefine function: " << *F << " => " << *FT << '\n'; report_fatal_error(SS.str(), false); } if (!F || F->getFunctionType() != FT) { auto NewF = Function::Create(FT, GlobalValue::ExternalLinkage, MangledName, M); if (F && TakeName) { NewF->takeName(F); LLVM_DEBUG( dbgs() << "[getOrCreateFunction] Warning: taking function Name\n"); } if (NewF->getName() != MangledName) { LLVM_DEBUG( dbgs() << "[getOrCreateFunction] Warning: function Name changed\n"); } LLVM_DEBUG(dbgs() << "[getOrCreateFunction] "; if (F) dbgs() << *F << " => "; dbgs() << *NewF << '\n';); F = NewF; F->setCallingConv(CallingConv::SPIR_FUNC); if (Attrs) F->setAttributes(*Attrs); } return F; } std::vector getArguments(CallInst *CI, unsigned Start, unsigned End) { std::vector Args; if (End == 0) End = CI->getNumArgOperands(); for (; Start != End; ++Start) { Args.push_back(CI->getArgOperand(Start)); } return Args; } uint64_t getArgAsInt(CallInst *CI, unsigned I) { return cast(CI->getArgOperand(I))->getZExtValue(); } Scope getArgAsScope(CallInst *CI, unsigned I) { return static_cast(getArgAsInt(CI, I)); } Decoration getArgAsDecoration(CallInst *CI, unsigned I) { return static_cast(getArgAsInt(CI, I)); } std::string decorateSPIRVFunction(const std::string &S) { return std::string(kSPIRVName::Prefix) + S + kSPIRVName::Postfix; } std::string undecorateSPIRVFunction(const std::string &S) { assert(S.find(kSPIRVName::Prefix) == 0); const size_t Start = strlen(kSPIRVName::Prefix); auto End = S.rfind(kSPIRVName::Postfix); return S.substr(Start, End - Start); } std::string prefixSPIRVName(const std::string &S) { return std::string(kSPIRVName::Prefix) + S; } StringRef dePrefixSPIRVName(StringRef R, SmallVectorImpl &Postfix) { const size_t Start = strlen(kSPIRVName::Prefix); if (!R.startswith(kSPIRVName::Prefix)) return R; R = R.drop_front(Start); R.split(Postfix, "_", -1, false); auto Name = Postfix.front(); Postfix.erase(Postfix.begin()); return Name; } std::string getSPIRVFuncName(Op OC, StringRef PostFix) { return prefixSPIRVName(getName(OC) + PostFix.str()); } std::string getSPIRVFuncName(Op OC, const Type *PRetTy, bool IsSigned) { return prefixSPIRVName(getName(OC) + kSPIRVPostfix::Divider + getPostfixForReturnType(PRetTy, false)); } std::string getSPIRVExtFuncName(SPIRVExtInstSetKind Set, unsigned ExtOp, StringRef PostFix) { std::string ExtOpName; switch (Set) { default: llvm_unreachable("invalid extended instruction set"); ExtOpName = "unknown"; break; case SPIRVEIS_OpenCL: ExtOpName = getName(static_cast(ExtOp)); break; } return prefixSPIRVName(SPIRVExtSetShortNameMap::map(Set) + '_' + ExtOpName + PostFix.str()); } SPIRVDecorate *mapPostfixToDecorate(StringRef Postfix, SPIRVEntry *Target) { if (Postfix == kSPIRVPostfix::Sat) return new SPIRVDecorate(spv::DecorationSaturatedConversion, Target); if (Postfix.startswith(kSPIRVPostfix::Rt)) return new SPIRVDecorate(spv::DecorationFPRoundingMode, Target, map(Postfix.str())); return nullptr; } SPIRVValue *addDecorations(SPIRVValue *Target, const SmallVectorImpl &Decs) { for (auto &I : Decs) if (auto Dec = mapPostfixToDecorate(I, Target)) Target->addDecorate(Dec); return Target; } std::string getPostfix(Decoration Dec, unsigned Value) { switch (Dec) { default: llvm_unreachable("not implemented"); return "unknown"; case spv::DecorationSaturatedConversion: return kSPIRVPostfix::Sat; case spv::DecorationFPRoundingMode: return rmap(static_cast(Value)); } } std::string getPostfixForReturnType(CallInst *CI, bool IsSigned) { return getPostfixForReturnType(CI->getType(), IsSigned); } std::string getPostfixForReturnType(const Type *PRetTy, bool IsSigned) { return std::string(kSPIRVPostfix::Return) + mapLLVMTypeToOCLType(PRetTy, IsSigned); } Op getSPIRVFuncOC(const std::string &S, SmallVectorImpl *Dec) { Op OC; SmallVector Postfix; std::string Name; if (!oclIsBuiltin(S, &Name)) Name = S; StringRef R(Name); R = dePrefixSPIRVName(R, Postfix); if (!getByName(R.str(), OC)) return OpNop; if (Dec) for (auto &I : Postfix) Dec->push_back(I.str()); return OC; } bool getSPIRVBuiltin(const std::string &OrigName, spv::BuiltIn &B) { SmallVector Postfix; StringRef R(OrigName); R = dePrefixSPIRVName(R, Postfix); assert(Postfix.empty() && "Invalid SPIR-V builtin Name"); return getByName(R.str(), B); } // Enqueue kernel, kernel query, pipe and address space cast built-ins // are not mangled. bool isNonMangledOCLBuiltin(const StringRef &Name) { if (!Name.startswith("__")) return false; return isEnqueueKernelBI(Name) || isKernelQueryBI(Name) || isPipeOrAddressSpaceCastBI(Name.drop_front(2)); } bool oclIsBuiltin(const StringRef &Name, std::string *DemangledName, bool IsCpp) { if (Name == "printf") { if (DemangledName) *DemangledName = Name; return true; } if (isNonMangledOCLBuiltin(Name)) { if (DemangledName) *DemangledName = Name.drop_front(2); return true; } if (!Name.startswith("_Z")) return false; if (!DemangledName) return true; // OpenCL C++ built-ins are declared in cl namespace. // TODO: consider using 'St' abbriviation for cl namespace mangling. // Similar to ::std:: in C++. if (IsCpp) { if (!Name.startswith("_ZN")) return false; // Skip CV and ref qualifiers. size_t NameSpaceStart = Name.find_first_not_of("rVKRO", 3); // All built-ins are in the ::cl:: namespace. if (Name.substr(NameSpaceStart, 11) != "2cl7__spirv") return false; size_t DemangledNameLenStart = NameSpaceStart + 11; size_t Start = Name.find_first_not_of("0123456789", DemangledNameLenStart); size_t Len = 0; Name.substr(DemangledNameLenStart, Start - DemangledNameLenStart) .getAsInteger(10, Len); *DemangledName = Name.substr(Start, Len); } else { size_t Start = Name.find_first_not_of("0123456789", 2); size_t Len = 0; Name.substr(2, Start - 2).getAsInteger(10, Len); *DemangledName = Name.substr(Start, Len); } return true; } // Check if a mangled type Name is unsigned bool isMangledTypeUnsigned(char Mangled) { return Mangled == 'h' /* uchar */ || Mangled == 't' /* ushort */ || Mangled == 'j' /* uint */ || Mangled == 'm' /* ulong */; } // Check if a mangled type Name is signed bool isMangledTypeSigned(char Mangled) { return Mangled == 'c' /* char */ || Mangled == 'a' /* signed char */ || Mangled == 's' /* short */ || Mangled == 'i' /* int */ || Mangled == 'l' /* long */; } // Check if a mangled type Name is floating point (excludes half) bool isMangledTypeFP(char Mangled) { return Mangled == 'f' /* float */ || Mangled == 'd'; /* double */ } // Check if a mangled type Name is half bool isMangledTypeHalf(std::string Mangled) { return Mangled == "Dh"; /* half */ } void eraseSubstitutionFromMangledName(std::string &MangledName) { auto Len = MangledName.length(); while (Len >= 2 && MangledName.substr(Len - 2, 2) == "S_") { Len -= 2; MangledName.erase(Len, 2); } } ParamType lastFuncParamType(const std::string &MangledName) { auto Copy = MangledName; eraseSubstitutionFromMangledName(Copy); char Mangled = Copy.back(); std::string Mangled2 = Copy.substr(Copy.size() - 2); if (isMangledTypeFP(Mangled) || isMangledTypeHalf(Mangled2)) { return ParamType::FLOAT; } else if (isMangledTypeUnsigned(Mangled)) { return ParamType::UNSIGNED; } else if (isMangledTypeSigned(Mangled)) { return ParamType::SIGNED; } return ParamType::UNKNOWN; } // Check if the last argument is signed bool isLastFuncParamSigned(const std::string &MangledName) { return lastFuncParamType(MangledName) == ParamType::SIGNED; } // Check if a mangled function Name contains unsigned atomic type bool containsUnsignedAtomicType(StringRef Name) { auto Loc = Name.find(kMangledName::AtomicPrefixIncoming); if (Loc == StringRef::npos) return false; return isMangledTypeUnsigned( Name[Loc + strlen(kMangledName::AtomicPrefixIncoming)]); } bool isFunctionPointerType(Type *T) { if (isa(T) && isa(T->getPointerElementType())) { return true; } return false; } bool hasFunctionPointerArg(Function *F, Function::arg_iterator &AI) { AI = F->arg_begin(); for (auto AE = F->arg_end(); AI != AE; ++AI) { LLVM_DEBUG(dbgs() << "[hasFuncPointerArg] " << *AI << '\n'); if (isFunctionPointerType(AI->getType())) { return true; } } return false; } Constant *castToVoidFuncPtr(Function *F) { auto T = getVoidFuncPtrType(F->getParent()); return ConstantExpr::getBitCast(F, T); } bool hasArrayArg(Function *F) { for (auto I = F->arg_begin(), E = F->arg_end(); I != E; ++I) { LLVM_DEBUG(dbgs() << "[hasArrayArg] " << *I << '\n'); if (I->getType()->isArrayTy()) { return true; } } return false; } CallInst *mutateCallInst( Module *M, CallInst *CI, std::function &)> ArgMutate, BuiltinFuncMangleInfo *Mangle, AttributeList *Attrs, bool TakeFuncName) { LLVM_DEBUG(dbgs() << "[mutateCallInst] " << *CI); auto Args = getArguments(CI); auto NewName = ArgMutate(CI, Args); std::string InstName; if (!CI->getType()->isVoidTy() && CI->hasName()) { InstName = CI->getName(); CI->setName(InstName + ".old"); } auto NewCI = addCallInst(M, NewName, CI->getType(), Args, Attrs, CI, Mangle, InstName, TakeFuncName); NewCI->setDebugLoc(CI->getDebugLoc()); LLVM_DEBUG(dbgs() << " => " << *NewCI << '\n'); CI->replaceAllUsesWith(NewCI); CI->eraseFromParent(); return NewCI; } Instruction *mutateCallInst( Module *M, CallInst *CI, std::function &, Type *&RetTy)> ArgMutate, std::function RetMutate, BuiltinFuncMangleInfo *Mangle, AttributeList *Attrs, bool TakeFuncName) { LLVM_DEBUG(dbgs() << "[mutateCallInst] " << *CI); auto Args = getArguments(CI); Type *RetTy = CI->getType(); auto NewName = ArgMutate(CI, Args, RetTy); std::string InstName; if (CI->hasName()) { InstName = CI->getName(); CI->setName(InstName + ".old"); } auto NewCI = addCallInst(M, NewName, RetTy, Args, Attrs, CI, Mangle, InstName + ".tmp", TakeFuncName); auto NewI = RetMutate(NewCI); NewI->takeName(CI); NewI->setDebugLoc(CI->getDebugLoc()); LLVM_DEBUG(dbgs() << " => " << *NewI << '\n'); if (!CI->getType()->isVoidTy()) CI->replaceAllUsesWith(NewI); CI->eraseFromParent(); return NewI; } void mutateFunction( Function *F, std::function &)> ArgMutate, BuiltinFuncMangleInfo *Mangle, AttributeList *Attrs, bool TakeFuncName) { auto M = F->getParent(); for (auto I = F->user_begin(), E = F->user_end(); I != E;) { if (auto CI = dyn_cast(*I++)) mutateCallInst(M, CI, ArgMutate, Mangle, Attrs, TakeFuncName); } if (F->use_empty()) F->eraseFromParent(); } CallInst *mutateCallInstSPIRV( Module *M, CallInst *CI, std::function &)> ArgMutate, AttributeList *Attrs) { BuiltinFuncMangleInfo BtnInfo; return mutateCallInst(M, CI, ArgMutate, &BtnInfo, Attrs); } Instruction *mutateCallInstSPIRV( Module *M, CallInst *CI, std::function &, Type *&RetTy)> ArgMutate, std::function RetMutate, AttributeList *Attrs) { BuiltinFuncMangleInfo BtnInfo; return mutateCallInst(M, CI, ArgMutate, RetMutate, &BtnInfo, Attrs); } CallInst *addCallInst(Module *M, StringRef FuncName, Type *RetTy, ArrayRef Args, AttributeList *Attrs, Instruction *Pos, BuiltinFuncMangleInfo *Mangle, StringRef InstName, bool TakeFuncName) { auto F = getOrCreateFunction(M, RetTy, getTypes(Args), FuncName, Mangle, Attrs, TakeFuncName); // Cannot assign a Name to void typed values auto CI = CallInst::Create(F, Args, RetTy->isVoidTy() ? "" : InstName, Pos); CI->setCallingConv(F->getCallingConv()); CI->setAttributes(F->getAttributes()); return CI; } CallInst *addCallInstSPIRV(Module *M, StringRef FuncName, Type *RetTy, ArrayRef Args, AttributeList *Attrs, Instruction *Pos, StringRef InstName) { BuiltinFuncMangleInfo BtnInfo; return addCallInst(M, FuncName, RetTy, Args, Attrs, Pos, &BtnInfo, InstName); } bool isValidVectorSize(unsigned I) { return I == 2 || I == 3 || I == 4 || I == 8 || I == 16; } Value *addVector(Instruction *InsPos, ValueVecRange Range) { size_t VecSize = Range.second - Range.first; if (VecSize == 1) return *Range.first; assert(isValidVectorSize(VecSize) && "Invalid vector size"); IRBuilder<> Builder(InsPos); auto Vec = Builder.CreateVectorSplat(VecSize, *Range.first); unsigned Index = 1; for (++Range.first; Range.first != Range.second; ++Range.first, ++Index) Vec = Builder.CreateInsertElement( Vec, *Range.first, ConstantInt::get(Type::getInt32Ty(InsPos->getContext()), Index, false)); return Vec; } void makeVector(Instruction *InsPos, std::vector &Ops, ValueVecRange Range) { auto Vec = addVector(InsPos, Range); Ops.erase(Range.first, Range.second); Ops.push_back(Vec); } void expandVector(Instruction *InsPos, std::vector &Ops, size_t VecPos) { auto Vec = Ops[VecPos]; auto VT = Vec->getType(); if (!VT->isVectorTy()) return; size_t N = VT->getVectorNumElements(); IRBuilder<> Builder(InsPos); for (size_t I = 0; I != N; ++I) Ops.insert(Ops.begin() + VecPos + I, Builder.CreateExtractElement( Vec, ConstantInt::get(Type::getInt32Ty(InsPos->getContext()), I, false))); Ops.erase(Ops.begin() + VecPos + N); } Constant *castToInt8Ptr(Constant *V, unsigned Addr = 0) { return ConstantExpr::getBitCast(V, Type::getInt8PtrTy(V->getContext(), Addr)); } PointerType *getInt8PtrTy(PointerType *T) { return Type::getInt8PtrTy(T->getContext(), T->getAddressSpace()); } Value *castToInt8Ptr(Value *V, Instruction *Pos) { return CastInst::CreatePointerCast( V, getInt8PtrTy(cast(V->getType())), "", Pos); } CallInst *addBlockBind(Module *M, Function *InvokeFunc, Value *BlkCtx, Value *CtxLen, Value *CtxAlign, Instruction *InsPos, StringRef InstName) { auto BlkTy = getOrCreateOpaquePtrType(M, SPIR_TYPE_NAME_BLOCK_T, SPIRAS_Private); auto &Ctx = M->getContext(); Value *BlkArgs[] = { castToInt8Ptr(InvokeFunc), CtxLen ? CtxLen : UndefValue::get(Type::getInt32Ty(Ctx)), CtxAlign ? CtxAlign : UndefValue::get(Type::getInt32Ty(Ctx)), BlkCtx ? BlkCtx : UndefValue::get(Type::getInt8PtrTy(Ctx))}; return addCallInst(M, SPIR_INTRINSIC_BLOCK_BIND, BlkTy, BlkArgs, nullptr, InsPos, nullptr, InstName); } IntegerType *getSizetType(Module *M) { return IntegerType::getIntNTy(M->getContext(), M->getDataLayout().getPointerSizeInBits(0)); } Type *getVoidFuncType(Module *M) { return FunctionType::get(Type::getVoidTy(M->getContext()), false); } Type *getVoidFuncPtrType(Module *M, unsigned AddrSpace) { return PointerType::get(getVoidFuncType(M), AddrSpace); } ConstantInt *getInt64(Module *M, int64_t Value) { return ConstantInt::getSigned(Type::getInt64Ty(M->getContext()), Value); } ConstantInt *getUInt64(Module *M, uint64_t Value) { return ConstantInt::get(Type::getInt64Ty(M->getContext()), Value, false); } Constant *getFloat32(Module *M, float Value) { return ConstantFP::get(Type::getFloatTy(M->getContext()), Value); } ConstantInt *getInt32(Module *M, int Value) { return ConstantInt::get(Type::getInt32Ty(M->getContext()), Value, true); } ConstantInt *getUInt32(Module *M, unsigned Value) { return ConstantInt::get(Type::getInt32Ty(M->getContext()), Value, false); } ConstantInt *getInt(Module *M, int64_t Value) { return Value >> 32 ? getInt64(M, Value) : getInt32(M, static_cast(Value)); } ConstantInt *getUInt(Module *M, uint64_t Value) { return Value >> 32 ? getUInt64(M, Value) : getUInt32(M, static_cast(Value)); } ConstantInt *getUInt16(Module *M, unsigned short Value) { return ConstantInt::get(Type::getInt16Ty(M->getContext()), Value, false); } std::vector getInt32(Module *M, const std::vector &Values) { std::vector V; for (auto &I : Values) V.push_back(getInt32(M, I)); return V; } ConstantInt *getSizet(Module *M, uint64_t Value) { return ConstantInt::get(getSizetType(M), Value, false); } /////////////////////////////////////////////////////////////////////////////// // // Functions for getting metadata // /////////////////////////////////////////////////////////////////////////////// int getMDOperandAsInt(MDNode *N, unsigned I) { return mdconst::dyn_extract(N->getOperand(I))->getZExtValue(); } // Additional helper function to be reused by getMDOperandAs* helpers Metadata *getMDOperandOrNull(MDNode *N, unsigned I) { if (!N) return nullptr; return N->getOperand(I); } std::string getMDOperandAsString(MDNode *N, unsigned I) { if (auto *Str = dyn_cast_or_null(getMDOperandOrNull(N, I))) return Str->getString().str(); return ""; } MDNode *getMDOperandAsMDNode(MDNode *N, unsigned I) { return dyn_cast_or_null(getMDOperandOrNull(N, I)); } Type *getMDOperandAsType(MDNode *N, unsigned I) { return cast(N->getOperand(I))->getType(); } std::set getNamedMDAsStringSet(Module *M, const std::string &MDName) { NamedMDNode *NamedMD = M->getNamedMetadata(MDName); std::set StrSet; if (!NamedMD) return StrSet; assert(NamedMD->getNumOperands() > 0 && "Invalid SPIR"); for (unsigned I = 0, E = NamedMD->getNumOperands(); I != E; ++I) { MDNode *MD = NamedMD->getOperand(I); if (!MD || MD->getNumOperands() == 0) continue; for (unsigned J = 0, N = MD->getNumOperands(); J != N; ++J) StrSet.insert(getMDOperandAsString(MD, J)); } return StrSet; } std::tuple getSPIRVSource(Module *M) { std::tuple Tup; if (auto N = SPIRVMDWalker(*M).getNamedMD(kSPIRVMD::Source).nextOp()) N.get(std::get<0>(Tup)) .get(std::get<1>(Tup)) .setQuiet(true) .get(std::get<2>(Tup)); return Tup; } ConstantInt *mapUInt(Module *M, ConstantInt *I, std::function F) { return ConstantInt::get(I->getType(), F(I->getZExtValue()), false); } ConstantInt *mapSInt(Module *M, ConstantInt *I, std::function F) { return ConstantInt::get(I->getType(), F(I->getSExtValue()), true); } bool isDecoratedSPIRVFunc(const Function *F, std::string *UndecoratedName) { if (!F->hasName() || !F->getName().startswith(kSPIRVName::Prefix)) return false; if (UndecoratedName) *UndecoratedName = undecorateSPIRVFunction(F->getName()); return true; } /// Get TypePrimitiveEnum for special OpenCL type except opencl.block. SPIR::TypePrimitiveEnum getOCLTypePrimitiveEnum(StringRef TyName) { return StringSwitch(TyName) .Case("opencl.image1d_ro_t", SPIR::PRIMITIVE_IMAGE1D_RO_T) .Case("opencl.image1d_array_ro_t", SPIR::PRIMITIVE_IMAGE1D_ARRAY_RO_T) .Case("opencl.image1d_buffer_ro_t", SPIR::PRIMITIVE_IMAGE1D_BUFFER_RO_T) .Case("opencl.image2d_ro_t", SPIR::PRIMITIVE_IMAGE2D_RO_T) .Case("opencl.image2d_array_ro_t", SPIR::PRIMITIVE_IMAGE2D_ARRAY_RO_T) .Case("opencl.image2d_depth_ro_t", SPIR::PRIMITIVE_IMAGE2D_DEPTH_RO_T) .Case("opencl.image2d_array_depth_ro_t", SPIR::PRIMITIVE_IMAGE2D_ARRAY_DEPTH_RO_T) .Case("opencl.image2d_msaa_ro_t", SPIR::PRIMITIVE_IMAGE2D_MSAA_RO_T) .Case("opencl.image2d_array_msaa_ro_t", SPIR::PRIMITIVE_IMAGE2D_ARRAY_MSAA_RO_T) .Case("opencl.image2d_msaa_depth_ro_t", SPIR::PRIMITIVE_IMAGE2D_MSAA_DEPTH_RO_T) .Case("opencl.image2d_array_msaa_depth_ro_t", SPIR::PRIMITIVE_IMAGE2D_ARRAY_MSAA_DEPTH_RO_T) .Case("opencl.image3d_ro_t", SPIR::PRIMITIVE_IMAGE3D_RO_T) .Case("opencl.image1d_wo_t", SPIR::PRIMITIVE_IMAGE1D_WO_T) .Case("opencl.image1d_array_wo_t", SPIR::PRIMITIVE_IMAGE1D_ARRAY_WO_T) .Case("opencl.image1d_buffer_wo_t", SPIR::PRIMITIVE_IMAGE1D_BUFFER_WO_T) .Case("opencl.image2d_wo_t", SPIR::PRIMITIVE_IMAGE2D_WO_T) .Case("opencl.image2d_array_wo_t", SPIR::PRIMITIVE_IMAGE2D_ARRAY_WO_T) .Case("opencl.image2d_depth_wo_t", SPIR::PRIMITIVE_IMAGE2D_DEPTH_WO_T) .Case("opencl.image2d_array_depth_wo_t", SPIR::PRIMITIVE_IMAGE2D_ARRAY_DEPTH_WO_T) .Case("opencl.image2d_msaa_wo_t", SPIR::PRIMITIVE_IMAGE2D_MSAA_WO_T) .Case("opencl.image2d_array_msaa_wo_t", SPIR::PRIMITIVE_IMAGE2D_ARRAY_MSAA_WO_T) .Case("opencl.image2d_msaa_depth_wo_t", SPIR::PRIMITIVE_IMAGE2D_MSAA_DEPTH_WO_T) .Case("opencl.image2d_array_msaa_depth_wo_t", SPIR::PRIMITIVE_IMAGE2D_ARRAY_MSAA_DEPTH_WO_T) .Case("opencl.image3d_wo_t", SPIR::PRIMITIVE_IMAGE3D_WO_T) .Case("opencl.image1d_rw_t", SPIR::PRIMITIVE_IMAGE1D_RW_T) .Case("opencl.image1d_array_rw_t", SPIR::PRIMITIVE_IMAGE1D_ARRAY_RW_T) .Case("opencl.image1d_buffer_rw_t", SPIR::PRIMITIVE_IMAGE1D_BUFFER_RW_T) .Case("opencl.image2d_rw_t", SPIR::PRIMITIVE_IMAGE2D_RW_T) .Case("opencl.image2d_array_rw_t", SPIR::PRIMITIVE_IMAGE2D_ARRAY_RW_T) .Case("opencl.image2d_depth_rw_t", SPIR::PRIMITIVE_IMAGE2D_DEPTH_RW_T) .Case("opencl.image2d_array_depth_rw_t", SPIR::PRIMITIVE_IMAGE2D_ARRAY_DEPTH_RW_T) .Case("opencl.image2d_msaa_rw_t", SPIR::PRIMITIVE_IMAGE2D_MSAA_RW_T) .Case("opencl.image2d_array_msaa_rw_t", SPIR::PRIMITIVE_IMAGE2D_ARRAY_MSAA_RW_T) .Case("opencl.image2d_msaa_depth_rw_t", SPIR::PRIMITIVE_IMAGE2D_MSAA_DEPTH_RW_T) .Case("opencl.image2d_array_msaa_depth_rw_t", SPIR::PRIMITIVE_IMAGE2D_ARRAY_MSAA_DEPTH_RW_T) .Case("opencl.image3d_rw_t", SPIR::PRIMITIVE_IMAGE3D_RW_T) .Case("opencl.event_t", SPIR::PRIMITIVE_EVENT_T) .Case("opencl.pipe_ro_t", SPIR::PRIMITIVE_PIPE_RO_T) .Case("opencl.pipe_wo_t", SPIR::PRIMITIVE_PIPE_WO_T) .Case("opencl.reserve_id_t", SPIR::PRIMITIVE_RESERVE_ID_T) .Case("opencl.queue_t", SPIR::PRIMITIVE_QUEUE_T) .Case("opencl.clk_event_t", SPIR::PRIMITIVE_CLK_EVENT_T) .Case("opencl.sampler_t", SPIR::PRIMITIVE_SAMPLER_T) .Case("struct.ndrange_t", SPIR::PRIMITIVE_NDRANGE_T) .Case("opencl.intel_sub_group_avc_mce_payload_t", SPIR::PRIMITIVE_SUB_GROUP_AVC_MCE_PAYLOAD_T) .Case("opencl.intel_sub_group_avc_ime_payload_t", SPIR::PRIMITIVE_SUB_GROUP_AVC_IME_PAYLOAD_T) .Case("opencl.intel_sub_group_avc_ref_payload_t", SPIR::PRIMITIVE_SUB_GROUP_AVC_REF_PAYLOAD_T) .Case("opencl.intel_sub_group_avc_sic_payload_t", SPIR::PRIMITIVE_SUB_GROUP_AVC_SIC_PAYLOAD_T) .Case("opencl.intel_sub_group_avc_mce_result_t", SPIR::PRIMITIVE_SUB_GROUP_AVC_MCE_RESULT_T) .Case("opencl.intel_sub_group_avc_ime_result_t", SPIR::PRIMITIVE_SUB_GROUP_AVC_IME_RESULT_T) .Case("opencl.intel_sub_group_avc_ref_result_t", SPIR::PRIMITIVE_SUB_GROUP_AVC_REF_RESULT_T) .Case("opencl.intel_sub_group_avc_sic_result_t", SPIR::PRIMITIVE_SUB_GROUP_AVC_SIC_RESULT_T) .Case( "opencl.intel_sub_group_avc_ime_result_single_reference_streamout_t", SPIR::PRIMITIVE_SUB_GROUP_AVC_IME_SINGLE_REF_STREAMOUT_T) .Case("opencl.intel_sub_group_avc_ime_result_dual_reference_streamout_t", SPIR::PRIMITIVE_SUB_GROUP_AVC_IME_DUAL_REF_STREAMOUT_T) .Case("opencl.intel_sub_group_avc_ime_single_reference_streamin_t", SPIR::PRIMITIVE_SUB_GROUP_AVC_IME_SINGLE_REF_STREAMIN_T) .Case("opencl.intel_sub_group_avc_ime_dual_reference_streamin_t", SPIR::PRIMITIVE_SUB_GROUP_AVC_IME_DUAL_REF_STREAMIN_T) .Default(SPIR::PRIMITIVE_NONE); } /// Translates LLVM type to descriptor for mangler. /// \param Signed indicates integer type should be translated as signed. /// \param VoidPtr indicates i8* should be translated as void*. static SPIR::RefParamType transTypeDesc(Type *Ty, const BuiltinArgTypeMangleInfo &Info) { bool Signed = Info.IsSigned; unsigned Attr = Info.Attr; bool VoidPtr = Info.IsVoidPtr; if (Info.IsEnum) return SPIR::RefParamType(new SPIR::PrimitiveType(Info.Enum)); if (Info.IsSampler) return SPIR::RefParamType( new SPIR::PrimitiveType(SPIR::PRIMITIVE_SAMPLER_T)); if (Info.IsAtomic && !Ty->isPointerTy()) { BuiltinArgTypeMangleInfo DTInfo = Info; DTInfo.IsAtomic = false; return SPIR::RefParamType(new SPIR::AtomicType(transTypeDesc(Ty, DTInfo))); } if (auto *IntTy = dyn_cast(Ty)) { switch (IntTy->getBitWidth()) { case 1: return SPIR::RefParamType(new SPIR::PrimitiveType(SPIR::PRIMITIVE_BOOL)); case 8: return SPIR::RefParamType(new SPIR::PrimitiveType( Signed ? SPIR::PRIMITIVE_CHAR : SPIR::PRIMITIVE_UCHAR)); case 16: return SPIR::RefParamType(new SPIR::PrimitiveType( Signed ? SPIR::PRIMITIVE_SHORT : SPIR::PRIMITIVE_USHORT)); case 32: return SPIR::RefParamType(new SPIR::PrimitiveType( Signed ? SPIR::PRIMITIVE_INT : SPIR::PRIMITIVE_UINT)); case 64: return SPIR::RefParamType(new SPIR::PrimitiveType( Signed ? SPIR::PRIMITIVE_LONG : SPIR::PRIMITIVE_ULONG)); default: llvm_unreachable("invliad int size"); } } if (Ty->isVoidTy()) return SPIR::RefParamType(new SPIR::PrimitiveType(SPIR::PRIMITIVE_VOID)); if (Ty->isHalfTy()) return SPIR::RefParamType(new SPIR::PrimitiveType(SPIR::PRIMITIVE_HALF)); if (Ty->isFloatTy()) return SPIR::RefParamType(new SPIR::PrimitiveType(SPIR::PRIMITIVE_FLOAT)); if (Ty->isDoubleTy()) return SPIR::RefParamType(new SPIR::PrimitiveType(SPIR::PRIMITIVE_DOUBLE)); if (Ty->isVectorTy()) { return SPIR::RefParamType( new SPIR::VectorType(transTypeDesc(Ty->getVectorElementType(), Info), Ty->getVectorNumElements())); } if (Ty->isArrayTy()) { return transTypeDesc(PointerType::get(Ty->getArrayElementType(), 0), Info); } if (Ty->isStructTy()) { auto Name = Ty->getStructName(); std::string Tmp; if (Name.startswith(kLLVMTypeName::StructPrefix)) Name = Name.drop_front(strlen(kLLVMTypeName::StructPrefix)); if (Name.startswith(kSPIRVTypeName::PrefixAndDelim)) { Name = Name.substr(sizeof(kSPIRVTypeName::PrefixAndDelim) - 1); Tmp = Name.str(); auto Pos = Tmp.find(kSPIRVTypeName::Delimiter); // first dot while (Pos != std::string::npos) { Tmp[Pos] = '_'; Pos = Tmp.find(kSPIRVTypeName::Delimiter, Pos); } Name = Tmp = kSPIRVName::Prefix + Tmp; } // ToDo: Create a better unique Name for struct without Name if (Name.empty()) { std::ostringstream OS; OS << reinterpret_cast(Ty); Name = Tmp = std::string("struct_") + OS.str(); } return SPIR::RefParamType(new SPIR::UserDefinedType(Name)); } if (Ty->isPointerTy()) { auto ET = Ty->getPointerElementType(); SPIR::ParamType *EPT = nullptr; if (isa(ET)) { assert(isVoidFuncTy(cast(ET)) && "Not supported"); EPT = new SPIR::BlockType; } else if (auto StructTy = dyn_cast(ET)) { LLVM_DEBUG(dbgs() << "ptr to struct: " << *Ty << '\n'); auto TyName = StructTy->getStructName(); if (TyName.startswith(kSPR2TypeName::OCLPrefix)) { auto DelimPos = TyName.find_first_of(kSPR2TypeName::Delimiter, strlen(kSPR2TypeName::OCLPrefix)); if (DelimPos != StringRef::npos) TyName = TyName.substr(0, DelimPos); } LLVM_DEBUG(dbgs() << " type Name: " << TyName << '\n'); auto Prim = getOCLTypePrimitiveEnum(TyName); if (StructTy->isOpaque()) { if (TyName == "opencl.block") { auto BlockTy = new SPIR::BlockType; // Handle block with local memory arguments according to OpenCL 2.0 // spec. if (Info.IsLocalArgBlock) { SPIR::RefParamType VoidTyRef( new SPIR::PrimitiveType(SPIR::PRIMITIVE_VOID)); auto VoidPtrTy = new SPIR::PointerType(VoidTyRef); VoidPtrTy->setAddressSpace(SPIR::ATTR_LOCAL); // "__local void *" BlockTy->setParam(0, SPIR::RefParamType(VoidPtrTy)); // "..." BlockTy->setParam(1, SPIR::RefParamType(new SPIR::PrimitiveType( SPIR::PRIMITIVE_VAR_ARG))); } EPT = BlockTy; } else if (Prim != SPIR::PRIMITIVE_NONE) { if (Prim == SPIR::PRIMITIVE_PIPE_RO_T || Prim == SPIR::PRIMITIVE_PIPE_WO_T) { SPIR::RefParamType OpaqueTyRef(new SPIR::PrimitiveType(Prim)); auto OpaquePtrTy = new SPIR::PointerType(OpaqueTyRef); OpaquePtrTy->setAddressSpace(getOCLOpaqueTypeAddrSpace(Prim)); EPT = OpaquePtrTy; } else { EPT = new SPIR::PrimitiveType(Prim); } } } else if (Prim == SPIR::PRIMITIVE_NDRANGE_T) // ndrange_t is not opaque type EPT = new SPIR::PrimitiveType(SPIR::PRIMITIVE_NDRANGE_T); } if (EPT) return SPIR::RefParamType(EPT); if (VoidPtr && ET->isIntegerTy(8)) ET = Type::getVoidTy(ET->getContext()); auto PT = new SPIR::PointerType(transTypeDesc(ET, Info)); PT->setAddressSpace(static_cast( Ty->getPointerAddressSpace() + (unsigned)SPIR::ATTR_ADDR_SPACE_FIRST)); for (unsigned I = SPIR::ATTR_QUALIFIER_FIRST, E = SPIR::ATTR_QUALIFIER_LAST; I <= E; ++I) PT->setQualifier(static_cast(I), I & Attr); return SPIR::RefParamType(PT); } LLVM_DEBUG(dbgs() << "[transTypeDesc] " << *Ty << '\n'); assert(0 && "not implemented"); return SPIR::RefParamType(new SPIR::PrimitiveType(SPIR::PRIMITIVE_INT)); } Value *getScalarOrArray(Value *V, unsigned Size, Instruction *Pos) { if (!V->getType()->isPointerTy()) return V; assert((isa(V) || isa(V)) && "unexpected value type"); auto GEP = cast(V); assert(GEP->getNumOperands() == 3 && "must be a GEP from an array"); auto P = GEP->getOperand(0); assert(P->getType()->getPointerElementType()->getArrayNumElements() == Size); assert(dyn_cast(GEP->getOperand(1))->getZExtValue() == 0); assert(dyn_cast(GEP->getOperand(2))->getZExtValue() == 0); return new LoadInst(P, "", Pos); } Constant *getScalarOrVectorConstantInt(Type *T, uint64_t V, bool IsSigned) { if (auto IT = dyn_cast(T)) return ConstantInt::get(IT, V); if (auto VT = dyn_cast(T)) { std::vector EV( VT->getVectorNumElements(), getScalarOrVectorConstantInt(VT->getVectorElementType(), V, IsSigned)); return ConstantVector::get(EV); } llvm_unreachable("Invalid type"); return nullptr; } Value *getScalarOrArrayConstantInt(Instruction *Pos, Type *T, unsigned Len, uint64_t V, bool IsSigned) { if (auto IT = dyn_cast(T)) { assert(Len == 1 && "Invalid length"); return ConstantInt::get(IT, V, IsSigned); } if (auto PT = dyn_cast(T)) { auto ET = PT->getPointerElementType(); auto AT = ArrayType::get(ET, Len); std::vector EV(Len, ConstantInt::get(ET, V, IsSigned)); auto CA = ConstantArray::get(AT, EV); auto Alloca = new AllocaInst(AT, 0, "", Pos); new StoreInst(CA, Alloca, Pos); auto Zero = ConstantInt::getNullValue(Type::getInt32Ty(T->getContext())); Value *Index[] = {Zero, Zero}; auto Ret = GetElementPtrInst::CreateInBounds(Alloca, Index, "", Pos); LLVM_DEBUG(dbgs() << "[getScalarOrArrayConstantInt] Alloca: " << *Alloca << ", Return: " << *Ret << '\n'); return Ret; } if (auto AT = dyn_cast(T)) { auto ET = AT->getArrayElementType(); assert(AT->getArrayNumElements() == Len); std::vector EV(Len, ConstantInt::get(ET, V, IsSigned)); auto Ret = ConstantArray::get(AT, EV); LLVM_DEBUG(dbgs() << "[getScalarOrArrayConstantInt] Array type: " << *AT << ", Return: " << *Ret << '\n'); return Ret; } llvm_unreachable("Invalid type"); return nullptr; } void dumpUsers(Value *V, StringRef Prompt) { if (!V) return; LLVM_DEBUG(dbgs() << Prompt << " Users of " << *V << " :\n"); for (auto UI = V->user_begin(), UE = V->user_end(); UI != UE; ++UI) LLVM_DEBUG(dbgs() << " " << **UI << '\n'); } std::string getSPIRVTypeName(StringRef BaseName, StringRef Postfixes) { assert(!BaseName.empty() && "Invalid SPIR-V type Name"); auto TN = std::string(kSPIRVTypeName::PrefixAndDelim) + BaseName.str(); if (Postfixes.empty()) return TN; return TN + kSPIRVTypeName::Delimiter + Postfixes.str(); } bool isSPIRVConstantName(StringRef TyName) { if (TyName == getSPIRVTypeName(kSPIRVTypeName::ConstantSampler) || TyName == getSPIRVTypeName(kSPIRVTypeName::ConstantPipeStorage)) return true; return false; } Type *getSPIRVTypeByChangeBaseTypeName(Module *M, Type *T, StringRef OldName, StringRef NewName) { StringRef Postfixes; if (isSPIRVType(T, OldName, &Postfixes)) return getOrCreateOpaquePtrType(M, getSPIRVTypeName(NewName, Postfixes)); LLVM_DEBUG(dbgs() << " Invalid SPIR-V type " << *T << '\n'); llvm_unreachable("Invalid SPIR-V type"); return nullptr; } std::string getSPIRVImageTypePostfixes(StringRef SampledType, SPIRVTypeImageDescriptor Desc, SPIRVAccessQualifierKind Acc) { std::string S; raw_string_ostream OS(S); OS << SampledType << kSPIRVTypeName::PostfixDelim << Desc.Dim << kSPIRVTypeName::PostfixDelim << Desc.Depth << kSPIRVTypeName::PostfixDelim << Desc.Arrayed << kSPIRVTypeName::PostfixDelim << Desc.MS << kSPIRVTypeName::PostfixDelim << Desc.Sampled << kSPIRVTypeName::PostfixDelim << Desc.Format << kSPIRVTypeName::PostfixDelim << Acc; return OS.str(); } std::string getSPIRVImageSampledTypeName(SPIRVType *Ty) { switch (Ty->getOpCode()) { case OpTypeVoid: return kSPIRVImageSampledTypeName::Void; case OpTypeInt: if (Ty->getIntegerBitWidth() == 32) { if (static_cast(Ty)->isSigned()) return kSPIRVImageSampledTypeName::Int; else return kSPIRVImageSampledTypeName::UInt; } break; case OpTypeFloat: switch (Ty->getFloatBitWidth()) { case 16: return kSPIRVImageSampledTypeName::Half; case 32: return kSPIRVImageSampledTypeName::Float; default: break; } break; default: break; } llvm_unreachable("Invalid sampled type for image"); return std::string(); } // ToDo: Find a way to represent uint sampled type in LLVM, maybe an // opaque type. Type *getLLVMTypeForSPIRVImageSampledTypePostfix(StringRef Postfix, LLVMContext &Ctx) { if (Postfix == kSPIRVImageSampledTypeName::Void) return Type::getVoidTy(Ctx); if (Postfix == kSPIRVImageSampledTypeName::Float) return Type::getFloatTy(Ctx); if (Postfix == kSPIRVImageSampledTypeName::Half) return Type::getHalfTy(Ctx); if (Postfix == kSPIRVImageSampledTypeName::Int || Postfix == kSPIRVImageSampledTypeName::UInt) return Type::getInt32Ty(Ctx); llvm_unreachable("Invalid sampled type postfix"); return nullptr; } std::string getImageBaseTypeName(StringRef Name) { std::string ImageTyName = Name; SmallVector SubStrs; const char Delims[] = {kSPR2TypeName::Delimiter, 0}; Name.split(SubStrs, Delims); if (Name.startswith(kSPR2TypeName::OCLPrefix)) { ImageTyName = SubStrs[1].str(); } else { ImageTyName = SubStrs[0].str(); } if (hasAccessQualifiedName(ImageTyName)) ImageTyName.erase(ImageTyName.size() - 5, 3); return ImageTyName; } std::string mapOCLTypeNameToSPIRV(StringRef Name, StringRef Acc) { std::string BaseTy; std::string Postfixes; raw_string_ostream OS(Postfixes); if (!Acc.empty()) OS << kSPIRVTypeName::PostfixDelim; if (Name.startswith(kSPR2TypeName::ImagePrefix)) { std::string ImageTyName = getImageBaseTypeName(Name); auto Desc = map(ImageTyName); LLVM_DEBUG(dbgs() << "[trans image type] " << Name << " => " << "(" << (unsigned)Desc.Dim << ", " << Desc.Depth << ", " << Desc.Arrayed << ", " << Desc.MS << ", " << Desc.Sampled << ", " << Desc.Format << ")\n"); BaseTy = kSPIRVTypeName::Image; OS << getSPIRVImageTypePostfixes(kSPIRVImageSampledTypeName::Void, Desc, SPIRSPIRVAccessQualifierMap::map(Acc)); } else { LLVM_DEBUG(dbgs() << "Mapping of " << Name << " is not implemented\n"); llvm_unreachable("Not implemented"); } return getSPIRVTypeName(BaseTy, OS.str()); } bool eraseIfNoUse(Function *F) { bool Changed = false; if (!F) return Changed; if (!GlobalValue::isInternalLinkage(F->getLinkage()) && !F->isDeclaration()) return Changed; dumpUsers(F, "[eraseIfNoUse] "); for (auto UI = F->user_begin(), UE = F->user_end(); UI != UE;) { auto U = *UI++; if (auto CE = dyn_cast(U)) { if (CE->use_empty()) { CE->dropAllReferences(); Changed = true; } } } if (F->use_empty()) { LLVM_DEBUG(dbgs() << "Erase "; F->printAsOperand(dbgs()); dbgs() << '\n'); F->eraseFromParent(); Changed = true; } return Changed; } void eraseIfNoUse(Value *V) { if (!V->use_empty()) return; if (Constant *C = dyn_cast(V)) { C->destroyConstant(); return; } if (Instruction *I = dyn_cast(V)) { if (!I->mayHaveSideEffects()) I->eraseFromParent(); } eraseIfNoUse(dyn_cast(V)); } bool eraseUselessFunctions(Module *M) { bool Changed = false; for (auto I = M->begin(), E = M->end(); I != E;) Changed |= eraseIfNoUse(&(*I++)); return Changed; } // The mangling algorithm follows OpenCL pipe built-ins clang 3.8 CodeGen rules. static SPIR::MangleError manglePipeOrAddressSpaceCastBuiltin(const SPIR::FunctionDescriptor &Fd, std::string &MangledName) { assert(OCLUtil::isPipeOrAddressSpaceCastBI(Fd.Name) && "Method is expected to be called only for pipe and address space cast " "builtins!"); if (Fd.isNull()) { MangledName.assign(SPIR::FunctionDescriptor::nullString()); return SPIR::MANGLE_NULL_FUNC_DESCRIPTOR; } MangledName.assign("__" + Fd.Name); return SPIR::MANGLE_SUCCESS; } std::string mangleBuiltin(const std::string &UniqName, ArrayRef ArgTypes, BuiltinFuncMangleInfo *BtnInfo) { if (!BtnInfo) return UniqName; BtnInfo->init(UniqName); std::string MangledName; LLVM_DEBUG(dbgs() << "[mangle] " << UniqName << " => "); SPIR::FunctionDescriptor FD; FD.Name = BtnInfo->getUnmangledName(); bool BIVarArgNegative = BtnInfo->getVarArg() < 0; if (ArgTypes.empty()) { // Function signature cannot be ()(void, ...) so if there is an ellipsis // it must be ()(...) if (BIVarArgNegative) { FD.Parameters.emplace_back( SPIR::RefParamType(new SPIR::PrimitiveType(SPIR::PRIMITIVE_VOID))); } } else { for (unsigned I = 0, E = BIVarArgNegative ? ArgTypes.size() : (unsigned)BtnInfo->getVarArg(); I != E; ++I) { auto T = ArgTypes[I]; FD.Parameters.emplace_back( transTypeDesc(T, BtnInfo->getTypeMangleInfo(I))); } } // Ellipsis must be the last argument of any function if (!BIVarArgNegative) { assert((unsigned)BtnInfo->getVarArg() <= ArgTypes.size() && "invalid index of an ellipsis"); FD.Parameters.emplace_back( SPIR::RefParamType(new SPIR::PrimitiveType(SPIR::PRIMITIVE_VAR_ARG))); } #if defined(SPIRV_SPIR20_MANGLING_REQUIREMENTS) SPIR::NameMangler Mangler(SPIR::SPIR20); Mangler.mangle(FD, MangledName); #else if (OCLUtil::isPipeOrAddressSpaceCastBI(BtnInfo->getUnmangledName())) { manglePipeOrAddressSpaceCastBuiltin(FD, MangledName); } else { SPIR::NameMangler Mangler(SPIR::SPIR20); Mangler.mangle(FD, MangledName); } #endif LLVM_DEBUG(dbgs() << MangledName << '\n'); return MangledName; } /// Check if access qualifier is encoded in the type Name. bool hasAccessQualifiedName(StringRef TyName) { if (TyName.endswith("_ro_t") || TyName.endswith("_wo_t") || TyName.endswith("_rw_t")) return true; return false; } /// Get access qualifier from the type Name. StringRef getAccessQualifier(StringRef TyName) { assert(hasAccessQualifiedName(TyName) && "Type is not qualified with access."); auto Acc = TyName.substr(TyName.size() - 4, 2); return llvm::StringSwitch(Acc) .Case("ro", "read_only") .Case("wo", "write_only") .Case("rw", "read_write") .Default(""); } /// Translates OpenCL image type names to SPIR-V. Type *getSPIRVImageTypeFromOCL(Module *M, Type *ImageTy) { assert(isOCLImageType(ImageTy) && "Unsupported type"); auto ImageTypeName = ImageTy->getPointerElementType()->getStructName(); std::string Acc = kAccessQualName::ReadOnly; if (hasAccessQualifiedName(ImageTypeName)) Acc = getAccessQualifier(ImageTypeName); return getOrCreateOpaquePtrType(M, mapOCLTypeNameToSPIRV(ImageTypeName, Acc)); } llvm::PointerType *getOCLClkEventType(Module *M) { return getOrCreateOpaquePtrType(M, SPIR_TYPE_NAME_CLK_EVENT_T, SPIRAS_Private); } llvm::PointerType *getOCLClkEventPtrType(Module *M) { return PointerType::get(getOCLClkEventType(M), SPIRAS_Generic); } llvm::Constant *getOCLNullClkEventPtr(Module *M) { return Constant::getNullValue(getOCLClkEventPtrType(M)); } bool hasLoopMetadata(const Module *M) { for (const Function &F : *M) for (const BasicBlock &BB : F) { const Instruction *Term = BB.getTerminator(); if (Term && Term->getMetadata("llvm.loop")) return true; } return false; } } // namespace SPIRV SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVWriter.cpp000066400000000000000000002717071363521741200216710ustar00rootroot00000000000000//===- SPIRVWriter.cpp - Converts LLVM to SPIR-V ----------------*- C++ -*-===// // // The LLVM/SPIR-V Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file implements conversion of LLVM intermediate language to SPIR-V /// binary. /// //===----------------------------------------------------------------------===// #include "SPIRVWriter.h" #include "LLVMToSPIRVDbgTran.h" #include "SPIRVAsm.h" #include "SPIRVBasicBlock.h" #include "SPIRVEntry.h" #include "SPIRVEnum.h" #include "SPIRVExtInst.h" #include "SPIRVFunction.h" #include "SPIRVInstruction.h" #include "SPIRVInternal.h" #include "SPIRVMDWalker.h" #include "SPIRVModule.h" #include "SPIRVType.h" #include "SPIRVUtil.h" #include "SPIRVValue.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/Pass.h" #include "llvm/PassSupport.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Transforms/Utils.h" // loop-simplify pass #include #include #include #include #include #include #define DEBUG_TYPE "spirv" using namespace llvm; using namespace SPIRV; using namespace OCLUtil; namespace SPIRV { cl::opt SPIRVMemToReg("spirv-mem2reg", cl::init(false), cl::desc("LLVM/SPIR-V translation enable mem2reg")); static void foreachKernelArgMD( MDNode *MD, SPIRVFunction *BF, std::function Func) { for (unsigned I = 0, E = MD->getNumOperands(); I != E; ++I) { SPIRVFunctionParameter *BA = BF->getArgument(I); Func(getMDOperandAsString(MD, I), BA); } } LLVMToSPIRV::LLVMToSPIRV(SPIRVModule *SMod) : ModulePass(ID), M(nullptr), Ctx(nullptr), BM(SMod), SrcLang(0), SrcLangVer(0) { DbgTran = std::make_unique(nullptr, SMod, this); } bool LLVMToSPIRV::runOnModule(Module &Mod) { M = &Mod; CG = std::make_unique(Mod); Ctx = &M->getContext(); DbgTran->setModule(M); assert(BM && "SPIR-V module not initialized"); translate(); return true; } SPIRVValue *LLVMToSPIRV::getTranslatedValue(const Value *V) const { auto Loc = ValueMap.find(V); if (Loc != ValueMap.end()) return Loc->second; return nullptr; } bool LLVMToSPIRV::oclIsKernel(Function *F) { if (F->getCallingConv() == CallingConv::SPIR_KERNEL) return true; return false; } bool LLVMToSPIRV::isBuiltinTransToInst(Function *F) { std::string DemangledName; if (!oclIsBuiltin(F->getName(), &DemangledName) && !isDecoratedSPIRVFunc(F, &DemangledName)) return false; SPIRVDBG(spvdbgs() << "CallInst: demangled name: " << DemangledName << '\n'); return getSPIRVFuncOC(DemangledName) != OpNop; } bool LLVMToSPIRV::isBuiltinTransToExtInst(Function *F, SPIRVExtInstSetKind *ExtSet, SPIRVWord *ExtOp, SmallVectorImpl *Dec) { std::string OrigName = F->getName(); std::string DemangledName; if (!oclIsBuiltin(OrigName, &DemangledName)) return false; LLVM_DEBUG(dbgs() << "[oclIsBuiltinTransToExtInst] CallInst: demangled name: " << DemangledName << '\n'); StringRef S = DemangledName; if (!S.startswith(kSPIRVName::Prefix)) return false; S = S.drop_front(strlen(kSPIRVName::Prefix)); auto Loc = S.find(kSPIRVPostfix::Divider); auto ExtSetName = S.substr(0, Loc); SPIRVExtInstSetKind Set = SPIRVEIS_Count; if (!SPIRVExtSetShortNameMap::rfind(ExtSetName, &Set)) return false; assert((Set == SPIRVEIS_OpenCL || Set == SPIRVEIS_Debug) && "Unsupported extended instruction set"); auto ExtOpName = S.substr(Loc + 1); auto Splited = ExtOpName.split(kSPIRVPostfix::ExtDivider); OCLExtOpKind EOC; if (!OCLExtOpMap::rfind(Splited.first, &EOC)) return false; if (ExtSet) *ExtSet = Set; if (ExtOp) *ExtOp = EOC; if (Dec) { SmallVector P; Splited.second.split(P, kSPIRVPostfix::Divider); for (auto &I : P) Dec->push_back(I.str()); } return true; } /// Decode SPIR-V type name in the format spirv.{TypeName}._{Postfixes} /// where Postfixes are strings separated by underscores. /// \return TypeName. /// \param Ops contains the integers decoded from postfixes. static std::string decodeSPIRVTypeName(StringRef Name, SmallVectorImpl &Strs) { SmallVector SubStrs; const char Delim[] = {kSPIRVTypeName::Delimiter, 0}; Name.split(SubStrs, Delim, -1, true); assert(SubStrs.size() >= 2 && "Invalid SPIRV type name"); assert(SubStrs[0] == kSPIRVTypeName::Prefix && "Invalid prefix"); assert((SubStrs.size() == 2 || !SubStrs[2].empty()) && "Invalid postfix"); if (SubStrs.size() > 2) { const char PostDelim[] = {kSPIRVTypeName::PostfixDelim, 0}; SmallVector Postfixes; SubStrs[2].split(Postfixes, PostDelim, -1, true); assert(Postfixes.size() > 1 && Postfixes[0].empty() && "Invalid postfix"); for (unsigned I = 1, E = Postfixes.size(); I != E; ++I) Strs.push_back(std::string(Postfixes[I]).c_str()); } return SubStrs[1].str(); } static bool recursiveType(const StructType *ST, const Type *Ty) { SmallPtrSet Seen; std::function Run = [&](const Type *Ty) { if (!isa(Ty) && !Ty->isPointerTy()) return false; if (auto *StructTy = dyn_cast(Ty)) { if (StructTy == ST) return true; if (Seen.count(StructTy)) return false; Seen.insert(StructTy); return find_if(StructTy->element_begin(), StructTy->element_end(), Run) != StructTy->element_end(); } if (auto *PtrTy = dyn_cast(Ty)) { Type *ElTy = PtrTy->getPointerElementType(); if (auto *FTy = dyn_cast(ElTy)) { // If we have a function pointer, then argument types and return type of // the referenced function also need to be checked return Run(FTy->getReturnType()) || any_of(FTy->param_begin(), FTy->param_end(), Run); } return Run(ElTy); } if (auto *ArrayTy = dyn_cast(Ty)) return Run(ArrayTy->getArrayElementType()); return false; }; return Run(Ty); } SPIRVType *LLVMToSPIRV::transType(Type *T) { LLVMToSPIRVTypeMap::iterator Loc = TypeMap.find(T); if (Loc != TypeMap.end()) return Loc->second; SPIRVDBG(dbgs() << "[transType] " << *T << '\n'); if (T->isVoidTy()) return mapType(T, BM->addVoidType()); if (T->isIntegerTy(1)) return mapType(T, BM->addBoolType()); if (T->isIntegerTy()) { unsigned BitWidth = T->getIntegerBitWidth(); // SPIR-V 2.16.1. Universal Validation Rules: Scalar integer types can be // parameterized only as 32 bit, plus any additional sizes enabled by // capabilities. if (BM->getErrorLog().checkError( BitWidth == 8 || BitWidth == 16 || BitWidth == 32 || BitWidth == 64, SPIRVEC_InvalidBitWidth, std::to_string(BitWidth))) { return mapType(T, BM->addIntegerType(T->getIntegerBitWidth())); } } if (T->isFloatingPointTy()) return mapType(T, BM->addFloatType(T->getPrimitiveSizeInBits())); // A pointer to image or pipe type in LLVM is translated to a SPIRV // (non-pointer) image or pipe type. if (T->isPointerTy()) { auto ET = T->getPointerElementType(); if (ET->isFunctionTy() && !BM->checkExtension(ExtensionID::SPV_INTEL_function_pointers, SPIRVEC_FunctionPointers, toString(T))) return nullptr; auto ST = dyn_cast(ET); auto AddrSpc = T->getPointerAddressSpace(); if (ST && !ST->isSized()) { Op OpCode; StringRef STName = ST->getName(); // Workaround for non-conformant SPIR binary if (STName == "struct._event_t") { STName = kSPR2TypeName::Event; ST->setName(STName); } if (STName.startswith(kSPR2TypeName::PipeRO) || STName.startswith(kSPR2TypeName::PipeWO)) { auto PipeT = BM->addPipeType(); PipeT->setPipeAcessQualifier(STName.startswith(kSPR2TypeName::PipeRO) ? AccessQualifierReadOnly : AccessQualifierWriteOnly); return mapType(T, PipeT); } if (STName.startswith(kSPR2TypeName::ImagePrefix)) { assert(AddrSpc == SPIRAS_Global); auto SPIRVImageTy = getSPIRVImageTypeFromOCL(M, T); return mapType(T, transType(SPIRVImageTy)); } if (STName == kSPR2TypeName::Sampler) return mapType(T, transType(getSamplerType(M))); if (STName.startswith(kSPIRVTypeName::PrefixAndDelim)) return transSPIRVOpaqueType(T); if (STName.startswith(kOCLSubgroupsAVCIntel::TypePrefix)) return mapType(T, BM->addSubgroupAvcINTELType( OCLSubgroupINTELTypeOpCodeMap::map(ST->getName()))); if (OCLOpaqueTypeOpCodeMap::find(STName, &OpCode)) { switch (OpCode) { default: return mapType(T, BM->addOpaqueGenericType(OpCode)); case OpTypeDeviceEvent: return mapType(T, BM->addDeviceEventType()); case OpTypeQueue: return mapType(T, BM->addQueueType()); } } if (isPointerToOpaqueStructType(T)) { return mapType( T, BM->addPointerType(SPIRSPIRVAddrSpaceMap::map( static_cast(AddrSpc)), transType(ET))); } } else { return mapType( T, BM->addPointerType(SPIRSPIRVAddrSpaceMap::map( static_cast(AddrSpc)), transType(ET))); } } if (T->isVectorTy()) return mapType(T, BM->addVectorType(transType(T->getVectorElementType()), T->getVectorNumElements())); if (T->isArrayTy()) { // SPIR-V 1.3 s3.32.6: Length is the number of elements in the array. // It must be at least 1. if (T->getArrayNumElements() < 1) { std::string Str; llvm::raw_string_ostream OS(Str); OS << *T; SPIRVCK(T->getArrayNumElements() >= 1, InvalidArraySize, OS.str()); } return mapType(T, BM->addArrayType( transType(T->getArrayElementType()), static_cast(transValue( ConstantInt::get(getSizetType(), T->getArrayNumElements(), false), nullptr)))); } if (T->isStructTy() && !T->isSized()) { auto ST = dyn_cast(T); (void)ST; // Silence warning assert(!ST->getName().startswith(kSPR2TypeName::PipeRO)); assert(!ST->getName().startswith(kSPR2TypeName::PipeWO)); assert(!ST->getName().startswith(kSPR2TypeName::ImagePrefix)); return mapType(T, BM->addOpaqueType(T->getStructName())); } if (auto ST = dyn_cast(T)) { assert(ST->isSized()); std::string Name; if (ST->hasName()) Name = ST->getName(); if (Name == getSPIRVTypeName(kSPIRVTypeName::ConstantSampler)) return transType(getSamplerType(M)); if (Name == getSPIRVTypeName(kSPIRVTypeName::ConstantPipeStorage)) return transType(getPipeStorageType(M)); auto *Struct = BM->openStructType(T->getStructNumElements(), Name); mapType(T, Struct); SmallVector ForwardRefs; for (unsigned I = 0, E = T->getStructNumElements(); I != E; ++I) { auto *ElemTy = ST->getElementType(I); if ((isa(ElemTy) || isa(ElemTy)) && recursiveType(ST, ElemTy)) ForwardRefs.push_back(I); else Struct->setMemberType(I, transType(ST->getElementType(I))); } BM->closeStructType(Struct, ST->isPacked()); for (auto I : ForwardRefs) Struct->setMemberType(I, transType(ST->getElementType(I))); return Struct; } if (FunctionType *FT = dyn_cast(T)) { SPIRVType *RT = transType(FT->getReturnType()); std::vector PT; for (FunctionType::param_iterator I = FT->param_begin(), E = FT->param_end(); I != E; ++I) PT.push_back(transType(*I)); return mapType(T, BM->addFunctionType(RT, PT)); } llvm_unreachable("Not implemented!"); return 0; } SPIRVType *LLVMToSPIRV::transSPIRVOpaqueType(Type *T) { auto ET = T->getPointerElementType(); auto ST = cast(ET); auto STName = ST->getStructName(); assert(STName.startswith(kSPIRVTypeName::PrefixAndDelim) && "Invalid SPIR-V opaque type name"); SmallVector Postfixes; auto TN = decodeSPIRVTypeName(STName, Postfixes); if (TN == kSPIRVTypeName::Pipe) { assert(T->getPointerAddressSpace() == SPIRAS_Global); assert(Postfixes.size() == 1 && "Invalid pipe type ops"); auto PipeT = BM->addPipeType(); PipeT->setPipeAcessQualifier( static_cast(atoi(Postfixes[0].c_str()))); return mapType(T, PipeT); } else if (TN == kSPIRVTypeName::Image) { assert(T->getPointerAddressSpace() == SPIRAS_Global); // The sampled type needs to be translated through LLVM type to guarantee // uniqueness. auto SampledT = transType( getLLVMTypeForSPIRVImageSampledTypePostfix(Postfixes[0], *Ctx)); SmallVector Ops; for (unsigned I = 1; I < 8; ++I) Ops.push_back(atoi(Postfixes[I].c_str())); SPIRVTypeImageDescriptor Desc(static_cast(Ops[0]), Ops[1], Ops[2], Ops[3], Ops[4], Ops[5]); return mapType(T, BM->addImageType(SampledT, Desc, static_cast(Ops[6]))); } else if (TN == kSPIRVTypeName::SampledImg) { return mapType( T, BM->addSampledImageType(static_cast( transType(getSPIRVTypeByChangeBaseTypeName( M, T, kSPIRVTypeName::SampledImg, kSPIRVTypeName::Image))))); } else if (TN == kSPIRVTypeName::VmeImageINTEL) { // This type is the same as SampledImageType, but consumed by Subgroup AVC // Intel extension instructions. return mapType( T, BM->addVmeImageINTELType(static_cast( transType(getSPIRVTypeByChangeBaseTypeName( M, T, kSPIRVTypeName::VmeImageINTEL, kSPIRVTypeName::Image))))); } else if (TN == kSPIRVTypeName::Sampler) return mapType(T, BM->addSamplerType()); else if (TN == kSPIRVTypeName::DeviceEvent) return mapType(T, BM->addDeviceEventType()); else if (TN == kSPIRVTypeName::Queue) return mapType(T, BM->addQueueType()); else if (TN == kSPIRVTypeName::PipeStorage) return mapType(T, BM->addPipeStorageType()); else return mapType(T, BM->addOpaqueGenericType(SPIRVOpaqueTypeOpCodeMap::map(TN))); } SPIRVFunction *LLVMToSPIRV::transFunctionDecl(Function *F) { if (auto BF = getTranslatedValue(F)) return static_cast(BF); if (F->isIntrinsic()) { // We should not translate LLVM intrinsics as a function assert(none_of(F->user_begin(), F->user_end(), [this](User *U) { return getTranslatedValue(U); }) && "LLVM intrinsics shouldn't be called in SPIRV"); return nullptr; } SPIRVTypeFunction *BFT = static_cast( transType(getAnalysis().getAdaptedType(F))); SPIRVFunction *BF = static_cast(mapValue(F, BM->addFunction(BFT))); BF->setFunctionControlMask(transFunctionControlMask(F)); if (F->hasName()) BM->setName(BF, F->getName()); if (oclIsKernel(F)) BM->addEntryPoint(ExecutionModelKernel, BF->getId()); else if (F->getLinkage() != GlobalValue::InternalLinkage) BF->setLinkageType(transLinkageType(F)); auto Attrs = F->getAttributes(); for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) { auto ArgNo = I->getArgNo(); SPIRVFunctionParameter *BA = BF->getArgument(ArgNo); if (I->hasName()) BM->setName(BA, I->getName()); if (I->hasByValAttr()) BA->addAttr(FunctionParameterAttributeByVal); if (I->hasNoAliasAttr()) BA->addAttr(FunctionParameterAttributeNoAlias); if (I->hasNoCaptureAttr()) BA->addAttr(FunctionParameterAttributeNoCapture); if (I->hasStructRetAttr()) BA->addAttr(FunctionParameterAttributeSret); if (Attrs.hasAttribute(ArgNo + 1, Attribute::ZExt)) BA->addAttr(FunctionParameterAttributeZext); if (Attrs.hasAttribute(ArgNo + 1, Attribute::SExt)) BA->addAttr(FunctionParameterAttributeSext); if (BM->isAllowedToUseVersion(VersionNumber::SPIRV_1_1) && Attrs.hasAttribute(ArgNo + 1, Attribute::Dereferenceable)) BA->addDecorate(DecorationMaxByteOffset, Attrs.getAttribute(ArgNo + 1, Attribute::Dereferenceable) .getDereferenceableBytes()); } if (Attrs.hasAttribute(AttributeList::ReturnIndex, Attribute::ZExt)) BF->addDecorate(DecorationFuncParamAttr, FunctionParameterAttributeZext); if (Attrs.hasAttribute(AttributeList::ReturnIndex, Attribute::SExt)) BF->addDecorate(DecorationFuncParamAttr, FunctionParameterAttributeSext); if (Attrs.hasFnAttribute("referenced-indirectly")) { assert(!oclIsKernel(F) && "kernel function was marked as referenced-indirectly"); BF->addDecorate(DecorationReferencedIndirectlyINTEL); } SPIRVDBG(dbgs() << "[transFunction] " << *F << " => "; spvdbgs() << *BF << '\n';) return BF; } SPIRVValue *LLVMToSPIRV::transConstant(Value *V) { if (auto CPNull = dyn_cast(V)) return BM->addNullConstant( bcast(transType(CPNull->getType()))); if (auto CAZero = dyn_cast(V)) { Type *AggType = CAZero->getType(); if (const StructType *ST = dyn_cast(AggType)) if (ST->hasName() && ST->getName() == getSPIRVTypeName(kSPIRVTypeName::ConstantSampler)) return BM->addSamplerConstant(transType(AggType), 0, 0, 0); return BM->addNullConstant(transType(AggType)); } if (auto ConstI = dyn_cast(V)) return BM->addConstant(transType(V->getType()), ConstI->getZExtValue()); if (auto ConstFP = dyn_cast(V)) { auto BT = static_cast(transType(V->getType())); return BM->addConstant( BT, ConstFP->getValueAPF().bitcastToAPInt().getZExtValue()); } if (auto ConstDA = dyn_cast(V)) { std::vector BV; for (unsigned I = 0, E = ConstDA->getNumElements(); I != E; ++I) BV.push_back(transValue(ConstDA->getElementAsConstant(I), nullptr)); return BM->addCompositeConstant(transType(V->getType()), BV); } if (auto ConstA = dyn_cast(V)) { std::vector BV; for (auto I = ConstA->op_begin(), E = ConstA->op_end(); I != E; ++I) BV.push_back(transValue(*I, nullptr)); return BM->addCompositeConstant(transType(V->getType()), BV); } if (auto ConstDV = dyn_cast(V)) { std::vector BV; for (unsigned I = 0, E = ConstDV->getNumElements(); I != E; ++I) BV.push_back(transValue(ConstDV->getElementAsConstant(I), nullptr)); return BM->addCompositeConstant(transType(V->getType()), BV); } if (auto ConstV = dyn_cast(V)) { std::vector BV; for (auto I = ConstV->op_begin(), E = ConstV->op_end(); I != E; ++I) BV.push_back(transValue(*I, nullptr)); return BM->addCompositeConstant(transType(V->getType()), BV); } if (const auto *ConstV = dyn_cast(V)) { StringRef StructName; if (ConstV->getType()->hasName()) StructName = ConstV->getType()->getName(); if (StructName == getSPIRVTypeName(kSPIRVTypeName::ConstantSampler)) { assert(ConstV->getNumOperands() == 3); SPIRVWord AddrMode = ConstV->getOperand(0)->getUniqueInteger().getZExtValue(), Normalized = ConstV->getOperand(1)->getUniqueInteger().getZExtValue(), FilterMode = ConstV->getOperand(2)->getUniqueInteger().getZExtValue(); assert(AddrMode < 5 && "Invalid addressing mode"); assert(Normalized < 2 && "Invalid value of normalized coords"); assert(FilterMode < 2 && "Invalid filter mode"); SPIRVType *SamplerTy = transType(ConstV->getType()); return BM->addSamplerConstant(SamplerTy, AddrMode, Normalized, FilterMode); } if (StructName == getSPIRVTypeName(kSPIRVTypeName::ConstantPipeStorage)) { assert(ConstV->getNumOperands() == 3); SPIRVWord PacketSize = ConstV->getOperand(0)->getUniqueInteger().getZExtValue(), PacketAlign = ConstV->getOperand(1)->getUniqueInteger().getZExtValue(), Capacity = ConstV->getOperand(2)->getUniqueInteger().getZExtValue(); assert(PacketAlign >= 1 && "Invalid packet alignment"); assert(PacketSize >= PacketAlign && PacketSize % PacketAlign == 0 && "Invalid packet size and/or alignment."); SPIRVType *PipeStorageTy = transType(ConstV->getType()); return BM->addPipeStorageConstant(PipeStorageTy, PacketSize, PacketAlign, Capacity); } std::vector BV; for (auto I = ConstV->op_begin(), E = ConstV->op_end(); I != E; ++I) BV.push_back(transValue(*I, nullptr)); return BM->addCompositeConstant(transType(V->getType()), BV); } if (auto ConstUE = dyn_cast(V)) { auto Inst = ConstUE->getAsInstruction(); SPIRVDBG(dbgs() << "ConstantExpr: " << *ConstUE << '\n'; dbgs() << "Instruction: " << *Inst << '\n';) auto BI = transValue(Inst, nullptr, false); Inst->dropAllReferences(); return BI; } if (isa(V)) { return BM->addUndef(transType(V->getType())); } return nullptr; } SPIRVValue *LLVMToSPIRV::transValue(Value *V, SPIRVBasicBlock *BB, bool CreateForward) { LLVMToSPIRVValueMap::iterator Loc = ValueMap.find(V); if (Loc != ValueMap.end() && (!Loc->second->isForward() || CreateForward)) return Loc->second; SPIRVDBG(dbgs() << "[transValue] " << *V << '\n'); assert((!isa(V) || isa(V) || isa(V) || BB) && "Invalid SPIRV BB"); auto BV = transValueWithoutDecoration(V, BB, CreateForward); if (!BV || !transDecoration(V, BV)) return nullptr; std::string Name = V->getName(); if (!Name.empty()) // Don't erase the name, which BM might already have BM->setName(BV, Name); return BV; } SPIRVInstruction *LLVMToSPIRV::transBinaryInst(BinaryOperator *B, SPIRVBasicBlock *BB) { unsigned LLVMOC = B->getOpcode(); auto Op0 = transValue(B->getOperand(0), BB); SPIRVInstruction *BI = BM->addBinaryInst( transBoolOpCode(Op0, OpCodeMap::map(LLVMOC)), transType(B->getType()), Op0, transValue(B->getOperand(1), BB), BB); checkFpContract(B, BB); return BI; } SPIRVInstruction *LLVMToSPIRV::transCmpInst(CmpInst *Cmp, SPIRVBasicBlock *BB) { auto *Op0 = Cmp->getOperand(0); SPIRVValue *TOp0 = transValue(Op0, BB); SPIRVValue *TOp1 = transValue(Cmp->getOperand(1), BB); // TODO: once the translator supports SPIR-V 1.4, update the condition below: // if (/* */->isPointerTy() && /* it is not allowed to use SPIR-V 1.4 */) if (Op0->getType()->isPointerTy()) { unsigned AS = cast(Op0->getType())->getAddressSpace(); SPIRVType *Ty = transType(getSizetType(AS)); TOp0 = BM->addUnaryInst(OpConvertPtrToU, Ty, TOp0, BB); TOp1 = BM->addUnaryInst(OpConvertPtrToU, Ty, TOp1, BB); } SPIRVInstruction *BI = BM->addCmpInst(transBoolOpCode(TOp0, CmpMap::map(Cmp->getPredicate())), transType(Cmp->getType()), TOp0, TOp1, BB); return BI; } SPIRV::SPIRVInstruction *LLVMToSPIRV::transUnaryInst(UnaryInstruction *U, SPIRVBasicBlock *BB) { Op BOC = OpNop; if (auto Cast = dyn_cast(U)) { if (Cast->getDestTy()->getPointerAddressSpace() == SPIRAS_Generic) { assert(Cast->getSrcTy()->getPointerAddressSpace() != SPIRAS_Constant && "Casts from constant address space to generic are illegal"); BOC = OpPtrCastToGeneric; } else { assert(Cast->getDestTy()->getPointerAddressSpace() != SPIRAS_Constant && "Casts from generic address space to constant are illegal"); assert(Cast->getSrcTy()->getPointerAddressSpace() == SPIRAS_Generic); BOC = OpGenericCastToPtr; } } else { auto OpCode = U->getOpcode(); BOC = OpCodeMap::map(OpCode); } auto Op = transValue(U->getOperand(0), BB); return BM->addUnaryInst(transBoolOpCode(Op, BOC), transType(U->getType()), Op, BB); } /// This helper class encapsulates information extraction from /// "llvm.loop.parallel_access_indices" metadata hints. Initialize /// with a pointer to an MDNode with the following structure: /// ! = !{!"llvm.loop.parallel_access_indices", !, !, ...} /// OR: /// ! = !{!"llvm.loop.parallel_access_indices", !, i32 } /// /// All of the MDNode-type operands mark the index groups for particular /// array variables. An optional i32 value indicates the safelen (safe /// number of iterations) for the optimization application to these /// array variables. If the safelen value is absent, an infinite /// number of iterations is implied. class LLVMParallelAccessIndices { public: LLVMParallelAccessIndices( MDNode *Node, LLVMToSPIRV::LLVMToSPIRVMetadataMap &IndexGroupArrayMap) : Node(Node), IndexGroupArrayMap(IndexGroupArrayMap) {} void initialize() { assert(isValid() && "LLVMParallelAccessIndices initialized from an invalid MDNode"); unsigned NumOperands = Node->getNumOperands(); auto *SafeLenExpression = mdconst::dyn_extract_or_null( Node->getOperand(NumOperands - 1)); // If no safelen value is specified and the last operand // casts to an MDNode* rather than an int, 0 will be stored SafeLen = SafeLenExpression ? SafeLenExpression->getZExtValue() : 0; // Count MDNode operands that refer to index groups: // - operand [0] is a string literal and should be ignored; // - depending on whether a particular safelen is specified as the // last operand, we may or may not want to extract the latter // as an index group unsigned NumIdxGroups = SafeLen ? NumOperands - 2 : NumOperands - 1; for (unsigned I = 1; I <= NumIdxGroups; ++I) { MDNode *IdxGroupNode = getMDOperandAsMDNode(Node, I); assert(IdxGroupNode && "Invalid operand in the MDNode for LLVMParallelAccessIndices"); auto IdxGroupArrayPairIt = IndexGroupArrayMap.find(IdxGroupNode); assert(IdxGroupArrayPairIt != IndexGroupArrayMap.end() && "Absent entry for this index group node"); ArrayVariablesVec.push_back(IdxGroupArrayPairIt->second); } } bool isValid() { bool IsNamedCorrectly = getMDOperandAsString(Node, 0) == ExpectedName; return Node && IsNamedCorrectly; } unsigned getSafeLen() { return SafeLen; } const std::vector &getArrayVariables() { return ArrayVariablesVec; } private: MDNode *Node; LLVMToSPIRV::LLVMToSPIRVMetadataMap &IndexGroupArrayMap; const std::string ExpectedName = "llvm.loop.parallel_access_indices"; std::vector ArrayVariablesVec; unsigned SafeLen; }; /// Go through the operands !llvm.loop metadata attached to the branch /// instruction, fill the Loop Control mask and possible parameters for its /// fields. static spv::LoopControlMask getLoopControl(const BranchInst *Branch, std::vector &Parameters, LLVMToSPIRV::LLVMToSPIRVMetadataMap &IndexGroupArrayMap) { if (!Branch) return spv::LoopControlMaskNone; MDNode *LoopMD = Branch->getMetadata("llvm.loop"); if (!LoopMD) return spv::LoopControlMaskNone; size_t LoopControl = spv::LoopControlMaskNone; // Unlike with most of the cases, some loop metadata specifications // can occur multiple times - for these, all correspondent tokens // need to be collected first, and only then added to SPIR-V loop // parameters in a separate routine std::vector> DependencyArrayParameters; for (const MDOperand &MDOp : LoopMD->operands()) { if (MDNode *Node = dyn_cast(MDOp)) { std::string S = getMDOperandAsString(Node, 0); // Set the loop control bits. Parameters are set in the order described // in 3.23 SPIR-V Spec. rev. 1.4: // Bits that are set can indicate whether an additional operand follows, // as described by the table. If there are multiple following operands // indicated, they are ordered: Those indicated by smaller-numbered bits // appear first. if (S == "llvm.loop.unroll.disable") LoopControl |= spv::LoopControlDontUnrollMask; else if (S == "llvm.loop.unroll.full" || S == "llvm.loop.unroll.enable") LoopControl |= spv::LoopControlUnrollMask; // PartialCount must not be used with the DontUnroll bit else if (S == "llvm.loop.unroll.count" && !(LoopControl & LoopControlDontUnrollMask)) { size_t I = getMDOperandAsInt(Node, 1); Parameters.push_back(I); LoopControl |= spv::LoopControlPartialCountMask; } else if (S == "llvm.loop.ivdep.enable") LoopControl |= spv::LoopControlDependencyInfiniteMask; else if (S == "llvm.loop.ivdep.safelen") { size_t I = getMDOperandAsInt(Node, 1); Parameters.push_back(I); LoopControl |= spv::LoopControlDependencyLengthMask; } else if (S == "llvm.loop.ii.count") { size_t I = getMDOperandAsInt(Node, 1); Parameters.push_back(I); LoopControl |= spv::InitiationIntervalINTEL; } else if (S == "llvm.loop.max_concurrency.count") { size_t I = getMDOperandAsInt(Node, 1); Parameters.push_back(I); LoopControl |= spv::MaxConcurrencyINTEL; } else if (S == "llvm.loop.parallel_access_indices") { // Intel FPGA IVDep loop attribute LLVMParallelAccessIndices IVDep(Node, IndexGroupArrayMap); IVDep.initialize(); // Store IVDep-specific parameters into an intermediate // container to address the case when there're multiple // IVDep metadata nodes and this condition gets entered multiple // times. The update of the main parameters vector & the loop control // mask will be done later, in the main scope of the function unsigned SafeLen = IVDep.getSafeLen(); for (auto &ArrayId : IVDep.getArrayVariables()) DependencyArrayParameters.emplace_back(ArrayId, SafeLen); } } } // If any loop control parameters were held back until fully collected, // now is the time to move the information to the main parameters collection if (!DependencyArrayParameters.empty()) { // The first parameter states the number of pairs to be // listed Parameters.push_back(DependencyArrayParameters.size()); for (auto &ArraySflnPair : DependencyArrayParameters) { Parameters.push_back(ArraySflnPair.first); Parameters.push_back(ArraySflnPair.second); } LoopControl |= spv::DependencyArrayINTEL; } return static_cast(LoopControl); } /// An instruction may use an instruction from another BB which has not been /// translated. SPIRVForward should be created as place holder for these /// instructions and replaced later by the real instructions. /// Use CreateForward = true to indicate such situation. SPIRVValue *LLVMToSPIRV::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB, bool CreateForward) { if (auto LBB = dyn_cast(V)) { auto BF = static_cast(getTranslatedValue(LBB->getParent())); assert(BF && "Function not translated"); BB = static_cast(mapValue(V, BM->addBasicBlock(BF))); BM->setName(BB, LBB->getName()); return BB; } if (auto F = dyn_cast(V)) return transFunctionDecl(F); if (auto GV = dyn_cast(V)) { llvm::PointerType *Ty = GV->getType(); // Though variables with common linkage type are initialized by 0, // they can be represented in SPIR-V as uninitialized variables with // 'Export' linkage type, just as tentative definitions look in C llvm::Value *Init = GV->hasInitializer() && !GV->hasCommonLinkage() ? GV->getInitializer() : nullptr; SPIRVValue *BVarInit = nullptr; StructType *ST = Init ? dyn_cast(Init->getType()) : nullptr; if (ST && ST->hasName() && isSPIRVConstantName(ST->getName())) { auto BV = transConstant(Init); assert(BV); return mapValue(V, BV); } else if (ConstantExpr *ConstUE = dyn_cast_or_null(Init)) { Instruction *Inst = ConstUE->getAsInstruction(); if (isSpecialTypeInitializer(Inst)) { Init = Inst->getOperand(0); Ty = static_cast(Init->getType()); } Inst->dropAllReferences(); BVarInit = transValue(Init, nullptr); } else if (ST && isa(Init)) { // Undef initializer for LLVM structure be can translated to // OpConstantComposite with OpUndef constituents. auto I = ValueMap.find(Init); if (I == ValueMap.end()) { std::vector Elements; for (Type *E : ST->elements()) Elements.push_back(transValue(UndefValue::get(E), nullptr)); BVarInit = BM->addCompositeConstant(transType(ST), Elements); ValueMap[Init] = BVarInit; } else BVarInit = I->second; } else if (Init && !isa(Init)) { BVarInit = transValue(Init, nullptr); } auto BVar = static_cast(BM->addVariable( transType(Ty), GV->isConstant(), transLinkageType(GV), BVarInit, GV->getName(), SPIRSPIRVAddrSpaceMap::map( static_cast(Ty->getAddressSpace())), nullptr)); mapValue(V, BVar); spv::BuiltIn Builtin = spv::BuiltInPosition; if (!GV->hasName() || !getSPIRVBuiltin(GV->getName().str(), Builtin)) return BVar; BVar->setBuiltin(Builtin); return BVar; } if (isa(V)) { auto BV = transConstant(V); assert(BV); return mapValue(V, BV); } if (auto Arg = dyn_cast(V)) { unsigned ArgNo = Arg->getArgNo(); SPIRVFunction *BF = BB->getParent(); // assert(BF->existArgument(ArgNo)); return mapValue(V, BF->getArgument(ArgNo)); } if (CreateForward) return mapValue(V, BM->addForward(transType(V->getType()))); if (StoreInst *ST = dyn_cast(V)) { std::vector MemoryAccess(1, 0); if (ST->isVolatile()) MemoryAccess[0] |= MemoryAccessVolatileMask; if (ST->getAlignment()) { MemoryAccess[0] |= MemoryAccessAlignedMask; MemoryAccess.push_back(ST->getAlignment()); } if (ST->getMetadata(LLVMContext::MD_nontemporal)) MemoryAccess[0] |= MemoryAccessNontemporalMask; if (MemoryAccess.front() == 0) MemoryAccess.clear(); SPIRVValue *BSV = nullptr; if (Function *F = dyn_cast(ST->getValueOperand())) { if (!BM->checkExtension(ExtensionID::SPV_INTEL_function_pointers, SPIRVEC_FunctionPointers, toString(ST))) return nullptr; // store of function pointer BSV = BM->addFunctionPointerINTELInst( transType(F->getType()), static_cast(transValue(F, BB)), BB); } else { BSV = transValue(ST->getValueOperand(), BB); } return mapValue(V, BM->addStoreInst(transValue(ST->getPointerOperand(), BB), BSV, MemoryAccess, BB)); } if (LoadInst *LD = dyn_cast(V)) { std::vector MemoryAccess(1, 0); if (LD->isVolatile()) MemoryAccess[0] |= MemoryAccessVolatileMask; if (LD->getAlignment()) { MemoryAccess[0] |= MemoryAccessAlignedMask; MemoryAccess.push_back(LD->getAlignment()); } if (LD->getMetadata(LLVMContext::MD_nontemporal)) MemoryAccess[0] |= MemoryAccessNontemporalMask; if (MemoryAccess.front() == 0) MemoryAccess.clear(); return mapValue(V, BM->addLoadInst(transValue(LD->getPointerOperand(), BB), MemoryAccess, BB)); } if (BinaryOperator *B = dyn_cast(V)) { SPIRVInstruction *BI = transBinaryInst(B, BB); return mapValue(V, BI); } if (dyn_cast(V)) return mapValue(V, BM->addUnreachableInst(BB)); if (auto RI = dyn_cast(V)) { if (auto RV = RI->getReturnValue()) return mapValue(V, BM->addReturnValueInst(transValue(RV, BB), BB)); return mapValue(V, BM->addReturnInst(BB)); } if (CmpInst *Cmp = dyn_cast(V)) { SPIRVInstruction *BI = transCmpInst(Cmp, BB); return mapValue(V, BI); } if (SelectInst *Sel = dyn_cast(V)) return mapValue(V, BM->addSelectInst(transValue(Sel->getCondition(), BB), transValue(Sel->getTrueValue(), BB), transValue(Sel->getFalseValue(), BB), BB)); if (AllocaInst *Alc = dyn_cast(V)) return mapValue( V, BM->addVariable(transType(Alc->getType()), false, SPIRVLinkageTypeKind::LinkageTypeInternal, nullptr, Alc->getName(), StorageClassFunction, BB)); if (auto *Switch = dyn_cast(V)) { std::vector Pairs; auto Select = transValue(Switch->getCondition(), BB); for (auto I = Switch->case_begin(), E = Switch->case_end(); I != E; ++I) { SPIRVSwitch::LiteralTy Lit; uint64_t CaseValue = I->getCaseValue()->getZExtValue(); Lit.push_back(CaseValue); assert(Select->getType()->getBitWidth() <= 64 && "unexpected selector bitwidth"); if (Select->getType()->getBitWidth() == 64) Lit.push_back(CaseValue >> 32); Pairs.push_back( std::make_pair(Lit, static_cast( transValue(I->getCaseSuccessor(), nullptr)))); } return mapValue( V, BM->addSwitchInst(Select, static_cast( transValue(Switch->getDefaultDest(), nullptr)), Pairs, BB)); } if (BranchInst *Branch = dyn_cast(V)) { SPIRVLabel *SuccessorTrue = static_cast(transValue(Branch->getSuccessor(0), BB)); /// Clang attaches !llvm.loop metadata to "latch" BB. This kind of blocks /// has an edge directed to the loop header. Thus latch BB matching to /// "Continue Target" per the SPIR-V spec. This statement is true only after /// applying the loop-simplify pass to the LLVM module. /// For "for" and "while" loops latch BB is terminated by an /// unconditional branch. Also for this kind of loops "Merge Block" can /// be found as block targeted by false edge of the "Header" BB. /// For "do while" loop the latch is terminated by a conditional branch /// with true edge going to the header and the false edge going out of /// the loop, which corresponds to a "Merge Block" per the SPIR-V spec. std::vector Parameters; spv::LoopControlMask LoopControl = getLoopControl(Branch, Parameters, IndexGroupArrayMap); if (Branch->isUnconditional()) { // For "for" and "while" loops llvm.loop metadata is attached to // an unconditional branch instruction. if (LoopControl != spv::LoopControlMaskNone) { // SuccessorTrue is the loop header BB. const SPIRVInstruction *Term = SuccessorTrue->getTerminateInstr(); if (Term && Term->getOpCode() == OpBranchConditional) { const auto *Br = static_cast(Term); BM->addLoopMergeInst(Br->getFalseLabel()->getId(), // Merge Block BB->getId(), // Continue Target LoopControl, Parameters, SuccessorTrue); } else { if (BM->isAllowedToUseExtension( ExtensionID::SPV_INTEL_unstructured_loop_controls)) { // For unstructured loop we add a special loop control instruction. // Simple example of unstructured loop is an infinite loop, that has // no terminate instruction. BM->addLoopControlINTELInst(LoopControl, Parameters, SuccessorTrue); } } } return mapValue(V, BM->addBranchInst(SuccessorTrue, BB)); } // For "do-while" loops llvm.loop metadata is attached to a conditional // branch instructions SPIRVLabel *SuccessorFalse = static_cast(transValue(Branch->getSuccessor(1), BB)); if (LoopControl != spv::LoopControlMaskNone) // SuccessorTrue is the loop header BB. BM->addLoopMergeInst(SuccessorFalse->getId(), // Merge Block BB->getId(), // Continue Target LoopControl, Parameters, SuccessorTrue); return mapValue( V, BM->addBranchConditionalInst(transValue(Branch->getCondition(), BB), SuccessorTrue, SuccessorFalse, BB)); } if (auto Phi = dyn_cast(V)) { std::vector IncomingPairs; for (size_t I = 0, E = Phi->getNumIncomingValues(); I != E; ++I) { SPIRVValue *BV = nullptr; if (Function *F = dyn_cast(Phi->getIncomingValue(I))) { if (!BM->checkExtension(ExtensionID::SPV_INTEL_function_pointers, SPIRVEC_FunctionPointers, toString(Phi))) return nullptr; BV = BM->addFunctionPointerINTELInst( transType(F->getType()), static_cast(transValue(F, BB)), BB); } else { BV = transValue(Phi->getIncomingValue(I), BB); } IncomingPairs.push_back(BV); IncomingPairs.push_back(transValue(Phi->getIncomingBlock(I), nullptr)); } return mapValue( V, BM->addPhiInst(transType(Phi->getType()), IncomingPairs, BB)); } if (auto Ext = dyn_cast(V)) { return mapValue(V, BM->addCompositeExtractInst( transType(Ext->getType()), transValue(Ext->getAggregateOperand(), BB), Ext->getIndices(), BB)); } if (auto Ins = dyn_cast(V)) { return mapValue(V, BM->addCompositeInsertInst( transValue(Ins->getInsertedValueOperand(), BB), transValue(Ins->getAggregateOperand(), BB), Ins->getIndices(), BB)); } if (UnaryInstruction *U = dyn_cast(V)) { if (isSpecialTypeInitializer(U)) return mapValue(V, transValue(U->getOperand(0), BB)); return mapValue(V, transUnaryInst(U, BB)); } if (GetElementPtrInst *GEP = dyn_cast(V)) { std::vector Indices; for (unsigned I = 0, E = GEP->getNumIndices(); I != E; ++I) Indices.push_back(transValue(GEP->getOperand(I + 1), BB)); auto *TransPointerOperand = transValue(GEP->getPointerOperand(), BB); // Certain array-related optimization hints can be expressed via // LLVM metadata. For the purpose of linking this metadata with // the accessed array variables, our GEP may have been marked into // a so-called index group, an MDNode by itself. if (MDNode *IndexGroup = GEP->getMetadata("llvm.index.group")) { // When where we work with embedded loops, it's natural that // the outer loop's hints apply to all code contained within. // The inner loop's specific hints, however, should stay private // to the inner loop's scope. // Consequently, the following division of the index group metadata // nodes emerges: // 1) The metadata node has no operands. It will be directly referenced // from within the optimization hint metadata. // 2) The metadata node has several operands. It serves to link an index // group specific to some embedded loop with other index groups that // mark the same array variable for the outer loop(s). unsigned NumOperands = IndexGroup->getNumOperands(); if (NumOperands > 0) // The index group for this particular "embedded loop depth" is always // signalled by the last variable. We'll want to associate this loop's // control parameters with this inner-loop-specific index group IndexGroup = getMDOperandAsMDNode(IndexGroup, NumOperands - 1); IndexGroupArrayMap[IndexGroup] = TransPointerOperand->getId(); } return mapValue(V, BM->addPtrAccessChainInst(transType(GEP->getType()), TransPointerOperand, Indices, BB, GEP->isInBounds())); } if (auto Ext = dyn_cast(V)) { auto Index = Ext->getIndexOperand(); if (auto Const = dyn_cast(Index)) return mapValue(V, BM->addCompositeExtractInst( transType(Ext->getType()), transValue(Ext->getVectorOperand(), BB), std::vector(1, Const->getZExtValue()), BB)); else return mapValue(V, BM->addVectorExtractDynamicInst( transValue(Ext->getVectorOperand(), BB), transValue(Index, BB), BB)); } if (auto Ins = dyn_cast(V)) { auto Index = Ins->getOperand(2); if (auto Const = dyn_cast(Index)) return mapValue(V, BM->addCompositeInsertInst( transValue(Ins->getOperand(1), BB), transValue(Ins->getOperand(0), BB), std::vector(1, Const->getZExtValue()), BB)); else return mapValue( V, BM->addVectorInsertDynamicInst(transValue(Ins->getOperand(0), BB), transValue(Ins->getOperand(1), BB), transValue(Index, BB), BB)); } if (auto SF = dyn_cast(V)) { std::vector Comp; for (auto &I : SF->getShuffleMask()) Comp.push_back(I); return mapValue(V, BM->addVectorShuffleInst( transType(SF->getType()), transValue(SF->getOperand(0), BB), transValue(SF->getOperand(1), BB), Comp, BB)); } if (IntrinsicInst *II = dyn_cast(V)) { SPIRVValue *BV = transIntrinsicInst(II, BB); return BV ? mapValue(V, BV) : nullptr; } if (InlineAsm *IA = dyn_cast(V)) if (BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_inline_assembly)) return mapValue(V, transAsmINTEL(IA)); if (CallInst *CI = dyn_cast(V)) return mapValue(V, transCallInst(CI, BB)); llvm_unreachable("Not implemented"); return nullptr; } SPIRVType *LLVMToSPIRV::mapType(Type *T, SPIRVType *BT) { TypeMap[T] = BT; SPIRVDBG(dbgs() << "[mapType] " << *T << " => "; spvdbgs() << *BT << '\n'); return BT; } SPIRVValue *LLVMToSPIRV::mapValue(Value *V, SPIRVValue *BV) { auto Loc = ValueMap.find(V); if (Loc != ValueMap.end()) { if (Loc->second == BV) return BV; assert(Loc->second->isForward() && "LLVM Value is mapped to different SPIRV Values"); auto Forward = static_cast(Loc->second); BM->replaceForward(Forward, BV); } ValueMap[V] = BV; SPIRVDBG(dbgs() << "[mapValue] " << *V << " => "; spvdbgs() << BV << "\n"); return BV; } bool LLVMToSPIRV::transDecoration(Value *V, SPIRVValue *BV) { if (!transAlign(V, BV)) return false; if ((isa(V) && cast(V)->isVolatile()) || (isa(V) && cast(V)->isVolatile())) BV->setVolatile(true); if (auto BVO = dyn_cast_or_null(V)) { if (BVO->hasNoSignedWrap()) { BV->setNoSignedWrap(true); } if (BVO->hasNoUnsignedWrap()) { BV->setNoUnsignedWrap(true); } } return true; } bool LLVMToSPIRV::transAlign(Value *V, SPIRVValue *BV) { if (auto AL = dyn_cast(V)) { BM->setAlignment(BV, AL->getAlignment()); return true; } if (auto GV = dyn_cast(V)) { BM->setAlignment(BV, GV->getAlignment()); return true; } return true; } /// Do this after source language is set. bool LLVMToSPIRV::transBuiltinSet() { SPIRVId EISId; if (!BM->importBuiltinSet("OpenCL.std", &EISId)) return false; if (SPIRVMDWalker(*M).getNamedMD("llvm.dbg.cu")) { if (!BM->importBuiltinSet("SPIRV.debug", &EISId)) return false; } return true; } /// Translate sampler* spcv.cast(i32 arg) or /// sampler* __translate_sampler_initializer(i32 arg) /// Three cases are possible: /// arg = ConstantInt x -> SPIRVConstantSampler /// arg = i32 argument -> transValue(arg) /// arg = load from sampler -> look through load SPIRVValue *LLVMToSPIRV::oclTransSpvcCastSampler(CallInst *CI, SPIRVBasicBlock *BB) { assert(CI->getCalledFunction() && "Unexpected indirect call"); llvm::Function *F = CI->getCalledFunction(); auto FT = F->getFunctionType(); auto RT = FT->getReturnType(); assert(FT->getNumParams() == 1); assert((isSPIRVType(RT, kSPIRVTypeName::Sampler) || isPointerToOpaqueStructType(RT, kSPR2TypeName::Sampler)) && FT->getParamType(0)->isIntegerTy() && "Invalid sampler type"); auto Arg = CI->getArgOperand(0); auto GetSamplerConstant = [&](uint64_t SamplerValue) { auto AddrMode = (SamplerValue & 0xE) >> 1; auto Param = SamplerValue & 0x1; auto Filter = SamplerValue ? ((SamplerValue & 0x30) >> 4) - 1 : 0; auto BV = BM->addSamplerConstant(transType(RT), AddrMode, Param, Filter); return BV; }; if (auto Const = dyn_cast(Arg)) { // Sampler is declared as a kernel scope constant return GetSamplerConstant(Const->getZExtValue()); } else if (auto Load = dyn_cast(Arg)) { // If value of the sampler is loaded from a global constant, use its // initializer for initialization of the sampler. auto Op = Load->getPointerOperand(); assert(isa(Op) && "Unknown sampler pattern!"); auto GV = cast(Op); assert(GV->isConstant() || GV->getType()->getPointerAddressSpace() == SPIRAS_Constant); auto Initializer = GV->getInitializer(); assert(isa(Initializer) && "sampler not constant int?"); return GetSamplerConstant(cast(Initializer)->getZExtValue()); } // Sampler is a function argument auto BV = transValue(Arg, BB); assert(BV && BV->getType() == transType(RT)); return BV; } std::vector> tryParseIntelFPGAAnnotationString(StringRef AnnotatedCode) { std::vector> Decorates; size_t OpenBracketNum = AnnotatedCode.count('{'); size_t CloseBracketNum = AnnotatedCode.count('}'); if (OpenBracketNum != CloseBracketNum) return {}; for (size_t I = 0; I < OpenBracketNum; ++I) { size_t From = AnnotatedCode.find('{'); size_t To = AnnotatedCode.find('}', From); StringRef AnnotatedDecoration = AnnotatedCode.substr(From + 1, To - 1); std::pair D = AnnotatedDecoration.split(':'); StringRef F = D.first, S = D.second; StringRef Value; Decoration Dec; if (F == "pump") { Dec = llvm::StringSwitch(S) .Case("1", DecorationSinglepumpINTEL) .Case("2", DecorationDoublepumpINTEL); } else if (F == "register") { Dec = DecorationRegisterINTEL; } else if (F == "simple_dual_port") { Dec = DecorationSimpleDualPortINTEL; } else { Dec = llvm::StringSwitch(F) .Case("memory", DecorationMemoryINTEL) .Case("numbanks", DecorationNumbanksINTEL) .Case("bankwidth", DecorationBankwidthINTEL) .Case("private_copies", DecorationMaxPrivateCopiesINTEL) .Case("max_replicates", DecorationMaxReplicatesINTEL) .Case("bank_bits", DecorationBankBitsINTEL) .Case("merge", DecorationMergeINTEL) .Default(DecorationUserSemantic); if (Dec == DecorationUserSemantic) Value = AnnotatedCode.substr(From, To + 1); else Value = S; } Decorates.push_back({Dec, Value}); AnnotatedCode = AnnotatedCode.drop_front(To + 1); } return Decorates; } std::vector getBankBitsFromString(StringRef S) { SmallVector BitsString; S.split(BitsString, ','); std::vector Bits(BitsString.size()); for (size_t J = 0; J < BitsString.size(); ++J) if (BitsString[J].getAsInteger(10, Bits[J])) return {}; return Bits; } void addIntelFPGADecorations( SPIRVEntry *E, std::vector> &Decorations) { if (!E->getModule()->isAllowedToUseExtension( ExtensionID::SPV_INTEL_fpga_memory_attributes)) return; for (const auto &I : Decorations) { // Such decoration already exists on a type, skip it if (E->hasDecorate(I.first, /*Index=*/0, /*Result=*/nullptr)) { continue; } switch (I.first) { case DecorationUserSemantic: E->addDecorate(new SPIRVDecorateUserSemanticAttr(E, I.second)); break; case DecorationMemoryINTEL: E->addDecorate(new SPIRVDecorateMemoryINTELAttr(E, I.second)); break; case DecorationMergeINTEL: { StringRef Name = StringRef(I.second).split(':').first; StringRef Direction = StringRef(I.second).split(':').second; E->addDecorate( new SPIRVDecorateMergeINTELAttr(E, Name.str(), Direction.str())); } break; case DecorationBankBitsINTEL: E->addDecorate(new SPIRVDecorateBankBitsINTELAttr( E, getBankBitsFromString(I.second))); break; case DecorationRegisterINTEL: case DecorationSinglepumpINTEL: case DecorationDoublepumpINTEL: case DecorationSimpleDualPortINTEL: assert(I.second.empty()); E->addDecorate(I.first); break; // The rest of IntelFPGA decorations: // DecorationNumbanksINTEL // DecorationBankwidthINTEL // DecorationMaxPrivateCopiesINTEL // DecorationMaxReplicatesINTEL default: SPIRVWord Result = 0; StringRef(I.second).getAsInteger(10, Result); E->addDecorate(I.first, Result); break; } } } void addIntelFPGADecorationsForStructMember( SPIRVEntry *E, SPIRVWord MemberNumber, std::vector> &Decorations) { if (!E->getModule()->isAllowedToUseExtension( ExtensionID::SPV_INTEL_fpga_memory_attributes)) return; for (const auto &I : Decorations) { // Such decoration already exists on a type, skip it if (E->hasMemberDecorate(I.first, /*Index=*/0, MemberNumber, /*Result=*/nullptr)) { continue; } switch (I.first) { case DecorationUserSemantic: E->addMemberDecorate( new SPIRVMemberDecorateUserSemanticAttr(E, MemberNumber, I.second)); break; case DecorationMemoryINTEL: E->addMemberDecorate( new SPIRVMemberDecorateMemoryINTELAttr(E, MemberNumber, I.second)); break; case DecorationMergeINTEL: { StringRef Name = StringRef(I.second).split(':').first; StringRef Direction = StringRef(I.second).split(':').second; E->addMemberDecorate(new SPIRVMemberDecorateMergeINTELAttr( E, MemberNumber, Name.str(), Direction.str())); } break; case DecorationBankBitsINTEL: E->addMemberDecorate(new SPIRVMemberDecorateBankBitsINTELAttr( E, MemberNumber, getBankBitsFromString(I.second))); break; case DecorationRegisterINTEL: case DecorationSinglepumpINTEL: case DecorationDoublepumpINTEL: case DecorationSimpleDualPortINTEL: assert(I.second.empty()); E->addMemberDecorate(MemberNumber, I.first); break; // The rest of IntelFPGA decorations: // DecorationNumbanksINTEL // DecorationBankwidthINTEL // DecorationMaxPrivateCopiesINTEL // DecorationMaxReplicatesINTEL default: SPIRVWord Result = 0; StringRef(I.second).getAsInteger(10, Result); E->addMemberDecorate(MemberNumber, I.first, Result); break; } } } SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II, SPIRVBasicBlock *BB) { auto GetMemoryAccess = [](MemIntrinsic *MI) -> std::vector { std::vector MemoryAccess(1, MemoryAccessMaskNone); if (SPIRVWord AlignVal = MI->getDestAlignment()) { MemoryAccess[0] |= MemoryAccessAlignedMask; if (auto MTI = dyn_cast(MI)) { SPIRVWord SourceAlignVal = MTI->getSourceAlignment(); assert(SourceAlignVal && "Missed Source alignment!"); // In a case when alignment of source differs from dest one // least value is guaranteed anyway. AlignVal = std::min(AlignVal, SourceAlignVal); } MemoryAccess.push_back(AlignVal); } if (MI->isVolatile()) MemoryAccess[0] |= MemoryAccessVolatileMask; return MemoryAccess; }; switch (II->getIntrinsicID()) { case Intrinsic::bitreverse: { BM->addCapability(CapabilityShader); SPIRVType *Ty = transType(II->getType()); SPIRVValue *Op = transValue(II->getArgOperand(0), BB); return BM->addUnaryInst(OpBitReverse, Ty, Op, BB); } case Intrinsic::ctlz: case Intrinsic::cttz: { SPIRVWord ExtOp = II->getIntrinsicID() == Intrinsic::ctlz ? OpenCLLIB::Clz : OpenCLLIB::Ctz; SPIRVType *Ty = transType(II->getType()); std::vector Ops(1, transValue(II->getArgOperand(0), BB)); return BM->addExtInst(Ty, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp, Ops, BB); } case Intrinsic::fmuladd: { // For llvm.fmuladd.* fusion is not guaranteed. If a fused multiply-add // is required the corresponding llvm.fma.* intrinsic function should be // used instead. BB->getParent()->setContractedFMulAddFound(); SPIRVType *Ty = transType(II->getType()); SPIRVValue *Mul = BM->addBinaryInst(OpFMul, Ty, transValue(II->getArgOperand(0), BB), transValue(II->getArgOperand(1), BB), BB); return BM->addBinaryInst(OpFAdd, Ty, Mul, transValue(II->getArgOperand(2), BB), BB); } case Intrinsic::memset: { // Generally memset can't be translated with current version of SPIRV spec. // But in most cases it turns out that memset is emited by Clang to do // zero-initializtion in default constructors. // The code below handles only cases with val = 0 and constant len. MemSetInst *MSI = cast(II); Value *Val = MSI->getValue(); if (!isa(Val)) { assert(!"Can't translate llvm.memset with non-const `value` argument"); return nullptr; } if (!cast(Val)->isZeroValue()) { assert(!"Can't translate llvm.memset with non-zero `value` argument"); return nullptr; } Value *Len = MSI->getLength(); if (!isa(Len)) { assert(!"Can't translate llvm.memset with non-const `length` argument"); return nullptr; } uint64_t NumElements = static_cast(Len)->getZExtValue(); auto *AT = ArrayType::get(Val->getType(), NumElements); SPIRVTypeArray *CompositeTy = static_cast(transType(AT)); SPIRVValue *Init = BM->addNullConstant(CompositeTy); SPIRVType *VarTy = transType(PointerType::get(AT, SPIRV::SPIRAS_Constant)); SPIRVValue *Var = BM->addVariable(VarTy, /*isConstant*/ true, spv::LinkageTypeInternal, Init, "", StorageClassUniformConstant, nullptr); SPIRVType *SourceTy = transType(PointerType::get(Val->getType(), SPIRV::SPIRAS_Constant)); SPIRVValue *Source = BM->addUnaryInst(OpBitcast, SourceTy, Var, BB); SPIRVValue *Target = transValue(MSI->getRawDest(), BB); return BM->addCopyMemorySizedInst(Target, Source, CompositeTy->getLength(), GetMemoryAccess(MSI), BB); } break; case Intrinsic::memcpy: return BM->addCopyMemorySizedInst( transValue(II->getOperand(0), BB), transValue(II->getOperand(1), BB), transValue(II->getOperand(2), BB), GetMemoryAccess(cast(II)), BB); case Intrinsic::lifetime_start: case Intrinsic::lifetime_end: { Op OC = (II->getIntrinsicID() == Intrinsic::lifetime_start) ? OpLifetimeStart : OpLifetimeStop; int64_t Size = dyn_cast(II->getOperand(0))->getSExtValue(); if (Size == -1) Size = 0; return BM->addLifetimeInst(OC, transValue(II->getOperand(1), BB), Size, BB); } // We don't want to mix translation of regular code and debug info, because // it creates a mess, therefore translation of debug intrinsics is // postponed until LLVMToSPIRVDbgTran::finalizeDebug...() methods. case Intrinsic::dbg_declare: return DbgTran->createDebugDeclarePlaceholder(cast(II), BB); case Intrinsic::dbg_value: return DbgTran->createDebugValuePlaceholder(cast(II), BB); case Intrinsic::annotation: { SPIRVType *Ty = transType(II->getType()); GetElementPtrInst *GEP = dyn_cast(II->getArgOperand(1)); if (!GEP) return nullptr; Constant *C = cast(GEP->getOperand(0)); StringRef AnnotationString; getConstantStringInfo(C, AnnotationString); if (AnnotationString == kOCLBuiltinName::FPGARegIntel) { if (BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_fpga_reg)) return BM->addFPGARegINTELInst(Ty, transValue(II->getOperand(0), BB), BB); else return transValue(II->getOperand(0), BB); } return nullptr; } case Intrinsic::var_annotation: { SPIRVValue *SV; if (auto *BI = dyn_cast(II->getArgOperand(0))) { SV = transValue(BI->getOperand(0), BB); } else { SV = transValue(II->getOperand(0), BB); } GetElementPtrInst *GEP = cast(II->getArgOperand(1)); Constant *C = cast(GEP->getOperand(0)); StringRef AnnotationString; getConstantStringInfo(C, AnnotationString); std::vector> Decorations; if (BB->getModule()->isAllowedToUseExtension( ExtensionID::SPV_INTEL_fpga_memory_attributes)) // If it is allowed, let's try to parse annotation string to find // IntelFPGA-specific decorations Decorations = tryParseIntelFPGAAnnotationString(AnnotationString); // If we didn't find any IntelFPGA-specific decorations, let's add the whole // annotation string as UserSemantic Decoration if (Decorations.empty()) { SV->addDecorate(new SPIRVDecorateUserSemanticAttr(SV, AnnotationString)); } else { addIntelFPGADecorations(SV, Decorations); } return SV; } case Intrinsic::ptr_annotation: { GetElementPtrInst *GEP = dyn_cast(II->getArgOperand(1)); Constant *C = dyn_cast(GEP->getOperand(0)); StringRef AnnotationString; getConstantStringInfo(C, AnnotationString); // Strip all bitcast and addrspace casts from the pointer argument: // llvm annotation intrinsic only takes i8*, so the original pointer // probably had to loose its addrspace and its original type. Value *AnnotSubj = II->getArgOperand(0); while (isa(AnnotSubj) || isa(AnnotSubj)) { AnnotSubj = cast(AnnotSubj)->getOperand(0); } // If the pointer is a GEP, then we have to emit a member decoration if (auto *GI = dyn_cast(AnnotSubj)) { auto *Ty = transType(GI->getSourceElementType()); SPIRVWord MemberNumber = dyn_cast(GI->getOperand(2))->getZExtValue(); std::vector> Decorations; if (BB->getModule()->isAllowedToUseExtension( ExtensionID::SPV_INTEL_fpga_memory_attributes)) // If it is allowed, let's try to parse annotation string to find // IntelFPGA-specific decorations Decorations = tryParseIntelFPGAAnnotationString(AnnotationString); // If we didn't find any IntelFPGA-specific decorations, let's add the // whole annotation string as UserSemantic Decoration if (Decorations.empty()) { Ty->addMemberDecorate(new SPIRVMemberDecorateUserSemanticAttr( Ty, MemberNumber, AnnotationString)); } else { addIntelFPGADecorationsForStructMember(Ty, MemberNumber, Decorations); } II->replaceAllUsesWith(II->getOperand(0)); } else { auto *Ty = transType(II->getType()); auto *BI = dyn_cast(II->getOperand(0)); if (AnnotationString == kOCLBuiltinName::FPGARegIntel) { if (BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_fpga_reg)) return BM->addFPGARegINTELInst(Ty, transValue(BI, BB), BB); else return transValue(BI, BB); } } return 0; } // We can just ignore/drop some intrinsics, like optimizations hint. case Intrinsic::invariant_start: case Intrinsic::invariant_end: case Intrinsic::dbg_label: return nullptr; default: // Other LLVM intrinsics shouldn't get to SPIRV, because they // can't be represented in SPIRV or not implemented yet. BM->getErrorLog().checkError(false, SPIRVEC_InvalidFunctionCall, II->getCalledValue()->getName().str(), "", __FILE__, __LINE__); } return nullptr; } SPIRVValue *LLVMToSPIRV::transCallInst(CallInst *CI, SPIRVBasicBlock *BB) { assert(CI); if (isa(CI->getCalledOperand()) && BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_inline_assembly)) return transAsmCallINTEL(CI, BB); if (CI->isIndirectCall()) return transIndirectCallInst(CI, BB); return transDirectCallInst(CI, BB); } SPIRVValue *LLVMToSPIRV::transDirectCallInst(CallInst *CI, SPIRVBasicBlock *BB) { SPIRVExtInstSetKind ExtSetKind = SPIRVEIS_Count; SPIRVWord ExtOp = SPIRVWORD_MAX; llvm::Function *F = CI->getCalledFunction(); auto MangledName = F->getName(); std::string DemangledName; if (MangledName.startswith(SPCV_CAST) || MangledName == SAMPLER_INIT) return oclTransSpvcCastSampler(CI, BB); if (oclIsBuiltin(MangledName, &DemangledName) || isDecoratedSPIRVFunc(F, &DemangledName)) if (auto BV = transBuiltinToInst(DemangledName, MangledName, CI, BB)) return BV; SmallVector Dec; if (isBuiltinTransToExtInst(CI->getCalledFunction(), &ExtSetKind, &ExtOp, &Dec)) return addDecorations( BM->addExtInst( transType(CI->getType()), BM->getExtInstSetId(ExtSetKind), ExtOp, transArguments(CI, BB, SPIRVEntry::createUnique(ExtSetKind, ExtOp).get()), BB), Dec); return BM->addCallInst( transFunctionDecl(CI->getCalledFunction()), transArguments(CI, BB, SPIRVEntry::createUnique(OpFunctionCall).get()), BB); } SPIRVValue *LLVMToSPIRV::transIndirectCallInst(CallInst *CI, SPIRVBasicBlock *BB) { if (!BM->checkExtension(ExtensionID::SPV_INTEL_function_pointers, SPIRVEC_FunctionPointers, toString(CI))) return nullptr; return BM->addIndirectCallInst( transValue(CI->getCalledValue(), BB), transType(CI->getType()), transArguments(CI, BB, SPIRVEntry::createUnique(OpFunctionCall).get()), BB); } SPIRVValue *LLVMToSPIRV::transAsmINTEL(InlineAsm *IA) { assert(IA); // TODO: intention here is to provide information about actual target // but in fact spir-64 is substituted as triple when translator works // eventually we need to fix it (not urgent) StringRef TripleStr(M->getTargetTriple()); auto AsmTarget = static_cast( BM->getOrAddAsmTargetINTEL(TripleStr.str())); auto SIA = BM->addAsmINTEL( static_cast(transType(IA->getFunctionType())), AsmTarget, IA->getAsmString(), IA->getConstraintString()); if (IA->hasSideEffects()) SIA->addDecorate(DecorationSideEffectsINTEL); return SIA; } SPIRVValue *LLVMToSPIRV::transAsmCallINTEL(CallInst *CI, SPIRVBasicBlock *BB) { assert(CI); auto IA = cast(CI->getCalledOperand()); return BM->addAsmCallINTELInst( static_cast(transValue(IA, BB, false)), transArguments(CI, BB, SPIRVEntry::createUnique(OpAsmCallINTEL).get()), BB); } bool LLVMToSPIRV::transAddressingMode() { Triple TargetTriple(M->getTargetTriple()); if (TargetTriple.isArch32Bit()) BM->setAddressingModel(AddressingModelPhysical32); else BM->setAddressingModel(AddressingModelPhysical64); // Physical addressing model requires Addresses capability BM->addCapability(CapabilityAddresses); return true; } std::vector LLVMToSPIRV::transValue(const std::vector &Args, SPIRVBasicBlock *BB) { std::vector BArgs; for (auto &I : Args) BArgs.push_back(transValue(I, BB)); return BArgs; } std::vector LLVMToSPIRV::transValue(const std::vector &Args, SPIRVBasicBlock *BB, SPIRVEntry *Entry) { std::vector Operands; for (size_t I = 0, E = Args.size(); I != E; ++I) { Operands.push_back(Entry->isOperandLiteral(I) ? cast(Args[I])->getZExtValue() : transValue(Args[I], BB)->getId()); } return Operands; } std::vector LLVMToSPIRV::transArguments(CallInst *CI, SPIRVBasicBlock *BB, SPIRVEntry *Entry) { return transValue(getArguments(CI), BB, Entry); } SPIRVWord LLVMToSPIRV::transFunctionControlMask(Function *F) { SPIRVWord FCM = 0; SPIRSPIRVFuncCtlMaskMap::foreach ( [&](Attribute::AttrKind Attr, SPIRVFunctionControlMaskKind Mask) { if (F->hasFnAttribute(Attr)) FCM |= Mask; }); return FCM; } void LLVMToSPIRV::transGlobalAnnotation(GlobalVariable *V) { SPIRVDBG(dbgs() << "[transGlobalAnnotation] " << *V << '\n'); // @llvm.global.annotations is an array that contains structs with 4 fields. // Get the array of structs with metadata ConstantArray *CA = cast(V->getOperand(0)); for (Value *Op : CA->operands()) { ConstantStruct *CS = cast(Op); // The first field of the struct contains a pointer to annotated variable Value *AnnotatedVar = CS->getOperand(0)->stripPointerCasts(); SPIRVValue *SV = transValue(AnnotatedVar, nullptr); // The second field contains a pointer to a global annotation string GlobalVariable *GV = cast(CS->getOperand(1)->stripPointerCasts()); StringRef AnnotationString; getConstantStringInfo(GV, AnnotationString); std::vector> Decorations; if (BM->isAllowedToUseExtension( ExtensionID::SPV_INTEL_fpga_memory_attributes)) Decorations = tryParseIntelFPGAAnnotationString(AnnotationString); // If we didn't find any IntelFPGA-specific decorations, let's // add the whole annotation string as UserSemantic Decoration if (Decorations.empty()) { SV->addDecorate(new SPIRVDecorateUserSemanticAttr(SV, AnnotationString)); } else { addIntelFPGADecorations(SV, Decorations); } } } bool LLVMToSPIRV::transGlobalVariables() { for (auto I = M->global_begin(), E = M->global_end(); I != E; ++I) { if ((*I).getName() == "llvm.global.annotations") transGlobalAnnotation(&(*I)); else if (!transValue(&(*I), nullptr)) return false; } return true; } bool LLVMToSPIRV::isAnyFunctionReachableFromFunction( const Function *FS, const std::unordered_set Funcs) const { std::unordered_set Done; std::unordered_set ToDo; ToDo.insert(FS); while (!ToDo.empty()) { auto It = ToDo.begin(); const Function *F = *It; if (Funcs.find(F) != Funcs.end()) return true; ToDo.erase(It); Done.insert(F); const CallGraphNode *FN = (*CG)[F]; for (unsigned I = 0; I < FN->size(); ++I) { const CallGraphNode *NN = (*FN)[I]; const Function *NNF = NN->getFunction(); if (!NNF) continue; if (Done.find(NNF) == Done.end()) { ToDo.insert(NNF); } } } return false; } void LLVMToSPIRV::collectInputOutputVariables(SPIRVFunction *SF, Function *F) { for (auto &GV : M->globals()) { const auto AS = GV.getAddressSpace(); if (AS != SPIRAS_Input && AS != SPIRAS_Output) continue; std::unordered_set Funcs; for (const auto &U : GV.uses()) { const Instruction *Inst = dyn_cast(U.getUser()); if (!Inst) continue; Funcs.insert(Inst->getFunction()); } if (isAnyFunctionReachableFromFunction(F, Funcs)) { SF->addVariable(ValueMap[&GV]); } } } void LLVMToSPIRV::mutateFuncArgType( const std::map &ChangedType, Function *F) { for (auto &I : ChangedType) { for (auto UI = F->user_begin(), UE = F->user_end(); UI != UE; ++UI) { auto Call = dyn_cast(*UI); if (!Call) continue; auto Arg = Call->getArgOperand(I.first); auto OrigTy = Arg->getType(); if (OrigTy == I.second) continue; SPIRVDBG(dbgs() << "[mutate arg type] " << *Call << ", " << *Arg << '\n'); auto CastF = M->getOrInsertFunction(SPCV_CAST, I.second, OrigTy); std::vector Args; Args.push_back(Arg); auto Cast = CallInst::Create(CastF, Args, "", Call); Call->replaceUsesOfWith(Arg, Cast); SPIRVDBG(dbgs() << "[mutate arg type] -> " << *Cast << '\n'); } } } void LLVMToSPIRV::transFunction(Function *I) { SPIRVFunction *BF = transFunctionDecl(I); // Creating all basic blocks before creating any instruction. for (auto &FI : *I) { transValue(&FI, nullptr); } for (auto &FI : *I) { SPIRVBasicBlock *BB = static_cast(transValue(&FI, nullptr)); for (auto &BI : FI) { transValue(&BI, BB, false); } } if (BF->getModule()->isEntryPoint(spv::ExecutionModelKernel, BF->getId()) && BF->shouldFPContractBeDisabled()) { BF->addExecutionMode(BF->getModule()->add( new SPIRVExecutionMode(BF, spv::ExecutionModeContractionOff))); } if (BF->getModule()->isEntryPoint(spv::ExecutionModelKernel, BF->getId())) { collectInputOutputVariables(BF, I); } } bool LLVMToSPIRV::translate() { BM->setGeneratorVer(KTranslatorVer); if (!transSourceLanguage()) return false; if (!transExtension()) return false; if (!transBuiltinSet()) return false; if (!transAddressingMode()) return false; if (!transGlobalVariables()) return false; for (auto &F : *M) { auto FT = F.getFunctionType(); std::map ChangedType; oclGetMutatedArgumentTypesByBuiltin(FT, ChangedType, &F); mutateFuncArgType(ChangedType, &F); } // SPIR-V logical layout requires all function declarations go before // function definitions. std::vector Decls, Defs; for (auto &F : *M) { if (isBuiltinTransToInst(&F) || isBuiltinTransToExtInst(&F) || F.getName().startswith(SPCV_CAST) || F.getName().startswith(LLVM_MEMCPY) || F.getName().startswith(SAMPLER_INIT)) continue; if (F.isDeclaration()) Decls.push_back(&F); else Defs.push_back(&F); } for (auto I : Decls) transFunctionDecl(I); for (auto I : Defs) transFunction(I); if (!transOCLKernelMetadata()) return false; if (!transExecutionMode()) return false; BM->optimizeDecorates(); BM->resolveUnknownStructFields(); BM->createForwardPointers(); DbgTran->transDebugMetadata(); return true; } llvm::IntegerType *LLVMToSPIRV::getSizetType(unsigned AS) { return IntegerType::getIntNTy(M->getContext(), M->getDataLayout().getPointerSizeInBits(AS)); } void LLVMToSPIRV::oclGetMutatedArgumentTypesByBuiltin( llvm::FunctionType *FT, std::map &ChangedType, Function *F) { auto Name = F->getName(); std::string Demangled; if (!oclIsBuiltin(Name, &Demangled)) return; if (Demangled.find(kSPIRVName::SampledImage) == std::string::npos) return; if (FT->getParamType(1)->isIntegerTy()) ChangedType[1] = getSamplerType(F->getParent()); } SPIRVInstruction * LLVMToSPIRV::transBuiltinToInst(const std::string &DemangledName, const std::string &MangledName, CallInst *CI, SPIRVBasicBlock *BB) { SmallVector Dec; auto OC = getSPIRVFuncOC(DemangledName, &Dec); if (OC == OpNop) return nullptr; if (OpReadPipeBlockingINTEL <= OC && OC <= OpWritePipeBlockingINTEL && !BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_blocking_pipes)) return nullptr; auto Inst = transBuiltinToInstWithoutDecoration(OC, CI, BB); addDecorations(Inst, Dec); return Inst; } bool LLVMToSPIRV::transExecutionMode() { if (auto NMD = SPIRVMDWalker(*M).getNamedMD(kSPIRVMD::ExecutionMode)) { while (!NMD.atEnd()) { unsigned EMode = ~0U; Function *F = nullptr; auto N = NMD.nextOp(); /* execution mode MDNode */ N.get(F).get(EMode); SPIRVFunction *BF = static_cast(getTranslatedValue(F)); assert(BF && "Invalid kernel function"); if (!BF) return false; switch (EMode) { case spv::ExecutionModeContractionOff: case spv::ExecutionModeInitializer: case spv::ExecutionModeFinalizer: BF->addExecutionMode(BM->add( new SPIRVExecutionMode(BF, static_cast(EMode)))); break; case spv::ExecutionModeLocalSize: case spv::ExecutionModeLocalSizeHint: { unsigned X, Y, Z; N.get(X).get(Y).get(Z); BF->addExecutionMode(BM->add(new SPIRVExecutionMode( BF, static_cast(EMode), X, Y, Z))); } break; case spv::ExecutionModeMaxWorkgroupSizeINTEL: { if (BM->isAllowedToUseExtension( ExtensionID::SPV_INTEL_kernel_attributes)) { unsigned X, Y, Z; N.get(X).get(Y).get(Z); BF->addExecutionMode(BM->add(new SPIRVExecutionMode( BF, static_cast(EMode), X, Y, Z))); BM->addCapability(CapabilityKernelAttributesINTEL); } } break; case spv::ExecutionModeVecTypeHint: case spv::ExecutionModeSubgroupSize: case spv::ExecutionModeSubgroupsPerWorkgroup: { unsigned X; N.get(X); BF->addExecutionMode(BM->add( new SPIRVExecutionMode(BF, static_cast(EMode), X))); } break; case spv::ExecutionModeNumSIMDWorkitemsINTEL: { if (BM->isAllowedToUseExtension( ExtensionID::SPV_INTEL_kernel_attributes)) { unsigned X; N.get(X); BF->addExecutionMode(BM->add(new SPIRVExecutionMode( BF, static_cast(EMode), X))); BM->addCapability(CapabilityFPGAKernelAttributesINTEL); } } break; case spv::ExecutionModeMaxWorkDimINTEL: { if (BM->isAllowedToUseExtension( ExtensionID::SPV_INTEL_kernel_attributes)) { unsigned X; N.get(X); BF->addExecutionMode(BM->add(new SPIRVExecutionMode( BF, static_cast(EMode), X))); BM->addCapability(CapabilityFPGAKernelAttributesINTEL); } } break; default: llvm_unreachable("invalid execution mode"); } } } return true; } bool LLVMToSPIRV::transOCLKernelMetadata() { for (auto &F : *M) { if (F.getCallingConv() != CallingConv::SPIR_KERNEL) continue; SPIRVFunction *BF = static_cast(getTranslatedValue(&F)); assert(BF && "Kernel function should be translated first"); // Create 'OpString' as a workaround to store information about // *orignal* (typedef'ed, unsigned integers) type names of kernel arguments. // OpString "kernel_arg_type.%kernel_name%.typename0,typename1,..." if (auto *KernelArgType = F.getMetadata(SPIR_MD_KERNEL_ARG_TYPE)) { std::string KernelArgTypesStr = std::string(SPIR_MD_KERNEL_ARG_TYPE) + "." + F.getName().str() + "."; for (const auto &TyOp : KernelArgType->operands()) KernelArgTypesStr += cast(TyOp)->getString().str() + ","; BM->getString(KernelArgTypesStr); } if (auto *KernelArgTypeQual = F.getMetadata(SPIR_MD_KERNEL_ARG_TYPE_QUAL)) { foreachKernelArgMD( KernelArgTypeQual, BF, [](const std::string &Str, SPIRVFunctionParameter *BA) { if (Str.find("volatile") != std::string::npos) BA->addDecorate(new SPIRVDecorate(DecorationVolatile, BA)); if (Str.find("restrict") != std::string::npos) BA->addDecorate( new SPIRVDecorate(DecorationFuncParamAttr, BA, FunctionParameterAttributeNoAlias)); if (Str.find("const") != std::string::npos) BA->addDecorate( new SPIRVDecorate(DecorationFuncParamAttr, BA, FunctionParameterAttributeNoWrite)); }); } if (auto *KernelArgName = F.getMetadata(SPIR_MD_KERNEL_ARG_NAME)) { foreachKernelArgMD( KernelArgName, BF, [=](const std::string &Str, SPIRVFunctionParameter *BA) { BM->setName(BA, Str); }); } } return true; } bool LLVMToSPIRV::transSourceLanguage() { auto Src = getSPIRVSource(M); SrcLang = std::get<0>(Src); SrcLangVer = std::get<1>(Src); BM->setSourceLanguage(static_cast(SrcLang), SrcLangVer); return true; } bool LLVMToSPIRV::transExtension() { if (auto N = SPIRVMDWalker(*M).getNamedMD(kSPIRVMD::Extension)) { while (!N.atEnd()) { std::string S; N.nextOp().get(S); assert(!S.empty() && "Invalid extension"); BM->getExtension().insert(S); } } if (auto N = SPIRVMDWalker(*M).getNamedMD(kSPIRVMD::SourceExtension)) { while (!N.atEnd()) { std::string S; N.nextOp().get(S); assert(!S.empty() && "Invalid extension"); BM->getSourceExtension().insert(S); } } for (auto &I : map(rmap(BM->getExtension()))) BM->addCapability(I); return true; } void LLVMToSPIRV::dumpUsers(Value *V) { SPIRVDBG(dbgs() << "Users of " << *V << " :\n"); for (auto UI = V->user_begin(), UE = V->user_end(); UI != UE; ++UI) SPIRVDBG(dbgs() << " " << **UI << '\n'); } Op LLVMToSPIRV::transBoolOpCode(SPIRVValue *Opn, Op OC) { if (!Opn->getType()->isTypeVectorOrScalarBool()) return OC; IntBoolOpMap::find(OC, &OC); return OC; } SPIRVInstruction * LLVMToSPIRV::transBuiltinToInstWithoutDecoration(Op OC, CallInst *CI, SPIRVBasicBlock *BB) { if (isGroupOpCode(OC)) BM->addCapability(CapabilityGroups); switch (OC) { case OpControlBarrier: { auto BArgs = transValue(getArguments(CI), BB); return BM->addControlBarrierInst(BArgs[0], BArgs[1], BArgs[2], BB); } break; case OpGroupAsyncCopy: { auto BArgs = transValue(getArguments(CI), BB); return BM->addAsyncGroupCopy(BArgs[0], BArgs[1], BArgs[2], BArgs[3], BArgs[4], BArgs[5], BB); } break; case OpSelect: { auto BArgs = transValue(getArguments(CI), BB); return BM->addSelectInst(BArgs[0], BArgs[1], BArgs[2], BB); } case OpSampledImage: { // Clang can generate SPIRV-friendly call for OpSampledImage instruction, // i.e. __spirv_SampledImage... But it can't generate correct return type // for this call, because there is no support for type corresponding to // OpTypeSampledImage. So, in this case, we create the required type here. Value *Image = CI->getArgOperand(0); Type *ImageTy = Image->getType(); if (isOCLImageType(ImageTy)) ImageTy = getSPIRVImageTypeFromOCL(M, ImageTy); Type *SampledImgTy = getSPIRVTypeByChangeBaseTypeName( M, ImageTy, kSPIRVTypeName::Image, kSPIRVTypeName::SampledImg); Value *Sampler = CI->getArgOperand(1); return BM->addSampledImageInst(transType(SampledImgTy), transValue(Image, BB), transValue(Sampler, BB), BB); } default: { if (isCvtOpCode(OC) && OC != OpGenericCastToPtrExplicit) { return BM->addUnaryInst(OC, transType(CI->getType()), transValue(CI->getArgOperand(0), BB), BB); } else if (isCmpOpCode(OC)) { assert(CI && CI->getNumArgOperands() == 2 && "Invalid call inst"); auto ResultTy = CI->getType(); Type *BoolTy = IntegerType::getInt1Ty(M->getContext()); auto IsVector = ResultTy->isVectorTy(); if (IsVector) BoolTy = VectorType::get(BoolTy, ResultTy->getVectorNumElements()); auto BBT = transType(BoolTy); auto Cmp = BM->addCmpInst(OC, BBT, transValue(CI->getArgOperand(0), BB), transValue(CI->getArgOperand(1), BB), BB); // OpenCL C and OpenCL C++ built-ins may have different return type if (ResultTy == BoolTy) return Cmp; assert(IsVector || (!IsVector && ResultTy->isIntegerTy(32))); auto Zero = transValue(Constant::getNullValue(ResultTy), BB); auto One = transValue( IsVector ? Constant::getAllOnesValue(ResultTy) : getInt32(M, 1), BB); return BM->addSelectInst(Cmp, One, Zero, BB); } else if (isBinaryOpCode(OC)) { assert(CI && CI->getNumArgOperands() == 2 && "Invalid call inst"); return BM->addBinaryInst(OC, transType(CI->getType()), transValue(CI->getArgOperand(0), BB), transValue(CI->getArgOperand(1), BB), BB); } else if (CI->getNumArgOperands() == 1 && !CI->getType()->isVoidTy() && !hasExecScope(OC) && !isAtomicOpCode(OC)) { return BM->addUnaryInst(OC, transType(CI->getType()), transValue(CI->getArgOperand(0), BB), BB); } else { auto Args = getArguments(CI); SPIRVType *SPRetTy = nullptr; Type *RetTy = CI->getType(); auto F = CI->getCalledFunction(); if (!RetTy->isVoidTy()) { SPRetTy = transType(RetTy); } else if (Args.size() > 0 && F->arg_begin()->hasStructRetAttr()) { SPRetTy = transType(F->arg_begin()->getType()->getPointerElementType()); Args.erase(Args.begin()); } auto SPI = BM->addInstTemplate(OC, BB, SPRetTy); std::vector SPArgs; for (size_t I = 0, E = Args.size(); I != E; ++I) { assert((!isFunctionPointerType(Args[I]->getType()) || isa(Args[I])) && "Invalid function pointer argument"); SPArgs.push_back(SPI->isOperandLiteral(I) ? cast(Args[I])->getZExtValue() : transValue(Args[I], BB)->getId()); } SPI->setOpWordsAndValidate(SPArgs); if (!SPRetTy || !SPRetTy->isTypeStruct()) return SPI; std::vector Mem; SPIRVDBG(spvdbgs() << *SPI << '\n'); return BM->addStoreInst(transValue(CI->getArgOperand(0), BB), SPI, Mem, BB); } } } return nullptr; } SPIRV::SPIRVLinkageTypeKind LLVMToSPIRV::transLinkageType(const GlobalValue *GV) { if (GV->isDeclarationForLinker()) return SPIRVLinkageTypeKind::LinkageTypeImport; if (GV->hasInternalLinkage() || GV->hasPrivateLinkage()) return SPIRVLinkageTypeKind::LinkageTypeInternal; return SPIRVLinkageTypeKind::LinkageTypeExport; } } // namespace SPIRV char LLVMToSPIRV::ID = 0; INITIALIZE_PASS_BEGIN(LLVMToSPIRV, "llvmtospv", "Translate LLVM to SPIR-V", false, false) INITIALIZE_PASS_DEPENDENCY(OCLTypeToSPIRV) INITIALIZE_PASS_END(LLVMToSPIRV, "llvmtospv", "Translate LLVM to SPIR-V", false, false) ModulePass *llvm::createLLVMToSPIRV(SPIRVModule *SMod) { return new LLVMToSPIRV(SMod); } void addPassesForSPIRV(legacy::PassManager &PassMgr) { if (SPIRVMemToReg) PassMgr.add(createPromoteMemoryToRegisterPass()); PassMgr.add(createPreprocessMetadata()); PassMgr.add(createOCL21ToSPIRV()); PassMgr.add(createSPIRVLowerSPIRBlocks()); PassMgr.add(createOCLTypeToSPIRV()); PassMgr.add(createSPIRVLowerOCLBlocks()); PassMgr.add(createOCL20ToSPIRV()); PassMgr.add(createSPIRVRegularizeLLVM()); PassMgr.add(createSPIRVLowerConstExpr()); PassMgr.add(createSPIRVLowerBool()); PassMgr.add(createSPIRVLowerMemmove()); } bool isValidLLVMModule(Module *M, SPIRVErrorLog &ErrorLog) { if (!M) return false; Triple TT(M->getTargetTriple()); if (!ErrorLog.checkError(isSupportedTriple(TT), SPIRVEC_InvalidTargetTriple, "Actual target triple is " + M->getTargetTriple())) return false; return true; } bool llvm::writeSpirv(Module *M, std::ostream &OS, std::string &ErrMsg) { SPIRV::TranslatorOpts DefaultOpts; // To preserve old behavior of the translator, let's enable all extensions // by default in this API DefaultOpts.enableAllExtensions(); return llvm::writeSpirv(M, DefaultOpts, OS, ErrMsg); } bool llvm::writeSpirv(Module *M, const SPIRV::TranslatorOpts &Opts, std::ostream &OS, std::string &ErrMsg) { std::unique_ptr BM(SPIRVModule::createSPIRVModule(Opts)); if (!isValidLLVMModule(M, BM->getErrorLog())) return false; legacy::PassManager PassMgr; addPassesForSPIRV(PassMgr); // Run loop simplify pass in order to avoid duplicate OpLoopMerge // instruction. It can happen in case of continue operand in the loop. if (hasLoopMetadata(M)) PassMgr.add(createLoopSimplifyPass()); PassMgr.add(createLLVMToSPIRV(BM.get())); PassMgr.run(*M); if (BM->getError(ErrMsg) != SPIRVEC_Success) return false; OS << *BM; return true; } bool llvm::regularizeLlvmForSpirv(Module *M, std::string &ErrMsg) { std::unique_ptr BM(SPIRVModule::createSPIRVModule()); if (!isValidLLVMModule(M, BM->getErrorLog())) return false; legacy::PassManager PassMgr; addPassesForSPIRV(PassMgr); PassMgr.run(*M); return true; } SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVWriter.h000066400000000000000000000171311363521741200213230ustar00rootroot00000000000000//===- SPIRVWriter.h - Converts LLVM to SPIR-V ------------------*- C++ -*-===// // // The LLVM/SPIR-V Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file contains declaration of LLVMToSPIRV class which implements /// conversion of LLVM intermediate language to SPIR-V /// binary. /// //===----------------------------------------------------------------------===// #ifndef SPIRVWRITER_H #define SPIRVWRITER_H #include "OCLTypeToSPIRV.h" #include "OCLUtil.h" #include "SPIRVBasicBlock.h" #include "SPIRVEntry.h" #include "SPIRVEnum.h" #include "SPIRVFunction.h" #include "SPIRVInstruction.h" #include "SPIRVModule.h" #include "SPIRVType.h" #include "SPIRVValue.h" #include "llvm/Analysis/CallGraph.h" #include "llvm/IR/IntrinsicInst.h" #include using namespace llvm; using namespace SPIRV; using namespace OCLUtil; namespace SPIRV { class LLVMToSPIRVDbgTran; class LLVMToSPIRV : public ModulePass { public: LLVMToSPIRV(SPIRVModule *SMod = nullptr); virtual StringRef getPassName() const override { return "LLVMToSPIRV"; } bool runOnModule(Module &Mod) override; void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired(); } static char ID; SPIRVType *transType(Type *T); SPIRVType *transSPIRVOpaqueType(Type *T); SPIRVValue *getTranslatedValue(const Value *) const; // Translation functions bool transAddressingMode(); bool transAlign(Value *V, SPIRVValue *BV); std::vector transArguments(CallInst *, SPIRVBasicBlock *, SPIRVEntry *); bool transSourceLanguage(); bool transExtension(); bool transBuiltinSet(); SPIRVValue *transIntrinsicInst(IntrinsicInst *Intrinsic, SPIRVBasicBlock *BB); SPIRVValue *transCallInst(CallInst *Call, SPIRVBasicBlock *BB); SPIRVValue *transDirectCallInst(CallInst *Call, SPIRVBasicBlock *BB); SPIRVValue *transIndirectCallInst(CallInst *Call, SPIRVBasicBlock *BB); SPIRVValue *transAsmINTEL(InlineAsm *Asm); SPIRVValue *transAsmCallINTEL(CallInst *Call, SPIRVBasicBlock *BB); bool transDecoration(Value *V, SPIRVValue *BV); SPIRVWord transFunctionControlMask(Function *); SPIRVFunction *transFunctionDecl(Function *F); bool transGlobalVariables(); Op transBoolOpCode(SPIRVValue *Opn, Op OC); // Translate LLVM module to SPIR-V module. // Returns true if succeeds. bool translate(); bool transExecutionMode(); SPIRVValue *transConstant(Value *V); SPIRVValue *transValue(Value *V, SPIRVBasicBlock *BB, bool CreateForward = true); void transGlobalAnnotation(GlobalVariable *V); SPIRVValue *transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB, bool CreateForward = true); typedef DenseMap LLVMToSPIRVTypeMap; typedef DenseMap LLVMToSPIRVValueMap; typedef DenseMap LLVMToSPIRVMetadataMap; private: Module *M; LLVMContext *Ctx; SPIRVModule *BM; LLVMToSPIRVTypeMap TypeMap; LLVMToSPIRVValueMap ValueMap; LLVMToSPIRVMetadataMap IndexGroupArrayMap; SPIRVWord SrcLang; SPIRVWord SrcLangVer; std::unique_ptr DbgTran; std::unique_ptr CG; SPIRVType *mapType(Type *T, SPIRVType *BT); SPIRVValue *mapValue(Value *V, SPIRVValue *BV); SPIRVType *getSPIRVType(Type *T) { return TypeMap[T]; } SPIRVErrorLog &getErrorLog() { return BM->getErrorLog(); } llvm::IntegerType *getSizetType(unsigned AS = 0); std::vector transValue(const std::vector &Values, SPIRVBasicBlock *BB); std::vector transValue(const std::vector &Values, SPIRVBasicBlock *BB, SPIRVEntry *Entry); SPIRVInstruction *transBinaryInst(BinaryOperator *B, SPIRVBasicBlock *BB); SPIRVInstruction *transCmpInst(CmpInst *Cmp, SPIRVBasicBlock *BB); SPIRVInstruction *transLifetimeIntrinsicInst(Op OC, IntrinsicInst *Intrinsic, SPIRVBasicBlock *BB); void dumpUsers(Value *V); template bool oclGetExtInstIndex(const std::string &MangledName, const std::string &DemangledName, SPIRVWord *EntryPoint); void oclGetMutatedArgumentTypesByBuiltin(llvm::FunctionType *FT, std::map &ChangedType, Function *F); bool isBuiltinTransToInst(Function *F); bool isBuiltinTransToExtInst(Function *F, SPIRVExtInstSetKind *BuiltinSet = nullptr, SPIRVWord *EntryPoint = nullptr, SmallVectorImpl *Dec = nullptr); bool oclIsKernel(Function *F); bool transOCLKernelMetadata(); SPIRVInstruction *transBuiltinToInst(const std::string &DemangledName, const std::string &MangledName, CallInst *CI, SPIRVBasicBlock *BB); SPIRVInstruction *transBuiltinToInstWithoutDecoration(Op OC, CallInst *CI, SPIRVBasicBlock *BB); void mutateFuncArgType(const std::map &ChangedType, Function *F); SPIRVValue *transSpcvCast(CallInst *CI, SPIRVBasicBlock *BB); SPIRVValue *oclTransSpvcCastSampler(CallInst *CI, SPIRVBasicBlock *BB); SPIRV::SPIRVInstruction *transUnaryInst(UnaryInstruction *U, SPIRVBasicBlock *BB); void transFunction(Function *I); SPIRV::SPIRVLinkageTypeKind transLinkageType(const GlobalValue *GV); bool isAnyFunctionReachableFromFunction( const Function *FS, const std::unordered_set Funcs) const; void collectInputOutputVariables(SPIRVFunction *SF, Function *F); }; } // namespace SPIRV #endif // SPIRVWRITER_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVWriterPass.cpp000066400000000000000000000027031363521741200225040ustar00rootroot00000000000000//===- SPIRVWriterPass.cpp - SPIRV writing pass -----------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // SPIRVWriterPass implementation. // //===----------------------------------------------------------------------===// #include "SPIRVWriterPass.h" #include "LLVMSPIRVLib.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassManager.h" #include "llvm/Pass.h" using namespace llvm; PreservedAnalyses SPIRVWriterPass::run(Module &M) { // FIXME: at the moment LLVM/SPIR-V translation errors are ignored. std::string Err; writeSpirv(&M, OS, Err); return PreservedAnalyses::all(); } namespace { class WriteSPIRVPass : public ModulePass { std::ostream &OS; // std::ostream to print on public: static char ID; // Pass identification, replacement for typeid explicit WriteSPIRVPass(std::ostream &O) : ModulePass(ID), OS(O) {} StringRef getPassName() const override { return "SPIRV Writer"; } bool runOnModule(Module &M) override { // FIXME: at the moment LLVM/SPIR-V translation errors are ignored. std::string Err; writeSpirv(&M, OS, Err); return false; } }; } // namespace char WriteSPIRVPass::ID = 0; ModulePass *llvm::createSPIRVWriterPass(std::ostream &Str) { return new WriteSPIRVPass(Str); } SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/SPIRVWriterPass.h000066400000000000000000000027701363521741200221550ustar00rootroot00000000000000//===------ SPIRVWriterPass.h - SPIRV writing pass --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// \file /// /// This file provides a SPIRV writing pass. /// //===----------------------------------------------------------------------===// #ifndef SPIRV_SPIRVWRITERPASS_H #define SPIRV_SPIRVWRITERPASS_H #include "llvm/ADT/StringRef.h" namespace llvm { class Module; class ModulePass; class PreservedAnalyses; /// \brief Create and return a pass that writes the module to the specified /// ostream. Note that this pass is designed for use with the legacy pass /// manager. ModulePass *createSPIRVWriterPass(std::ostream &Str); /// \brief Pass for writing a module of IR out to a SPIRV file. /// /// Note that this is intended for use with the new pass manager. To construct /// a pass for the legacy pass manager, use the function above. class SPIRVWriterPass { std::ostream &OS; public: /// \brief Construct a SPIRV writer pass around a particular output stream. explicit SPIRVWriterPass(std::ostream &OS) : OS(OS) {} /// \brief Run the SPIRV writer pass, and output the module to the selected /// output stream. PreservedAnalyses run(Module &M); static StringRef name() { return "SPIRVWriterPass"; } }; } // namespace llvm #endif // SPIRV_SPIRVWRITERPASS_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/000077500000000000000000000000001363521741200204415ustar00rootroot00000000000000SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/OpenCL.std.h000066400000000000000000000117051363521741200225270ustar00rootroot00000000000000/* ** Copyright (c) 2015 The Khronos Group Inc. ** ** Permission is hereby granted, free of charge, to any person obtaining a copy ** of this software and/or associated documentation files (the "Materials"), ** to deal in the Materials without restriction, including without limitation ** the rights to use, copy, modify, merge, publish, distribute, sublicense, ** and/or sell copies of the Materials, and to permit persons to whom the ** Materials are furnished to do so, subject to the following conditions: ** ** The above copyright notice and this permission notice shall be included in ** all copies or substantial portions of the Materials. ** ** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS ** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND ** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ ** ** THE MATERIALS ARE 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 AUTHORS 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 MATERIALS OR THE USE OR OTHER DEALINGS ** IN THE MATERIALS. */ // // Author: Boaz Ouriel, Intel // namespace OpenCLLIB { enum Entrypoints { // math functions Acos = 0, Acosh = 1, Acospi = 2, Asin = 3, Asinh = 4, Asinpi = 5, Atan = 6, Atan2 = 7, Atanh = 8, Atanpi = 9, Atan2pi = 10, Cbrt = 11, Ceil = 12, Copysign = 13, Cos = 14, Cosh = 15, Cospi = 16, Erfc = 17, Erf = 18, Exp = 19, Exp2 = 20, Exp10 = 21, Expm1 = 22, Fabs = 23, Fdim = 24, Floor = 25, Fma = 26, Fmax = 27, Fmin = 28, Fmod = 29, Fract = 30, Frexp = 31, Hypot = 32, Ilogb = 33, Ldexp = 34, Lgamma = 35, Lgamma_r = 36, Log = 37, Log2 = 38, Log10 = 39, Log1p = 40, Logb = 41, Mad = 42, Maxmag = 43, Minmag = 44, Modf = 45, Nan = 46, Nextafter = 47, Pow = 48, Pown = 49, Powr = 50, Remainder = 51, Remquo = 52, Rint = 53, Rootn = 54, Round = 55, Rsqrt = 56, Sin = 57, Sincos = 58, Sinh = 59, Sinpi = 60, Sqrt = 61, Tan = 62, Tanh = 63, Tanpi = 64, Tgamma = 65, Trunc = 66, Half_cos = 67, Half_divide = 68, Half_exp = 69, Half_exp2 = 70, Half_exp10 = 71, Half_log = 72, Half_log2 = 73, Half_log10 = 74, Half_powr = 75, Half_recip = 76, Half_rsqrt = 77, Half_sin = 78, Half_sqrt = 79, Half_tan = 80, Native_cos = 81, Native_divide = 82, Native_exp = 83, Native_exp2 = 84, Native_exp10 = 85, Native_log = 86, Native_log2 = 87, Native_log10 = 88, Native_powr = 89, Native_recip = 90, Native_rsqrt = 91, Native_sin = 92, Native_sqrt = 93, Native_tan = 94, // Common FClamp = 95, Degrees = 96, FMax_common = 97, FMin_common = 98, Mix = 99, Radians = 100, Step = 101, Smoothstep = 102, Sign = 103, // Geometrics Cross = 104, Distance = 105, Length = 106, Normalize = 107, Fast_distance = 108, Fast_length = 109, Fast_normalize = 110, // Integers SAbs = 141, SAbs_diff = 142, SAdd_sat = 143, UAdd_sat = 144, SHadd = 145, UHadd = 146, SRhadd = 147, URhadd = 148, SClamp = 149, UClamp = 150, Clz = 151, Ctz = 152, SMad_hi = 153, UMad_sat = 154, SMad_sat = 155, SMax = 156, UMax = 157, SMin = 158, UMin = 159, SMul_hi = 160, Rotate = 161, SSub_sat = 162, USub_sat = 163, U_Upsample = 164, S_Upsample = 165, Popcount = 166, SMad24 = 167, UMad24 = 168, SMul24 = 169, UMul24 = 170, // Vector Loads/Stores Vloadn = 171, Vstoren = 172, Vload_half = 173, Vload_halfn = 174, Vstore_half = 175, Vstore_half_r = 176, Vstore_halfn = 177, Vstore_halfn_r = 178, Vloada_halfn = 179, Vstorea_halfn = 180, Vstorea_halfn_r = 181, // Vector Misc Shuffle = 182, Shuffle2 = 183, // Printf = 184, Prefetch = 185, // Relationals Bitselect = 186, Select = 187, // pipes Read_pipe = 188, Write_pipe = 189, Reserve_read_pipe = 190, Reserve_write_pipe = 191, Commit_read_pipe = 192, Commit_write_pipe = 193, Is_valid_reserve_id = 194, Work_group_reserve_read_pipe = 195, Work_group_reserve_write_pipe = 196, Work_group_commit_read_pipe = 197, Work_group_commit_write_pipe = 198, Get_pipe_num_packets = 199, Get_pipe_max_packets = 200, // more integers UAbs = 201, UAbs_diff = 202, UMul_hi = 203, UMad_hi = 204, }; } // end namespace OpenCL20 SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRV.debug.h000066400000000000000000000255261363521741200226140ustar00rootroot00000000000000#ifndef SPIRV_DEBUG_H #define SPIRV_DEBUG_H #include "SPIRVUtil.h" #include "llvm/BinaryFormat/Dwarf.h" namespace SPIRVDebug { const unsigned int DebugInfoVersion = 0x00010000; // clang-format off enum Instruction { DebugInfoNone = 0, CompilationUnit = 1, TypeBasic = 2, TypePointer = 3, TypeQualifier = 4, TypeArray = 5, TypeVector = 6, Typedef = 7, TypeFunction = 8, TypeEnum = 9, TypeComposite = 10, TypeMember = 11, Inheritance = 12, TypePtrToMember = 13, TypeTemplate = 14, TypeTemplateParameter = 15, TypeTemplateParameterPack = 16, TypeTemplateTemplateParameter = 17, GlobalVariable = 18, FunctionDecl = 19, Function = 20, LexicalBlock = 21, LexicalBlockDiscriminator = 22, Scope = 23, NoScope = 24, InlinedAt = 25, LocalVariable = 26, InlinedVariable = 27, Declare = 28, Value = 29, Operation = 30, Expression = 31, MacroDef = 32, MacroUndef = 33, ImportedEntity = 34, Source = 35, InstCount = 36 }; enum Flag { FlagIsPrivate = 1 << 0, FlagIsProtected = 1 << 1, FlagIsPublic = FlagIsPrivate | FlagIsProtected, FlagAccess = FlagIsPublic, FlagIsLocal = 1 << 2, FlagIsDefinition = 1 << 3, FlagIsFwdDecl = 1 << 4, FlagIsArtificial = 1 << 5, FlagIsExplicit = 1 << 6, FlagIsPrototyped = 1 << 7, FlagIsObjectPointer = 1 << 8, FlagIsStaticMember = 1 << 9, FlagIsIndirectVariable = 1 << 10, FlagIsLValueReference = 1 << 11, FlagIsRValueReference = 1 << 12, FlagIsOptimized = 1 << 13, FlagIsEnumClass = 1 << 14, FlagTypePassByValue = 1 << 15, FlagTypePassByReference = 1 << 16, }; enum EncodingTag { Unspecified = 0, Address = 1, Boolean = 2, Float = 3, Signed = 4, SignedChar = 5, Unsigned = 6, UnsignedChar = 7 }; enum CompositeTypeTag { Class = 0, Structure = 1, Union = 2 }; enum TypeQualifierTag { ConstType = 0, VolatileType = 1, RestrictType = 2, AtomicType = 3 }; enum ExpressionOpCode { Deref = 0, Plus = 1, Minus = 2, PlusUconst = 3, BitPiece = 4, Swap = 5, Xderef = 6, StackValue = 7, Constu = 8, Fragment = 9 }; enum ImportedEntityTag { ImportedModule = 0, ImportedDeclaration = 1, }; namespace Operand { namespace CompilationUnit { enum { SPIRVDebugInfoVersionIdx = 0, DWARFVersionIdx = 1, SourceIdx = 2, LanguageIdx = 3, OperandCount = 4 }; } namespace Source { enum { FileIdx = 0, TextIdx = 1, OperandCount = 2 }; } namespace TypeBasic { enum { NameIdx = 0, SizeIdx = 1, EncodingIdx = 2, OperandCount = 3 }; } namespace TypePointer { enum { BaseTypeIdx = 0, StorageClassIdx = 1, FlagsIdx = 2, OperandCount = 3 }; } namespace TypeQualifier { enum { BaseTypeIdx = 0, QualifierIdx = 1, OperandCount = 2 }; } namespace TypeArray { enum { BaseTypeIdx = 0, ComponentCountIdx = 1, MinOperandCount = 2 }; } namespace TypeVector = TypeArray; namespace Typedef { enum { NameIdx = 0, BaseTypeIdx = 1, SourceIdx = 2, LineIdx = 3, ColumnIdx = 4, ParentIdx = 5, OperandCount = 6 }; } namespace TypeFunction { enum { FlagsIdx = 0, ReturnTypeIdx = 1, FirstParameterIdx = 2, MinOperandCount = 2 }; } namespace TypeEnum { enum { NameIdx = 0, UnderlyingTypeIdx = 1, SourceIdx = 2, LineIdx = 3, ColumnIdx = 4, ParentIdx = 5, SizeIdx = 6, FlagsIdx = 7, FirstEnumeratorIdx = 8, MinOperandCount = 8 }; } namespace TypeComposite { enum { NameIdx = 0, TagIdx = 1, SourceIdx = 2, LineIdx = 3, ColumnIdx = 4, ParentIdx = 5, LinkageNameIdx = 6, SizeIdx = 7, FlagsIdx = 8, FirstMemberIdx = 9, MinOperandCount = 9 }; } namespace TypeMember { enum { NameIdx = 0, TypeIdx = 1, SourceIdx = 2, LineIdx = 3, ColumnIdx = 4, ParentIdx = 5, OffsetIdx = 6, SizeIdx = 7, FlagsIdx = 8, ValueIdx = 9, MinOperandCount = 9 }; } namespace TypeInheritance { enum { ChildIdx = 0, ParentIdx = 1, OffsetIdx = 2, SizeIdx = 3, FlagsIdx = 4, OperandCount = 5 }; } namespace PtrToMember { enum { MemberTypeIdx = 0, ParentIdx = 1, OperandCount = 2 }; } namespace Template { enum { TargetIdx = 0, FirstParameterIdx = 1, MinOperandCount = 1 }; } namespace TemplateParameter { enum { NameIdx = 0, TypeIdx = 1, ValueIdx = 2, SourceIdx = 3, LineIdx = 4, ColumnIdx = 5, OperandCount = 6 }; } namespace TemplateTemplateParameter { enum { NameIdx = 0, TemplateNameIdx = 1, SourceIdx = 2, LineIdx = 3, ColumnIdx = 4, OperandCount = 5 }; } namespace TemplateParameterPack { enum { NameIdx = 0, SourceIdx = 1, LineIdx = 2, ColumnIdx = 3, FirstParameterIdx = 4, MinOperandCount = 4 }; } namespace GlobalVariable { enum { NameIdx = 0, TypeIdx = 1, SourceIdx = 2, LineIdx = 3, ColumnIdx = 4, ParentIdx = 5, LinkageNameIdx = 6, VariableIdx = 7, FlagsIdx = 8, StaticMemberDeclarationIdx = 9, MinOperandCount = 9 }; } namespace FunctionDeclaration { enum { NameIdx = 0, TypeIdx = 1, SourceIdx = 2, LineIdx = 3, ColumnIdx = 4, ParentIdx = 5, LinkageNameIdx = 6, FlagsIdx = 7, OperandCount = 8 }; } namespace Function { enum { NameIdx = 0, TypeIdx = 1, SourceIdx = 2, LineIdx = 3, ColumnIdx = 4, ParentIdx = 5, LinkageNameIdx = 6, FlagsIdx = 7, ScopeLineIdx = 8, FunctionIdIdx = 9, DeclarationIdx = 10, MinOperandCount = 10 }; } namespace LexicalBlock { enum { SourceIdx = 0, LineIdx = 1, ColumnIdx = 2, ParentIdx = 3, NameIdx = 4, MinOperandCount = 4 }; } namespace LexicalBlockDiscriminator { enum { SourceIdx = 0, DiscriminatorIdx = 1, ParentIdx = 2, OperandCount = 3 }; } namespace Scope { enum { ScopeIdx = 0, InlinedAtIdx = 1, MinOperandCount = 1 }; } namespace NoScope { // No operands } namespace InlinedAt { enum { LineIdx = 0, ScopeIdx = 1, InlinedIdx = 2, MinOperandCount = 2 }; } namespace LocalVariable { enum { NameIdx = 0, TypeIdx = 1, SourceIdx = 2, LineIdx = 3, ColumnIdx = 4, ParentIdx = 5, FlagsIdx = 6, ArgNumberIdx = 7, MinOperandCount = 7 }; } namespace InlinedVariable { enum { VariableIdx = 0, InlinedIdx = 1, OperandCount = 2 }; } namespace DebugDeclare { enum { DebugLocalVarIdx = 0, VariableIdx = 1, ExpressionIdx = 2, OperandCount = 3 }; } namespace DebugValue { enum { DebugLocalVarIdx = 0, ValueIdx = 1, ExpressionIdx = 2, FirstIndexOperandIdx = 3, MinOperandCount = 3 }; } namespace Operation { enum { OpCodeIdx = 0 }; static std::map OpCountMap { { Deref, 1 }, { Plus, 1 }, { Minus, 1 }, { PlusUconst, 2 }, { BitPiece, 3 }, { Swap, 1 }, { Xderef, 1 }, { StackValue, 1 }, { Constu, 2 }, { Fragment, 3 } }; } namespace ImportedEntity { enum { NameIdx = 0, TagIdx = 1, SourceIdx = 3, EntityIdx = 4, LineIdx = 5, ColumnIdx = 6, ParentIdx = 7, OperandCount = 8 }; } } // namespace Operand } // namespace SPIRVDebug using namespace llvm; namespace SPIRV { typedef SPIRVMap DbgEncodingMap; template <> inline void DbgEncodingMap::init() { add(static_cast(0), SPIRVDebug::Unspecified); add(dwarf::DW_ATE_address, SPIRVDebug::Address); add(dwarf::DW_ATE_boolean, SPIRVDebug::Boolean); add(dwarf::DW_ATE_float, SPIRVDebug::Float); add(dwarf::DW_ATE_signed, SPIRVDebug::Signed); add(dwarf::DW_ATE_signed_char, SPIRVDebug::SignedChar); add(dwarf::DW_ATE_unsigned, SPIRVDebug::Unsigned); add(dwarf::DW_ATE_unsigned_char, SPIRVDebug::UnsignedChar); } typedef SPIRVMap DbgTypeQulifierMap; template <> inline void DbgTypeQulifierMap::init() { add(dwarf::DW_TAG_const_type, SPIRVDebug::ConstType); add(dwarf::DW_TAG_volatile_type, SPIRVDebug::VolatileType); add(dwarf::DW_TAG_restrict_type, SPIRVDebug::RestrictType); add(dwarf::DW_TAG_atomic_type, SPIRVDebug::AtomicType); } typedef SPIRVMap DbgCompositeTypeMap; template <> inline void DbgCompositeTypeMap::init() { add(dwarf::DW_TAG_class_type, SPIRVDebug::Class); add(dwarf::DW_TAG_structure_type, SPIRVDebug::Structure); add(dwarf::DW_TAG_union_type, SPIRVDebug::Union); } typedef SPIRVMap DbgExpressionOpCodeMap; template <> inline void DbgExpressionOpCodeMap::init() { add(dwarf::DW_OP_deref, SPIRVDebug::Deref); add(dwarf::DW_OP_plus, SPIRVDebug::Plus); add(dwarf::DW_OP_minus, SPIRVDebug::Minus); add(dwarf::DW_OP_plus_uconst, SPIRVDebug::PlusUconst); add(dwarf::DW_OP_bit_piece, SPIRVDebug::BitPiece); add(dwarf::DW_OP_swap, SPIRVDebug::Swap); add(dwarf::DW_OP_xderef, SPIRVDebug::Xderef); add(dwarf::DW_OP_stack_value, SPIRVDebug::StackValue); add(dwarf::DW_OP_constu, SPIRVDebug::Constu); add(dwarf::DW_OP_LLVM_fragment, SPIRVDebug::Fragment); } typedef SPIRVMap DbgImportedEntityMap; template <> inline void DbgImportedEntityMap::init() { add(dwarf::DW_TAG_imported_module, SPIRVDebug::ImportedModule); add(dwarf::DW_TAG_imported_declaration, SPIRVDebug::ImportedDeclaration); } } // namespace SPIRV #endif // SPIRV_DEBUG_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVAsm.h000066400000000000000000000111631363521741200221600ustar00rootroot00000000000000//===- SPIRVAsm.h - --*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines the inline assembler entries defined in SPIRV spec with op /// codes. /// //===----------------------------------------------------------------------===// #ifndef SPIRV_LIBSPIRV_SPIRVASM_H #define SPIRV_LIBSPIRV_SPIRVASM_H #include "SPIRVEntry.h" #include "SPIRVInstruction.h" #include "SPIRVValue.h" namespace SPIRV { class SPIRVAsmTargetINTEL : public SPIRVEntry { public: static const SPIRVWord FixedWC = 2; static const Op OC = OpAsmTargetINTEL; // Complete constructor SPIRVAsmTargetINTEL(SPIRVModule *M, SPIRVId TheId, const std::string &TheTarget) : SPIRVEntry(M, FixedWC + getSizeInWords(TheTarget), OC, TheId), Target(TheTarget) { validate(); } // Incomplete constructor SPIRVAsmTargetINTEL() : SPIRVEntry(OC) {} SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilityAsmINTEL); } SPIRVExtSet getRequiredExtensions() const override { return getSet(ExtensionID::SPV_INTEL_inline_assembly); } const std::string &getTarget() const { return Target; } protected: void validate() const override { SPIRVEntry::validate(); assert(WordCount > FixedWC); assert(OpCode == OC); } _SPIRV_DEF_ENCDEC2(Id, Target) std::string Target; }; class SPIRVAsmINTEL : public SPIRVValue { public: static const SPIRVWord FixedWC = 5; static const Op OC = OpAsmINTEL; // Complete constructor SPIRVAsmINTEL(SPIRVModule *M, SPIRVTypeFunction *TheFunctionType, SPIRVId TheId, SPIRVAsmTargetINTEL *TheTarget, const std::string &TheInstructions, const std::string &TheConstraints) : SPIRVValue(M, FixedWC + getSizeInWords(TheInstructions) + getSizeInWords(TheConstraints), OC, TheFunctionType->getReturnType(), TheId), Target(TheTarget), FunctionType(TheFunctionType), Instructions(TheInstructions), Constraints(TheConstraints) { validate(); } // Incomplete constructor SPIRVAsmINTEL() : SPIRVValue(OC) {} SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilityAsmINTEL); } SPIRVExtSet getRequiredExtensions() const override { return getSet(ExtensionID::SPV_INTEL_inline_assembly); } const std::string &getInstructions() const { return Instructions; } const std::string &getConstraints() const { return Constraints; } SPIRVTypeFunction *getFunctionType() const { return FunctionType; } protected: _SPIRV_DEF_ENCDEC6(Type, Id, FunctionType, Target, Instructions, Constraints) void validate() const override { SPIRVValue::validate(); assert(WordCount > FixedWC); assert(OpCode == OC); } SPIRVAsmTargetINTEL *Target; SPIRVTypeFunction *FunctionType; std::string Instructions; std::string Constraints; }; class SPIRVAsmCallINTEL : public SPIRVInstruction { public: static const SPIRVWord FixedWC = 4; static const Op OC = OpAsmCallINTEL; // Complete constructor SPIRVAsmCallINTEL(SPIRVId TheId, SPIRVAsmINTEL *TheAsm, const std::vector &TheArgs, SPIRVBasicBlock *TheBB) : SPIRVInstruction(FixedWC + TheArgs.size(), OC, TheAsm->getType(), TheId, TheBB), Asm(TheAsm), Args(TheArgs) { validate(); } // Incomplete constructor SPIRVAsmCallINTEL() : SPIRVInstruction(OC) {} SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilityAsmINTEL); } SPIRVExtSet getRequiredExtensions() const override { return getSet(ExtensionID::SPV_INTEL_inline_assembly); } bool isOperandLiteral(unsigned int Index) const override { return false; } void setWordCount(SPIRVWord TheWordCount) override { SPIRVEntry::setWordCount(TheWordCount); Args.resize(TheWordCount - FixedWC); } const std::vector &getArguments() const { return Args; } SPIRVAsmINTEL *getAsm() const { return Asm; } protected: _SPIRV_DEF_ENCDEC4(Type, Id, Asm, Args) void validate() const override { SPIRVInstruction::validate(); assert(WordCount >= FixedWC); assert(OpCode == OC); assert(getBasicBlock() && "Invalid BB"); assert(getBasicBlock()->getModule() == Asm->getModule()); } SPIRVAsmINTEL *Asm; std::vector Args; }; } // namespace SPIRV #endif // SPIRV_LIBSPIRV_SPIRVASM_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVBasicBlock.cpp000066400000000000000000000071161363521741200237720ustar00rootroot00000000000000//===- SPIRVBasicBlock.cpp - SPIR-V Basic Block -----------------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file implements SPIRV basic block. /// //===----------------------------------------------------------------------===// #include "SPIRVBasicBlock.h" #include "SPIRVEntry.h" #include "SPIRVFunction.h" #include "SPIRVInstruction.h" #include "SPIRVStream.h" #include "SPIRVValue.h" #include using namespace SPIRV; SPIRVBasicBlock::SPIRVBasicBlock(SPIRVId TheId, SPIRVFunction *Func) : SPIRVValue(Func->getModule(), 2, OpLabel, TheId), ParentF(Func) { setAttr(); validate(); } SPIRVDecoder SPIRVBasicBlock::getDecoder(std::istream &IS) { return SPIRVDecoder(IS, *this); } /// Assume I contains valid Id. SPIRVInstruction * SPIRVBasicBlock::addInstruction(SPIRVInstruction *I, const SPIRVInstruction *InsertBefore) { assert(I && "Invalid instruction"); Module->add(I); I->setParent(this); if (InsertBefore) { auto Pos = find(InsertBefore); // If insertion of a new instruction before the one passed to the function // is illegal, insertion before the returned instruction is guaranteed // to retain correct instruction order in a block if (Pos != InstVec.begin() && (isa(*std::prev(Pos)) || isa(*std::prev(Pos)))) --Pos; InstVec.insert(Pos, I); } else InstVec.push_back(I); return I; } void SPIRVBasicBlock::encodeChildren(spv_ostream &O) const { O << SPIRVNL(); for (size_t I = 0, E = InstVec.size(); I != E; ++I) O << *InstVec[I]; } _SPIRV_IMP_ENCDEC1(SPIRVBasicBlock, Id) void SPIRVBasicBlock::setScope(SPIRVEntry *Scope) { assert(Scope && Scope->getOpCode() == OpFunction && "Invalid scope"); setParent(static_cast(Scope)); } SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVBasicBlock.h000066400000000000000000000104711363521741200234350ustar00rootroot00000000000000//===- SPIRVBasicBlock.h - SPIR-V Basic Block -------------------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines Basic Block class for SPIR-V. /// //===----------------------------------------------------------------------===// #ifndef SPIRV_LIBSPIRV_SPIRVBASICBLOCK_H #define SPIRV_LIBSPIRV_SPIRVBASICBLOCK_H #include "SPIRVValue.h" #include namespace SPIRV { class SPIRVFunction; class SPIRVInstruction; class SPIRVDecoder; class SPIRVBasicBlock : public SPIRVValue { public: SPIRVBasicBlock(SPIRVId TheId, SPIRVFunction *Func); SPIRVBasicBlock() : SPIRVValue(OpLabel), ParentF(NULL) { setAttr(); } SPIRVDecoder getDecoder(std::istream &IS) override; SPIRVFunction *getParent() const { return ParentF; } size_t getNumInst() const { return InstVec.size(); } SPIRVInstruction *getInst(size_t I) const { return InstVec[I]; } SPIRVInstruction *getPrevious(const SPIRVInstruction *I) const { auto Loc = find(I); if (Loc == InstVec.end() || Loc == InstVec.begin()) return nullptr; return *(--Loc); } SPIRVInstruction *getNext(const SPIRVInstruction *I) const { auto Loc = find(I); if (Loc == InstVec.end()) return nullptr; ++Loc; if (Loc == InstVec.end()) return nullptr; return *Loc; } // Return the last instruction in the BB or nullptr if the BB is empty. const SPIRVInstruction *getTerminateInstr() const { return InstVec.empty() ? nullptr : InstVec.back(); } void setScope(SPIRVEntry *Scope) override; void setParent(SPIRVFunction *F) { ParentF = F; } SPIRVInstruction * addInstruction(SPIRVInstruction *I, const SPIRVInstruction *InsertBefore = nullptr); void eraseInstruction(const SPIRVInstruction *I) { auto Loc = find(I); assert(Loc != InstVec.end()); InstVec.erase(Loc); } void setAttr() { setHasNoType(); } _SPIRV_DCL_ENCDEC void encodeChildren(spv_ostream &) const override; void validate() const override { SPIRVValue::validate(); assert(ParentF && "Invalid parent function"); } private: SPIRVFunction *ParentF; typedef std::vector SPIRVInstructionVector; SPIRVInstructionVector InstVec; SPIRVInstructionVector::const_iterator find(const SPIRVInstruction *Inst) const { return std::find(InstVec.begin(), InstVec.end(), Inst); } SPIRVInstructionVector::iterator find(const SPIRVInstruction *Inst) { return std::find(InstVec.begin(), InstVec.end(), Inst); } }; typedef SPIRVBasicBlock SPIRVLabel; } // namespace SPIRV #endif // SPIRV_LIBSPIRV_SPIRVBASICBLOCK_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVDebug.cpp000066400000000000000000000043311363521741200230200ustar00rootroot00000000000000//===- SPIRVDebug.cpp - SPIR-V Debug Utility --------------------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines variables for enabling/disabling SPIR-V debug macro. /// //===----------------------------------------------------------------------===// #include "SPIRVDebug.h" using namespace SPIRV; bool SPIRV::SPIRVDbgEnable = false; bool SPIRV::SPIRVDbgAbortOnError = true; bool SPIRV::SPIRVDbgErrorMsgIncludesSourceInfo = true; SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVDebug.h000066400000000000000000000055351363521741200224740ustar00rootroot00000000000000//===- SPIRVDebug.h - SPIR-V Debug Utility ----------------------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines Macros and variables for debugging SPIRV. /// //===----------------------------------------------------------------------===// #ifndef SPIRV_LIBSPIRV_SPIRVDEBUG_H #define SPIRV_LIBSPIRV_SPIRVDEBUG_H #include "SPIRVUtil.h" #include namespace SPIRV { #define _SPIRVDBG #ifdef _SPIRVDBG #define SPIRVDBG(x) \ if (SPIRVDbgEnable) { \ x; \ } // Enable debug output. extern bool SPIRVDbgEnable; // Include source file and line number in error message. extern bool SPIRVDbgErrorMsgIncludesSourceInfo; // Enable assert on error extern bool SPIRVDbgAbortOnError; // Output stream for SPIRV debug information. inline spv_ostream &spvdbgs() { return std::cerr; } #else #define SPIRVDBG(x) #endif } // namespace SPIRV #endif // SPIRV_LIBSPIRV_SPIRVDEBUG_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVDecorate.cpp000066400000000000000000000214721363521741200235250ustar00rootroot00000000000000//===- SPIRVDecorate.cpp -SPIR-V Decorations --------------------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file implements SPIR-V decorations. /// //===----------------------------------------------------------------------===// #include "SPIRVDecorate.h" #include "SPIRVModule.h" #include "SPIRVStream.h" #include "SPIRVValue.h" namespace SPIRV { template spv_ostream &operator<<(spv_ostream &O, const std::multiset &V) { for (auto &I : V) O << *I; return O; } SPIRVDecorateGeneric::SPIRVDecorateGeneric(Op OC, SPIRVWord WC, Decoration TheDec, SPIRVEntry *TheTarget) : SPIRVAnnotationGeneric(TheTarget->getModule(), WC, OC, TheTarget->getId()), Dec(TheDec), Owner(nullptr) { validate(); updateModuleVersion(); } SPIRVDecorateGeneric::SPIRVDecorateGeneric(Op OC, SPIRVWord WC, Decoration TheDec, SPIRVEntry *TheTarget, SPIRVWord V) : SPIRVAnnotationGeneric(TheTarget->getModule(), WC, OC, TheTarget->getId()), Dec(TheDec), Owner(nullptr) { Literals.push_back(V); validate(); updateModuleVersion(); } SPIRVDecorateGeneric::SPIRVDecorateGeneric(Op OC) : SPIRVAnnotationGeneric(OC), Dec(DecorationRelaxedPrecision), Owner(nullptr) {} Decoration SPIRVDecorateGeneric::getDecorateKind() const { return Dec; } SPIRVWord SPIRVDecorateGeneric::getLiteral(size_t I) const { assert(I <= Literals.size() && "Out of bounds"); return Literals[I]; } std::vector SPIRVDecorateGeneric::getVecLiteral() const { return Literals; } size_t SPIRVDecorateGeneric::getLiteralCount() const { return Literals.size(); } void SPIRVDecorate::encode(spv_ostream &O) const { SPIRVEncoder Encoder = getEncoder(O); Encoder << Target << Dec; switch (Dec) { case DecorationLinkageAttributes: SPIRVDecorateLinkageAttr::encodeLiterals(Encoder, Literals); break; case DecorationMemoryINTEL: SPIRVDecorateMemoryINTELAttr::encodeLiterals(Encoder, Literals); break; case DecorationMergeINTEL: SPIRVDecorateMergeINTELAttr::encodeLiterals(Encoder, Literals); break; case DecorationUserSemantic: SPIRVDecorateUserSemanticAttr::encodeLiterals(Encoder, Literals); break; default: Encoder << Literals; } } void SPIRVDecorate::setWordCount(SPIRVWord Count) { WordCount = Count; Literals.resize(WordCount - FixedWC); } void SPIRVDecorate::decode(std::istream &I) { SPIRVDecoder Decoder = getDecoder(I); Decoder >> Target >> Dec; switch (Dec) { case DecorationLinkageAttributes: SPIRVDecorateLinkageAttr::decodeLiterals(Decoder, Literals); break; case DecorationMemoryINTEL: SPIRVDecorateMemoryINTELAttr::decodeLiterals(Decoder, Literals); break; case DecorationMergeINTEL: SPIRVDecorateMergeINTELAttr::decodeLiterals(Decoder, Literals); break; case DecorationUserSemantic: SPIRVDecorateUserSemanticAttr::decodeLiterals(Decoder, Literals); break; default: Decoder >> Literals; } getOrCreateTarget()->addDecorate(this); } void SPIRVMemberDecorate::encode(spv_ostream &O) const { SPIRVEncoder Encoder = getEncoder(O); Encoder << Target << MemberNumber << Dec; switch (Dec) { case DecorationMemoryINTEL: SPIRVDecorateMemoryINTELAttr::encodeLiterals(Encoder, Literals); break; case DecorationMergeINTEL: SPIRVDecorateMergeINTELAttr::encodeLiterals(Encoder, Literals); break; case DecorationUserSemantic: SPIRVDecorateUserSemanticAttr::encodeLiterals(Encoder, Literals); break; default: Encoder << Literals; } } void SPIRVMemberDecorate::setWordCount(SPIRVWord Count) { WordCount = Count; Literals.resize(WordCount - FixedWC); } void SPIRVMemberDecorate::decode(std::istream &I) { SPIRVDecoder Decoder = getDecoder(I); Decoder >> Target >> MemberNumber >> Dec; switch (Dec) { case DecorationMemoryINTEL: SPIRVDecorateMemoryINTELAttr::decodeLiterals(Decoder, Literals); break; case DecorationMergeINTEL: SPIRVDecorateMergeINTELAttr::decodeLiterals(Decoder, Literals); break; case DecorationUserSemantic: SPIRVDecorateUserSemanticAttr::decodeLiterals(Decoder, Literals); break; default: Decoder >> Literals; } getOrCreateTarget()->addMemberDecorate(this); } void SPIRVDecorationGroup::encode(spv_ostream &O) const { getEncoder(O) << Id; } void SPIRVDecorationGroup::decode(std::istream &I) { getDecoder(I) >> Id; Module->addDecorationGroup(this); } void SPIRVDecorationGroup::encodeAll(spv_ostream &O) const { O << Decorations; SPIRVEntry::encodeAll(O); } void SPIRVGroupDecorateGeneric::encode(spv_ostream &O) const { getEncoder(O) << DecorationGroup << Targets; } void SPIRVGroupDecorateGeneric::decode(std::istream &I) { getDecoder(I) >> DecorationGroup >> Targets; Module->addGroupDecorateGeneric(this); } void SPIRVGroupDecorate::decorateTargets() { for (auto &I : Targets) { auto Target = getOrCreate(I); for (auto &Dec : DecorationGroup->getDecorations()) { assert(Dec->isDecorate()); Target->addDecorate(static_cast(Dec)); } } } void SPIRVGroupMemberDecorate::decorateTargets() { for (auto &I : Targets) { auto Target = getOrCreate(I); for (auto &Dec : DecorationGroup->getDecorations()) { assert(Dec->isMemberDecorate()); Target->addMemberDecorate(static_cast(Dec)); } } } bool SPIRVDecorateGeneric::Comparator:: operator()(const SPIRVDecorateGeneric *A, const SPIRVDecorateGeneric *B) const { auto Action = [=]() { if (A->getOpCode() < B->getOpCode()) return true; if (A->getOpCode() > B->getOpCode()) return false; if (A->getDecorateKind() < B->getDecorateKind()) return true; if (A->getDecorateKind() > B->getDecorateKind()) return false; if (A->getLiteralCount() < B->getLiteralCount()) return true; if (A->getLiteralCount() > B->getLiteralCount()) return false; for (size_t I = 0, E = A->getLiteralCount(); I != E; ++I) { auto EA = A->getLiteral(I); auto EB = B->getLiteral(I); if (EA < EB) return true; if (EA > EB) return false; } return false; }; auto Res = Action(); return Res; } bool operator==(const SPIRVDecorateGeneric &A, const SPIRVDecorateGeneric &B) { if (A.getTargetId() != B.getTargetId()) return false; if (A.getOpCode() != B.getOpCode()) return false; if (B.isMemberDecorate()) { auto &MDA = static_cast(A); auto &MDB = static_cast(B); if (MDA.getMemberNumber() != MDB.getMemberNumber()) return false; } if (A.getDecorateKind() != B.getDecorateKind()) return false; if (A.getLiteralCount() != B.getLiteralCount()) return false; for (size_t I = 0, E = A.getLiteralCount(); I != E; ++I) { auto EA = A.getLiteral(I); auto EB = B.getLiteral(I); if (EA != EB) return false; } return true; } } // namespace SPIRV SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVDecorate.h000066400000000000000000000443561363521741200232000ustar00rootroot00000000000000//===- SPIRVDecorate.h - SPIR-V Decorations ---------------------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines SPIR-V decorations. /// //===----------------------------------------------------------------------===// #ifndef SPIRV_LIBSPIRV_SPIRVDECORATE_H #define SPIRV_LIBSPIRV_SPIRVDECORATE_H #include "SPIRVEntry.h" #include "SPIRVStream.h" #include "SPIRVUtil.h" #include #include #include namespace SPIRV { class SPIRVDecorationGroup; class SPIRVDecorateGeneric : public SPIRVAnnotationGeneric { public: // Complete constructor for decorations without literals SPIRVDecorateGeneric(Op OC, SPIRVWord WC, Decoration TheDec, SPIRVEntry *TheTarget); // Complete constructor for decorations with one word literal SPIRVDecorateGeneric(Op OC, SPIRVWord WC, Decoration TheDec, SPIRVEntry *TheTarget, SPIRVWord V); // Incomplete constructor SPIRVDecorateGeneric(Op OC); SPIRVWord getLiteral(size_t) const; std::vector getVecLiteral() const; Decoration getDecorateKind() const; size_t getLiteralCount() const; /// Compare for kind and literal only. struct Comparator { bool operator()(const SPIRVDecorateGeneric *A, const SPIRVDecorateGeneric *B) const; }; /// Compare kind, literals and target. friend bool operator==(const SPIRVDecorateGeneric &A, const SPIRVDecorateGeneric &B); SPIRVDecorationGroup *getOwner() const { return Owner; } void setOwner(SPIRVDecorationGroup *Owner) { this->Owner = Owner; } SPIRVCapVec getRequiredCapability() const override { return getCapability(Dec); } SPIRVWord getRequiredSPIRVVersion() const override { switch (Dec) { case DecorationSpecId: if (getModule()->hasCapability(CapabilityKernel)) return static_cast(VersionNumber::SPIRV_1_1); else return static_cast(VersionNumber::SPIRV_1_0); case DecorationMaxByteOffset: return static_cast(VersionNumber::SPIRV_1_1); default: return static_cast(VersionNumber::SPIRV_1_0); } } protected: Decoration Dec; std::vector Literals; SPIRVDecorationGroup *Owner; // Owning decorate group }; class SPIRVDecorateSet : public std::multiset { public: typedef std::multiset BaseType; iterator insert(value_type &Dec) { auto ER = BaseType::equal_range(Dec); for (auto I = ER.first, E = ER.second; I != E; ++I) { SPIRVDBG(spvdbgs() << "[compare decorate] " << *Dec << " vs " << **I << " : "); if (**I == *Dec) return I; SPIRVDBG(spvdbgs() << " diff\n"); } SPIRVDBG(spvdbgs() << "[add decorate] " << *Dec << '\n'); return BaseType::insert(Dec); } }; class SPIRVDecorate : public SPIRVDecorateGeneric { public: static const Op OC = OpDecorate; static const SPIRVWord FixedWC = 3; // Complete constructor for decorations without literals SPIRVDecorate(Decoration TheDec, SPIRVEntry *TheTarget) : SPIRVDecorateGeneric(OC, 3, TheDec, TheTarget) {} // Complete constructor for decorations with one word literal SPIRVDecorate(Decoration TheDec, SPIRVEntry *TheTarget, SPIRVWord V) : SPIRVDecorateGeneric(OC, 4, TheDec, TheTarget, V) {} // Incomplete constructor SPIRVDecorate() : SPIRVDecorateGeneric(OC) {} SPIRVExtSet getRequiredExtensions() const override { switch (Dec) { case DecorationNoSignedWrap: case DecorationNoUnsignedWrap: return getSet(ExtensionID::SPV_KHR_no_integer_wrap_decoration); case DecorationRegisterINTEL: case DecorationMemoryINTEL: case DecorationNumbanksINTEL: case DecorationBankwidthINTEL: case DecorationMaxPrivateCopiesINTEL: case DecorationSinglepumpINTEL: case DecorationDoublepumpINTEL: case DecorationMaxReplicatesINTEL: case DecorationSimpleDualPortINTEL: case DecorationMergeINTEL: case DecorationBankBitsINTEL: return getSet(ExtensionID::SPV_INTEL_fpga_memory_attributes); case DecorationReferencedIndirectlyINTEL: return getSet(ExtensionID::SPV_INTEL_function_pointers); default: return SPIRVExtSet(); } } _SPIRV_DCL_ENCDEC void setWordCount(SPIRVWord) override; void validate() const override { SPIRVDecorateGeneric::validate(); assert(WordCount == Literals.size() + FixedWC); } }; class SPIRVDecorateLinkageAttr : public SPIRVDecorate { public: // Complete constructor for LinkageAttributes decorations SPIRVDecorateLinkageAttr(SPIRVEntry *TheTarget, const std::string &Name, SPIRVLinkageTypeKind Kind) : SPIRVDecorate(DecorationLinkageAttributes, TheTarget) { for (auto &I : getVec(Name)) Literals.push_back(I); Literals.push_back(Kind); WordCount += Literals.size(); } // Incomplete constructor SPIRVDecorateLinkageAttr() : SPIRVDecorate() {} std::string getLinkageName() const { return getString(Literals.cbegin(), Literals.cend() - 1); } SPIRVLinkageTypeKind getLinkageType() const { return (SPIRVLinkageTypeKind)Literals.back(); } static void encodeLiterals(SPIRVEncoder &Encoder, const std::vector &Literals) { #ifdef _SPIRV_SUPPORT_TEXT_FMT if (SPIRVUseTextFormat) { Encoder << getString(Literals.cbegin(), Literals.cend() - 1); Encoder.OS << " "; Encoder << (SPIRVLinkageTypeKind)Literals.back(); } else #endif Encoder << Literals; } static void decodeLiterals(SPIRVDecoder &Decoder, std::vector &Literals) { #ifdef _SPIRV_SUPPORT_TEXT_FMT if (SPIRVUseTextFormat) { std::string Name; Decoder >> Name; SPIRVLinkageTypeKind Kind; Decoder >> Kind; std::copy_n(getVec(Name).begin(), Literals.size() - 1, Literals.begin()); Literals.back() = Kind; } else #endif Decoder >> Literals; } }; class SPIRVMemberDecorate : public SPIRVDecorateGeneric { public: static const Op OC = OpMemberDecorate; static const SPIRVWord FixedWC = 4; // Complete constructor for decorations without literals SPIRVMemberDecorate(Decoration TheDec, SPIRVWord Member, SPIRVEntry *TheTarget) : SPIRVDecorateGeneric(OC, 4, TheDec, TheTarget), MemberNumber(Member) {} // Complete constructor for decorations with one word literal SPIRVMemberDecorate(Decoration TheDec, SPIRVWord Member, SPIRVEntry *TheTarget, SPIRVWord V) : SPIRVDecorateGeneric(OC, 5, TheDec, TheTarget, V), MemberNumber(Member) {} // Incomplete constructor SPIRVMemberDecorate() : SPIRVDecorateGeneric(OC), MemberNumber(SPIRVWORD_MAX) {} SPIRVExtSet getRequiredExtensions() const override { switch (Dec) { case DecorationRegisterINTEL: case DecorationMemoryINTEL: case DecorationNumbanksINTEL: case DecorationBankwidthINTEL: case DecorationMaxPrivateCopiesINTEL: case DecorationSinglepumpINTEL: case DecorationDoublepumpINTEL: case DecorationMaxReplicatesINTEL: case DecorationSimpleDualPortINTEL: case DecorationMergeINTEL: case DecorationBankBitsINTEL: return getSet(ExtensionID::SPV_INTEL_fpga_memory_attributes); default: return SPIRVExtSet(); } } SPIRVWord getMemberNumber() const { return MemberNumber; } std::pair getPair() const { return std::make_pair(MemberNumber, Dec); } _SPIRV_DCL_ENCDEC void setWordCount(SPIRVWord) override; void validate() const override { SPIRVDecorateGeneric::validate(); assert(WordCount == Literals.size() + FixedWC); } protected: SPIRVWord MemberNumber; }; class SPIRVDecorationGroup : public SPIRVEntry { public: static const Op OC = OpDecorationGroup; static const SPIRVWord WC = 2; // Complete constructor. Does not populate Decorations. SPIRVDecorationGroup(SPIRVModule *TheModule, SPIRVId TheId) : SPIRVEntry(TheModule, WC, OC, TheId) { validate(); }; // Incomplete constructor SPIRVDecorationGroup() : SPIRVEntry(OC) {} void encodeAll(spv_ostream &O) const override; _SPIRV_DCL_ENCDEC // Move the given decorates to the decoration group void takeDecorates(SPIRVDecorateSet &Decs) { Decorations = std::move(Decs); for (auto &I : Decorations) const_cast(I)->setOwner(this); Decs.clear(); } SPIRVDecorateSet &getDecorations() { return Decorations; } protected: SPIRVDecorateSet Decorations; void validate() const override { assert(OpCode == OC); assert(WordCount == WC); } }; class SPIRVGroupDecorateGeneric : public SPIRVEntryNoIdGeneric { public: static const SPIRVWord FixedWC = 2; // Complete constructor SPIRVGroupDecorateGeneric(Op OC, SPIRVDecorationGroup *TheGroup, const std::vector &TheTargets) : SPIRVEntryNoIdGeneric(TheGroup->getModule(), FixedWC + TheTargets.size(), OC), DecorationGroup(TheGroup), Targets(TheTargets) {} // Incomplete constructor SPIRVGroupDecorateGeneric(Op OC) : SPIRVEntryNoIdGeneric(OC), DecorationGroup(nullptr) {} void setWordCount(SPIRVWord WC) override { SPIRVEntryNoIdGeneric::setWordCount(WC); Targets.resize(WC - FixedWC); } virtual void decorateTargets() = 0; _SPIRV_DCL_ENCDEC protected: SPIRVDecorationGroup *DecorationGroup; std::vector Targets; }; class SPIRVGroupDecorate : public SPIRVGroupDecorateGeneric { public: static const Op OC = OpGroupDecorate; // Complete constructor SPIRVGroupDecorate(SPIRVDecorationGroup *TheGroup, const std::vector &TheTargets) : SPIRVGroupDecorateGeneric(OC, TheGroup, TheTargets) {} // Incomplete constructor SPIRVGroupDecorate() : SPIRVGroupDecorateGeneric(OC) {} void decorateTargets() override; }; class SPIRVGroupMemberDecorate : public SPIRVGroupDecorateGeneric { public: static const Op OC = OpGroupMemberDecorate; // Complete constructor SPIRVGroupMemberDecorate(SPIRVDecorationGroup *TheGroup, const std::vector &TheTargets) : SPIRVGroupDecorateGeneric(OC, TheGroup, TheTargets) {} // Incomplete constructor SPIRVGroupMemberDecorate() : SPIRVGroupDecorateGeneric(OC) {} void decorateTargets() override; }; template class SPIRVDecorateStrAttrBase : public SPIRVDecorate { public: // Complete constructor for decoration with string literal SPIRVDecorateStrAttrBase(SPIRVEntry *TheTarget, const std::string &Str) : SPIRVDecorate(D, TheTarget) { for (auto &I : getVec(Str)) Literals.push_back(I); WordCount += Literals.size(); } // Incomplete constructor SPIRVDecorateStrAttrBase() : SPIRVDecorate() {} static void encodeLiterals(SPIRVEncoder &Encoder, const std::vector &Literals) { #ifdef _SPIRV_SUPPORT_TEXT_FMT if (SPIRVUseTextFormat) { Encoder << getString(Literals.cbegin(), Literals.cend()); } else #endif Encoder << Literals; } static void decodeLiterals(SPIRVDecoder &Decoder, std::vector &Literals) { #ifdef _SPIRV_SUPPORT_TEXT_FMT if (SPIRVUseTextFormat) { std::string Str; Decoder >> Str; std::copy_n(getVec(Str).begin(), Literals.size(), Literals.begin()); } else #endif Decoder >> Literals; } }; class SPIRVDecorateMemoryINTELAttr : public SPIRVDecorateStrAttrBase { public: // Complete constructor for MemoryINTEL decoration SPIRVDecorateMemoryINTELAttr(SPIRVEntry *TheTarget, const std::string &MemoryType) : SPIRVDecorateStrAttrBase(TheTarget, MemoryType) {} }; class SPIRVDecorateUserSemanticAttr : public SPIRVDecorateStrAttrBase { public: // Complete constructor for UserSemantic decoration SPIRVDecorateUserSemanticAttr(SPIRVEntry *TheTarget, const std::string &AnnotateString) : SPIRVDecorateStrAttrBase(TheTarget, AnnotateString) {} }; class SPIRVDecorateMergeINTELAttr : public SPIRVDecorate { public: // Complete constructor for MergeINTEL decoration SPIRVDecorateMergeINTELAttr(SPIRVEntry *TheTarget, const std::string &Name, const std::string &Direction) : SPIRVDecorate(DecorationMergeINTEL, TheTarget) { for (auto &I : getVec(Name)) Literals.push_back(I); for (auto &I : getVec(Direction)) Literals.push_back(I); WordCount += Literals.size(); } static void encodeLiterals(SPIRVEncoder &Encoder, const std::vector &Literals) { #ifdef _SPIRV_SUPPORT_TEXT_FMT if (SPIRVUseTextFormat) { std::string FirstString = getString(Literals.cbegin(), Literals.cend()); Encoder << FirstString; Encoder.OS << " "; Encoder << getString(Literals.cbegin() + getVec(FirstString).size(), Literals.cend()); } else #endif Encoder << Literals; } static void decodeLiterals(SPIRVDecoder &Decoder, std::vector &Literals) { #ifdef _SPIRV_SUPPORT_TEXT_FMT if (SPIRVUseTextFormat) { std::string Name; Decoder >> Name; std::string Direction; Decoder >> Direction; std::string Buf = Name + ':' + Direction; std::copy_n(getVec(Buf).begin(), Literals.size(), Literals.begin()); } else #endif Decoder >> Literals; } }; class SPIRVDecorateBankBitsINTELAttr : public SPIRVDecorate { public: // Complete constructor for BankBitsINTEL decoration SPIRVDecorateBankBitsINTELAttr(SPIRVEntry *TheTarget, const std::vector &TheBits) : SPIRVDecorate(DecorationBankBitsINTEL, TheTarget) { Literals = TheBits; WordCount += Literals.size(); } }; template class SPIRVMemberDecorateStrAttrBase : public SPIRVMemberDecorate { public: // Complete constructor for decoration with string literal SPIRVMemberDecorateStrAttrBase(SPIRVEntry *TheTarget, SPIRVWord MemberNumber, const std::string &Str) : SPIRVMemberDecorate(D, MemberNumber, TheTarget) { for (auto &I : getVec(Str)) Literals.push_back(I); WordCount += Literals.size(); } // Incomplete constructor SPIRVMemberDecorateStrAttrBase() : SPIRVMemberDecorate() {} }; class SPIRVMemberDecorateMemoryINTELAttr : public SPIRVMemberDecorateStrAttrBase { public: // Complete constructor for MemoryINTEL decoration SPIRVMemberDecorateMemoryINTELAttr(SPIRVEntry *TheTarget, SPIRVWord MemberNumber, const std::string &MemoryType) : SPIRVMemberDecorateStrAttrBase(TheTarget, MemberNumber, MemoryType) {} }; class SPIRVMemberDecorateUserSemanticAttr : public SPIRVMemberDecorateStrAttrBase { public: // Complete constructor for UserSemantic decoration SPIRVMemberDecorateUserSemanticAttr(SPIRVEntry *TheTarget, SPIRVWord MemberNumber, const std::string &AnnotateString) : SPIRVMemberDecorateStrAttrBase(TheTarget, MemberNumber, AnnotateString) {} }; class SPIRVMemberDecorateMergeINTELAttr : public SPIRVMemberDecorate { public: // Complete constructor for MergeINTEL decoration SPIRVMemberDecorateMergeINTELAttr(SPIRVEntry *TheTarget, SPIRVWord MemberNumber, const std::string &Name, const std::string &Direction) : SPIRVMemberDecorate(DecorationMergeINTEL, MemberNumber, TheTarget) { for (auto &I : getVec(Name)) Literals.push_back(I); for (auto &I : getVec(Direction)) Literals.push_back(I); WordCount += Literals.size(); } }; class SPIRVMemberDecorateBankBitsINTELAttr : public SPIRVMemberDecorate { public: // Complete constructor for BankBitsINTEL decoration SPIRVMemberDecorateBankBitsINTELAttr(SPIRVEntry *TheTarget, SPIRVWord MemberNumber, const std::vector &TheBits) : SPIRVMemberDecorate(DecorationBankBitsINTEL, MemberNumber, TheTarget) { Literals = TheBits; WordCount += Literals.size(); } }; } // namespace SPIRV #endif // SPIRV_LIBSPIRV_SPIRVDECORATE_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVEntry.cpp000066400000000000000000000467241363521741200231070ustar00rootroot00000000000000//===- SPIRVEntry.cpp - Base Class for SPIR-V Entities ----------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file implements base class for SPIR-V entities. /// //===----------------------------------------------------------------------===// #include "SPIRVEntry.h" #include "SPIRVAsm.h" #include "SPIRVBasicBlock.h" #include "SPIRVDebug.h" #include "SPIRVDecorate.h" #include "SPIRVFunction.h" #include "SPIRVInstruction.h" #include "SPIRVStream.h" #include "SPIRVType.h" #include #include #include #include #include #include using namespace SPIRV; namespace SPIRV { template SPIRVEntry *create() { return new T(); } SPIRVEntry *SPIRVEntry::create(Op OpCode) { typedef SPIRVEntry *(*SPIRVFactoryTy)(); struct TableEntry { Op Opn; SPIRVFactoryTy Factory; operator std::pair() { return std::make_pair(Opn, Factory); } }; static TableEntry Table[] = { #define _SPIRV_OP(x, ...) {Op##x, &SPIRV::create}, #include "SPIRVOpCodeEnum.h" #undef _SPIRV_OP }; typedef std::map OpToFactoryMapTy; static const OpToFactoryMapTy OpToFactoryMap(std::begin(Table), std::end(Table)); OpToFactoryMapTy::const_iterator Loc = OpToFactoryMap.find(OpCode); if (Loc != OpToFactoryMap.end()) return Loc->second(); SPIRVDBG(spvdbgs() << "No factory for OpCode " << (unsigned)OpCode << '\n';) assert(0 && "Not implemented"); return 0; } std::unique_ptr SPIRVEntry::createUnique(Op OC) { return std::unique_ptr(create(OC)); } std::unique_ptr SPIRVEntry::createUnique(SPIRVExtInstSetKind Set, unsigned ExtOp) { return std::unique_ptr(new SPIRVExtInst(Set, ExtOp)); } SPIRVErrorLog &SPIRVEntry::getErrorLog() const { return Module->getErrorLog(); } bool SPIRVEntry::exist(SPIRVId TheId) const { return Module->exist(TheId); } SPIRVEntry *SPIRVEntry::getOrCreate(SPIRVId TheId) const { SPIRVEntry *Entry = nullptr; bool Found = Module->exist(TheId, &Entry); if (!Found) return Module->addForward(TheId, nullptr); return Entry; } SPIRVValue *SPIRVEntry::getValue(SPIRVId TheId) const { return get(TheId); } SPIRVType *SPIRVEntry::getValueType(SPIRVId TheId) const { return get(TheId)->getType(); } SPIRVEncoder SPIRVEntry::getEncoder(spv_ostream &O) const { return SPIRVEncoder(O); } SPIRVDecoder SPIRVEntry::getDecoder(std::istream &I) { return SPIRVDecoder(I, *Module); } void SPIRVEntry::setWordCount(SPIRVWord TheWordCount) { WordCount = TheWordCount; } void SPIRVEntry::setName(const std::string &TheName) { Name = TheName; SPIRVDBG(spvdbgs() << "Set name for obj " << Id << " " << Name << '\n'); } void SPIRVEntry::setModule(SPIRVModule *TheModule) { assert(TheModule && "Invalid module"); if (TheModule == Module) return; assert(Module == NULL && "Cannot change owner of entry"); Module = TheModule; } void SPIRVEntry::encode(spv_ostream &O) const { assert(0 && "Not implemented"); } void SPIRVEntry::encodeName(spv_ostream &O) const { if (!Name.empty()) O << SPIRVName(this, Name); } bool SPIRVEntry::isEndOfBlock() const { switch (OpCode) { case OpBranch: case OpBranchConditional: case OpSwitch: case OpKill: case OpReturn: case OpReturnValue: case OpUnreachable: return true; default: return false; } } void SPIRVEntry::encodeLine(spv_ostream &O) const { if (!Module) return; const std::shared_ptr &CurrLine = Module->getCurrentLine(); if (Line && ((CurrLine && *Line != *CurrLine) || !CurrLine)) { O << *Line; Module->setCurrentLine(Line); } if (isEndOfBlock() || OpCode == OpNoLine) Module->setCurrentLine(nullptr); } void SPIRVEntry::encodeAll(spv_ostream &O) const { encodeLine(O); encodeWordCountOpCode(O); encode(O); encodeChildren(O); } void SPIRVEntry::encodeChildren(spv_ostream &O) const {} void SPIRVEntry::encodeWordCountOpCode(spv_ostream &O) const { #ifdef _SPIRV_SUPPORT_TEXT_FMT if (SPIRVUseTextFormat) { getEncoder(O) << WordCount << OpCode; return; } #endif getEncoder(O) << mkWord(WordCount, OpCode); } // Read words from SPIRV binary and create members for SPIRVEntry. // The word count and op code has already been read before calling this // function for creating the SPIRVEntry. Therefore the input stream only // contains the remaining part of the words for the SPIRVEntry. void SPIRVEntry::decode(std::istream &I) { assert(0 && "Not implemented"); } std::vector SPIRVEntry::getValues(const std::vector &IdVec) const { std::vector ValueVec; for (auto I : IdVec) ValueVec.push_back(getValue(I)); return ValueVec; } std::vector SPIRVEntry::getValueTypes(const std::vector &IdVec) const { std::vector TypeVec; for (auto I : IdVec) TypeVec.push_back(getValue(I)->getType()); return TypeVec; } std::vector SPIRVEntry::getIds(const std::vector ValueVec) const { std::vector IdVec; for (auto I : ValueVec) IdVec.push_back(I->getId()); return IdVec; } SPIRVEntry *SPIRVEntry::getEntry(SPIRVId TheId) const { return Module->getEntry(TheId); } void SPIRVEntry::validateFunctionControlMask(SPIRVWord TheFCtlMask) const { SPIRVCK(isValidFunctionControlMask(TheFCtlMask), InvalidFunctionControlMask, ""); } void SPIRVEntry::validateValues(const std::vector &Ids) const { for (auto I : Ids) getValue(I)->validate(); } void SPIRVEntry::validateBuiltin(SPIRVWord TheSet, SPIRVWord Index) const { assert(TheSet != SPIRVWORD_MAX && Index != SPIRVWORD_MAX && "Invalid builtin"); } void SPIRVEntry::addDecorate(SPIRVDecorate *Dec) { auto Kind = Dec->getDecorateKind(); Decorates.insert(std::make_pair(Dec->getDecorateKind(), Dec)); Module->addDecorate(Dec); if (Kind == spv::DecorationLinkageAttributes) { auto *LinkageAttr = static_cast(Dec); setName(LinkageAttr->getLinkageName()); } SPIRVDBG(spvdbgs() << "[addDecorate] " << *Dec << '\n';) } void SPIRVEntry::addDecorate(Decoration Kind) { addDecorate(new SPIRVDecorate(Kind, this)); } void SPIRVEntry::addDecorate(Decoration Kind, SPIRVWord Literal) { addDecorate(new SPIRVDecorate(Kind, this, Literal)); } void SPIRVEntry::eraseDecorate(Decoration Dec) { Decorates.erase(Dec); } void SPIRVEntry::takeDecorates(SPIRVEntry *E) { Decorates = std::move(E->Decorates); SPIRVDBG(spvdbgs() << "[takeDecorates] " << Id << '\n';) } void SPIRVEntry::setLine(const std::shared_ptr &L) { Line = L; SPIRVDBG(if (L) spvdbgs() << "[setLine] " << *L << '\n';) } void SPIRVEntry::addMemberDecorate(SPIRVMemberDecorate *Dec) { assert(canHaveMemberDecorates() && MemberDecorates.find(Dec->getPair()) == MemberDecorates.end()); MemberDecorates[Dec->getPair()] = Dec; Module->addDecorate(Dec); SPIRVDBG(spvdbgs() << "[addMemberDecorate] " << *Dec << '\n';) } void SPIRVEntry::addMemberDecorate(SPIRVWord MemberNumber, Decoration Kind) { addMemberDecorate(new SPIRVMemberDecorate(Kind, MemberNumber, this)); } void SPIRVEntry::addMemberDecorate(SPIRVWord MemberNumber, Decoration Kind, SPIRVWord Literal) { addMemberDecorate(new SPIRVMemberDecorate(Kind, MemberNumber, this, Literal)); } void SPIRVEntry::eraseMemberDecorate(SPIRVWord MemberNumber, Decoration Dec) { MemberDecorates.erase(std::make_pair(MemberNumber, Dec)); } void SPIRVEntry::takeMemberDecorates(SPIRVEntry *E) { MemberDecorates = std::move(E->MemberDecorates); SPIRVDBG(spvdbgs() << "[takeMemberDecorates] " << Id << '\n';) } void SPIRVEntry::takeAnnotations(SPIRVForward *E) { Module->setName(this, E->getName()); takeDecorates(E); takeMemberDecorates(E); if (OpCode == OpFunction) static_cast(this)->takeExecutionModes(E); } // Check if an entry has Kind of decoration and get the literal of the // first decoration of such kind at Index. bool SPIRVEntry::hasDecorate(Decoration Kind, size_t Index, SPIRVWord *Result) const { DecorateMapType::const_iterator Loc = Decorates.find(Kind); if (Loc == Decorates.end()) return false; if (Result) *Result = Loc->second->getLiteral(Index); return true; } // Check if an entry member has Kind of decoration and get the literal of the // first decoration of such kind at Index. bool SPIRVEntry::hasMemberDecorate(Decoration Kind, size_t Index, SPIRVWord MemberNumber, SPIRVWord *Result) const { auto Loc = MemberDecorates.find({MemberNumber, Kind}); if (Loc == MemberDecorates.end()) return false; if (Result) *Result = Loc->second->getLiteral(Index); return true; } std::vector SPIRVEntry::getDecorationStringLiteral(Decoration Kind) const { auto Loc = Decorates.find(Kind); if (Loc == Decorates.end()) return {}; return getVecString(Loc->second->getVecLiteral()); } std::vector SPIRVEntry::getMemberDecorationStringLiteral(Decoration Kind, SPIRVWord MemberNumber) const { auto Loc = MemberDecorates.find({MemberNumber, Kind}); if (Loc == MemberDecorates.end()) return {}; return getVecString(Loc->second->getVecLiteral()); } std::vector SPIRVEntry::getDecorationLiterals(Decoration Kind) const { auto Loc = Decorates.find(Kind); if (Loc == Decorates.end()) return {}; return (Loc->second->getVecLiteral()); } std::vector SPIRVEntry::getMemberDecorationLiterals(Decoration Kind, SPIRVWord MemberNumber) const { auto Loc = MemberDecorates.find({MemberNumber, Kind}); if (Loc == MemberDecorates.end()) return {}; return (Loc->second->getVecLiteral()); } // Get literals of all decorations of Kind at Index. std::set SPIRVEntry::getDecorate(Decoration Kind, size_t Index) const { auto Range = Decorates.equal_range(Kind); std::set Value; for (auto I = Range.first, E = Range.second; I != E; ++I) { assert(Index < I->second->getLiteralCount() && "Invalid index"); Value.insert(I->second->getLiteral(Index)); } return Value; } bool SPIRVEntry::hasLinkageType() const { return OpCode == OpFunction || OpCode == OpVariable; } bool SPIRVEntry::isExtInst(const SPIRVExtInstSetKind InstSet) const { if (isExtInst()) { const SPIRVExtInst *EI = static_cast(this); return EI->getExtSetKind() == InstSet; } return false; } bool SPIRVEntry::isExtInst(const SPIRVExtInstSetKind InstSet, const SPIRVWord ExtOp) const { if (isExtInst()) { const SPIRVExtInst *EI = static_cast(this); if (EI->getExtSetKind() == InstSet) { return EI->getExtOp() == ExtOp; } } return false; } void SPIRVEntry::encodeDecorate(spv_ostream &O) const { for (auto &I : Decorates) O << *I.second; } SPIRVLinkageTypeKind SPIRVEntry::getLinkageType() const { assert(hasLinkageType()); DecorateMapType::const_iterator Loc = Decorates.find(DecorationLinkageAttributes); if (Loc == Decorates.end()) return LinkageTypeInternal; return static_cast(Loc->second) ->getLinkageType(); } void SPIRVEntry::setLinkageType(SPIRVLinkageTypeKind LT) { assert(isValid(LT)); assert(hasLinkageType()); addDecorate(new SPIRVDecorateLinkageAttr(this, Name, LT)); } void SPIRVEntry::updateModuleVersion() const { if (!Module) return; Module->setMinSPIRVVersion(getRequiredSPIRVVersion()); } spv_ostream &operator<<(spv_ostream &O, const SPIRVEntry &E) { E.validate(); E.encodeAll(O); O << SPIRVNL(); return O; } std::istream &operator>>(std::istream &I, SPIRVEntry &E) { E.decode(I); return I; } SPIRVEntryPoint::SPIRVEntryPoint(SPIRVModule *TheModule, SPIRVExecutionModelKind TheExecModel, SPIRVId TheId, const std::string &TheName, std::vector Variables) : SPIRVAnnotation(TheModule->get(TheId), getSizeInWords(TheName) + Variables.size() + 3), ExecModel(TheExecModel), Name(TheName), Variables(Variables) {} void SPIRVEntryPoint::encode(spv_ostream &O) const { getEncoder(O) << ExecModel << Target << Name << Variables; } void SPIRVEntryPoint::decode(std::istream &I) { getDecoder(I) >> ExecModel >> Target >> Name >> Variables; Module->setName(getOrCreateTarget(), Name); Module->addEntryPoint(ExecModel, Target); } void SPIRVExecutionMode::encode(spv_ostream &O) const { getEncoder(O) << Target << ExecMode << WordLiterals; } void SPIRVExecutionMode::decode(std::istream &I) { getDecoder(I) >> Target >> ExecMode; switch (ExecMode) { case ExecutionModeLocalSize: case ExecutionModeLocalSizeHint: case ExecutionModeMaxWorkgroupSizeINTEL: WordLiterals.resize(3); break; case ExecutionModeInvocations: case ExecutionModeOutputVertices: case ExecutionModeVecTypeHint: case ExecutionModeSubgroupSize: case ExecutionModeMaxWorkDimINTEL: case ExecutionModeNumSIMDWorkitemsINTEL: WordLiterals.resize(1); break; default: // Do nothing. Keep this to avoid VS2013 warning. break; } getDecoder(I) >> WordLiterals; getOrCreateTarget()->addExecutionMode(Module->add(this)); } SPIRVForward *SPIRVAnnotationGeneric::getOrCreateTarget() const { SPIRVEntry *Entry = nullptr; bool Found = Module->exist(Target, &Entry); assert((!Found || Entry->getOpCode() == OpForward) && "Annotations only allowed on forward"); if (!Found) Entry = Module->addForward(Target, nullptr); return static_cast(Entry); } SPIRVName::SPIRVName(const SPIRVEntry *TheTarget, const std::string &TheStr) : SPIRVAnnotation(TheTarget, getSizeInWords(TheStr) + 2), Str(TheStr) {} void SPIRVName::encode(spv_ostream &O) const { getEncoder(O) << Target << Str; } void SPIRVName::decode(std::istream &I) { getDecoder(I) >> Target >> Str; Module->setName(getOrCreateTarget(), Str); } void SPIRVName::validate() const { assert(WordCount == getSizeInWords(Str) + 2 && "Incorrect word count"); } _SPIRV_IMP_ENCDEC2(SPIRVString, Id, Str) _SPIRV_IMP_ENCDEC3(SPIRVMemberName, Target, MemberNumber, Str) void SPIRVLine::encode(spv_ostream &O) const { getEncoder(O) << FileName << Line << Column; } void SPIRVLine::decode(std::istream &I) { getDecoder(I) >> FileName >> Line >> Column; std::shared_ptr L(this); Module->setCurrentLine(L); } void SPIRVLine::validate() const { assert(OpCode == OpLine); assert(WordCount == 4); assert(get(FileName)->getOpCode() == OpString); assert(Line != SPIRVWORD_MAX); assert(Column != SPIRVWORD_MAX); assert(!hasId()); } void SPIRVMemberName::validate() const { assert(OpCode == OpMemberName); assert(WordCount == getSizeInWords(Str) + FixedWC); assert(get(Target)->getOpCode() == OpTypeStruct); assert(MemberNumber < get(Target)->getStructMemberCount()); } SPIRVExtInstImport::SPIRVExtInstImport(SPIRVModule *TheModule, SPIRVId TheId, const std::string &TheStr) : SPIRVEntry(TheModule, 2 + getSizeInWords(TheStr), OC, TheId), Str(TheStr) { validate(); } void SPIRVExtInstImport::encode(spv_ostream &O) const { getEncoder(O) << Id << Str; } void SPIRVExtInstImport::decode(std::istream &I) { getDecoder(I) >> Id >> Str; Module->importBuiltinSetWithId(Str, Id); } void SPIRVExtInstImport::validate() const { SPIRVEntry::validate(); assert(!Str.empty() && "Invalid builtin set"); } void SPIRVMemoryModel::encode(spv_ostream &O) const { getEncoder(O) << Module->getAddressingModel() << Module->getMemoryModel(); } void SPIRVMemoryModel::decode(std::istream &I) { SPIRVAddressingModelKind AddrModel; SPIRVMemoryModelKind MemModel; getDecoder(I) >> AddrModel >> MemModel; Module->setAddressingModel(AddrModel); Module->setMemoryModel(MemModel); } void SPIRVMemoryModel::validate() const { auto AM = Module->getAddressingModel(); auto MM = Module->getMemoryModel(); SPIRVCK(isValid(AM), InvalidAddressingModel, "Actual is " + std::to_string(AM)); SPIRVCK(isValid(MM), InvalidMemoryModel, "Actual is " + std::to_string(MM)); } void SPIRVSource::encode(spv_ostream &O) const { SPIRVWord Ver = SPIRVWORD_MAX; auto Language = Module->getSourceLanguage(&Ver); getEncoder(O) << Language << Ver; } void SPIRVSource::decode(std::istream &I) { SourceLanguage Lang = SourceLanguageUnknown; SPIRVWord Ver = SPIRVWORD_MAX; getDecoder(I) >> Lang >> Ver; Module->setSourceLanguage(Lang, Ver); } SPIRVSourceExtension::SPIRVSourceExtension(SPIRVModule *M, const std::string &SS) : SPIRVEntryNoId(M, 1 + getSizeInWords(SS)), S(SS) {} void SPIRVSourceExtension::encode(spv_ostream &O) const { getEncoder(O) << S; } void SPIRVSourceExtension::decode(std::istream &I) { getDecoder(I) >> S; Module->getSourceExtension().insert(S); } SPIRVExtension::SPIRVExtension(SPIRVModule *M, const std::string &SS) : SPIRVEntryNoId(M, 1 + getSizeInWords(SS)), S(SS) {} void SPIRVExtension::encode(spv_ostream &O) const { getEncoder(O) << S; } void SPIRVExtension::decode(std::istream &I) { getDecoder(I) >> S; Module->getExtension().insert(S); } SPIRVCapability::SPIRVCapability(SPIRVModule *M, SPIRVCapabilityKind K) : SPIRVEntryNoId(M, 2), Kind(K) { updateModuleVersion(); } void SPIRVCapability::encode(spv_ostream &O) const { getEncoder(O) << Kind; } void SPIRVCapability::decode(std::istream &I) { getDecoder(I) >> Kind; Module->addCapability(Kind); } } // namespace SPIRV SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVEntry.h000066400000000000000000001003551363521741200225430ustar00rootroot00000000000000//===- SPIRVEntry.h - Base Class for SPIR-V Entities ------------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines the base class for SPIRV entities. /// //===----------------------------------------------------------------------===// #ifndef SPIRV_LIBSPIRV_SPIRVENTRY_H #define SPIRV_LIBSPIRV_SPIRVENTRY_H #include "LLVMSPIRVOpts.h" #include "SPIRVEnum.h" #include "SPIRVError.h" #include "SPIRVIsValidEnum.h" #include #include #include #include #include #include #include namespace SPIRV { class SPIRVModule; class SPIRVEncoder; class SPIRVDecoder; class SPIRVType; class SPIRVValue; class SPIRVDecorate; class SPIRVForward; class SPIRVMemberDecorate; class SPIRVLine; class SPIRVString; class SPIRVExtInst; // Add declaration of encode/decode functions to a class. // Used inside class definition. #define _SPIRV_DCL_ENCDEC \ void encode(spv_ostream &O) const override; \ void decode(std::istream &I) override; #define _REQ_SPIRV_VER(Version) \ SPIRVWord getRequiredSPIRVVersion() const override { return Version; } // Add implementation of encode/decode functions to a class. // Used out side of class definition. #define _SPIRV_IMP_ENCDEC0(Ty) \ void Ty::encode(spv_ostream &O) const {} \ void Ty::decode(std::istream &I) {} #define _SPIRV_IMP_ENCDEC1(Ty, x) \ void Ty::encode(spv_ostream &O) const { getEncoder(O) << (x); } \ void Ty::decode(std::istream &I) { getDecoder(I) >> (x); } #define _SPIRV_IMP_ENCDEC2(Ty, x, y) \ void Ty::encode(spv_ostream &O) const { getEncoder(O) << (x) << (y); } \ void Ty::decode(std::istream &I) { getDecoder(I) >> (x) >> (y); } #define _SPIRV_IMP_ENCDEC3(Ty, x, y, z) \ void Ty::encode(spv_ostream &O) const { \ getEncoder(O) << (x) << (y) << (z); \ } \ void Ty::decode(std::istream &I) { getDecoder(I) >> (x) >> (y) >> (z); } #define _SPIRV_IMP_ENCDEC4(Ty, x, y, z, u) \ void Ty::encode(spv_ostream &O) const { \ getEncoder(O) << (x) << (y) << (z) << (u); \ } \ void Ty::decode(std::istream &I) { \ getDecoder(I) >> (x) >> (y) >> (z) >> (u); \ } #define _SPIRV_IMP_ENCDEC5(Ty, x, y, z, u, v) \ void Ty::encode(spv_ostream &O) const { \ getEncoder(O) << (x) << (y) << (z) << (u) << (v); \ } \ void Ty::decode(std::istream &I) { \ getDecoder(I) >> (x) >> (y) >> (z) >> (u) >> (v); \ } #define _SPIRV_IMP_ENCDEC6(Ty, x, y, z, u, v, w) \ void Ty::encode(spv_ostream &O) const { \ getEncoder(O) << (x) << (y) << (z) << (u) << (v) << (w); \ } \ void Ty::decode(std::istream &I) { \ getDecoder(I) >> (x) >> (y) >> (z) >> (u) >> (v) >> (w); \ } #define _SPIRV_IMP_ENCDEC7(Ty, x, y, z, u, v, w, r) \ void Ty::encode(spv_ostream &O) const { \ getEncoder(O) << (x) << (y) << (z) << (u) << (v) << (w) << (r); \ } \ void Ty::decode(std::istream &I) { \ getDecoder(I) >> (x) >> (y) >> (z) >> (u) >> (v) >> (w) >> (r); \ } #define _SPIRV_IMP_ENCDEC8(Ty, x, y, z, u, v, w, r, s) \ void Ty::encode(spv_ostream &O) const { \ getEncoder(O) << (x) << (y) << (z) << (u) << (v) << (w) << (r) << (s); \ } \ void Ty::decode(std::istream &I) { \ getDecoder(I) >> (x) >> (y) >> (z) >> (u) >> (v) >> (w) >> (r) >> (s); \ } #define _SPIRV_IMP_ENCDEC9(Ty, x, y, z, u, v, w, r, s, t) \ void Ty::encode(spv_ostream &O) const { \ getEncoder(O) << (x) << (y) << (z) << (u) << (v) << (w) << (r) << (s) \ << (t); \ } \ void Ty::decode(std::istream &I) { \ getDecoder(I) >> (x) >> (y) >> (z) >> (u) >> (v) >> (w) >> (r) >> (s) >> \ (t); \ } // Add definition of encode/decode functions to a class. // Used inside class definition. #define _SPIRV_DEF_ENCDEC0 \ void encode(spv_ostream &O) const override {} \ void decode(std::istream &I) override {} #define _SPIRV_DEF_ENCDEC1(x) \ void encode(spv_ostream &O) const override { getEncoder(O) << (x); } \ void decode(std::istream &I) override { getDecoder(I) >> (x); } #define _SPIRV_DEF_ENCDEC2(x, y) \ void encode(spv_ostream &O) const override { getEncoder(O) << (x) << (y); } \ void decode(std::istream &I) override { getDecoder(I) >> (x) >> (y); } #define _SPIRV_DEF_ENCDEC3(x, y, z) \ void encode(spv_ostream &O) const override { \ getEncoder(O) << (x) << (y) << (z); \ } \ void decode(std::istream &I) override { getDecoder(I) >> (x) >> (y) >> (z); } #define _SPIRV_DEF_ENCDEC4(x, y, z, u) \ void encode(spv_ostream &O) const override { \ getEncoder(O) << (x) << (y) << (z) << (u); \ } \ void decode(std::istream &I) override { \ getDecoder(I) >> (x) >> (y) >> (z) >> (u); \ } #define _SPIRV_DEF_ENCDEC5(x, y, z, u, v) \ void encode(spv_ostream &O) const override { \ getEncoder(O) << (x) << (y) << (z) << (u) << (v); \ } \ void decode(std::istream &I) override { \ getDecoder(I) >> (x) >> (y) >> (z) >> (u) >> (v); \ } #define _SPIRV_DEF_ENCDEC6(x, y, z, u, v, w) \ void encode(spv_ostream &O) const override { \ getEncoder(O) << (x) << (y) << (z) << (u) << (v) << (w); \ } \ void decode(std::istream &I) override { \ getDecoder(I) >> (x) >> (y) >> (z) >> (u) >> (v) >> (w); \ } #define _SPIRV_DEF_ENCDEC7(x, y, z, u, v, w, r) \ void encode(spv_ostream &O) const override { \ getEncoder(O) << (x) << (y) << (z) << (u) << (v) << (w) << (r); \ } \ void decode(std::istream &I) override { \ getDecoder(I) >> (x) >> (y) >> (z) >> (u) >> (v) >> (w) >> (r); \ } #define _SPIRV_DEF_ENCDEC8(x, y, z, u, v, w, r, s) \ void encode(spv_ostream &O) const override { \ getEncoder(O) << (x) << (y) << (z) << (u) << (v) << (w) << (r) << (s); \ } \ void decode(std::istream &I) override { \ getDecoder(I) >> (x) >> (y) >> (z) >> (u) >> (v) >> (w) >> (r) >> (s); \ } #define _SPIRV_DEF_ENCDEC9(x, y, z, u, v, w, r, s, t) \ void encode(spv_ostream &O) const override { \ getEncoder(O) << (x) << (y) << (z) << (u) << (v) << (w) << (r) << (s) \ << (t); \ } \ void decode(std::istream &I) override { \ getDecoder(I) >> (x) >> (y) >> (z) >> (u) >> (v) >> (w) >> (r) >> (s) >> \ (t); \ } /// All SPIR-V in-memory-representation entities inherits from SPIRVEntry. /// Usually there are two flavors of constructors of SPIRV objects: /// /// 1. complete constructor: It requires all the parameters needed to create a /// SPIRV entity with complete information which can be validated. It is /// usually used by LLVM/SPIR-V translator to create SPIRV object /// corresponding to LLVM object. Such constructor calls validate() at /// the end of the construction. /// /// 2. incomplete constructor: For leaf classes, it has no parameters. /// It is usually called by SPIRVEntry::make(opcode) to create an incomplete /// object which should not be validated. Then setWordCount(count) is /// called to fix the size of the object if it is variable, and then the /// information is filled by the virtual function decode(istream). /// After that the object can be validated. /// /// To add a new SPIRV class: /// /// 1. It is recommended to name the class as SPIRVXXX if it has a fixed op code /// OpXXX. Although it is not mandatory, doing this facilitates adding it to /// the table of the factory function SPIRVEntry::create(). /// 2. Inherit from proper SPIRV class such as SPIRVType, SPIRVValue, /// SPIRVInstruction, etc. /// 3. Implement virtual function encode(), decode(), validate(). /// 4. If the object has variable size, implement virtual function /// setWordCount(). /// 5. If the class has special attributes, e.g. having no id, or having no /// type as a value, set them in the constructors. /// 6. If the class may represent SPIRV entity which has been added in version /// later than 1.0, implement virtual function getRequiredSPIRVVersion(). /// To automaticly update module's version you can also call protected /// function updateModuleVersion() in the constructor. /// 7. Add the class to the Table of SPIRVEntry::create(). /// 8. Add the class to SPIRVToLLVM and LLVMToSPIRV. class SPIRVEntry { public: enum SPIRVEntryAttrib { SPIRVEA_DEFAULT = 0, SPIRVEA_NOID = 1, // Entry has no valid id SPIRVEA_NOTYPE = 2, // Value has no type }; // Complete constructor for objects with id SPIRVEntry(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode, SPIRVId TheId) : Module(M), OpCode(TheOpCode), Id(TheId), Attrib(SPIRVEA_DEFAULT), WordCount(TheWordCount), Line(nullptr) { SPIRVEntry::validate(); } // Complete constructor for objects without id SPIRVEntry(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode) : Module(M), OpCode(TheOpCode), Id(SPIRVID_INVALID), Attrib(SPIRVEA_NOID), WordCount(TheWordCount), Line(nullptr) { SPIRVEntry::validate(); } // Incomplete constructor SPIRVEntry(Op TheOpCode) : Module(NULL), OpCode(TheOpCode), Id(SPIRVID_INVALID), Attrib(SPIRVEA_DEFAULT), WordCount(0), Line(nullptr) {} SPIRVEntry() : Module(NULL), OpCode(OpNop), Id(SPIRVID_INVALID), Attrib(SPIRVEA_DEFAULT), WordCount(0), Line(nullptr) {} virtual ~SPIRVEntry() {} bool exist(SPIRVId) const; template T *get(SPIRVId TheId) const { return static_cast(getEntry(TheId)); } SPIRVEntry *getEntry(SPIRVId) const; SPIRVEntry *getOrCreate(SPIRVId TheId) const; SPIRVValue *getValue(SPIRVId TheId) const; std::vector getValues(const std::vector &) const; std::vector getIds(const std::vector) const; SPIRVType *getValueType(SPIRVId TheId) const; std::vector getValueTypes(const std::vector &) const; virtual SPIRVDecoder getDecoder(std::istream &); virtual SPIRVEncoder getEncoder(spv_ostream &) const; SPIRVErrorLog &getErrorLog() const; SPIRVId getId() const { assert(hasId()); return Id; } std::shared_ptr getLine() const { return Line; } SPIRVLinkageTypeKind getLinkageType() const; Op getOpCode() const { return OpCode; } SPIRVModule *getModule() const { return Module; } virtual SPIRVCapVec getRequiredCapability() const { return SPIRVCapVec(); } virtual SPIRVExtSet getRequiredExtensions() const { return SPIRVExtSet(); } const std::string &getName() const { return Name; } bool hasDecorate(Decoration Kind, size_t Index = 0, SPIRVWord *Result = 0) const; bool hasMemberDecorate(Decoration Kind, size_t Index = 0, SPIRVWord MemberNumber = 0, SPIRVWord *Result = 0) const; std::vector getDecorationLiterals(Decoration Kind) const; std::vector getMemberDecorationLiterals(Decoration Kind, SPIRVWord MemberNumber) const; std::vector getDecorationStringLiteral(Decoration Kind) const; std::vector getMemberDecorationStringLiteral(Decoration Kind, SPIRVWord MemberNumber) const; std::set getDecorate(Decoration Kind, size_t Index = 0) const; bool hasId() const { return !(Attrib & SPIRVEA_NOID); } bool hasLine() const { return Line != nullptr; } bool hasLinkageType() const; bool isAtomic() const { return isAtomicOpCode(OpCode); } bool isBasicBlock() const { return isLabel(); } bool isExtInst() const { return OpCode == OpExtInst; } bool isExtInst(const SPIRVExtInstSetKind InstSet) const; bool isExtInst(const SPIRVExtInstSetKind InstSet, const SPIRVWord ExtOp) const; bool isDecorate() const { return OpCode == OpDecorate; } bool isMemberDecorate() const { return OpCode == OpMemberDecorate; } bool isForward() const { return OpCode == OpForward; } bool isLabel() const { return OpCode == OpLabel; } bool isUndef() const { return OpCode == OpUndef; } bool isControlBarrier() const { return OpCode == OpControlBarrier; } bool isMemoryBarrier() const { return OpCode == OpMemoryBarrier; } bool isVariable() const { return OpCode == OpVariable; } bool isEndOfBlock() const; virtual bool isInst() const { return false; } virtual bool isOperandLiteral(unsigned Index) const { assert(0 && "not implemented"); return false; } virtual bool isImplemented() const { return true; } void addDecorate(SPIRVDecorate *); void addDecorate(Decoration Kind); void addDecorate(Decoration Kind, SPIRVWord Literal); void eraseDecorate(Decoration); void addMemberDecorate(SPIRVMemberDecorate *); void addMemberDecorate(SPIRVWord MemberNumber, Decoration Kind); void addMemberDecorate(SPIRVWord MemberNumber, Decoration Kind, SPIRVWord Literal); void eraseMemberDecorate(SPIRVWord MemberNumber, Decoration Kind); void setHasNoId() { Attrib |= SPIRVEA_NOID; } void setId(SPIRVId TheId) { Id = TheId; } void setLine(const std::shared_ptr &L); void setLinkageType(SPIRVLinkageTypeKind); void setModule(SPIRVModule *TheModule); void setName(const std::string &TheName); virtual void setScope(SPIRVEntry *Scope){}; void takeAnnotations(SPIRVForward *); void takeDecorates(SPIRVEntry *); void takeMemberDecorates(SPIRVEntry *); /// After a SPIRV entry is created during reading SPIRV binary by default /// constructor, this function is called to allow the SPIRV entry to resize /// its variable sized member before decoding the remaining words. virtual void setWordCount(SPIRVWord TheWordCount); /// Create an empty SPIRV object by op code, e.g. OpTypeInt creates /// SPIRVTypeInt. static SPIRVEntry *create(Op); static std::unique_ptr createUnique(Op); /// Create an empty extended instruction. static std::unique_ptr createUnique(SPIRVExtInstSetKind Set, unsigned ExtOp); friend spv_ostream &operator<<(spv_ostream &O, const SPIRVEntry &E); friend std::istream &operator>>(std::istream &I, SPIRVEntry &E); virtual void encodeLine(spv_ostream &O) const; virtual void encodeAll(spv_ostream &O) const; virtual void encodeName(spv_ostream &O) const; virtual void encodeChildren(spv_ostream &O) const; virtual void encodeDecorate(spv_ostream &O) const; virtual void encodeWordCountOpCode(spv_ostream &O) const; virtual void encode(spv_ostream &O) const; virtual void decode(std::istream &I); friend class SPIRVDecoder; /// Checks the integrity of the object. virtual void validate() const { assert(Module && "Invalid module"); assert(OpCode != OpNop && "Invalid op code"); assert((!hasId() || isValidId(Id)) && "Invalid Id"); } void validateFunctionControlMask(SPIRVWord FCtlMask) const; void validateValues(const std::vector &) const; void validateBuiltin(SPIRVWord, SPIRVWord) const; // By default assume SPIRV 1.0 as required version virtual SPIRVWord getRequiredSPIRVVersion() const { return static_cast(VersionNumber::SPIRV_1_0); } virtual std::vector getNonLiteralOperands() const { return std::vector(); } protected: /// An entry may have multiple FuncParamAttr decorations. typedef std::multimap DecorateMapType; typedef std::map, const SPIRVMemberDecorate *> MemberDecorateMapType; bool canHaveMemberDecorates() const { return OpCode == OpTypeStruct || OpCode == OpForward; } MemberDecorateMapType &getMemberDecorates() { assert(canHaveMemberDecorates()); return MemberDecorates; } void updateModuleVersion() const; SPIRVModule *Module; Op OpCode; SPIRVId Id; std::string Name; unsigned Attrib; SPIRVWord WordCount; DecorateMapType Decorates; MemberDecorateMapType MemberDecorates; std::shared_ptr Line; }; class SPIRVEntryNoIdGeneric : public SPIRVEntry { public: SPIRVEntryNoIdGeneric(SPIRVModule *M, unsigned TheWordCount, Op OC) : SPIRVEntry(M, TheWordCount, OC) { setAttr(); } SPIRVEntryNoIdGeneric(Op OC) : SPIRVEntry(OC) { setAttr(); } protected: void setAttr() { setHasNoId(); } }; template class SPIRVEntryNoId : public SPIRVEntryNoIdGeneric { public: SPIRVEntryNoId(SPIRVModule *M, unsigned TheWordCount) : SPIRVEntryNoIdGeneric(M, TheWordCount, OC) {} SPIRVEntryNoId() : SPIRVEntryNoIdGeneric(OC) {} }; template class SPIRVEntryOpCodeOnly : public SPIRVEntryNoId { public: SPIRVEntryOpCodeOnly() { SPIRVEntry::WordCount = 1; validate(); } protected: _SPIRV_DEF_ENCDEC0 void validate() const override { assert(isValidId(SPIRVEntry::OpCode)); } }; template class SPIRVEntryUnimplemented : public SPIRVEntryNoId { public: SPIRVEntryUnimplemented() { SPIRVEntry::WordCount = 1; validate(); } bool isImplemented() const override { return false; } protected: _SPIRV_DEF_ENCDEC0 void validate() const override { assert(isValidId(SPIRVEntry::OpCode)); } }; class SPIRVAnnotationGeneric : public SPIRVEntryNoIdGeneric { public: // Complete constructor SPIRVAnnotationGeneric(SPIRVModule *TheModule, unsigned TheWordCount, Op OC, SPIRVId TheTarget = SPIRVID_INVALID) : SPIRVEntryNoIdGeneric(TheModule, TheWordCount, OC), Target(TheTarget) {} // Incomplete constructor SPIRVAnnotationGeneric(Op OC) : SPIRVEntryNoIdGeneric(OC), Target(SPIRVID_INVALID) {} SPIRVId getTargetId() const { return Target; } SPIRVForward *getOrCreateTarget() const; void setTargetId(SPIRVId T) { Target = T; } protected: SPIRVId Target; }; template class SPIRVAnnotation : public SPIRVAnnotationGeneric { public: // Complete constructor SPIRVAnnotation(const SPIRVEntry *TheTarget, unsigned TheWordCount) : SPIRVAnnotationGeneric(TheTarget->getModule(), TheWordCount, OC, TheTarget->getId()) {} // Incomplete constructor SPIRVAnnotation() : SPIRVAnnotationGeneric(OC) {} }; class SPIRVEntryPoint : public SPIRVAnnotation { public: SPIRVEntryPoint(SPIRVModule *TheModule, SPIRVExecutionModelKind, SPIRVId TheId, const std::string &TheName, std::vector Variables); SPIRVEntryPoint() : ExecModel(ExecutionModelKernel) {} _SPIRV_DCL_ENCDEC protected: SPIRVExecutionModelKind ExecModel; std::string Name; private: std::vector Variables; }; class SPIRVName : public SPIRVAnnotation { public: // Complete constructor SPIRVName(const SPIRVEntry *TheTarget, const std::string &TheStr); // Incomplete constructor SPIRVName() {} protected: _SPIRV_DCL_ENCDEC void validate() const override; std::string Str; }; class SPIRVMemberName : public SPIRVAnnotation { public: static const SPIRVWord FixedWC = 3; // Complete constructor SPIRVMemberName(const SPIRVEntry *TheTarget, SPIRVWord TheMemberNumber, const std::string &TheStr) : SPIRVAnnotation(TheTarget, FixedWC + getSizeInWords(TheStr)), MemberNumber(TheMemberNumber), Str(TheStr) { validate(); } // Incomplete constructor SPIRVMemberName() : MemberNumber(SPIRVWORD_MAX) {} protected: _SPIRV_DCL_ENCDEC void validate() const override; SPIRVWord MemberNumber; std::string Str; }; class SPIRVString : public SPIRVEntry { static const Op OC = OpString; static const SPIRVWord FixedWC = 2; public: SPIRVString(SPIRVModule *M, SPIRVId TheId, const std::string &TheStr) : SPIRVEntry(M, FixedWC + getSizeInWords(TheStr), OC, TheId), Str(TheStr) {} SPIRVString() : SPIRVEntry(OC) {} _SPIRV_DCL_ENCDEC const std::string &getStr() const { return Str; } protected: std::string Str; }; class SPIRVLine : public SPIRVEntry { public: static const SPIRVWord WC = 4; // Complete constructor SPIRVLine(SPIRVModule *M, SPIRVId TheFileName, SPIRVWord TheLine, SPIRVWord TheColumn) : SPIRVEntry(M, WC, OpLine), FileName(TheFileName), Line(TheLine), Column(TheColumn) { Attrib = SPIRVEA_NOID | SPIRVEA_NOTYPE; validate(); } // Incomplete constructor SPIRVLine() : SPIRVEntry(OpLine), FileName(SPIRVID_INVALID), Line(SPIRVWORD_MAX), Column(SPIRVWORD_MAX) { Attrib = SPIRVEA_NOID | SPIRVEA_NOTYPE; } SPIRVWord getColumn() const { return Column; } void setColumn(const SPIRVWord Column) { this->Column = Column; } SPIRVId getFileName() const { return FileName; } const std::string &getFileNameStr() const { return get(FileName)->getStr(); } void setFileName(const SPIRVId FileName) { this->FileName = FileName; } SPIRVWord getLine() const { return Line; } void setLine(const SPIRVWord Line) { this->Line = Line; } bool operator!=(const SPIRVLine &O) const { return !equals(O.FileName, O.Line, O.Column); } bool equals(const SPIRVId TheFileName, const SPIRVWord TheLine, const SPIRVWord TheColumn) const { return FileName == TheFileName && Line == TheLine && Column == TheColumn; } protected: _SPIRV_DCL_ENCDEC void validate() const override; SPIRVId FileName; SPIRVWord Line; SPIRVWord Column; }; class SPIRVExecutionMode : public SPIRVAnnotation { public: // Complete constructor for LocalSize, LocalSizeHint SPIRVExecutionMode(SPIRVEntry *TheTarget, SPIRVExecutionModeKind TheExecMode, SPIRVWord X, SPIRVWord Y, SPIRVWord Z) : SPIRVAnnotation(TheTarget, 6), ExecMode(TheExecMode) { WordLiterals.push_back(X); WordLiterals.push_back(Y); WordLiterals.push_back(Z); updateModuleVersion(); } // Complete constructor for VecTypeHint, SubgroupSize, SubgroupsPerWorkgroup SPIRVExecutionMode(SPIRVEntry *TheTarget, SPIRVExecutionModeKind TheExecMode, SPIRVWord Code) : SPIRVAnnotation(TheTarget, 4), ExecMode(TheExecMode) { WordLiterals.push_back(Code); updateModuleVersion(); } // Complete constructor for ContractionOff SPIRVExecutionMode(SPIRVEntry *TheTarget, SPIRVExecutionModeKind TheExecMode) : SPIRVAnnotation(TheTarget, 3), ExecMode(TheExecMode) { updateModuleVersion(); } // Incomplete constructor SPIRVExecutionMode() : ExecMode(ExecutionModeInvocations) {} SPIRVExecutionModeKind getExecutionMode() const { return ExecMode; } const std::vector &getLiterals() const { return WordLiterals; } SPIRVCapVec getRequiredCapability() const override { return getCapability(ExecMode); } SPIRVWord getRequiredSPIRVVersion() const override { switch (ExecMode) { case ExecutionModeFinalizer: case ExecutionModeInitializer: case ExecutionModeSubgroupSize: case ExecutionModeSubgroupsPerWorkgroup: return static_cast(VersionNumber::SPIRV_1_1); default: return static_cast(VersionNumber::SPIRV_1_0); } } protected: _SPIRV_DCL_ENCDEC SPIRVExecutionModeKind ExecMode; std::vector WordLiterals; }; class SPIRVComponentExecutionModes { typedef std::map SPIRVExecutionModeMap; public: void addExecutionMode(SPIRVExecutionMode *ExecMode) { ExecModes[ExecMode->getExecutionMode()] = ExecMode; } SPIRVExecutionMode *getExecutionMode(SPIRVExecutionModeKind EMK) const { auto Loc = ExecModes.find(EMK); if (Loc == ExecModes.end()) return nullptr; return Loc->second; } protected: SPIRVExecutionModeMap ExecModes; }; class SPIRVExtInstImport : public SPIRVEntry { public: const static Op OC = OpExtInstImport; // Complete constructor SPIRVExtInstImport(SPIRVModule *TheModule, SPIRVId TheId, const std::string &TheStr); // Incomplete constructor SPIRVExtInstImport() : SPIRVEntry(OC) {} protected: _SPIRV_DCL_ENCDEC void validate() const override; std::string Str; }; class SPIRVMemoryModel : public SPIRVEntryNoId { public: SPIRVMemoryModel(SPIRVModule *M) : SPIRVEntryNoId(M, 3) {} SPIRVMemoryModel() {} _SPIRV_DCL_ENCDEC void validate() const override; }; class SPIRVSource : public SPIRVEntryNoId { public: SPIRVSource(SPIRVModule *M) : SPIRVEntryNoId(M, 3) {} SPIRVSource() {} _SPIRV_DCL_ENCDEC }; class SPIRVSourceExtension : public SPIRVEntryNoId { public: SPIRVSourceExtension(SPIRVModule *M, const std::string &SS); SPIRVSourceExtension() {} _SPIRV_DCL_ENCDEC private: std::string S; }; class SPIRVExtension : public SPIRVEntryNoId { public: SPIRVExtension(SPIRVModule *M, const std::string &SS); SPIRVExtension() {} std::string getExtensionName() const { return S; } _SPIRV_DCL_ENCDEC private: std::string S; }; class SPIRVCapability : public SPIRVEntryNoId { public: SPIRVCapability(SPIRVModule *M, SPIRVCapabilityKind K); SPIRVCapability() : Kind(CapabilityMatrix) {} _SPIRV_DCL_ENCDEC SPIRVWord getRequiredSPIRVVersion() const override { switch (Kind) { case CapabilityNamedBarrier: case CapabilitySubgroupDispatch: case CapabilityPipeStorage: return static_cast(VersionNumber::SPIRV_1_1); default: return static_cast(VersionNumber::SPIRV_1_0); } } private: SPIRVCapabilityKind Kind; }; template T *bcast(SPIRVEntry *E) { return static_cast(E); } template bool isa(SPIRVEntry *E) { return E ? E->getOpCode() == OC : false; } // ToDo: The following typedef's are place holders for SPIRV entity classes // to be implemented. // Each time a new class is implemented, remove the corresponding typedef. // This is also an indication of how much work is left. #define _SPIRV_OP(x) typedef SPIRVEntryUnimplemented SPIRV##x; _SPIRV_OP(Nop) _SPIRV_OP(SourceContinued) _SPIRV_OP(TypeRuntimeArray) _SPIRV_OP(Image) _SPIRV_OP(ImageTexelPointer) _SPIRV_OP(ImageSampleDrefImplicitLod) _SPIRV_OP(ImageSampleDrefExplicitLod) _SPIRV_OP(ImageSampleProjImplicitLod) _SPIRV_OP(ImageSampleProjExplicitLod) _SPIRV_OP(ImageSampleProjDrefImplicitLod) _SPIRV_OP(ImageSampleProjDrefExplicitLod) _SPIRV_OP(ImageFetch) _SPIRV_OP(ImageGather) _SPIRV_OP(ImageDrefGather) _SPIRV_OP(QuantizeToF16) _SPIRV_OP(ArrayLength) _SPIRV_OP(OuterProduct) _SPIRV_OP(IAddCarry) _SPIRV_OP(ISubBorrow) _SPIRV_OP(SMulExtended) _SPIRV_OP(UMulExtended) _SPIRV_OP(BitFieldInsert) _SPIRV_OP(BitFieldSExtract) _SPIRV_OP(BitFieldUExtract) _SPIRV_OP(DPdx) _SPIRV_OP(DPdy) _SPIRV_OP(Fwidth) _SPIRV_OP(DPdxFine) _SPIRV_OP(DPdyFine) _SPIRV_OP(FwidthFine) _SPIRV_OP(DPdxCoarse) _SPIRV_OP(DPdyCoarse) _SPIRV_OP(FwidthCoarse) _SPIRV_OP(EmitVertex) _SPIRV_OP(EndPrimitive) _SPIRV_OP(EmitStreamVertex) _SPIRV_OP(EndStreamPrimitive) _SPIRV_OP(Kill) _SPIRV_OP(ImageSparseSampleImplicitLod) _SPIRV_OP(ImageSparseSampleExplicitLod) _SPIRV_OP(ImageSparseSampleDrefImplicitLod) _SPIRV_OP(ImageSparseSampleDrefExplicitLod) _SPIRV_OP(ImageSparseSampleProjImplicitLod) _SPIRV_OP(ImageSparseSampleProjExplicitLod) _SPIRV_OP(ImageSparseSampleProjDrefImplicitLod) _SPIRV_OP(ImageSparseSampleProjDrefExplicitLod) _SPIRV_OP(ImageSparseFetch) _SPIRV_OP(ImageSparseGather) _SPIRV_OP(ImageSparseDrefGather) _SPIRV_OP(ImageSparseTexelsResident) _SPIRV_OP(NoLine) _SPIRV_OP(TypeNamedBarrier) _SPIRV_OP(NamedBarrierInitialize) _SPIRV_OP(MemoryNamedBarrier) _SPIRV_OP(GetKernelMaxNumSubgroups) _SPIRV_OP(GetKernelLocalSizeForSubgroupCount) _SPIRV_OP(SizeOf) #undef _SPIRV_OP } // namespace SPIRV #endif // SPIRV_LIBSPIRV_SPIRVENTRY_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVEnum.h000066400000000000000000000520541363521741200223500ustar00rootroot00000000000000//===- SPIRVEnum.h - SPIR-V enums -------------------------------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines SPIR-V enums. /// //===----------------------------------------------------------------------===// #ifndef SPIRV_LIBSPIRV_SPIRVENUM_H #define SPIRV_LIBSPIRV_SPIRVENUM_H #include "LLVMSPIRVOpts.h" #include "SPIRVOpCode.h" #include "spirv.hpp" #include using namespace spv; namespace SPIRV { typedef uint32_t SPIRVWord; typedef uint32_t SPIRVId; #define SPIRVID_MAX ~0U #define SPIRVID_INVALID ~0U #define SPIRVWORD_MAX ~0U inline bool isValidId(SPIRVId Id) { return Id != SPIRVID_INVALID && Id != 0; } inline SPIRVWord mkWord(unsigned WordCount, Op OpCode) { return (WordCount << 16) | OpCode; } const static unsigned KSpirvMemOrderSemanticMask = 0x1F; enum SPIRVGeneratorKind { SPIRVGEN_KhronosLLVMSPIRVTranslator = 6, SPIRVGEN_KhronosSPIRVAssembler = 7, }; enum SPIRVInstructionSchemaKind { SPIRVISCH_Default, }; enum SPIRVExtInstSetKind { SPIRVEIS_OpenCL, SPIRVEIS_Debug, SPIRVEIS_Count, }; enum SPIRVSamplerAddressingModeKind { SPIRVSAM_None = 0, SPIRVSAM_ClampEdge = 2, SPIRVSAM_Clamp = 4, SPIRVSAM_Repeat = 6, SPIRVSAM_RepeatMirrored = 8, SPIRVSAM_Invalid = 255, }; enum SPIRVSamplerFilterModeKind { SPIRVSFM_Nearest = 16, SPIRVSFM_Linear = 32, SPIRVSFM_Invalid = 255, }; typedef spv::Capability SPIRVCapabilityKind; typedef spv::ExecutionModel SPIRVExecutionModelKind; typedef spv::ExecutionMode SPIRVExecutionModeKind; typedef spv::AccessQualifier SPIRVAccessQualifierKind; typedef spv::AddressingModel SPIRVAddressingModelKind; typedef spv::LinkageType SPIRVLinkageTypeKind; typedef spv::MemoryModel SPIRVMemoryModelKind; typedef spv::StorageClass SPIRVStorageClassKind; typedef spv::FunctionControlMask SPIRVFunctionControlMaskKind; typedef spv::FPRoundingMode SPIRVFPRoundingModeKind; typedef spv::FunctionParameterAttribute SPIRVFuncParamAttrKind; typedef spv::BuiltIn SPIRVBuiltinVariableKind; typedef spv::MemoryAccessMask SPIRVMemoryAccessKind; typedef spv::GroupOperation SPIRVGroupOperationKind; typedef spv::Dim SPIRVImageDimKind; typedef std::vector SPIRVCapVec; typedef std::set SPIRVExtSet; template <> inline void SPIRVMap::init() { #define _STRINGIFY(X) #X #define STRINGIFY(X) _STRINGIFY(X) #define EXT(X) add(ExtensionID::X, STRINGIFY(X)); #include "LLVMSPIRVExtensions.inc" #undef EXT #undef STRINGIFY #undef _STRINGIFY } template <> inline void SPIRVMap::init() { add(SPIRVEIS_OpenCL, "OpenCL.std"); add(SPIRVEIS_Debug, "SPIRV.debug"); } typedef SPIRVMap SPIRVBuiltinSetNameMap; template SPIRVCapVec getCapability(K Key) { SPIRVCapVec V; SPIRVMap::find(Key, &V); return V; } #define ADD_VEC_INIT(Cap, ...) \ { \ SPIRVCapabilityKind C[] = __VA_ARGS__; \ SPIRVCapVec V(C, C + sizeof(C) / sizeof(C[0])); \ add(Cap, V); \ } template <> inline void SPIRVMap::init() { ADD_VEC_INIT(CapabilityShader, {CapabilityMatrix}); ADD_VEC_INIT(CapabilityGeometry, {CapabilityShader}); ADD_VEC_INIT(CapabilityTessellation, {CapabilityShader}); ADD_VEC_INIT(CapabilityVector16, {CapabilityKernel}); ADD_VEC_INIT(CapabilityFloat16Buffer, {CapabilityKernel}); ADD_VEC_INIT(CapabilityInt64Atomics, {CapabilityInt64}); ADD_VEC_INIT(CapabilityImageBasic, {CapabilityKernel}); ADD_VEC_INIT(CapabilityImageReadWrite, {CapabilityImageBasic}); ADD_VEC_INIT(CapabilityImageMipmap, {CapabilityImageBasic}); ADD_VEC_INIT(CapabilityPipes, {CapabilityKernel}); ADD_VEC_INIT(CapabilityBlockingPipesINTEL, {CapabilityKernel}); ADD_VEC_INIT(CapabilityDeviceEnqueue, {CapabilityKernel}); ADD_VEC_INIT(CapabilityLiteralSampler, {CapabilityKernel}); ADD_VEC_INIT(CapabilityAtomicStorage, {CapabilityShader}); ADD_VEC_INIT(CapabilityTessellationPointSize, {CapabilityTessellation}); ADD_VEC_INIT(CapabilityGeometryPointSize, {CapabilityGeometry}); ADD_VEC_INIT(CapabilityImageGatherExtended, {CapabilityShader}); ADD_VEC_INIT(CapabilityStorageImageMultisample, {CapabilityShader}); ADD_VEC_INIT(CapabilityUniformBufferArrayDynamicIndexing, {CapabilityShader}); ADD_VEC_INIT(CapabilitySampledImageArrayDynamicIndexing, {CapabilityShader}); ADD_VEC_INIT(CapabilityStorageBufferArrayDynamicIndexing, {CapabilityShader}); ADD_VEC_INIT(CapabilityStorageImageArrayDynamicIndexing, {CapabilityShader}); ADD_VEC_INIT(CapabilityClipDistance, {CapabilityShader}); ADD_VEC_INIT(CapabilityCullDistance, {CapabilityShader}); ADD_VEC_INIT(CapabilityImageCubeArray, {CapabilitySampledCubeArray}); ADD_VEC_INIT(CapabilitySampleRateShading, {CapabilityShader}); ADD_VEC_INIT(CapabilityImageRect, {CapabilitySampledRect}); ADD_VEC_INIT(CapabilitySampledRect, {CapabilityShader}); ADD_VEC_INIT(CapabilityGenericPointer, {CapabilityAddresses}); ADD_VEC_INIT(CapabilityInt8, {CapabilityKernel}); ADD_VEC_INIT(CapabilityInputAttachment, {CapabilityShader}); ADD_VEC_INIT(CapabilitySparseResidency, {CapabilityShader}); ADD_VEC_INIT(CapabilityMinLod, {CapabilityShader}); ADD_VEC_INIT(CapabilityImage1D, {CapabilitySampled1D}); ADD_VEC_INIT(CapabilitySampledCubeArray, {CapabilityShader}); ADD_VEC_INIT(CapabilityImageBuffer, {CapabilitySampledBuffer}); ADD_VEC_INIT(CapabilityImageMSArray, {CapabilityShader}); ADD_VEC_INIT(CapabilityStorageImageExtendedFormats, {CapabilityShader}); ADD_VEC_INIT(CapabilityImageQuery, {CapabilityShader}); ADD_VEC_INIT(CapabilityDerivativeControl, {CapabilityShader}); ADD_VEC_INIT(CapabilityInterpolationFunction, {CapabilityShader}); ADD_VEC_INIT(CapabilityTransformFeedback, {CapabilityShader}); ADD_VEC_INIT(CapabilityGeometryStreams, {CapabilityGeometry}); ADD_VEC_INIT(CapabilityStorageImageReadWithoutFormat, {CapabilityShader}); ADD_VEC_INIT(CapabilityStorageImageWriteWithoutFormat, {CapabilityShader}); ADD_VEC_INIT(CapabilityMultiViewport, {CapabilityGeometry}); ADD_VEC_INIT(CapabilitySubgroupAvcMotionEstimationINTEL, {CapabilityGroups}); ADD_VEC_INIT(CapabilitySubgroupAvcMotionEstimationIntraINTEL, {CapabilitySubgroupAvcMotionEstimationINTEL}); ADD_VEC_INIT(CapabilitySubgroupAvcMotionEstimationChromaINTEL, {CapabilitySubgroupAvcMotionEstimationIntraINTEL}); } template <> inline void SPIRVMap::init() { ADD_VEC_INIT(ExecutionModelVertex, {CapabilityShader}); ADD_VEC_INIT(ExecutionModelTessellationControl, {CapabilityTessellation}); ADD_VEC_INIT(ExecutionModelTessellationEvaluation, {CapabilityTessellation}); ADD_VEC_INIT(ExecutionModelGeometry, {CapabilityGeometry}); ADD_VEC_INIT(ExecutionModelFragment, {CapabilityShader}); ADD_VEC_INIT(ExecutionModelGLCompute, {CapabilityShader}); ADD_VEC_INIT(ExecutionModelKernel, {CapabilityKernel}); } template <> inline void SPIRVMap::init() { ADD_VEC_INIT(ExecutionModeInvocations, {CapabilityGeometry}); ADD_VEC_INIT(ExecutionModeSpacingEqual, {CapabilityTessellation}); ADD_VEC_INIT(ExecutionModeSpacingFractionalEven, {CapabilityTessellation}); ADD_VEC_INIT(ExecutionModeSpacingFractionalOdd, {CapabilityTessellation}); ADD_VEC_INIT(ExecutionModeVertexOrderCw, {CapabilityTessellation}); ADD_VEC_INIT(ExecutionModeVertexOrderCcw, {CapabilityTessellation}); ADD_VEC_INIT(ExecutionModePixelCenterInteger, {CapabilityShader}); ADD_VEC_INIT(ExecutionModeOriginUpperLeft, {CapabilityShader}); ADD_VEC_INIT(ExecutionModeOriginLowerLeft, {CapabilityShader}); ADD_VEC_INIT(ExecutionModeEarlyFragmentTests, {CapabilityShader}); ADD_VEC_INIT(ExecutionModePointMode, {CapabilityTessellation}); ADD_VEC_INIT(ExecutionModeXfb, {CapabilityTransformFeedback}); ADD_VEC_INIT(ExecutionModeDepthReplacing, {CapabilityShader}); ADD_VEC_INIT(ExecutionModeDepthGreater, {CapabilityShader}); ADD_VEC_INIT(ExecutionModeDepthLess, {CapabilityShader}); ADD_VEC_INIT(ExecutionModeDepthUnchanged, {CapabilityShader}); ADD_VEC_INIT(ExecutionModeLocalSizeHint, {CapabilityKernel}); ADD_VEC_INIT(ExecutionModeInputPoints, {CapabilityGeometry}); ADD_VEC_INIT(ExecutionModeInputLines, {CapabilityGeometry}); ADD_VEC_INIT(ExecutionModeInputLinesAdjacency, {CapabilityGeometry}); ADD_VEC_INIT(ExecutionModeTriangles, {CapabilityGeometry, CapabilityTessellation}); ADD_VEC_INIT(ExecutionModeInputTrianglesAdjacency, {CapabilityGeometry}); ADD_VEC_INIT(ExecutionModeQuads, {CapabilityTessellation}); ADD_VEC_INIT(ExecutionModeIsolines, {CapabilityTessellation}); ADD_VEC_INIT(ExecutionModeOutputVertices, {CapabilityGeometry, CapabilityTessellation}); ADD_VEC_INIT(ExecutionModeOutputPoints, {CapabilityGeometry}); ADD_VEC_INIT(ExecutionModeOutputLineStrip, {CapabilityGeometry}); ADD_VEC_INIT(ExecutionModeOutputTriangleStrip, {CapabilityGeometry}); ADD_VEC_INIT(ExecutionModeVecTypeHint, {CapabilityKernel}); ADD_VEC_INIT(ExecutionModeContractionOff, {CapabilityKernel}); } template <> inline void SPIRVMap::init() { ADD_VEC_INIT(MemoryModelSimple, {CapabilityShader}); ADD_VEC_INIT(MemoryModelGLSL450, {CapabilityShader}); ADD_VEC_INIT(MemoryModelOpenCL, {CapabilityKernel}); } template <> inline void SPIRVMap::init() { ADD_VEC_INIT(StorageClassUniform, {CapabilityShader}); ADD_VEC_INIT(StorageClassOutput, {CapabilityShader}); ADD_VEC_INIT(StorageClassPrivate, {CapabilityShader}); ADD_VEC_INIT(StorageClassGeneric, {CapabilityGenericPointer}); ADD_VEC_INIT(StorageClassPushConstant, {CapabilityShader}); ADD_VEC_INIT(StorageClassAtomicCounter, {CapabilityAtomicStorage}); } template <> inline void SPIRVMap::init() { ADD_VEC_INIT(Dim1D, {CapabilitySampled1D}); ADD_VEC_INIT(DimCube, {CapabilityShader}); ADD_VEC_INIT(DimRect, {CapabilitySampledRect}); ADD_VEC_INIT(DimBuffer, {CapabilitySampledBuffer}); ADD_VEC_INIT(DimSubpassData, {CapabilityInputAttachment}); } template <> inline void SPIRVMap::init() { ADD_VEC_INIT(ImageFormatRgba32f, {CapabilityShader}); ADD_VEC_INIT(ImageFormatRgba16f, {CapabilityShader}); ADD_VEC_INIT(ImageFormatR32f, {CapabilityShader}); ADD_VEC_INIT(ImageFormatRgba8, {CapabilityShader}); ADD_VEC_INIT(ImageFormatRgba8Snorm, {CapabilityShader}); ADD_VEC_INIT(ImageFormatRg32f, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatRg16f, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatR11fG11fB10f, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatR16f, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatRgba16, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatRgb10A2, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatRg16, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatRg8, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatR16, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatR8, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatRgba16Snorm, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatRg16Snorm, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatRg8Snorm, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatR16Snorm, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatR8Snorm, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatRgba32i, {CapabilityShader}); ADD_VEC_INIT(ImageFormatRgba16i, {CapabilityShader}); ADD_VEC_INIT(ImageFormatRgba8i, {CapabilityShader}); ADD_VEC_INIT(ImageFormatR32i, {CapabilityShader}); ADD_VEC_INIT(ImageFormatRg32i, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatRg16i, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatRg8i, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatR16i, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatR8i, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatRgba32ui, {CapabilityShader}); ADD_VEC_INIT(ImageFormatRgba16ui, {CapabilityShader}); ADD_VEC_INIT(ImageFormatRgba8ui, {CapabilityShader}); ADD_VEC_INIT(ImageFormatR32ui, {CapabilityShader}); ADD_VEC_INIT(ImageFormatRgb10a2ui, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatRg32ui, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatRg16ui, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatR16ui, {CapabilityStorageImageExtendedFormats}); ADD_VEC_INIT(ImageFormatR8ui, {CapabilityStorageImageExtendedFormats}); } template <> inline void SPIRVMap::init() { ADD_VEC_INIT(ImageOperandsBiasMask, {CapabilityShader}); ADD_VEC_INIT(ImageOperandsOffsetMask, {CapabilityImageGatherExtended}); ADD_VEC_INIT(ImageOperandsMinLodMask, {CapabilityMinLod}); } template <> inline void SPIRVMap::init() { ADD_VEC_INIT(DecorationRelaxedPrecision, {CapabilityShader}); ADD_VEC_INIT(DecorationSpecId, {CapabilityShader}); ADD_VEC_INIT(DecorationBlock, {CapabilityShader}); ADD_VEC_INIT(DecorationBufferBlock, {CapabilityShader}); ADD_VEC_INIT(DecorationRowMajor, {CapabilityMatrix}); ADD_VEC_INIT(DecorationColMajor, {CapabilityMatrix}); ADD_VEC_INIT(DecorationArrayStride, {CapabilityShader}); ADD_VEC_INIT(DecorationMatrixStride, {CapabilityMatrix}); ADD_VEC_INIT(DecorationGLSLShared, {CapabilityShader}); ADD_VEC_INIT(DecorationGLSLPacked, {CapabilityShader}); ADD_VEC_INIT(DecorationCPacked, {CapabilityKernel}); ADD_VEC_INIT(DecorationNoPerspective, {CapabilityShader}); ADD_VEC_INIT(DecorationFlat, {CapabilityShader}); ADD_VEC_INIT(DecorationPatch, {CapabilityTessellation}); ADD_VEC_INIT(DecorationCentroid, {CapabilityShader}); ADD_VEC_INIT(DecorationSample, {CapabilitySampleRateShading}); ADD_VEC_INIT(DecorationInvariant, {CapabilityShader}); ADD_VEC_INIT(DecorationConstant, {CapabilityKernel}); ADD_VEC_INIT(DecorationUniform, {CapabilityShader}); ADD_VEC_INIT(DecorationSaturatedConversion, {CapabilityKernel}); ADD_VEC_INIT(DecorationStream, {CapabilityGeometryStreams}); ADD_VEC_INIT(DecorationLocation, {CapabilityShader}); ADD_VEC_INIT(DecorationComponent, {CapabilityShader}); ADD_VEC_INIT(DecorationIndex, {CapabilityShader}); ADD_VEC_INIT(DecorationBinding, {CapabilityShader}); ADD_VEC_INIT(DecorationDescriptorSet, {CapabilityShader}); ADD_VEC_INIT(DecorationOffset, {CapabilityShader}); ADD_VEC_INIT(DecorationXfbBuffer, {CapabilityTransformFeedback}); ADD_VEC_INIT(DecorationXfbStride, {CapabilityTransformFeedback}); ADD_VEC_INIT(DecorationFuncParamAttr, {CapabilityKernel}); ADD_VEC_INIT(DecorationFPRoundingMode, {CapabilityKernel}); ADD_VEC_INIT(DecorationFPFastMathMode, {CapabilityKernel}); ADD_VEC_INIT(DecorationLinkageAttributes, {CapabilityLinkage}); ADD_VEC_INIT(DecorationNoContraction, {CapabilityShader}); ADD_VEC_INIT(DecorationInputAttachmentIndex, {CapabilityInputAttachment}); ADD_VEC_INIT(DecorationAlignment, {CapabilityKernel}); ADD_VEC_INIT(DecorationRegisterINTEL, {CapabilityFPGAMemoryAttributesINTEL}); ADD_VEC_INIT(DecorationMemoryINTEL, {CapabilityFPGAMemoryAttributesINTEL}); ADD_VEC_INIT(DecorationNumbanksINTEL, {CapabilityFPGAMemoryAttributesINTEL}); ADD_VEC_INIT(DecorationBankwidthINTEL, {CapabilityFPGAMemoryAttributesINTEL}); ADD_VEC_INIT(DecorationMaxPrivateCopiesINTEL, {CapabilityFPGAMemoryAttributesINTEL}); ADD_VEC_INIT(DecorationSinglepumpINTEL, {CapabilityFPGAMemoryAttributesINTEL}); ADD_VEC_INIT(DecorationDoublepumpINTEL, {CapabilityFPGAMemoryAttributesINTEL}); ADD_VEC_INIT(DecorationMaxReplicatesINTEL, {CapabilityFPGAMemoryAttributesINTEL}); ADD_VEC_INIT(DecorationSimpleDualPortINTEL, {CapabilityFPGAMemoryAttributesINTEL}); ADD_VEC_INIT(DecorationMergeINTEL, {CapabilityFPGAMemoryAttributesINTEL}); ADD_VEC_INIT(DecorationBankBitsINTEL, {CapabilityFPGAMemoryAttributesINTEL}); ADD_VEC_INIT(DecorationReferencedIndirectlyINTEL, {CapabilityIndirectReferencesINTEL}); ADD_VEC_INIT(DecorationSideEffectsINTEL, {CapabilityAsmINTEL}); } template <> inline void SPIRVMap::init() { ADD_VEC_INIT(BuiltInPosition, {CapabilityShader}); ADD_VEC_INIT(BuiltInPointSize, {CapabilityShader}); ADD_VEC_INIT(BuiltInClipDistance, {CapabilityClipDistance}); ADD_VEC_INIT(BuiltInCullDistance, {CapabilityCullDistance}); ADD_VEC_INIT(BuiltInVertexId, {CapabilityShader}); ADD_VEC_INIT(BuiltInInstanceId, {CapabilityShader}); ADD_VEC_INIT(BuiltInPrimitiveId, {CapabilityGeometry, CapabilityTessellation}); ADD_VEC_INIT(BuiltInInvocationId, {CapabilityGeometry, CapabilityTessellation}); ADD_VEC_INIT(BuiltInLayer, {CapabilityGeometry}); ADD_VEC_INIT(BuiltInViewportIndex, {CapabilityMultiViewport}); ADD_VEC_INIT(BuiltInTessLevelOuter, {CapabilityTessellation}); ADD_VEC_INIT(BuiltInTessLevelInner, {CapabilityTessellation}); ADD_VEC_INIT(BuiltInTessCoord, {CapabilityTessellation}); ADD_VEC_INIT(BuiltInPatchVertices, {CapabilityTessellation}); ADD_VEC_INIT(BuiltInFragCoord, {CapabilityShader}); ADD_VEC_INIT(BuiltInPointCoord, {CapabilityShader}); ADD_VEC_INIT(BuiltInFrontFacing, {CapabilityShader}); ADD_VEC_INIT(BuiltInSampleId, {CapabilitySampleRateShading}); ADD_VEC_INIT(BuiltInSamplePosition, {CapabilitySampleRateShading}); ADD_VEC_INIT(BuiltInSampleMask, {CapabilitySampleRateShading}); ADD_VEC_INIT(BuiltInFragDepth, {CapabilityShader}); ADD_VEC_INIT(BuiltInHelperInvocation, {CapabilityShader}); ADD_VEC_INIT(BuiltInWorkDim, {CapabilityKernel}); ADD_VEC_INIT(BuiltInGlobalSize, {CapabilityKernel}); ADD_VEC_INIT(BuiltInEnqueuedWorkgroupSize, {CapabilityKernel}); ADD_VEC_INIT(BuiltInGlobalOffset, {CapabilityKernel}); ADD_VEC_INIT(BuiltInGlobalLinearId, {CapabilityKernel}); ADD_VEC_INIT(BuiltInSubgroupSize, {CapabilityKernel}); ADD_VEC_INIT(BuiltInSubgroupMaxSize, {CapabilityKernel}); ADD_VEC_INIT(BuiltInNumSubgroups, {CapabilityKernel}); ADD_VEC_INIT(BuiltInNumEnqueuedSubgroups, {CapabilityKernel}); ADD_VEC_INIT(BuiltInSubgroupId, {CapabilityKernel}); ADD_VEC_INIT(BuiltInSubgroupLocalInvocationId, {CapabilityKernel}); ADD_VEC_INIT(BuiltInVertexIndex, {CapabilityShader}); ADD_VEC_INIT(BuiltInInstanceIndex, {CapabilityShader}); } template <> inline void SPIRVMap::init() { ADD_VEC_INIT(MemorySemanticsUniformMemoryMask, {CapabilityShader}); ADD_VEC_INIT(MemorySemanticsAtomicCounterMemoryMask, {CapabilityAtomicStorage}); } #undef ADD_VEC_INIT inline unsigned getImageDimension(SPIRVImageDimKind K) { switch (K) { case Dim1D: return 1; case Dim2D: return 2; case Dim3D: return 3; case DimCube: return 2; case DimRect: return 2; case DimBuffer: return 1; default: return 0; } } /// Extract memory order part of SPIR-V memory semantics. inline unsigned extractSPIRVMemOrderSemantic(unsigned Sema) { return Sema & KSpirvMemOrderSemanticMask; } } // namespace SPIRV #endif // SPIRV_LIBSPIRV_SPIRVENUM_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVError.h000066400000000000000000000117361363521741200225370ustar00rootroot00000000000000//===- SPIRVError.h - SPIR-V error code and checking ------------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// // // This file defines SPIRV error code and checking utility. // //===----------------------------------------------------------------------===// #ifndef SPIRV_LIBSPIRV_SPIRVERROR_H #define SPIRV_LIBSPIRV_SPIRVERROR_H #include "SPIRVDebug.h" #include "SPIRVUtil.h" #include #include namespace SPIRV { // Check condition and set error code and error msg. // To use this macro, function checkError must be defined in the scope. #define SPIRVCK(Condition, ErrCode, ErrMsg) \ getErrorLog().checkError(Condition, SPIRVEC_##ErrCode, \ std::string() + (ErrMsg), #Condition, __FILE__, \ __LINE__) // Check condition and set error code and error msg. If fail returns false. #define SPIRVCKRT(Condition, ErrCode, ErrMsg) \ if (!getErrorLog().checkError(Condition, SPIRVEC_##ErrCode, \ std::string() + (ErrMsg), #Condition, \ __FILE__, __LINE__)) \ return false; // Defines error code enum type SPIRVErrorCode. enum SPIRVErrorCode { #define _SPIRV_OP(x, y) SPIRVEC_##x, #include "SPIRVErrorEnum.h" #undef _SPIRV_OP }; // Defines SPIRVErrorMap which maps error code to a string describing the error. template <> inline void SPIRVMap::init() { #define _SPIRV_OP(x, y) add(SPIRVEC_##x, std::string(#x) + ": " + (y)); #include "SPIRVErrorEnum.h" #undef _SPIRV_OP } typedef SPIRVMap SPIRVErrorMap; class SPIRVErrorLog { public: SPIRVErrorLog() : ErrorCode(SPIRVEC_Success) {} SPIRVErrorCode getError(std::string &ErrMsg) { ErrMsg = ErrorMsg; return ErrorCode; } void setError(SPIRVErrorCode ErrCode, const std::string &ErrMsg) { ErrorCode = ErrCode; ErrorMsg = ErrMsg; } // Check if Condition is satisfied and set ErrCode and DetailedMsg // if not. Returns true if no error. bool checkError(bool Condition, SPIRVErrorCode ErrCode, const std::string &DetailedMsg = "", const char *CondString = nullptr, const char *FileName = nullptr, unsigned LineNumber = 0); protected: SPIRVErrorCode ErrorCode; std::string ErrorMsg; }; inline bool SPIRVErrorLog::checkError(bool Cond, SPIRVErrorCode ErrCode, const std::string &Msg, const char *CondString, const char *FileName, unsigned LineNo) { std::stringstream SS; if (Cond) return Cond; // Do not overwrite previous failure. if (ErrorCode != SPIRVEC_Success) return Cond; SS << SPIRVErrorMap::map(ErrCode) << " " << Msg; if (SPIRVDbgErrorMsgIncludesSourceInfo && FileName) SS << " [Src: " << FileName << ":" << LineNo << " " << CondString << " ]"; setError(ErrCode, SS.str()); if (SPIRVDbgAbortOnError) { spvdbgs() << SS.str() << '\n'; spvdbgs().flush(); abort(); } return Cond; } } // namespace SPIRV #endif // SPIRV_LIBSPIRV_SPIRVERROR_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVErrorEnum.h000066400000000000000000000013601363521741200233540ustar00rootroot00000000000000/* The error code name should be meaningful since it is part of error message */ _SPIRV_OP(Success, "") _SPIRV_OP(InvalidTargetTriple, "Expects spir-unknown-unknown or spir64-unknown-unknown.") _SPIRV_OP(InvalidAddressingModel, "Expects 0-2.") _SPIRV_OP(InvalidMemoryModel, "Expects 0-3.") _SPIRV_OP(InvalidFunctionControlMask, "") _SPIRV_OP(InvalidBuiltinSetName, "Expects OpenCL.std.") _SPIRV_OP(InvalidFunctionCall, "Unexpected llvm intrinsic:") _SPIRV_OP(InvalidArraySize, "Array size must be at least 1:") _SPIRV_OP(InvalidBitWidth, "Invalid bit width in input:") _SPIRV_OP(InvalidModule, "Invalid SPIR-V module:") _SPIRV_OP(UnimplementedOpCode, "Unimplemented opcode") _SPIRV_OP(FunctionPointers, "Can't translate function pointer:\n") SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVExtInst.h000066400000000000000000000246631363521741200230470ustar00rootroot00000000000000//===- SPIRVBuiltin.h - SPIR-V extended instruction -------------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines SPIR-V extended instructions. /// //===----------------------------------------------------------------------===// #ifndef SPIRV_LIBSPIRV_SPIRVEXTINST_H #define SPIRV_LIBSPIRV_SPIRVEXTINST_H #include "OpenCL.std.h" #include "SPIRV.debug.h" #include "SPIRVEnum.h" #include "SPIRVUtil.h" #include #include namespace SPIRV { typedef OpenCLLIB::Entrypoints OCLExtOpKind; template <> inline void SPIRVMap::init() { add(OpenCLLIB::Acos, "acos"); add(OpenCLLIB::Acosh, "acosh"); add(OpenCLLIB::Acospi, "acospi"); add(OpenCLLIB::Asin, "asin"); add(OpenCLLIB::Asinh, "asinh"); add(OpenCLLIB::Asinpi, "asinpi"); add(OpenCLLIB::Atan, "atan"); add(OpenCLLIB::Atan2, "atan2"); add(OpenCLLIB::Atanh, "atanh"); add(OpenCLLIB::Atanpi, "atanpi"); add(OpenCLLIB::Atan2pi, "atan2pi"); add(OpenCLLIB::Cbrt, "cbrt"); add(OpenCLLIB::Ceil, "ceil"); add(OpenCLLIB::Copysign, "copysign"); add(OpenCLLIB::Cos, "cos"); add(OpenCLLIB::Cosh, "cosh"); add(OpenCLLIB::Cospi, "cospi"); add(OpenCLLIB::Erfc, "erfc"); add(OpenCLLIB::Erf, "erf"); add(OpenCLLIB::Exp, "exp"); add(OpenCLLIB::Exp2, "exp2"); add(OpenCLLIB::Exp10, "exp10"); add(OpenCLLIB::Expm1, "expm1"); add(OpenCLLIB::Fabs, "fabs"); add(OpenCLLIB::Fdim, "fdim"); add(OpenCLLIB::Floor, "floor"); add(OpenCLLIB::Fma, "fma"); add(OpenCLLIB::Fmax, "fmax"); add(OpenCLLIB::Fmin, "fmin"); add(OpenCLLIB::Fmod, "fmod"); add(OpenCLLIB::Fract, "fract"); add(OpenCLLIB::Frexp, "frexp"); add(OpenCLLIB::Hypot, "hypot"); add(OpenCLLIB::Ilogb, "ilogb"); add(OpenCLLIB::Ldexp, "ldexp"); add(OpenCLLIB::Lgamma, "lgamma"); add(OpenCLLIB::Lgamma_r, "lgamma_r"); add(OpenCLLIB::Log, "log"); add(OpenCLLIB::Log2, "log2"); add(OpenCLLIB::Log10, "log10"); add(OpenCLLIB::Log1p, "log1p"); add(OpenCLLIB::Logb, "logb"); add(OpenCLLIB::Mad, "mad"); add(OpenCLLIB::Maxmag, "maxmag"); add(OpenCLLIB::Minmag, "minmag"); add(OpenCLLIB::Modf, "modf"); add(OpenCLLIB::Nan, "nan"); add(OpenCLLIB::Nextafter, "nextafter"); add(OpenCLLIB::Pow, "pow"); add(OpenCLLIB::Pown, "pown"); add(OpenCLLIB::Powr, "powr"); add(OpenCLLIB::Remainder, "remainder"); add(OpenCLLIB::Remquo, "remquo"); add(OpenCLLIB::Rint, "rint"); add(OpenCLLIB::Rootn, "rootn"); add(OpenCLLIB::Round, "round"); add(OpenCLLIB::Rsqrt, "rsqrt"); add(OpenCLLIB::Sin, "sin"); add(OpenCLLIB::Sincos, "sincos"); add(OpenCLLIB::Sinh, "sinh"); add(OpenCLLIB::Sinpi, "sinpi"); add(OpenCLLIB::Sqrt, "sqrt"); add(OpenCLLIB::Tan, "tan"); add(OpenCLLIB::Tanh, "tanh"); add(OpenCLLIB::Tanpi, "tanpi"); add(OpenCLLIB::Tgamma, "tgamma"); add(OpenCLLIB::Trunc, "trunc"); add(OpenCLLIB::Half_cos, "half_cos"); add(OpenCLLIB::Half_divide, "half_divide"); add(OpenCLLIB::Half_exp, "half_exp"); add(OpenCLLIB::Half_exp2, "half_exp2"); add(OpenCLLIB::Half_exp10, "half_exp10"); add(OpenCLLIB::Half_log, "half_log"); add(OpenCLLIB::Half_log2, "half_log2"); add(OpenCLLIB::Half_log10, "half_log10"); add(OpenCLLIB::Half_powr, "half_powr"); add(OpenCLLIB::Half_recip, "half_recip"); add(OpenCLLIB::Half_rsqrt, "half_rsqrt"); add(OpenCLLIB::Half_sin, "half_sin"); add(OpenCLLIB::Half_sqrt, "half_sqrt"); add(OpenCLLIB::Half_tan, "half_tan"); add(OpenCLLIB::Native_cos, "native_cos"); add(OpenCLLIB::Native_divide, "native_divide"); add(OpenCLLIB::Native_exp, "native_exp"); add(OpenCLLIB::Native_exp2, "native_exp2"); add(OpenCLLIB::Native_exp10, "native_exp10"); add(OpenCLLIB::Native_log, "native_log"); add(OpenCLLIB::Native_log2, "native_log2"); add(OpenCLLIB::Native_log10, "native_log10"); add(OpenCLLIB::Native_powr, "native_powr"); add(OpenCLLIB::Native_recip, "native_recip"); add(OpenCLLIB::Native_rsqrt, "native_rsqrt"); add(OpenCLLIB::Native_sin, "native_sin"); add(OpenCLLIB::Native_sqrt, "native_sqrt"); add(OpenCLLIB::Native_tan, "native_tan"); add(OpenCLLIB::FClamp, "fclamp"); add(OpenCLLIB::Degrees, "degrees"); add(OpenCLLIB::Mix, "mix"); add(OpenCLLIB::FMax_common, "fmax_common"); add(OpenCLLIB::FMin_common, "fmin_common"); add(OpenCLLIB::Radians, "radians"); add(OpenCLLIB::Step, "step"); add(OpenCLLIB::Smoothstep, "smoothstep"); add(OpenCLLIB::Sign, "sign"); add(OpenCLLIB::Cross, "cross"); add(OpenCLLIB::Distance, "distance"); add(OpenCLLIB::Length, "length"); add(OpenCLLIB::Normalize, "normalize"); add(OpenCLLIB::Fast_distance, "fast_distance"); add(OpenCLLIB::Fast_length, "fast_length"); add(OpenCLLIB::Fast_normalize, "fast_normalize"); add(OpenCLLIB::SAbs, "s_abs"); add(OpenCLLIB::SAbs_diff, "s_abs_diff"); add(OpenCLLIB::SAdd_sat, "s_add_sat"); add(OpenCLLIB::UAdd_sat, "u_add_sat"); add(OpenCLLIB::SHadd, "s_hadd"); add(OpenCLLIB::UHadd, "u_hadd"); add(OpenCLLIB::SRhadd, "s_rhadd"); add(OpenCLLIB::URhadd, "u_rhadd"); add(OpenCLLIB::SClamp, "s_clamp"); add(OpenCLLIB::UClamp, "u_clamp"); add(OpenCLLIB::Clz, "clz"); add(OpenCLLIB::Ctz, "ctz"); add(OpenCLLIB::SMad_hi, "s_mad_hi"); add(OpenCLLIB::SMad_sat, "s_mad_sat"); add(OpenCLLIB::UMad_sat, "u_mad_sat"); add(OpenCLLIB::SMax, "s_max"); add(OpenCLLIB::SMin, "s_min"); add(OpenCLLIB::UMax, "u_max"); add(OpenCLLIB::UMin, "u_min"); add(OpenCLLIB::SMul_hi, "s_mul_hi"); add(OpenCLLIB::Rotate, "rotate"); add(OpenCLLIB::SSub_sat, "s_sub_sat"); add(OpenCLLIB::USub_sat, "u_sub_sat"); add(OpenCLLIB::U_Upsample, "u_upsample"); add(OpenCLLIB::S_Upsample, "s_upsample"); add(OpenCLLIB::Popcount, "popcount"); add(OpenCLLIB::SMad24, "s_mad24"); add(OpenCLLIB::UMad24, "u_mad24"); add(OpenCLLIB::SMul24, "s_mul24"); add(OpenCLLIB::UMul24, "u_mul24"); add(OpenCLLIB::Vloadn, "vloadn"); add(OpenCLLIB::Vstoren, "vstoren"); add(OpenCLLIB::Vload_half, "vload_half"); add(OpenCLLIB::Vload_halfn, "vload_halfn"); add(OpenCLLIB::Vstore_half, "vstore_half"); add(OpenCLLIB::Vstore_half_r, "vstore_half_r"); add(OpenCLLIB::Vstore_halfn, "vstore_halfn"); add(OpenCLLIB::Vstore_halfn_r, "vstore_halfn_r"); add(OpenCLLIB::Vloada_halfn, "vloada_halfn"); add(OpenCLLIB::Vstorea_halfn, "vstorea_halfn"); add(OpenCLLIB::Vstorea_halfn_r, "vstorea_halfn_r"); add(OpenCLLIB::Shuffle, "shuffle"); add(OpenCLLIB::Shuffle2, "shuffle2"); add(OpenCLLIB::Printf, "printf"); add(OpenCLLIB::Prefetch, "prefetch"); add(OpenCLLIB::Bitselect, "bitselect"); add(OpenCLLIB::Select, "select"); add(OpenCLLIB::UAbs, "u_abs"); add(OpenCLLIB::UAbs_diff, "u_abs_diff"); add(OpenCLLIB::UMul_hi, "u_mul_hi"); add(OpenCLLIB::UMad_hi, "u_mad_hi"); } SPIRV_DEF_NAMEMAP(OCLExtOpKind, OCLExtOpMap) typedef SPIRVDebug::Instruction SPIRVDebugExtOpKind; template <> inline void SPIRVMap::init() { add(SPIRVDebug::DebugInfoNone, "DebugInfoNone"); add(SPIRVDebug::CompilationUnit, "DebugCompileUnit"); add(SPIRVDebug::Source, "DebugSource"); add(SPIRVDebug::TypeBasic, "DebugTypeBasic"); add(SPIRVDebug::TypePointer, "DebugTypePointer"); add(SPIRVDebug::TypeArray, "DebugTypeArray"); add(SPIRVDebug::TypeVector, "DebugTypeVector"); add(SPIRVDebug::TypeQualifier, "DebugTypeQualifier"); add(SPIRVDebug::TypeFunction, "DebugTypeFunction"); add(SPIRVDebug::TypeComposite, "DebugTypeComposite"); add(SPIRVDebug::TypeMember, "DebugTypeMember"); add(SPIRVDebug::TypeEnum, "DebugTypeEnum"); add(SPIRVDebug::Typedef, "DebugTypedef"); add(SPIRVDebug::TypeTemplateParameter, "DebugTemplateParameter"); add(SPIRVDebug::TypeTemplateParameterPack, "DebugTemplateParameterPack"); add(SPIRVDebug::TypeTemplateTemplateParameter, "DebugTemplateTemplateParameter"); add(SPIRVDebug::TypeTemplate, "DebugTemplate"); add(SPIRVDebug::TypePtrToMember, "DebugTypePtrToMember,"); add(SPIRVDebug::Inheritance, "DebugInheritance"); add(SPIRVDebug::Function, "DebugFunction"); add(SPIRVDebug::FunctionDecl, "DebugFunctionDecl"); add(SPIRVDebug::LexicalBlock, "DebugLexicalBlock"); add(SPIRVDebug::LexicalBlockDiscriminator, "LexicalBlockDiscriminator"); add(SPIRVDebug::LocalVariable, "DebugLocalVariable"); add(SPIRVDebug::InlinedVariable, "DebugInlinedVariable"); add(SPIRVDebug::GlobalVariable, "DebugGlobalVariable"); add(SPIRVDebug::Declare, "DebugDeclare"); add(SPIRVDebug::Value, "DebugValue"); add(SPIRVDebug::Scope, "DebugScope"); add(SPIRVDebug::NoScope, "DebugNoScope"); add(SPIRVDebug::InlinedAt, "DebugInlinedAt"); add(SPIRVDebug::ImportedEntity, "DebugImportedEntity"); add(SPIRVDebug::Expression, "DebugExpression"); add(SPIRVDebug::Operation, "DebugOperation"); } SPIRV_DEF_NAMEMAP(SPIRVDebugExtOpKind, SPIRVDebugExtOpMap) } // namespace SPIRV #endif // SPIRV_LIBSPIRV_SPIRVEXTINST_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVFunction.cpp000066400000000000000000000142331363521741200235610ustar00rootroot00000000000000//===- SPIRVFunction.cpp - Class to represent a SPIR-V Function --- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements Function class for SPIRV. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// #include "SPIRVFunction.h" #include "SPIRVBasicBlock.h" #include "SPIRVEntry.h" #include "SPIRVInstruction.h" #include "SPIRVStream.h" #include #include using namespace SPIRV; SPIRVFunctionParameter::SPIRVFunctionParameter(SPIRVType *TheType, SPIRVId TheId, SPIRVFunction *TheParent, unsigned TheArgNo) : SPIRVValue(TheParent->getModule(), 3, OpFunctionParameter, TheType, TheId), ParentFunc(TheParent), ArgNo(TheArgNo) { validate(); } void SPIRVFunctionParameter::foreachAttr( std::function Func) { auto Locs = Decorates.equal_range(DecorationFuncParamAttr); for (auto I = Locs.first, E = Locs.second; I != E; ++I) { auto Attr = static_cast(I->second->getLiteral(0)); assert(isValid(Attr)); Func(Attr); } } SPIRVDecoder SPIRVFunction::getDecoder(std::istream &IS) { return SPIRVDecoder(IS, *this); } void SPIRVFunction::encode(spv_ostream &O) const { getEncoder(O) << Type << Id << FCtrlMask << FuncType; } void SPIRVFunction::encodeChildren(spv_ostream &O) const { O << SPIRVNL(); for (auto &I : Parameters) O << *I; O << SPIRVNL(); for (auto &I : BBVec) O << *I; O << SPIRVFunctionEnd(); } void SPIRVFunction::encodeExecutionModes(spv_ostream &O) const { for (auto &I : ExecModes) O << *I.second; } void SPIRVFunction::decode(std::istream &I) { SPIRVDecoder Decoder = getDecoder(I); Decoder >> Type >> Id >> FCtrlMask >> FuncType; Module->addFunction(this); SPIRVDBG(spvdbgs() << "Decode function: " << Id << '\n'); Decoder.getWordCountAndOpCode(); while (!I.eof()) { if (Decoder.OpCode == OpFunctionEnd) break; switch (Decoder.OpCode) { case OpFunctionParameter: { auto Param = static_cast(Decoder.getEntry()); assert(Param); Module->add(Param); Param->setParent(this); Parameters.push_back(Param); Decoder.getWordCountAndOpCode(); break; } case OpLabel: { if (!decodeBB(Decoder)) return; break; } default: assert(0 && "Invalid SPIRV format"); } } } /// Decode basic block and contained instructions. /// Do it here instead of in BB:decode to avoid back track in input stream. bool SPIRVFunction::decodeBB(SPIRVDecoder &Decoder) { SPIRVBasicBlock *BB = static_cast(Decoder.getEntry()); assert(BB); addBasicBlock(BB); SPIRVDBG(spvdbgs() << "Decode BB: " << BB->getId() << '\n'); Decoder.setScope(BB); SPIRVEntry *DebugScope = nullptr; while (Decoder.getWordCountAndOpCode()) { if (Decoder.OpCode == OpFunctionEnd || Decoder.OpCode == OpLabel) { break; } if (Decoder.OpCode == OpNoLine || Decoder.OpCode == OpNop) { continue; } SPIRVEntry *Entry = Decoder.getEntry(); if (Decoder.OpCode == OpLine) { Module->add(Entry); continue; } if (!Module->getErrorLog().checkError(Entry->isImplemented(), SPIRVEC_UnimplementedOpCode, std::to_string(Entry->getOpCode()))) { // Bail out if the opcode is not implemented. Module->setInvalid(); return false; } auto *Inst = static_cast(Entry); assert(Inst); if (Inst->getOpCode() == OpUndef) { Module->add(Inst); } else { if (Inst->isExtInst(SPIRVEIS_Debug, SPIRVDebug::Scope)) { DebugScope = Inst; } else if (Inst->isExtInst(SPIRVEIS_Debug, SPIRVDebug::NoScope)) { DebugScope = nullptr; } else { Inst->setDebugScope(DebugScope); } BB->addInstruction(Inst); } } Decoder.setScope(this); return true; } void SPIRVFunction::foreachReturnValueAttr( std::function Func) { auto Locs = Decorates.equal_range(DecorationFuncParamAttr); for (auto I = Locs.first, E = Locs.second; I != E; ++I) { auto Attr = static_cast(I->second->getLiteral(0)); assert(isValid(Attr)); Func(Attr); } } SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVFunction.h000066400000000000000000000163171363521741200232330ustar00rootroot00000000000000//===- SPIRVFunction.h - Class to represent a SPIR-V function ---*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines Function class for SPIRV. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// #ifndef SPIRV_LIBSPIRV_SPIRVFUNCTION_H #define SPIRV_LIBSPIRV_SPIRVFUNCTION_H #include "SPIRVBasicBlock.h" #include "SPIRVValue.h" #include namespace SPIRV { class BIFunction; class SPIRVDecoder; class SPIRVFunctionParameter : public SPIRVValue { public: SPIRVFunctionParameter(SPIRVType *TheType, SPIRVId TheId, SPIRVFunction *TheParent, unsigned TheArgNo); SPIRVFunctionParameter() : SPIRVValue(OpFunctionParameter), ParentFunc(nullptr), ArgNo(0) {} unsigned getArgNo() const { return ArgNo; } void foreachAttr(std::function); void addAttr(SPIRVFuncParamAttrKind Kind) { addDecorate(new SPIRVDecorate(DecorationFuncParamAttr, this, Kind)); } void setParent(SPIRVFunction *Parent) { ParentFunc = Parent; } bool hasAttr(SPIRVFuncParamAttrKind Kind) const { return getDecorate(DecorationFuncParamAttr).count(Kind); } bool isByVal() const { return hasAttr(FunctionParameterAttributeByVal); } bool isZext() const { return hasAttr(FunctionParameterAttributeZext); } SPIRVCapVec getRequiredCapability() const override { if (hasLinkageType() && getLinkageType() == LinkageTypeImport) return getVec(CapabilityLinkage); return SPIRVCapVec(); } protected: void validate() const override { SPIRVValue::validate(); assert(ParentFunc && "Invalid parent function"); } _SPIRV_DEF_ENCDEC2(Type, Id) private: SPIRVFunction *ParentFunc; unsigned ArgNo; }; class SPIRVFunction : public SPIRVValue, public SPIRVComponentExecutionModes { public: // Complete constructor. It does not construct basic blocks. SPIRVFunction(SPIRVModule *M, SPIRVTypeFunction *FunctionType, SPIRVId TheId) : SPIRVValue(M, 5, OpFunction, FunctionType->getReturnType(), TheId), FuncType(FunctionType), FCtrlMask(FunctionControlMaskNone) { addAllArguments(TheId + 1); validate(); } // Incomplete constructor SPIRVFunction() : SPIRVValue(OpFunction), FuncType(NULL), FCtrlMask(FunctionControlMaskNone) {} SPIRVDecoder getDecoder(std::istream &IS) override; SPIRVTypeFunction *getFunctionType() const { return FuncType; } SPIRVWord getFuncCtlMask() const { return FCtrlMask; } size_t getNumBasicBlock() const { return BBVec.size(); } SPIRVBasicBlock *getBasicBlock(size_t I) const { return BBVec[I]; } size_t getNumArguments() const { return getFunctionType()->getNumParameters(); } SPIRVId getArgumentId(size_t I) const { return Parameters[I]->getId(); } const std::vector getVariables() const { std::vector Ids; for (auto Variable : Variables) Ids.push_back(Variable->getId()); return Ids; } void addVariable(const SPIRVValue *Variable) { Variables.push_back(Variable); } SPIRVFunctionParameter *getArgument(size_t I) const { return Parameters[I]; } void foreachArgument(std::function Func) { for (size_t I = 0, E = getNumArguments(); I != E; ++I) Func(getArgument(I)); } void foreachReturnValueAttr(std::function); void setFunctionControlMask(SPIRVWord Mask) { FCtrlMask = Mask; } void takeExecutionModes(SPIRVForward *Forward) { ExecModes = std::move(Forward->ExecModes); } // Assume BB contains valid Id. SPIRVBasicBlock *addBasicBlock(SPIRVBasicBlock *BB) { Module->add(BB); BB->setParent(this); BBVec.push_back(BB); return BB; } void encodeChildren(spv_ostream &) const override; void encodeExecutionModes(spv_ostream &) const; _SPIRV_DCL_ENCDEC void validate() const override { SPIRVValue::validate(); validateFunctionControlMask(FCtrlMask); assert(FuncType && "Invalid func type"); } bool shouldFPContractBeDisabled() const { // We could find some instructions in LLVM IR which look exactly like an // unfused fmuladd. So, we assume that FP_CONTRACT was disabled only if // there are something that looks like uncointracted fmul + fadd, but there // no calls to @llvm.fmuladd.* return FoundUncontractedFMulAdd && !FoundContractedFMulAdd; } void setUncontractedFMulAddFound(bool Value = true) { FoundUncontractedFMulAdd = Value; } void setContractedFMulAddFound(bool Value = true) { FoundContractedFMulAdd = Value; } private: SPIRVFunctionParameter *addArgument(unsigned TheArgNo, SPIRVId TheId) { SPIRVFunctionParameter *Arg = new SPIRVFunctionParameter( getFunctionType()->getParameterType(TheArgNo), TheId, this, TheArgNo); Module->add(Arg); Parameters.push_back(Arg); return Arg; } void addAllArguments(SPIRVId FirstArgId) { for (size_t I = 0, E = getFunctionType()->getNumParameters(); I != E; ++I) addArgument(I, FirstArgId + I); } bool decodeBB(SPIRVDecoder &); SPIRVTypeFunction *FuncType; // Function type SPIRVWord FCtrlMask; // Function control mask std::vector Parameters; std::vector Variables; typedef std::vector SPIRVLBasicBlockVector; SPIRVLBasicBlockVector BBVec; bool FoundUncontractedFMulAdd = false; bool FoundContractedFMulAdd = false; }; typedef SPIRVEntryOpCodeOnly SPIRVFunctionEnd; } // namespace SPIRV #endif // SPIRV_LIBSPIRV_SPIRVFUNCTION_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVInstruction.cpp000066400000000000000000000217561363521741200243250ustar00rootroot00000000000000//===- SPIRVInstruction.cpp -Class to represent SPIR-V instruction - C++ --===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file implements SPIR-V instructions. /// //===----------------------------------------------------------------------===// #include "SPIRVInstruction.h" #include "SPIRVBasicBlock.h" #include "SPIRVFunction.h" #include namespace SPIRV { // Complete constructor for instruction with type and id SPIRVInstruction::SPIRVInstruction(unsigned TheWordCount, Op TheOC, SPIRVType *TheType, SPIRVId TheId, SPIRVBasicBlock *TheBB) : SPIRVValue(TheBB->getModule(), TheWordCount, TheOC, TheType, TheId), BB(TheBB), DebugScope(nullptr) { SPIRVInstruction::validate(); } SPIRVInstruction::SPIRVInstruction(unsigned TheWordCount, Op TheOC, SPIRVType *TheType, SPIRVId TheId, SPIRVBasicBlock *TheBB, SPIRVModule *TheBM) : SPIRVValue(TheBM, TheWordCount, TheOC, TheType, TheId), BB(TheBB), DebugScope(nullptr) { SPIRVInstruction::validate(); } // Complete constructor for instruction with id but no type SPIRVInstruction::SPIRVInstruction(unsigned TheWordCount, Op TheOC, SPIRVId TheId, SPIRVBasicBlock *TheBB) : SPIRVValue(TheBB->getModule(), TheWordCount, TheOC, TheId), BB(TheBB), DebugScope(nullptr) { SPIRVInstruction::validate(); } // Complete constructor for instruction without type and id SPIRVInstruction::SPIRVInstruction(unsigned TheWordCount, Op TheOC, SPIRVBasicBlock *TheBB) : SPIRVValue(TheBB->getModule(), TheWordCount, TheOC), BB(TheBB), DebugScope(nullptr) { SPIRVInstruction::validate(); } // Complete constructor for instruction with type but no id SPIRVInstruction::SPIRVInstruction(unsigned TheWordCount, Op TheOC, SPIRVType *TheType, SPIRVBasicBlock *TheBB) : SPIRVValue(TheBB->getModule(), TheWordCount, TheOC, TheType), BB(TheBB), DebugScope(nullptr) { SPIRVInstruction::validate(); } // Special constructor for debug instruction SPIRVInstruction::SPIRVInstruction(unsigned TheWordCount, Op TheOC, SPIRVType *TheType, SPIRVId TheId, SPIRVModule *TheBM, SPIRVBasicBlock *TheBB) : SPIRVValue(TheBM, TheWordCount, TheOC, TheType, TheId), BB(TheBB), DebugScope(nullptr) { SPIRVInstruction::validate(); } void SPIRVInstruction::setParent(SPIRVBasicBlock *TheBB) { assert(TheBB && "Invalid BB"); if (BB == TheBB) return; assert(BB == NULL && "BB cannot change parent"); BB = TheBB; } void SPIRVInstruction::setScope(SPIRVEntry *Scope) { assert(Scope && Scope->getOpCode() == OpLabel && "Invalid scope"); setParent(static_cast(Scope)); } SPIRVFunctionCall::SPIRVFunctionCall(SPIRVId TheId, SPIRVFunction *TheFunction, const std::vector &TheArgs, SPIRVBasicBlock *BB) : SPIRVFunctionCallGeneric(TheFunction->getFunctionType()->getReturnType(), TheId, TheArgs, BB), FunctionId(TheFunction->getId()) { validate(); } void SPIRVFunctionCall::validate() const { SPIRVFunctionCallGeneric::validate(); } SPIRVFunctionPointerCallINTEL::SPIRVFunctionPointerCallINTEL( SPIRVId TheId, SPIRVValue *TheCalledValue, SPIRVType *TheReturnType, const std::vector &TheArgs, SPIRVBasicBlock *BB) : SPIRVFunctionCallGeneric(TheReturnType, TheId, TheArgs, BB), CalledValueId(TheCalledValue->getId()) { validate(); } void SPIRVFunctionPointerCallINTEL::validate() const { SPIRVFunctionCallGeneric::validate(); } SPIRVFunctionPointerINTEL::SPIRVFunctionPointerINTEL(SPIRVId TheId, SPIRVType *TheType, SPIRVFunction *TheFunction, SPIRVBasicBlock *BB) : SPIRVInstruction(FixedWordCount, OC, TheType, TheId, BB), TheFunction(TheFunction->getId()) { validate(); } void SPIRVFunctionPointerINTEL::validate() const { SPIRVInstruction::validate(); } // ToDo: Each instruction should implement this function std::vector SPIRVInstruction::getOperands() { std::vector Empty; assert(0 && "not supported"); return Empty; } std::vector SPIRVInstruction::getOperandTypes(const std::vector &Ops) { std::vector Tys; for (auto &I : Ops) { SPIRVType *Ty = nullptr; if (I->getOpCode() == OpFunction) Ty = reinterpret_cast(I)->getFunctionType(); else Ty = I->getType(); Tys.push_back(Ty); } return Tys; } std::vector SPIRVInstruction::getOperandTypes() { return getOperandTypes(getOperands()); } bool isSpecConstantOpAllowedOp(Op OC) { static SPIRVWord Table[] = { OpSConvert, OpFConvert, OpConvertFToS, OpConvertSToF, OpConvertFToU, OpConvertUToF, OpUConvert, OpConvertPtrToU, OpConvertUToPtr, OpGenericCastToPtr, OpPtrCastToGeneric, OpBitcast, OpQuantizeToF16, OpSNegate, OpNot, OpIAdd, OpISub, OpIMul, OpUDiv, OpSDiv, OpUMod, OpSRem, OpSMod, OpShiftRightLogical, OpShiftRightArithmetic, OpShiftLeftLogical, OpBitwiseOr, OpBitwiseXor, OpBitwiseAnd, OpFNegate, OpFAdd, OpFSub, OpFMul, OpFDiv, OpFRem, OpFMod, OpVectorShuffle, OpCompositeExtract, OpCompositeInsert, OpLogicalOr, OpLogicalAnd, OpLogicalNot, OpLogicalEqual, OpLogicalNotEqual, OpSelect, OpIEqual, OpULessThan, OpSLessThan, OpUGreaterThan, OpSGreaterThan, OpULessThanEqual, OpSLessThanEqual, OpUGreaterThanEqual, OpSGreaterThanEqual, OpAccessChain, OpInBoundsAccessChain, OpPtrAccessChain, OpInBoundsPtrAccessChain, }; static std::unordered_set Allow(std::begin(Table), std::end(Table)); return Allow.count(OC); } SPIRVSpecConstantOp *createSpecConstantOpInst(SPIRVInstruction *Inst) { auto OC = Inst->getOpCode(); assert(isSpecConstantOpAllowedOp(OC) && "Op code not allowed for OpSpecConstantOp"); auto Ops = Inst->getIds(Inst->getOperands()); Ops.insert(Ops.begin(), OC); return static_cast(SPIRVSpecConstantOp::create( OpSpecConstantOp, Inst->getType(), Inst->getId(), Ops, nullptr, Inst->getModule())); } SPIRVInstruction *createInstFromSpecConstantOp(SPIRVSpecConstantOp *Inst) { assert(Inst->getOpCode() == OpSpecConstantOp && "Not OpSpecConstantOp"); auto Ops = Inst->getOpWords(); auto OC = static_cast(Ops[0]); assert(isSpecConstantOpAllowedOp(OC) && "Op code not allowed for OpSpecConstantOp"); Ops.erase(Ops.begin(), Ops.begin() + 1); return SPIRVInstTemplateBase::create(OC, Inst->getType(), Inst->getId(), Ops, nullptr, Inst->getModule()); } } // namespace SPIRV SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVInstruction.h000066400000000000000000003004441363521741200237640ustar00rootroot00000000000000//===- SPIRVInstruction.h - Class to represent SPIRV instruction -- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines Instruction class for SPIR-V. /// //===----------------------------------------------------------------------===// #ifndef SPIRV_LIBSPIRV_SPIRVINSTRUCTION_H #define SPIRV_LIBSPIRV_SPIRVINSTRUCTION_H #include "SPIRVBasicBlock.h" #include "SPIRVEnum.h" #include "SPIRVIsValidEnum.h" #include "SPIRVOpCode.h" #include "SPIRVStream.h" #include "SPIRVValue.h" #include #include #include #include #include #include #include #include namespace SPIRV { typedef std::vector ValueVec; typedef std::pair ValueRange; class SPIRVBasicBlock; class SPIRVFunction; bool isSpecConstantOpAllowedOp(Op OC); class SPIRVComponentExecutionScope { public: SPIRVComponentExecutionScope(Scope TheScope = ScopeInvocation) : ExecScope(TheScope) {} Scope ExecScope; }; class SPIRVComponentMemorySemanticsMask { public: SPIRVComponentMemorySemanticsMask(SPIRVWord TheSema = SPIRVWORD_MAX) : MemSema(TheSema) {} SPIRVWord MemSema; }; class SPIRVComponentOperands { public: SPIRVComponentOperands(){}; SPIRVComponentOperands(const std::vector &TheOperands) : Operands(TheOperands){}; SPIRVComponentOperands(std::vector &&TheOperands) : Operands(std::move(TheOperands)){}; std::vector getCompOperands() { return Operands; } std::vector getCompOperandTypes() { std::vector Tys; for (auto &I : getCompOperands()) Tys.push_back(I->getType()); return Tys; } protected: std::vector Operands; }; class SPIRVInstruction : public SPIRVValue { public: // Complete constructor for instruction with type and id SPIRVInstruction(unsigned TheWordCount, Op TheOC, SPIRVType *TheType, SPIRVId TheId, SPIRVBasicBlock *TheBB); // Complete constructor for instruction with module, type and id SPIRVInstruction(unsigned TheWordCount, Op TheOC, SPIRVType *TheType, SPIRVId TheId, SPIRVBasicBlock *TheBB, SPIRVModule *TheBM); // Complete constructor for instruction with id but no type SPIRVInstruction(unsigned TheWordCount, Op TheOC, SPIRVId TheId, SPIRVBasicBlock *TheBB); // Complete constructor for instruction without type and id SPIRVInstruction(unsigned TheWordCount, Op TheOC, SPIRVBasicBlock *TheBB); // Complete constructor for instruction with type but no id SPIRVInstruction(unsigned TheWordCount, Op TheOC, SPIRVType *TheType, SPIRVBasicBlock *TheBB); // Special constructor for debug instruction SPIRVInstruction(unsigned TheWordCount, Op TheOC, SPIRVType *TheType, SPIRVId TheId, SPIRVModule *TheBM, SPIRVBasicBlock *TheBB = nullptr); // Incomplete constructor SPIRVInstruction(Op TheOC = OpNop) : SPIRVValue(TheOC), BB(NULL), DebugScope(nullptr) {} bool isInst() const override { return true; } SPIRVBasicBlock *getParent() const { return BB; } SPIRVInstruction *getPrevious() const { return BB->getPrevious(this); } SPIRVInstruction *getNext() const { return BB->getNext(this); } virtual std::vector getOperands(); std::vector getOperandTypes(); static std::vector getOperandTypes(const std::vector &Ops); void setParent(SPIRVBasicBlock *); void setScope(SPIRVEntry *) override; void addFPRoundingMode(SPIRVFPRoundingModeKind Kind) { addDecorate(DecorationFPRoundingMode, Kind); } void eraseFPRoundingMode() { eraseDecorate(DecorationFPRoundingMode); } void setSaturatedConversion(bool Enable) { if (Enable) addDecorate(DecorationSaturatedConversion); else eraseDecorate(DecorationSaturatedConversion); } bool hasFPRoundingMode(SPIRVFPRoundingModeKind *Kind = nullptr) { SPIRVWord V; auto Found = hasDecorate(DecorationFPRoundingMode, 0, &V); if (Found && Kind) *Kind = static_cast(V); return Found; } bool isSaturatedConversion() { return hasDecorate(DecorationSaturatedConversion) || OpCode == OpSatConvertSToU || OpCode == OpSatConvertUToS; } SPIRVBasicBlock *getBasicBlock() const { return BB; } void setBasicBlock(SPIRVBasicBlock *TheBB) { BB = TheBB; if (TheBB) setModule(TheBB->getModule()); } void setDebugScope(SPIRVEntry *Scope) { DebugScope = Scope; } SPIRVEntry *getDebugScope() const { return DebugScope; } protected: void validate() const override { SPIRVValue::validate(); } private: SPIRVBasicBlock *BB; SPIRVEntry *DebugScope; }; class SPIRVInstTemplateBase : public SPIRVInstruction { public: /// Create an empty instruction. Mainly for getting format information, /// e.g. whether an operand is literal. static SPIRVInstTemplateBase *create(Op TheOC) { auto Inst = static_cast(SPIRVEntry::create(TheOC)); assert(Inst); Inst->init(); return Inst; } /// Create a instruction without operands. static SPIRVInstTemplateBase *create(Op TheOC, SPIRVType *TheType, SPIRVId TheId, SPIRVBasicBlock *TheBB, SPIRVModule *TheModule) { auto Inst = create(TheOC); Inst->init(TheType, TheId, TheBB, TheModule); return Inst; } /// Create a complete and valid instruction. static SPIRVInstTemplateBase *create(Op TheOC, SPIRVType *TheType, SPIRVId TheId, const std::vector &TheOps, SPIRVBasicBlock *TheBB, SPIRVModule *TheModule) { auto Inst = create(TheOC); Inst->init(TheType, TheId, TheBB, TheModule); Inst->setOpWords(TheOps); Inst->validate(); return Inst; } SPIRVInstTemplateBase(Op OC = OpNop) : SPIRVInstruction(OC), HasVariWC(false) { init(); } ~SPIRVInstTemplateBase() override {} SPIRVInstTemplateBase *init(SPIRVType *TheType, SPIRVId TheId, SPIRVBasicBlock *TheBB, SPIRVModule *TheModule) { assert((TheBB || TheModule) && "Invalid BB or Module"); if (TheBB) setBasicBlock(TheBB); else { setModule(TheModule); } setId(hasId() ? TheId : SPIRVID_INVALID); setType(hasType() ? TheType : nullptr); return this; } virtual void init() {} virtual void initImpl(Op OC, bool HasId = true, SPIRVWord WC = 0, bool VariWC = false, unsigned Lit1 = ~0U, unsigned Lit2 = ~0U, unsigned Lit3 = ~0U) { OpCode = OC; if (!HasId) { setHasNoId(); setHasNoType(); } if (WC) SPIRVEntry::setWordCount(WC); setHasVariableWordCount(VariWC); addLit(Lit1); addLit(Lit2); addLit(Lit3); } bool isOperandLiteral(unsigned I) const override { return Lit.count(I); } void addLit(unsigned L) { if (L != ~0U) Lit.insert(L); } /// \return Expected number of operands. If the instruction has variable /// number of words, return the minimum. SPIRVWord getExpectedNumOperands() const { assert(WordCount > 0 && "Word count not initialized"); auto Exp = WordCount - 1; if (hasId()) --Exp; if (hasType()) --Exp; return Exp; } virtual void setOpWordsAndValidate(const std::vector &TheOps) { setOpWords(TheOps); validate(); } virtual void setOpWords(const std::vector &TheOps) { SPIRVWord WC = TheOps.size() + 1; if (hasId()) ++WC; if (hasType()) ++WC; if (WordCount) { if (WordCount == WC) { // do nothing } else { assert(HasVariWC && WC >= WordCount && "Invalid word count"); SPIRVEntry::setWordCount(WC); } } else SPIRVEntry::setWordCount(WC); Ops = TheOps; } void setWordCount(SPIRVWord TheWordCount) override { SPIRVEntry::setWordCount(TheWordCount); auto NumOps = WordCount - 1; if (hasId()) --NumOps; if (hasType()) --NumOps; Ops.resize(NumOps); } std::vector &getOpWords() { return Ops; } const std::vector &getOpWords() const { return Ops; } SPIRVWord getOpWord(int I) const { return Ops[I]; } /// Get operand as value. /// If the operand is a literal, return it as a uint32 constant. SPIRVValue *getOpValue(int I) { return isOperandLiteral(I) ? Module->getLiteralAsConstant(Ops[I]) : getValue(Ops[I]); } // Get the offset of operands. // Some instructions skip literals when returning operands. size_t getOperandOffset() const { if (hasExecScope() && !isGroupOpCode(OpCode) && !isPipeOpCode(OpCode)) return 1; return 0; } // Get operands which are values. // Drop execution scope and group operation literals. // Return other literals as uint32 constants. std::vector getOperands() override { std::vector VOps; auto Offset = getOperandOffset(); for (size_t I = 0, E = Ops.size() - Offset; I != E; ++I) VOps.push_back(getOperand(I)); return VOps; } std::vector getNonLiteralOperands() const override { std::vector Operands; for (size_t I = getOperandOffset(), E = Ops.size(); I < E; ++I) if (!isOperandLiteral(I)) Operands.push_back(getEntry(Ops[I])); return Operands; } virtual SPIRVValue *getOperand(unsigned I) { return getOpValue(I + getOperandOffset()); } bool hasExecScope() const { return SPIRV::hasExecScope(OpCode); } bool hasGroupOperation() const { return SPIRV::hasGroupOperation(OpCode); } bool getSPIRVGroupOperation(SPIRVGroupOperationKind &GroupOp) const { if (!hasGroupOperation()) return false; GroupOp = static_cast(Ops[1]); return true; } Scope getExecutionScope() const { if (!hasExecScope()) return ScopeInvocation; return static_cast( static_cast(getValue(Ops[0]))->getZExtIntValue()); } bool hasVariableWordCount() const { return HasVariWC; } void setHasVariableWordCount(bool VariWC) { HasVariWC = VariWC; } protected: void encode(spv_ostream &O) const override { auto E = getEncoder(O); if (hasType()) E << Type; if (hasId()) E << Id; E << Ops; } void decode(std::istream &I) override { auto D = getDecoder(I); if (hasType()) D >> Type; if (hasId()) D >> Id; D >> Ops; } std::vector Ops; bool HasVariWC; std::unordered_set Lit; // Literal operand index }; template class SPIRVInstTemplate : public BT { public: typedef BT BaseTy; SPIRVInstTemplate() { init(); } ~SPIRVInstTemplate() override {} void init() override { this->initImpl(OC, HasId, WC, HasVariableWC, Literal1, Literal2, Literal3); } }; class SPIRVMemoryAccess { public: SPIRVMemoryAccess(const std::vector &TheMemoryAccess) : TheMemoryAccessMask(0), Alignment(0) { memoryAccessUpdate(TheMemoryAccess); } SPIRVMemoryAccess() : TheMemoryAccessMask(0), Alignment(0) {} void memoryAccessUpdate(const std::vector &MemoryAccess) { if (!MemoryAccess.size()) return; assert((MemoryAccess.size() == 1 || MemoryAccess.size() == 2) && "Invalid memory access operand size"); TheMemoryAccessMask = MemoryAccess[0]; if (MemoryAccess[0] & MemoryAccessAlignedMask) { assert(MemoryAccess.size() == 2 && "Alignment operand is missing"); Alignment = MemoryAccess[1]; } } SPIRVWord isVolatile() const { return getMemoryAccessMask() & MemoryAccessVolatileMask; } SPIRVWord isNonTemporal() const { return getMemoryAccessMask() & MemoryAccessNontemporalMask; } SPIRVWord getMemoryAccessMask() const { return TheMemoryAccessMask; } SPIRVWord getAlignment() const { return Alignment; } protected: SPIRVWord TheMemoryAccessMask; SPIRVWord Alignment; }; class SPIRVVariable : public SPIRVInstruction { public: // Complete constructor for integer constant SPIRVVariable(SPIRVType *TheType, SPIRVId TheId, SPIRVValue *TheInitializer, const std::string &TheName, SPIRVStorageClassKind TheStorageClass, SPIRVBasicBlock *TheBB, SPIRVModule *TheM) : SPIRVInstruction(TheInitializer ? 5 : 4, OpVariable, TheType, TheId, TheBB, TheM), StorageClass(TheStorageClass) { if (TheInitializer) Initializer.push_back(TheInitializer->getId()); Name = TheName; validate(); } // Incomplete constructor SPIRVVariable() : SPIRVInstruction(OpVariable), StorageClass(StorageClassFunction) {} SPIRVStorageClassKind getStorageClass() const { return StorageClass; } SPIRVValue *getInitializer() const { if (Initializer.empty()) return nullptr; assert(Initializer.size() == 1); return getValue(Initializer[0]); } bool isConstant() const { return hasDecorate(DecorationConstant); } bool isBuiltin(SPIRVBuiltinVariableKind *BuiltinKind = nullptr) const { SPIRVWord Kind; bool Found = hasDecorate(DecorationBuiltIn, 0, &Kind); if (!Found) return false; if (BuiltinKind) *BuiltinKind = static_cast(Kind); return true; } void setBuiltin(SPIRVBuiltinVariableKind Kind) { assert(isValid(Kind)); addDecorate(new SPIRVDecorate(DecorationBuiltIn, this, Kind)); } void setIsConstant(bool Is) { if (Is) addDecorate(new SPIRVDecorate(DecorationConstant, this)); else eraseDecorate(DecorationConstant); } std::vector getNonLiteralOperands() const override { if (SPIRVValue *V = getInitializer()) return std::vector(1, V); return std::vector(); } protected: void validate() const override { SPIRVValue::validate(); assert(isValid(StorageClass)); assert(Initializer.size() == 1 || Initializer.empty()); assert(getType()->isTypePointer()); } void setWordCount(SPIRVWord TheWordCount) override { SPIRVEntry::setWordCount(TheWordCount); Initializer.resize(WordCount - 4); } _SPIRV_DEF_ENCDEC4(Type, Id, StorageClass, Initializer) SPIRVStorageClassKind StorageClass; std::vector Initializer; }; class SPIRVStore : public SPIRVInstruction, public SPIRVMemoryAccess { public: const static SPIRVWord FixedWords = 3; // Complete constructor SPIRVStore(SPIRVId PointerId, SPIRVId ValueId, const std::vector &TheMemoryAccess, SPIRVBasicBlock *TheBB) : SPIRVInstruction(FixedWords + TheMemoryAccess.size(), OpStore, TheBB), SPIRVMemoryAccess(TheMemoryAccess), MemoryAccess(TheMemoryAccess), PtrId(PointerId), ValId(ValueId) { setAttr(); validate(); assert(TheBB && "Invalid BB"); } // Incomplete constructor SPIRVStore() : SPIRVInstruction(OpStore), SPIRVMemoryAccess(), PtrId(SPIRVID_INVALID), ValId(SPIRVID_INVALID) { setAttr(); } SPIRVValue *getSrc() const { return getValue(ValId); } SPIRVValue *getDst() const { return getValue(PtrId); } protected: void setAttr() { setHasNoType(); setHasNoId(); } void setWordCount(SPIRVWord TheWordCount) override { SPIRVEntry::setWordCount(TheWordCount); MemoryAccess.resize(TheWordCount - FixedWords); } void encode(spv_ostream &O) const override { getEncoder(O) << PtrId << ValId << MemoryAccess; } void decode(std::istream &I) override { getDecoder(I) >> PtrId >> ValId >> MemoryAccess; memoryAccessUpdate(MemoryAccess); } void validate() const override { SPIRVInstruction::validate(); if (getSrc()->isForward() || getDst()->isForward()) return; assert(getValueType(PtrId)->getPointerElementType() == getValueType(ValId) && "Inconsistent operand types"); } private: std::vector MemoryAccess; SPIRVId PtrId; SPIRVId ValId; }; class SPIRVLoad : public SPIRVInstruction, public SPIRVMemoryAccess { public: const static SPIRVWord FixedWords = 4; // Complete constructor SPIRVLoad(SPIRVId TheId, SPIRVId PointerId, const std::vector &TheMemoryAccess, SPIRVBasicBlock *TheBB) : SPIRVInstruction( FixedWords + TheMemoryAccess.size(), OpLoad, TheBB->getValueType(PointerId)->getPointerElementType(), TheId, TheBB), SPIRVMemoryAccess(TheMemoryAccess), PtrId(PointerId), MemoryAccess(TheMemoryAccess) { validate(); assert(TheBB && "Invalid BB"); } // Incomplete constructor SPIRVLoad() : SPIRVInstruction(OpLoad), SPIRVMemoryAccess(), PtrId(SPIRVID_INVALID) {} SPIRVValue *getSrc() const { return Module->get(PtrId); } protected: void setWordCount(SPIRVWord TheWordCount) override { SPIRVEntry::setWordCount(TheWordCount); MemoryAccess.resize(TheWordCount - FixedWords); } void encode(spv_ostream &O) const override { getEncoder(O) << Type << Id << PtrId << MemoryAccess; } void decode(std::istream &I) override { getDecoder(I) >> Type >> Id >> PtrId >> MemoryAccess; memoryAccessUpdate(MemoryAccess); } void validate() const override { SPIRVInstruction::validate(); assert((getValue(PtrId)->isForward() || Type == getValueType(PtrId)->getPointerElementType()) && "Inconsistent types"); } private: SPIRVId PtrId; std::vector MemoryAccess; }; class SPIRVBinary : public SPIRVInstTemplateBase { protected: void validate() const override { SPIRVId Op1 = Ops[0]; SPIRVId Op2 = Ops[1]; SPIRVType *Op1Ty, *Op2Ty; SPIRVInstruction::validate(); if (getValue(Op1)->isForward() || getValue(Op2)->isForward()) return; if (getValueType(Op1)->isTypeVector()) { Op1Ty = getValueType(Op1)->getVectorComponentType(); Op2Ty = getValueType(Op2)->getVectorComponentType(); assert(getValueType(Op1)->getVectorComponentCount() == getValueType(Op2)->getVectorComponentCount() && "Inconsistent Vector component width"); } else { Op1Ty = getValueType(Op1); Op2Ty = getValueType(Op2); } (void)Op1Ty; (void)Op2Ty; if (isBinaryOpCode(OpCode)) { assert(getValueType(Op1) == getValueType(Op2) && "Invalid type for binary instruction"); assert((Op1Ty->isTypeInt() || Op2Ty->isTypeFloat()) && "Invalid type for Binary instruction"); assert((Op1Ty->getBitWidth() == Op2Ty->getBitWidth()) && "Inconsistent BitWidth"); } else if (isShiftOpCode(OpCode)) { assert((Op1Ty->isTypeInt() || Op2Ty->isTypeInt()) && "Invalid type for shift instruction"); } else if (isLogicalOpCode(OpCode)) { assert((Op1Ty->isTypeBool() || Op2Ty->isTypeBool()) && "Invalid type for logical instruction"); } else if (isBitwiseOpCode(OpCode)) { assert((Op1Ty->isTypeInt() || Op2Ty->isTypeInt()) && "Invalid type for bitwise instruction"); assert((Op1Ty->getIntegerBitWidth() == Op2Ty->getIntegerBitWidth()) && "Inconsistent BitWidth"); } else { assert(0 && "Invalid op code!"); } } }; template class SPIRVBinaryInst : public SPIRVInstTemplate {}; /* ToDo: SMod and FMod to be added */ #define _SPIRV_OP(x) typedef SPIRVBinaryInst SPIRV##x; _SPIRV_OP(IAdd) _SPIRV_OP(FAdd) _SPIRV_OP(ISub) _SPIRV_OP(FSub) _SPIRV_OP(IMul) _SPIRV_OP(FMul) _SPIRV_OP(UDiv) _SPIRV_OP(SDiv) _SPIRV_OP(FDiv) _SPIRV_OP(SRem) _SPIRV_OP(FRem) _SPIRV_OP(UMod) _SPIRV_OP(ShiftLeftLogical) _SPIRV_OP(ShiftRightLogical) _SPIRV_OP(ShiftRightArithmetic) _SPIRV_OP(LogicalAnd) _SPIRV_OP(LogicalOr) _SPIRV_OP(LogicalEqual) _SPIRV_OP(LogicalNotEqual) _SPIRV_OP(BitwiseAnd) _SPIRV_OP(BitwiseOr) _SPIRV_OP(BitwiseXor) _SPIRV_OP(Dot) #undef _SPIRV_OP template class SPIRVInstNoOperand : public SPIRVInstruction { public: // Complete constructor SPIRVInstNoOperand(SPIRVBasicBlock *TheBB) : SPIRVInstruction(1, TheOpCode, TheBB) { setAttr(); validate(); } // Incomplete constructor SPIRVInstNoOperand() : SPIRVInstruction(TheOpCode) { setAttr(); } protected: void setAttr() { setHasNoId(); setHasNoType(); } _SPIRV_DEF_ENCDEC0 }; typedef SPIRVInstNoOperand SPIRVReturn; typedef SPIRVInstNoOperand SPIRVUnreachable; class SPIRVReturnValue : public SPIRVInstruction { public: static const Op OC = OpReturnValue; // Complete constructor SPIRVReturnValue(SPIRVValue *TheReturnValue, SPIRVBasicBlock *TheBB) : SPIRVInstruction(2, OC, TheBB), ReturnValueId(TheReturnValue->getId()) { setAttr(); validate(); assert(TheBB && "Invalid BB"); } // Incomplete constructor SPIRVReturnValue() : SPIRVInstruction(OC), ReturnValueId(SPIRVID_INVALID) { setAttr(); } SPIRVValue *getReturnValue() const { return getValue(ReturnValueId); } protected: void setAttr() { setHasNoId(); setHasNoType(); } _SPIRV_DEF_ENCDEC1(ReturnValueId) void validate() const override { SPIRVInstruction::validate(); } SPIRVId ReturnValueId; }; class SPIRVBranch : public SPIRVInstruction { public: static const Op OC = OpBranch; // Complete constructor SPIRVBranch(SPIRVLabel *TheTargetLabel, SPIRVBasicBlock *TheBB) : SPIRVInstruction(2, OC, TheBB), TargetLabelId(TheTargetLabel->getId()) { validate(); assert(TheBB && "Invalid BB"); } // Incomplete constructor SPIRVBranch() : SPIRVInstruction(OC), TargetLabelId(SPIRVID_INVALID) { setHasNoId(); setHasNoType(); } SPIRVValue *getTargetLabel() const { return getValue(TargetLabelId); } protected: _SPIRV_DEF_ENCDEC1(TargetLabelId) void validate() const override { SPIRVInstruction::validate(); assert(WordCount == 2); assert(OpCode == OC); assert(getTargetLabel()->isLabel() || getTargetLabel()->isForward()); } SPIRVId TargetLabelId; }; class SPIRVBranchConditional : public SPIRVInstruction { public: static const Op OC = OpBranchConditional; // Complete constructor SPIRVBranchConditional(SPIRVValue *TheCondition, SPIRVLabel *TheTrueLabel, SPIRVLabel *TheFalseLabel, SPIRVBasicBlock *TheBB) : SPIRVInstruction(4, OC, TheBB), ConditionId(TheCondition->getId()), TrueLabelId(TheTrueLabel->getId()), FalseLabelId(TheFalseLabel->getId()) { validate(); } SPIRVBranchConditional(SPIRVValue *TheCondition, SPIRVLabel *TheTrueLabel, SPIRVLabel *TheFalseLabel, SPIRVBasicBlock *TheBB, SPIRVWord TrueWeight, SPIRVWord FalseWeight) : SPIRVInstruction(6, OC, TheBB), ConditionId(TheCondition->getId()), TrueLabelId(TheTrueLabel->getId()), FalseLabelId(TheFalseLabel->getId()) { BranchWeights.push_back(TrueWeight); BranchWeights.push_back(FalseWeight); validate(); assert(TheBB && "Invalid BB"); } // Incomplete constructor SPIRVBranchConditional() : SPIRVInstruction(OC), ConditionId(SPIRVID_INVALID), TrueLabelId(SPIRVID_INVALID), FalseLabelId(SPIRVID_INVALID) { setHasNoId(); setHasNoType(); } SPIRVValue *getCondition() const { return getValue(ConditionId); } SPIRVLabel *getTrueLabel() const { return get(TrueLabelId); } SPIRVLabel *getFalseLabel() const { return get(FalseLabelId); } protected: void setWordCount(SPIRVWord TheWordCount) override { SPIRVEntry::setWordCount(TheWordCount); BranchWeights.resize(TheWordCount - 4); } _SPIRV_DEF_ENCDEC4(ConditionId, TrueLabelId, FalseLabelId, BranchWeights) void validate() const override { SPIRVInstruction::validate(); assert(WordCount == 4 || WordCount == 6); assert(WordCount == BranchWeights.size() + 4); assert(OpCode == OC); assert(getCondition()->isForward() || getCondition()->getType()->isTypeBool()); assert(getTrueLabel()->isForward() || getTrueLabel()->isLabel()); assert(getFalseLabel()->isForward() || getFalseLabel()->isLabel()); } SPIRVId ConditionId; SPIRVId TrueLabelId; SPIRVId FalseLabelId; std::vector BranchWeights; }; class SPIRVPhi : public SPIRVInstruction { public: static const Op OC = OpPhi; static const SPIRVWord FixedWordCount = 3; SPIRVPhi(SPIRVType *TheType, SPIRVId TheId, const std::vector &ThePairs, SPIRVBasicBlock *BB) : SPIRVInstruction(ThePairs.size() + FixedWordCount, OC, TheType, TheId, BB) { Pairs = getIds(ThePairs); validate(); assert(BB && "Invalid BB"); } SPIRVPhi() : SPIRVInstruction(OC) {} std::vector getPairs() { return getValues(Pairs); } void addPair(SPIRVValue *Value, SPIRVBasicBlock *BB) { Pairs.push_back(Value->getId()); Pairs.push_back(BB->getId()); WordCount = Pairs.size() + FixedWordCount; validate(); } void setPairs(const std::vector &ThePairs) { Pairs = getIds(ThePairs); WordCount = Pairs.size() + FixedWordCount; validate(); } void foreachPair( std::function Func) { for (size_t I = 0, E = Pairs.size() / 2; I != E; ++I) { SPIRVEntry *Value, *BB; if (!Module->exist(Pairs[2 * I], &Value) || !Module->exist(Pairs[2 * I + 1], &BB)) continue; Func(static_cast(Value), static_cast(BB), I); } } void foreachPair(std::function Func) const { for (size_t I = 0, E = Pairs.size() / 2; I != E; ++I) { SPIRVEntry *Value, *BB; if (!Module->exist(Pairs[2 * I], &Value) || !Module->exist(Pairs[2 * I + 1], &BB)) continue; Func(static_cast(Value), static_cast(BB)); } } void setWordCount(SPIRVWord TheWordCount) override { SPIRVEntry::setWordCount(TheWordCount); Pairs.resize(TheWordCount - FixedWordCount); } _SPIRV_DEF_ENCDEC3(Type, Id, Pairs) void validate() const override { assert(WordCount == Pairs.size() + FixedWordCount); assert(OpCode == OC); assert(Pairs.size() % 2 == 0); foreachPair([=](SPIRVValue *IncomingV, SPIRVBasicBlock *IncomingBB) { assert(IncomingV->isForward() || IncomingV->getType() == Type); assert(IncomingBB->isBasicBlock() || IncomingBB->isForward()); }); SPIRVInstruction::validate(); } protected: std::vector Pairs; }; class SPIRVFPGARegINTELInstBase : public SPIRVInstTemplateBase { public: SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilityFPGARegINTEL); } SPIRVExtSet getRequiredExtensions() const override { return getSet(ExtensionID::SPV_INTEL_fpga_reg); } protected: void validate() const override { SPIRVInstruction::validate(); assert(OpCode == OpFPGARegINTEL && "Invalid op code for FPGARegINTEL instruction"); assert(getType() == getValueType(Ops[0]) && "Inconsistent type"); } }; typedef SPIRVInstTemplate SPIRVFPGARegINTEL; class SPIRVCompare : public SPIRVInstTemplateBase { protected: void validate() const override { auto Op1 = Ops[0]; auto Op2 = Ops[1]; SPIRVType *Op1Ty, *Op2Ty, *ResTy; SPIRVInstruction::validate(); if (getValue(Op1)->isForward() || getValue(Op2)->isForward()) return; (void)Op1Ty; (void)Op2Ty; (void)ResTy; if (getValueType(Op1)->isTypeVector()) { Op1Ty = getValueType(Op1)->getVectorComponentType(); Op2Ty = getValueType(Op2)->getVectorComponentType(); ResTy = Type->getVectorComponentType(); assert(getValueType(Op1)->getVectorComponentCount() == getValueType(Op2)->getVectorComponentCount() && "Inconsistent Vector component width"); } else { Op1Ty = getValueType(Op1); Op2Ty = getValueType(Op2); ResTy = Type; } assert(isCmpOpCode(OpCode) && "Invalid op code for cmp inst"); assert((ResTy->isTypeBool() || ResTy->isTypeInt()) && "Invalid type for compare instruction"); assert(Op1Ty == Op2Ty && "Inconsistent types"); } }; template class SPIRVCmpInst : public SPIRVInstTemplate {}; #define _SPIRV_OP(x) typedef SPIRVCmpInst SPIRV##x; _SPIRV_OP(IEqual) _SPIRV_OP(FOrdEqual) _SPIRV_OP(FUnordEqual) _SPIRV_OP(INotEqual) _SPIRV_OP(FOrdNotEqual) _SPIRV_OP(FUnordNotEqual) _SPIRV_OP(ULessThan) _SPIRV_OP(SLessThan) _SPIRV_OP(FOrdLessThan) _SPIRV_OP(FUnordLessThan) _SPIRV_OP(UGreaterThan) _SPIRV_OP(SGreaterThan) _SPIRV_OP(FOrdGreaterThan) _SPIRV_OP(FUnordGreaterThan) _SPIRV_OP(ULessThanEqual) _SPIRV_OP(SLessThanEqual) _SPIRV_OP(FOrdLessThanEqual) _SPIRV_OP(FUnordLessThanEqual) _SPIRV_OP(UGreaterThanEqual) _SPIRV_OP(SGreaterThanEqual) _SPIRV_OP(FOrdGreaterThanEqual) _SPIRV_OP(FUnordGreaterThanEqual) _SPIRV_OP(LessOrGreater) _SPIRV_OP(Ordered) _SPIRV_OP(Unordered) #undef _SPIRV_OP class SPIRVSelect : public SPIRVInstruction { public: // Complete constructor SPIRVSelect(SPIRVId TheId, SPIRVId TheCondition, SPIRVId TheOp1, SPIRVId TheOp2, SPIRVBasicBlock *TheBB) : SPIRVInstruction(6, OpSelect, TheBB->getValueType(TheOp1), TheId, TheBB), Condition(TheCondition), Op1(TheOp1), Op2(TheOp2) { validate(); assert(TheBB && "Invalid BB"); } // Incomplete constructor SPIRVSelect() : SPIRVInstruction(OpSelect), Condition(SPIRVID_INVALID), Op1(SPIRVID_INVALID), Op2(SPIRVID_INVALID) {} SPIRVValue *getCondition() { return getValue(Condition); } SPIRVValue *getTrueValue() { return getValue(Op1); } SPIRVValue *getFalseValue() { return getValue(Op2); } protected: _SPIRV_DEF_ENCDEC5(Type, Id, Condition, Op1, Op2) void validate() const override { SPIRVInstruction::validate(); if (getValue(Condition)->isForward() || getValue(Op1)->isForward() || getValue(Op2)->isForward()) return; SPIRVType *ConTy = getValueType(Condition)->isTypeVector() ? getValueType(Condition)->getVectorComponentType() : getValueType(Condition); (void)ConTy; assert(ConTy->isTypeBool() && "Invalid type"); assert(getType() == getValueType(Op1) && getType() == getValueType(Op2) && "Inconsistent type"); } SPIRVId Condition; SPIRVId Op1; SPIRVId Op2; }; class SPIRVSelectionMerge : public SPIRVInstruction { public: static const Op OC = OpSelectionMerge; static const SPIRVWord FixedWordCount = 3; SPIRVSelectionMerge(SPIRVId TheMergeBlock, SPIRVWord TheSelectionControl, SPIRVBasicBlock *BB) : SPIRVInstruction(3, OC, BB), MergeBlock(TheMergeBlock), SelectionControl(TheSelectionControl) { validate(); assert(BB && "Invalid BB"); } SPIRVSelectionMerge() : SPIRVInstruction(OC), MergeBlock(SPIRVID_INVALID), SelectionControl(SPIRVWORD_MAX) { setHasNoId(); setHasNoType(); } SPIRVId getMergeBlock() { return MergeBlock; } SPIRVWord getSelectionControl() { return SelectionControl; } _SPIRV_DEF_ENCDEC2(MergeBlock, SelectionControl) protected: SPIRVId MergeBlock; SPIRVWord SelectionControl; }; class SPIRVLoopMerge : public SPIRVInstruction { public: static const Op OC = OpLoopMerge; static const SPIRVWord FixedWordCount = 4; SPIRVLoopMerge(SPIRVId TheMergeBlock, SPIRVId TheContinueTarget, SPIRVWord TheLoopControl, std::vector TheLoopControlParameters, SPIRVBasicBlock *BB) : SPIRVInstruction(FixedWordCount + TheLoopControlParameters.size(), OC, BB), MergeBlock(TheMergeBlock), ContinueTarget(TheContinueTarget), LoopControl(TheLoopControl), LoopControlParameters(TheLoopControlParameters) { validate(); assert(BB && "Invalid BB"); } SPIRVLoopMerge() : SPIRVInstruction(OC), MergeBlock(SPIRVID_MAX), LoopControl(SPIRVWORD_MAX) { setHasNoId(); setHasNoType(); } SPIRVId getMergeBlock() { return MergeBlock; } SPIRVId getContinueTarget() { return ContinueTarget; } SPIRVWord getLoopControl() const { return LoopControl; } std::vector getLoopControlParameters() const { return LoopControlParameters; } void setWordCount(SPIRVWord TheWordCount) override { SPIRVEntry::setWordCount(TheWordCount); LoopControlParameters.resize(TheWordCount - FixedWordCount); } _SPIRV_DEF_ENCDEC4(MergeBlock, ContinueTarget, LoopControl, LoopControlParameters) protected: SPIRVId MergeBlock; SPIRVId ContinueTarget; SPIRVWord LoopControl; std::vector LoopControlParameters; }; class SPIRVSwitch : public SPIRVInstruction { public: static const Op OC = OpSwitch; static const SPIRVWord FixedWordCount = 3; typedef std::vector LiteralTy; typedef std::pair PairTy; SPIRVSwitch(SPIRVValue *TheSelect, SPIRVBasicBlock *TheDefault, const std::vector &ThePairs, SPIRVBasicBlock *BB) : SPIRVInstruction(FixedWordCount, OC, BB), Select(TheSelect->getId()), Default(TheDefault->getId()) { if (!ThePairs.empty()) SPIRVEntry::setWordCount( ThePairs.size() * (ThePairs.at(0).first.size() + 1) + FixedWordCount); for (auto &I : ThePairs) { for (auto &U : I.first) Pairs.push_back(U); Pairs.push_back(I.second->getId()); } validate(); assert(BB && "Invalid BB"); } SPIRVSwitch() : SPIRVInstruction(OC), Select(SPIRVWORD_MAX), Default(SPIRVWORD_MAX) { setHasNoId(); setHasNoType(); } std::vector getPairs() const { return getValues(Pairs); } SPIRVValue *getSelect() const { return getValue(Select); } SPIRVBasicBlock *getDefault() const { return static_cast(getValue(Default)); } size_t getLiteralSize() const { unsigned ByteWidth = getSelect()->getType()->getBitWidth() / 8; unsigned Remainder = (ByteWidth % sizeof(SPIRVWord)) != 0; return (ByteWidth / sizeof(SPIRVWord)) + Remainder; } size_t getPairSize() const { return getLiteralSize() + 1; } size_t getNumPairs() const { return Pairs.size() / getPairSize(); } void foreachPair(std::function Func) const { unsigned PairSize = getPairSize(); for (size_t I = 0, E = getNumPairs(); I != E; ++I) { SPIRVEntry *BB; LiteralTy Literals; if (!Module->exist(Pairs[PairSize * I + getLiteralSize()], &BB)) continue; for (size_t J = 0; J < getLiteralSize(); ++J) { Literals.push_back(Pairs.at(PairSize * I + J)); } Func(Literals, static_cast(BB)); } } void setWordCount(SPIRVWord TheWordCount) override { SPIRVEntry::setWordCount(TheWordCount); Pairs.resize(TheWordCount - FixedWordCount); } _SPIRV_DEF_ENCDEC3(Select, Default, Pairs) void validate() const override { assert(WordCount == Pairs.size() + FixedWordCount); assert(OpCode == OC); assert(Pairs.size() % getPairSize() == 0); foreachPair([=](LiteralTy Literals, SPIRVBasicBlock *BB) { assert(BB->isBasicBlock() || BB->isForward()); }); SPIRVInstruction::validate(); } protected: SPIRVId Select; SPIRVId Default; std::vector Pairs; }; class SPIRVFSMod : public SPIRVInstruction { public: static const SPIRVWord FixedWordCount = 4; SPIRVFSMod(Op OC, SPIRVType *TheType, SPIRVId TheId, SPIRVId TheDividend, SPIRVId TheDivisor, SPIRVBasicBlock *BB) : SPIRVInstruction(5, OC, TheType, TheId, BB), Dividend(TheDividend), Divisor(TheDivisor) { validate(); assert(BB && "Invalid BB"); } // Incomplete constructor SPIRVFSMod(Op OC) : SPIRVInstruction(OC), Dividend(SPIRVID_INVALID), Divisor(SPIRVID_INVALID) {} SPIRVValue *getDividend() const { return getValue(Dividend); } SPIRVValue *getDivisor() const { return getValue(Divisor); } std::vector getOperands() override { std::vector Operands; Operands.push_back(Dividend); Operands.push_back(Divisor); return getValues(Operands); } void setWordCount(SPIRVWord FixedWordCount) override { SPIRVEntry::setWordCount(FixedWordCount); } _SPIRV_DEF_ENCDEC4(Type, Id, Dividend, Divisor) void validate() const override { SPIRVInstruction::validate(); if (getValue(Dividend)->isForward() || getValue(Divisor)->isForward()) return; SPIRVInstruction::validate(); } protected: SPIRVId Dividend; SPIRVId Divisor; }; class SPIRVFMod : public SPIRVFSMod { public: static const Op OC = OpFMod; // Complete constructor SPIRVFMod(SPIRVType *TheType, SPIRVId TheId, SPIRVId TheDividend, SPIRVId TheDivisor, SPIRVBasicBlock *BB) : SPIRVFSMod(OC, TheType, TheId, TheDividend, TheDivisor, BB) {} // Incomplete constructor SPIRVFMod() : SPIRVFSMod(OC) {} }; class SPIRVSMod : public SPIRVFSMod { public: static const Op OC = OpSMod; // Complete constructor SPIRVSMod(SPIRVType *TheType, SPIRVId TheId, SPIRVId TheDividend, SPIRVId TheDivisor, SPIRVBasicBlock *BB) : SPIRVFSMod(OC, TheType, TheId, TheDividend, TheDivisor, BB) {} // Incomplete constructor SPIRVSMod() : SPIRVFSMod(OC) {} }; class SPIRVVectorTimesScalar : public SPIRVInstruction { public: static const Op OC = OpVectorTimesScalar; static const SPIRVWord FixedWordCount = 4; // Complete constructor SPIRVVectorTimesScalar(SPIRVType *TheType, SPIRVId TheId, SPIRVId TheVector, SPIRVId TheScalar, SPIRVBasicBlock *BB) : SPIRVInstruction(5, OC, TheType, TheId, BB), Vector(TheVector), Scalar(TheScalar) { validate(); assert(BB && "Invalid BB"); } // Incomplete constructor SPIRVVectorTimesScalar() : SPIRVInstruction(OC), Vector(SPIRVID_INVALID), Scalar(SPIRVID_INVALID) { } SPIRVValue *getVector() const { return getValue(Vector); } SPIRVValue *getScalar() const { return getValue(Scalar); } std::vector getOperands() override { std::vector Operands; Operands.push_back(Vector); Operands.push_back(Scalar); return getValues(Operands); } void setWordCount(SPIRVWord FixedWordCount) override { SPIRVEntry::setWordCount(FixedWordCount); } _SPIRV_DEF_ENCDEC4(Type, Id, Vector, Scalar) void validate() const override { SPIRVInstruction::validate(); if (getValue(Vector)->isForward() || getValue(Scalar)->isForward()) return; assert(getValueType(Vector)->isTypeVector() && getValueType(Vector)->getVectorComponentType()->isTypeFloat() && "First operand must be a vector of floating-point type"); assert(getValueType(getId())->isTypeVector() && getValueType(getId())->getVectorComponentType()->isTypeFloat() && "Result type must be a vector of floating-point type"); assert( getValueType(Vector)->getVectorComponentType() == getValueType(getId())->getVectorComponentType() && "Scalar must have the same type as the Component Type in Result Type"); SPIRVInstruction::validate(); } protected: SPIRVId Vector; SPIRVId Scalar; }; class SPIRVVectorTimesMatrix : public SPIRVInstruction { public: static const Op OC = OpVectorTimesMatrix; static const SPIRVWord FixedWordCount = 4; // Complete constructor SPIRVVectorTimesMatrix(SPIRVType *TheType, SPIRVId TheId, SPIRVId TheVector, SPIRVId TheMatrix, SPIRVBasicBlock *BB) : SPIRVInstruction(5, OC, TheType, TheId, BB), Vector(TheVector), Matrix(TheMatrix) { validate(); assert(BB && "Invalid BB"); } // Incomplete constructor SPIRVVectorTimesMatrix() : SPIRVInstruction(OC), Vector(SPIRVID_INVALID), Matrix(SPIRVID_INVALID) { } SPIRVValue *getVector() const { return getValue(Vector); } SPIRVValue *getMatrix() const { return getValue(Matrix); } std::vector getOperands() override { std::vector Operands; Operands.push_back(Vector); Operands.push_back(Matrix); return getValues(Operands); } void setWordCount(SPIRVWord FixedWordCount) override { SPIRVEntry::setWordCount(FixedWordCount); } _SPIRV_DEF_ENCDEC4(Type, Id, Vector, Matrix) void validate() const override { SPIRVInstruction::validate(); if (getValue(Vector)->isForward() || getValue(Matrix)->isForward()) return; SPIRVType *Ty = getType()->getScalarType(); SPIRVType *MTy = getValueType(Matrix)->getScalarType(); SPIRVType *VTy = getValueType(Vector)->getScalarType(); (void)Ty; (void)MTy; (void)VTy; assert(Ty->isTypeFloat() && "Invalid result type for OpVectorTimesMatrix"); assert(VTy->isTypeFloat() && "Invalid Vector type for OpVectorTimesMatrix"); assert(MTy->isTypeFloat() && "Invalid Matrix type for OpVectorTimesMatrix"); assert(Ty == MTy && Ty == VTy && "Mismatch float type"); } private: SPIRVId Vector; SPIRVId Matrix; }; class SPIRVMatrixTimesScalar : public SPIRVInstruction { public: static const Op OC = OpMatrixTimesScalar; static const SPIRVWord FixedWordCount = 4; // Complete constructor SPIRVMatrixTimesScalar(SPIRVType *TheType, SPIRVId TheId, SPIRVId TheMatrix, SPIRVId TheScalar, SPIRVBasicBlock *BB) : SPIRVInstruction(5, OC, TheType, TheId, BB), Matrix(TheMatrix), Scalar(TheScalar) { validate(); assert(BB && "Invalid BB"); } // Incomplete constructor SPIRVMatrixTimesScalar() : SPIRVInstruction(OC), Matrix(SPIRVID_INVALID), Scalar(SPIRVID_INVALID) { } SPIRVValue *getMatrix() const { return getValue(Matrix); } SPIRVValue *getScalar() const { return getValue(Scalar); } std::vector getOperands() override { std::vector Operands; Operands.push_back(Matrix); Operands.push_back(Scalar); return getValues(Operands); } void setWordCount(SPIRVWord FixedWordCount) override { SPIRVEntry::setWordCount(FixedWordCount); } _SPIRV_DEF_ENCDEC4(Type, Id, Matrix, Scalar) void validate() const override { SPIRVInstruction::validate(); if (getValue(Matrix)->isForward() || getValue(Scalar)->isForward()) return; SPIRVType *Ty = getType()->getScalarType(); SPIRVType *MTy = getValueType(Matrix)->getScalarType(); SPIRVType *STy = getValueType(Scalar); (void)Ty; (void)MTy; (void)STy; assert(Ty && Ty->isTypeFloat() && "Invalid result type for OpMatrixTimesScalar"); assert(MTy && MTy->isTypeFloat() && "Invalid Matrix type for OpMatrixTimesScalar"); assert(STy->isTypeFloat() && "Invalid Scalar type for OpMatrixTimesScalar"); assert(Ty == MTy && Ty == STy && "Mismatch float type"); } private: SPIRVId Matrix; SPIRVId Scalar; }; class SPIRVMatrixTimesVector : public SPIRVInstruction { public: static const Op OC = OpMatrixTimesVector; static const SPIRVWord FixedWordCount = 4; // Complete constructor SPIRVMatrixTimesVector(SPIRVType *TheType, SPIRVId TheId, SPIRVId TheMatrix, SPIRVId TheVector, SPIRVBasicBlock *BB) : SPIRVInstruction(5, OC, TheType, TheId, BB), Matrix(TheMatrix), Vector(TheVector) { validate(); assert(BB && "Invalid BB"); } // Incomplete constructor SPIRVMatrixTimesVector() : SPIRVInstruction(OC), Matrix(SPIRVID_INVALID), Vector(SPIRVID_INVALID) { } SPIRVValue *getMatrix() const { return getValue(Matrix); } SPIRVValue *getVector() const { return getValue(Vector); } std::vector getOperands() override { std::vector Operands; Operands.push_back(Matrix); Operands.push_back(Vector); return getValues(Operands); } void setWordCount(SPIRVWord FixedWordCount) override { SPIRVEntry::setWordCount(FixedWordCount); } _SPIRV_DEF_ENCDEC4(Type, Id, Matrix, Vector) void validate() const override { SPIRVInstruction::validate(); if (getValue(Matrix)->isForward() || getValue(Vector)->isForward()) return; SPIRVType *Ty = getType()->getScalarType(); SPIRVType *MTy = getValueType(Matrix)->getScalarType(); SPIRVType *VTy = getValueType(Vector)->getScalarType(); (void)Ty; (void)MTy; (void)VTy; assert(Ty->isTypeFloat() && "Invalid result type for OpMatrixTimesVector"); assert(MTy->isTypeFloat() && "Invalid Matrix type for OpMatrixTimesVector"); assert(VTy->isTypeFloat() && "Invalid Vector type for OpMatrixTimesVector"); assert(Ty == MTy && Ty == VTy && "Mismatch float type"); } private: SPIRVId Matrix; SPIRVId Vector; }; class SPIRVMatrixTimesMatrix : public SPIRVInstruction { public: static const Op OC = OpMatrixTimesMatrix; static const SPIRVWord FixedWordCount = 4; // Complete constructor SPIRVMatrixTimesMatrix(SPIRVType *TheType, SPIRVId TheId, SPIRVId M1, SPIRVId M2, SPIRVBasicBlock *BB) : SPIRVInstruction(5, OC, TheType, TheId, BB), LeftMatrix(M1), RightMatrix(M2) { validate(); assert(BB && "Invalid BB"); } // Incomplete constructor SPIRVMatrixTimesMatrix() : SPIRVInstruction(OC), LeftMatrix(SPIRVID_INVALID), RightMatrix(SPIRVID_INVALID) {} SPIRVValue *getLeftMatrix() const { return getValue(LeftMatrix); } SPIRVValue *getRightMatrix() const { return getValue(RightMatrix); } std::vector getOperands() override { std::vector Operands; Operands.push_back(LeftMatrix); Operands.push_back(RightMatrix); return getValues(Operands); } void setWordCount(SPIRVWord FixedWordCount) override { SPIRVEntry::setWordCount(FixedWordCount); } _SPIRV_DEF_ENCDEC4(Type, Id, LeftMatrix, RightMatrix) void validate() const override { SPIRVInstruction::validate(); if (getValue(LeftMatrix)->isForward() || getValue(RightMatrix)->isForward()) return; SPIRVType *Ty = getType()->getScalarType(); SPIRVType *LMTy = getValueType(LeftMatrix)->getScalarType(); SPIRVType *RMTy = getValueType(RightMatrix)->getScalarType(); (void)Ty; (void)LMTy; (void)RMTy; assert(Ty->isTypeFloat() && "Invalid result type for OpMatrixTimesMatrix"); assert(LMTy->isTypeFloat() && "Invalid Matrix type for OpMatrixTimesMatrix"); assert(RMTy->isTypeFloat() && "Invalid Matrix type for OpMatrixTimesMatrix"); assert(Ty == LMTy && Ty == RMTy && "Mismatch float type"); } private: SPIRVId LeftMatrix; SPIRVId RightMatrix; }; class SPIRVTranspose : public SPIRVInstruction { public: static const Op OC = OpTranspose; static const SPIRVWord FixedWordCount = 3; // Complete constructor SPIRVTranspose(SPIRVType *TheType, SPIRVId TheId, SPIRVId TheMatrix, SPIRVBasicBlock *BB) : SPIRVInstruction(4, OC, TheType, TheId, BB), Matrix(TheMatrix) { validate(); assert(BB && "Invalid BB"); } // Incomplete constructor SPIRVTranspose() : SPIRVInstruction(OC), Matrix(SPIRVID_INVALID) {} SPIRVValue *getMatrix() const { return getValue(Matrix); } std::vector getOperands() override { std::vector Operands; Operands.push_back(Matrix); return getValues(Operands); } void setWordCount(SPIRVWord FixedWordCount) override { SPIRVEntry::setWordCount(FixedWordCount); } _SPIRV_DEF_ENCDEC3(Type, Id, Matrix) void validate() const override { SPIRVInstruction::validate(); if (getValue(Matrix)->isForward()) return; SPIRVType *Ty = getType()->getScalarType(); SPIRVType *MTy = getValueType(Matrix)->getScalarType(); (void)Ty; (void)MTy; assert(Ty->isTypeFloat() && "Invalid result type for OpTranspose"); assert(Ty == MTy && "Mismatch float type"); } private: SPIRVId Matrix; }; class SPIRVUnary : public SPIRVInstTemplateBase { protected: void validate() const override { auto Op = Ops[0]; SPIRVInstruction::validate(); if (getValue(Op)->isForward()) return; if (isGenericNegateOpCode(OpCode)) { SPIRVType *ResTy = Type->isTypeVector() ? Type->getVectorComponentType() : Type; SPIRVType *OpTy = Type->isTypeVector() ? getValueType(Op)->getVectorComponentType() : getValueType(Op); (void)ResTy; (void)OpTy; assert(getType() == getValueType(Op) && "Inconsistent type"); assert((ResTy->isTypeInt() || ResTy->isTypeFloat()) && "Invalid type for Generic Negate instruction"); assert((ResTy->getBitWidth() == OpTy->getBitWidth()) && "Invalid bitwidth for Generic Negate instruction"); assert((Type->isTypeVector() ? (Type->getVectorComponentCount() == getValueType(Op)->getVectorComponentCount()) : 1) && "Invalid vector component Width for Generic Negate instruction"); } } }; template class SPIRVUnaryInst : public SPIRVInstTemplate {}; #define _SPIRV_OP(x) typedef SPIRVUnaryInst SPIRV##x; _SPIRV_OP(ConvertFToU) _SPIRV_OP(ConvertFToS) _SPIRV_OP(ConvertSToF) _SPIRV_OP(ConvertUToF) _SPIRV_OP(UConvert) _SPIRV_OP(SConvert) _SPIRV_OP(FConvert) _SPIRV_OP(SatConvertSToU) _SPIRV_OP(SatConvertUToS) _SPIRV_OP(ConvertPtrToU) _SPIRV_OP(ConvertUToPtr) _SPIRV_OP(PtrCastToGeneric) _SPIRV_OP(GenericCastToPtr) _SPIRV_OP(Bitcast) _SPIRV_OP(SNegate) _SPIRV_OP(FNegate) _SPIRV_OP(Not) _SPIRV_OP(LogicalNot) _SPIRV_OP(IsNan) _SPIRV_OP(IsInf) _SPIRV_OP(IsFinite) _SPIRV_OP(IsNormal) _SPIRV_OP(SignBitSet) _SPIRV_OP(Any) _SPIRV_OP(All) _SPIRV_OP(BitCount) _SPIRV_OP(BitReverse) #undef _SPIRV_OP class SPIRVAccessChainBase : public SPIRVInstTemplateBase { public: SPIRVValue *getBase() { return this->getValue(this->Ops[0]); } std::vector getIndices() const { std::vector IndexWords(this->Ops.begin() + 1, this->Ops.end()); return this->getValues(IndexWords); } bool isInBounds() { return OpCode == OpInBoundsAccessChain || OpCode == OpInBoundsPtrAccessChain; } bool hasPtrIndex() { return OpCode == OpPtrAccessChain || OpCode == OpInBoundsPtrAccessChain; } }; template class SPIRVAccessChainGeneric : public SPIRVInstTemplate { }; typedef SPIRVAccessChainGeneric SPIRVAccessChain; typedef SPIRVAccessChainGeneric SPIRVInBoundsAccessChain; typedef SPIRVAccessChainGeneric SPIRVPtrAccessChain; typedef SPIRVAccessChainGeneric SPIRVInBoundsPtrAccessChain; class SPIRVLoopControlINTEL : public SPIRVInstruction { public: static const Op OC = OpLoopControlINTEL; static const SPIRVWord FixedWordCount = 2; SPIRVLoopControlINTEL(SPIRVWord TheLoopControl, std::vector TheLoopControlParameters, SPIRVBasicBlock *BB) : SPIRVInstruction(FixedWordCount + TheLoopControlParameters.size(), OC, BB), LoopControl(TheLoopControl), LoopControlParameters(TheLoopControlParameters) { validate(); assert(BB && "Invalid BB"); } SPIRVLoopControlINTEL() : SPIRVInstruction(OC), LoopControl(SPIRVWORD_MAX) { setHasNoId(); setHasNoType(); } SPIRVWord getLoopControl() const { return LoopControl; } std::vector getLoopControlParameters() const { return LoopControlParameters; } SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilityUnstructuredLoopControlsINTEL); } SPIRVExtSet getRequiredExtensions() const override { return getSet(ExtensionID::SPV_INTEL_unstructured_loop_controls); } void setWordCount(SPIRVWord TheWordCount) override { SPIRVEntry::setWordCount(TheWordCount); LoopControlParameters.resize(TheWordCount - FixedWordCount); } _SPIRV_DEF_ENCDEC2(LoopControl, LoopControlParameters) protected: SPIRVWord LoopControl; std::vector LoopControlParameters; }; template class SPIRVFunctionCallGeneric : public SPIRVInstruction { public: SPIRVFunctionCallGeneric(SPIRVType *TheType, SPIRVId TheId, const std::vector &TheArgs, SPIRVBasicBlock *BB) : SPIRVInstruction(TheArgs.size() + FixedWordCount, OC, TheType, TheId, BB), Args(TheArgs) { SPIRVFunctionCallGeneric::validate(); assert(BB && "Invalid BB"); } SPIRVFunctionCallGeneric(SPIRVType *TheType, SPIRVId TheId, const std::vector &TheArgs, SPIRVBasicBlock *BB) : SPIRVInstruction(TheArgs.size() + FixedWordCount, OC, TheType, TheId, BB) { Args = getIds(TheArgs); SPIRVFunctionCallGeneric::validate(); assert(BB && "Invalid BB"); } SPIRVFunctionCallGeneric(SPIRVModule *BM, SPIRVWord ResId, SPIRVType *TheType, const std::vector &TheArgs) : SPIRVInstruction(TheArgs.size() + FixedWordCount, OC, TheType, ResId, BM), Args(TheArgs) {} SPIRVFunctionCallGeneric() : SPIRVInstruction(OC) {} const std::vector &getArguments() const { return Args; } void setArguments(const std::vector &A) { Args = A; setWordCount(Args.size() + FixedWordCount); } std::vector getArgumentValues() { return getValues(Args); } std::vector getArgumentValueTypes() const { std::vector ArgTypes; for (auto &I : Args) ArgTypes.push_back(getValue(I)->getType()); return ArgTypes; } void setWordCount(SPIRVWord TheWordCount) override { SPIRVEntry::setWordCount(TheWordCount); Args.resize(TheWordCount - FixedWordCount); } void validate() const override { SPIRVInstruction::validate(); } protected: std::vector Args; }; class SPIRVFunctionCall : public SPIRVFunctionCallGeneric { public: SPIRVFunctionCall(SPIRVId TheId, SPIRVFunction *TheFunction, const std::vector &TheArgs, SPIRVBasicBlock *BB); SPIRVFunctionCall() : FunctionId(SPIRVID_INVALID) {} SPIRVFunction *getFunction() const { return get(FunctionId); } _SPIRV_DEF_ENCDEC4(Type, Id, FunctionId, Args) void validate() const override; bool isOperandLiteral(unsigned Index) const override { return false; } protected: SPIRVId FunctionId; }; class SPIRVFunctionPointerCallINTEL : public SPIRVFunctionCallGeneric { public: SPIRVFunctionPointerCallINTEL(SPIRVId TheId, SPIRVValue *TheCalledValue, SPIRVType *TheReturnType, const std::vector &TheArgs, SPIRVBasicBlock *BB); SPIRVFunctionPointerCallINTEL() : CalledValueId(SPIRVID_INVALID) {} SPIRVValue *getCalledValue() const { return get(CalledValueId); } _SPIRV_DEF_ENCDEC4(Type, Id, CalledValueId, Args) void validate() const override; bool isOperandLiteral(unsigned Index) const override { return false; } SPIRVExtSet getRequiredExtensions() const override { return getSet(ExtensionID::SPV_INTEL_function_pointers); } SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilityFunctionPointersINTEL); } protected: SPIRVId CalledValueId; }; class SPIRVFunctionPointerINTEL : public SPIRVInstruction { const static Op OC = OpFunctionPointerINTEL; const static SPIRVWord FixedWordCount = 4; public: SPIRVFunctionPointerINTEL(SPIRVId TheId, SPIRVType *TheType, SPIRVFunction *TheFunction, SPIRVBasicBlock *BB); SPIRVFunctionPointerINTEL() : SPIRVInstruction(OC), TheFunction(SPIRVID_INVALID) {} SPIRVFunction *getFunction() const { return get(TheFunction); } _SPIRV_DEF_ENCDEC3(Type, Id, TheFunction) void validate() const override; bool isOperandLiteral(unsigned Index) const override { return false; } SPIRVExtSet getRequiredExtensions() const override { return getSet(ExtensionID::SPV_INTEL_function_pointers); } SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilityFunctionPointersINTEL); } protected: SPIRVId TheFunction; }; class SPIRVExtInst : public SPIRVFunctionCallGeneric { public: SPIRVExtInst(SPIRVType *TheType, SPIRVId TheId, SPIRVId TheBuiltinSet, SPIRVWord TheEntryPoint, const std::vector &TheArgs, SPIRVBasicBlock *BB) : SPIRVFunctionCallGeneric(TheType, TheId, TheArgs, BB), ExtSetId(TheBuiltinSet), ExtOp(TheEntryPoint) { setExtSetKindById(); SPIRVExtInst::validate(); } SPIRVExtInst(SPIRVType *TheType, SPIRVId TheId, SPIRVId TheBuiltinSet, SPIRVWord TheEntryPoint, const std::vector &TheArgs, SPIRVBasicBlock *BB) : SPIRVFunctionCallGeneric(TheType, TheId, TheArgs, BB), ExtSetId(TheBuiltinSet), ExtOp(TheEntryPoint) { setExtSetKindById(); SPIRVExtInst::validate(); } SPIRVExtInst(SPIRVModule *BM, SPIRVId ResId, SPIRVType *TheType, SPIRVExtInstSetKind SetKind, SPIRVWord SetId, SPIRVWord InstId, const std::vector &Args) : SPIRVFunctionCallGeneric(BM, ResId, TheType, Args), ExtSetKind(SetKind), ExtSetId(SetId), ExtOp(InstId) {} SPIRVExtInst(SPIRVExtInstSetKind SetKind = SPIRVEIS_Count, unsigned ExtOC = SPIRVWORD_MAX) : ExtSetKind(SetKind), ExtSetId(SPIRVWORD_MAX), ExtOp(ExtOC) {} void setExtSetId(unsigned Set) { ExtSetId = Set; } void setExtOp(unsigned ExtOC) { ExtOp = ExtOC; } SPIRVId getExtSetId() const { return ExtSetId; } SPIRVWord getExtOp() const { return ExtOp; } SPIRVExtInstSetKind getExtSetKind() const { return ExtSetKind; } void setExtSetKindById() { assert(Module && "Invalid module"); ExtSetKind = Module->getBuiltinSet(ExtSetId); assert((ExtSetKind == SPIRVEIS_OpenCL || ExtSetKind == SPIRVEIS_Debug) && "not supported"); } void encode(spv_ostream &O) const override { getEncoder(O) << Type << Id << ExtSetId; switch (ExtSetKind) { case SPIRVEIS_OpenCL: getEncoder(O) << ExtOpOCL; break; case SPIRVEIS_Debug: getEncoder(O) << ExtOpDebug; break; default: assert(0 && "not supported"); getEncoder(O) << ExtOp; } getEncoder(O) << Args; } void decode(std::istream &I) override { getDecoder(I) >> Type >> Id >> ExtSetId; setExtSetKindById(); switch (ExtSetKind) { case SPIRVEIS_OpenCL: getDecoder(I) >> ExtOpOCL; break; case SPIRVEIS_Debug: getDecoder(I) >> ExtOpDebug; break; default: assert(0 && "not supported"); getDecoder(I) >> ExtOp; } getDecoder(I) >> Args; } void validate() const override { SPIRVFunctionCallGeneric::validate(); validateBuiltin(ExtSetId, ExtOp); } bool isOperandLiteral(unsigned Index) const override { assert(ExtSetKind == SPIRVEIS_OpenCL && "Unsupported extended instruction set"); auto EOC = static_cast(ExtOp); switch (EOC) { default: return false; case OpenCLLIB::Vloadn: case OpenCLLIB::Vload_halfn: case OpenCLLIB::Vloada_halfn: return Index == 2; case OpenCLLIB::Vstore_half_r: case OpenCLLIB::Vstore_halfn_r: case OpenCLLIB::Vstorea_halfn_r: return Index == 3; } } protected: SPIRVExtInstSetKind ExtSetKind; SPIRVId ExtSetId; union { SPIRVWord ExtOp; OCLExtOpKind ExtOpOCL; SPIRVDebugExtOpKind ExtOpDebug; }; }; class SPIRVCompositeConstruct : public SPIRVInstruction { public: const static Op OC = OpCompositeConstruct; const static SPIRVWord FixedWordCount = 3; // Complete constructor SPIRVCompositeConstruct(SPIRVType *TheType, SPIRVId TheId, const std::vector &TheConstituents, SPIRVBasicBlock *TheBB) : SPIRVInstruction(TheConstituents.size() + FixedWordCount, OC, TheType, TheId, TheBB), Constituents(TheConstituents) { validate(); assert(TheBB && "Invalid BB"); } // Incomplete constructor SPIRVCompositeConstruct() : SPIRVInstruction(OC) {} const std::vector getConstituents() const { return getValues(Constituents); } protected: void setWordCount(SPIRVWord TheWordCount) override { SPIRVEntry::setWordCount(TheWordCount); Constituents.resize(TheWordCount - FixedWordCount); } _SPIRV_DEF_ENCDEC3(Type, Id, Constituents) void validate() const override { SPIRVInstruction::validate(); switch (getValueType(this->getId())->getOpCode()) { case OpTypeVector: assert(getConstituents().size() > 1 && "There must be at least two Constituent operands in vector"); break; case OpTypeArray: case OpTypeStruct: break; default: assert(false && "Invalid type"); } } std::vector Constituents; }; class SPIRVCompositeExtract : public SPIRVInstruction { public: const static Op OC = OpCompositeExtract; // Complete constructor SPIRVCompositeExtract(SPIRVType *TheType, SPIRVId TheId, SPIRVValue *TheComposite, const std::vector &TheIndices, SPIRVBasicBlock *TheBB) : SPIRVInstruction(TheIndices.size() + 4, OC, TheType, TheId, TheBB), Composite(TheComposite->getId()), Indices(TheIndices) { validate(); assert(TheBB && "Invalid BB"); } // Incomplete constructor SPIRVCompositeExtract() : SPIRVInstruction(OC), Composite(SPIRVID_INVALID) {} SPIRVValue *getComposite() { return getValue(Composite); } const std::vector &getIndices() const { return Indices; } protected: void setWordCount(SPIRVWord TheWordCount) override { SPIRVEntry::setWordCount(TheWordCount); Indices.resize(TheWordCount - 4); } _SPIRV_DEF_ENCDEC4(Type, Id, Composite, Indices) // ToDo: validate the result type is consistent with the base type and indices // need to trace through the base type for struct types void validate() const override { SPIRVInstruction::validate(); assert(getValueType(Composite)->isTypeArray() || getValueType(Composite)->isTypeStruct() || getValueType(Composite)->isTypeVector()); } SPIRVId Composite; std::vector Indices; }; class SPIRVCompositeInsert : public SPIRVInstruction { public: const static Op OC = OpCompositeInsert; const static SPIRVWord FixedWordCount = 5; // Complete constructor SPIRVCompositeInsert(SPIRVId TheId, SPIRVValue *TheObject, SPIRVValue *TheComposite, const std::vector &TheIndices, SPIRVBasicBlock *TheBB) : SPIRVInstruction(TheIndices.size() + FixedWordCount, OC, TheComposite->getType(), TheId, TheBB), Object(TheObject->getId()), Composite(TheComposite->getId()), Indices(TheIndices) { validate(); assert(TheBB && "Invalid BB"); } // Incomplete constructor SPIRVCompositeInsert() : SPIRVInstruction(OC), Object(SPIRVID_INVALID), Composite(SPIRVID_INVALID) {} SPIRVValue *getObject() { return getValue(Object); } SPIRVValue *getComposite() { return getValue(Composite); } const std::vector &getIndices() const { return Indices; } protected: void setWordCount(SPIRVWord TheWordCount) override { SPIRVEntry::setWordCount(TheWordCount); Indices.resize(TheWordCount - FixedWordCount); } _SPIRV_DEF_ENCDEC5(Type, Id, Object, Composite, Indices) // ToDo: validate the object type is consistent with the base type and indices // need to trace through the base type for struct types void validate() const override { SPIRVInstruction::validate(); assert(OpCode == OC); assert(WordCount == Indices.size() + FixedWordCount); assert(getValueType(Composite)->isTypeArray() || getValueType(Composite)->isTypeStruct() || getValueType(Composite)->isTypeVector()); assert(Type == getValueType(Composite)); } SPIRVId Object; SPIRVId Composite; std::vector Indices; }; class SPIRVCopyObject : public SPIRVInstruction { public: const static Op OC = OpCopyObject; // Complete constructor SPIRVCopyObject(SPIRVType *TheType, SPIRVId TheId, SPIRVValue *TheOperand, SPIRVBasicBlock *TheBB) : SPIRVInstruction(4, OC, TheType, TheId, TheBB), Operand(TheOperand->getId()) { validate(); assert(TheBB && "Invalid BB"); } // Incomplete constructor SPIRVCopyObject() : SPIRVInstruction(OC), Operand(SPIRVID_INVALID) {} SPIRVValue *getOperand() { return getValue(Operand); } protected: _SPIRV_DEF_ENCDEC3(Type, Id, Operand) void validate() const override { SPIRVInstruction::validate(); } SPIRVId Operand; }; class SPIRVCopyMemory : public SPIRVInstruction, public SPIRVMemoryAccess { public: const static Op OC = OpCopyMemory; const static SPIRVWord FixedWords = 3; // Complete constructor SPIRVCopyMemory(SPIRVValue *TheTarget, SPIRVValue *TheSource, const std::vector &TheMemoryAccess, SPIRVBasicBlock *TheBB) : SPIRVInstruction(FixedWords + TheMemoryAccess.size(), OC, TheBB), SPIRVMemoryAccess(TheMemoryAccess), MemoryAccess(TheMemoryAccess), Target(TheTarget->getId()), Source(TheSource->getId()) { validate(); assert(TheBB && "Invalid BB"); } // Incomplete constructor SPIRVCopyMemory() : SPIRVInstruction(OC), SPIRVMemoryAccess(), Target(SPIRVID_INVALID), Source(SPIRVID_INVALID) { setHasNoId(); setHasNoType(); } SPIRVValue *getSource() { return getValue(Source); } SPIRVValue *getTarget() { return getValue(Target); } protected: void setWordCount(SPIRVWord TheWordCount) override { SPIRVEntry::setWordCount(TheWordCount); MemoryAccess.resize(TheWordCount - FixedWords); } void encode(spv_ostream &O) const override { getEncoder(O) << Target << Source << MemoryAccess; } void decode(std::istream &I) override { getDecoder(I) >> Target >> Source >> MemoryAccess; memoryAccessUpdate(MemoryAccess); } void validate() const override { assert((getValueType(Id) == getValueType(Source)) && "Inconsistent type"); assert(getValueType(Id)->isTypePointer() && "Invalid type"); assert(!(getValueType(Id)->getPointerElementType()->isTypeVoid()) && "Invalid type"); SPIRVInstruction::validate(); } std::vector MemoryAccess; SPIRVId Target; SPIRVId Source; }; class SPIRVCopyMemorySized : public SPIRVInstruction, public SPIRVMemoryAccess { public: const static Op OC = OpCopyMemorySized; const static SPIRVWord FixedWords = 4; // Complete constructor SPIRVCopyMemorySized(SPIRVValue *TheTarget, SPIRVValue *TheSource, SPIRVValue *TheSize, const std::vector &TheMemoryAccess, SPIRVBasicBlock *TheBB) : SPIRVInstruction(FixedWords + TheMemoryAccess.size(), OC, TheBB), SPIRVMemoryAccess(TheMemoryAccess), MemoryAccess(TheMemoryAccess), Target(TheTarget->getId()), Source(TheSource->getId()), Size(TheSize->getId()) { validate(); assert(TheBB && "Invalid BB"); } // Incomplete constructor SPIRVCopyMemorySized() : SPIRVInstruction(OC), SPIRVMemoryAccess(), Target(SPIRVID_INVALID), Source(SPIRVID_INVALID), Size(0) { setHasNoId(); setHasNoType(); } SPIRVValue *getSource() { return getValue(Source); } SPIRVValue *getTarget() { return getValue(Target); } SPIRVValue *getSize() { return getValue(Size); } protected: void setWordCount(SPIRVWord TheWordCount) override { SPIRVEntry::setWordCount(TheWordCount); MemoryAccess.resize(TheWordCount - FixedWords); } void encode(spv_ostream &O) const override { getEncoder(O) << Target << Source << Size << MemoryAccess; } void decode(std::istream &I) override { getDecoder(I) >> Target >> Source >> Size >> MemoryAccess; memoryAccessUpdate(MemoryAccess); } void validate() const override { SPIRVInstruction::validate(); } std::vector MemoryAccess; SPIRVId Target; SPIRVId Source; SPIRVId Size; }; class SPIRVVectorExtractDynamic : public SPIRVInstruction { public: const static Op OC = OpVectorExtractDynamic; // Complete constructor SPIRVVectorExtractDynamic(SPIRVId TheId, SPIRVValue *TheVector, SPIRVValue *TheIndex, SPIRVBasicBlock *TheBB) : SPIRVInstruction(5, OC, TheVector->getType()->getVectorComponentType(), TheId, TheBB), VectorId(TheVector->getId()), IndexId(TheIndex->getId()) { validate(); assert(TheBB && "Invalid BB"); } // Incomplete constructor SPIRVVectorExtractDynamic() : SPIRVInstruction(OC), VectorId(SPIRVID_INVALID), IndexId(SPIRVID_INVALID) {} SPIRVValue *getVector() { return getValue(VectorId); } SPIRVValue *getIndex() const { return getValue(IndexId); } protected: _SPIRV_DEF_ENCDEC4(Type, Id, VectorId, IndexId) void validate() const override { SPIRVInstruction::validate(); if (getValue(VectorId)->isForward()) return; assert(getValueType(VectorId)->isTypeVector()); } SPIRVId VectorId; SPIRVId IndexId; }; class SPIRVVectorInsertDynamic : public SPIRVInstruction { public: const static Op OC = OpVectorInsertDynamic; // Complete constructor SPIRVVectorInsertDynamic(SPIRVId TheId, SPIRVValue *TheVector, SPIRVValue *TheComponent, SPIRVValue *TheIndex, SPIRVBasicBlock *TheBB) : SPIRVInstruction(6, OC, TheVector->getType(), TheId, TheBB), VectorId(TheVector->getId()), IndexId(TheIndex->getId()), ComponentId(TheComponent->getId()) { validate(); assert(TheBB && "Invalid BB"); } // Incomplete constructor SPIRVVectorInsertDynamic() : SPIRVInstruction(OC), VectorId(SPIRVID_INVALID), IndexId(SPIRVID_INVALID), ComponentId(SPIRVID_INVALID) {} SPIRVValue *getVector() { return getValue(VectorId); } SPIRVValue *getIndex() const { return getValue(IndexId); } SPIRVValue *getComponent() { return getValue(ComponentId); } protected: _SPIRV_DEF_ENCDEC5(Type, Id, VectorId, ComponentId, IndexId) void validate() const override { SPIRVInstruction::validate(); if (getValue(VectorId)->isForward()) return; assert(getValueType(VectorId)->isTypeVector()); } SPIRVId VectorId; SPIRVId IndexId; SPIRVId ComponentId; }; class SPIRVVectorShuffle : public SPIRVInstruction { public: const static Op OC = OpVectorShuffle; const static SPIRVWord FixedWordCount = 5; // Complete constructor SPIRVVectorShuffle(SPIRVId TheId, SPIRVType *TheType, SPIRVValue *TheVector1, SPIRVValue *TheVector2, const std::vector &TheComponents, SPIRVBasicBlock *TheBB) : SPIRVInstruction(TheComponents.size() + FixedWordCount, OC, TheType, TheId, TheBB), Vector1(TheVector1->getId()), Vector2(TheVector2->getId()), Components(TheComponents) { validate(); assert(TheBB && "Invalid BB"); } // Incomplete constructor SPIRVVectorShuffle() : SPIRVInstruction(OC), Vector1(SPIRVID_INVALID), Vector2(SPIRVID_INVALID) {} SPIRVValue *getVector1() { return getValue(Vector1); } SPIRVValue *getVector2() { return getValue(Vector2); } const std::vector &getComponents() const { return Components; } protected: void setWordCount(SPIRVWord TheWordCount) override { SPIRVEntry::setWordCount(TheWordCount); Components.resize(TheWordCount - FixedWordCount); } _SPIRV_DEF_ENCDEC5(Type, Id, Vector1, Vector2, Components) void validate() const override { SPIRVInstruction::validate(); assert(OpCode == OC); assert(WordCount == Components.size() + FixedWordCount); assert(Type->isTypeVector()); assert(Type->getVectorComponentType() == getValueType(Vector1)->getVectorComponentType()); if (getValue(Vector1)->isForward() || getValue(Vector2)->isForward()) return; assert(getValueType(Vector1) == getValueType(Vector2)); assert(Components.size() == Type->getVectorComponentCount()); assert(Components.size() > 1); } SPIRVId Vector1; SPIRVId Vector2; std::vector Components; }; class SPIRVControlBarrier : public SPIRVInstruction { public: static const Op OC = OpControlBarrier; // Complete constructor SPIRVControlBarrier(SPIRVValue *TheScope, SPIRVValue *TheMemScope, SPIRVValue *TheMemSema, SPIRVBasicBlock *TheBB) : SPIRVInstruction(4, OC, TheBB), ExecScope(TheScope->getId()), MemScope(TheMemScope->getId()), MemSema(TheMemSema->getId()) { validate(); assert(TheBB && "Invalid BB"); } // Incomplete constructor SPIRVControlBarrier() : SPIRVInstruction(OC), ExecScope(ScopeInvocation) { setHasNoId(); setHasNoType(); } void setWordCount(SPIRVWord TheWordCount) override { SPIRVEntry::setWordCount(TheWordCount); } SPIRVValue *getExecScope() const { return getValue(ExecScope); } SPIRVValue *getMemScope() const { return getValue(MemScope); } SPIRVValue *getMemSemantic() const { return getValue(MemSema); } std::vector getOperands() override { std::vector Operands; Operands.push_back(ExecScope); Operands.push_back(MemScope); Operands.push_back(MemSema); return getValues(Operands); } protected: _SPIRV_DEF_ENCDEC3(ExecScope, MemScope, MemSema) void validate() const override { assert(OpCode == OC); assert(WordCount == 4); SPIRVInstruction::validate(); } SPIRVId ExecScope; SPIRVId MemScope; SPIRVId MemSema; }; template class SPIRVLifetime : public SPIRVInstruction { public: // Complete constructor SPIRVLifetime(SPIRVId TheObject, SPIRVWord TheSize, SPIRVBasicBlock *TheBB) : SPIRVInstruction(3, OC, TheBB), Object(TheObject), Size(TheSize) { validate(); assert(TheBB && "Invalid BB"); }; // Incomplete constructor SPIRVLifetime() : SPIRVInstruction(OC), Object(SPIRVID_INVALID), Size(SPIRVWORD_MAX) { setHasNoId(); setHasNoType(); } SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilityKernel); } SPIRVValue *getObject() { return getValue(Object); }; SPIRVWord getSize() { return Size; }; protected: void validate() const override { auto ObjType = getValue(Object)->getType(); // Type must be an OpTypePointer with Storage Class Function. assert(ObjType->isTypePointer() && "Objects type must be a pointer"); assert(static_cast(ObjType)->getStorageClass() == StorageClassFunction && "Invalid storage class"); // Size must be 0 if Pointer is a pointer to a non-void type or the // Addresses capability is not being used. If Size is non-zero, it is the // number of bytes of memory whose lifetime is starting. Its type must be an // integer type scalar. It is treated as unsigned; if its type has // Signedness of 1, its sign bit cannot be set. if (!(ObjType->getPointerElementType()->isTypeVoid() || // (void *) is i8* in LLVM IR ObjType->getPointerElementType()->isTypeInt(8)) || !Module->hasCapability(CapabilityAddresses)) assert(Size == 0 && "Size must be 0"); } _SPIRV_DEF_ENCDEC2(Object, Size) SPIRVId Object; SPIRVWord Size; }; typedef SPIRVLifetime SPIRVLifetimeStart; typedef SPIRVLifetime SPIRVLifetimeStop; class SPIRVGroupAsyncCopy : public SPIRVInstruction { public: static const Op OC = OpGroupAsyncCopy; static const SPIRVWord WC = 9; // Complete constructor SPIRVGroupAsyncCopy(SPIRVValue *TheScope, SPIRVId TheId, SPIRVValue *TheDest, SPIRVValue *TheSrc, SPIRVValue *TheNumElems, SPIRVValue *TheStride, SPIRVValue *TheEvent, SPIRVBasicBlock *TheBB) : SPIRVInstruction(WC, OC, TheEvent->getType(), TheId, TheBB), ExecScope(TheScope->getId()), Destination(TheDest->getId()), Source(TheSrc->getId()), NumElements(TheNumElems->getId()), Stride(TheStride->getId()), Event(TheEvent->getId()) { validate(); assert(TheBB && "Invalid BB"); } // Incomplete constructor SPIRVGroupAsyncCopy() : SPIRVInstruction(OC), ExecScope(SPIRVID_INVALID), Destination(SPIRVID_INVALID), Source(SPIRVID_INVALID), NumElements(SPIRVID_INVALID), Stride(SPIRVID_INVALID), Event(SPIRVID_INVALID) {} SPIRVValue *getExecScope() const { return getValue(ExecScope); } SPIRVValue *getDestination() const { return getValue(Destination); } SPIRVValue *getSource() const { return getValue(Source); } SPIRVValue *getNumElements() const { return getValue(NumElements); } SPIRVValue *getStride() const { return getValue(Stride); } SPIRVValue *getEvent() const { return getValue(Event); } std::vector getOperands() override { std::vector Operands; Operands.push_back(Destination); Operands.push_back(Source); Operands.push_back(NumElements); Operands.push_back(Stride); Operands.push_back(Event); return getValues(Operands); } protected: _SPIRV_DEF_ENCDEC8(Type, Id, ExecScope, Destination, Source, NumElements, Stride, Event) void validate() const override { assert(OpCode == OC); assert(WordCount == WC); SPIRVInstruction::validate(); } SPIRVId ExecScope; SPIRVId Destination; SPIRVId Source; SPIRVId NumElements; SPIRVId Stride; SPIRVId Event; }; enum SPIRVOpKind { SPIRVOPK_Id, SPIRVOPK_Literal, SPIRVOPK_Count }; class SPIRVDevEnqInstBase : public SPIRVInstTemplateBase { public: SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilityDeviceEnqueue); } }; #define _SPIRV_OP(x, ...) \ typedef SPIRVInstTemplate SPIRV##x; // CL 2.0 enqueue kernel builtins _SPIRV_OP(EnqueueMarker, true, 7) _SPIRV_OP(EnqueueKernel, true, 13, true) _SPIRV_OP(GetKernelNDrangeSubGroupCount, true, 8) _SPIRV_OP(GetKernelNDrangeMaxSubGroupSize, true, 8) _SPIRV_OP(GetKernelWorkGroupSize, true, 7) _SPIRV_OP(GetKernelPreferredWorkGroupSizeMultiple, true, 7) _SPIRV_OP(RetainEvent, false, 2) _SPIRV_OP(ReleaseEvent, false, 2) _SPIRV_OP(CreateUserEvent, true, 3) _SPIRV_OP(IsValidEvent, true, 4) _SPIRV_OP(SetUserEventStatus, false, 3) _SPIRV_OP(CaptureEventProfilingInfo, false, 4) _SPIRV_OP(GetDefaultQueue, true, 3) _SPIRV_OP(BuildNDRange, true, 6) #undef _SPIRV_OP class SPIRVPipeInstBase : public SPIRVInstTemplateBase { public: SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilityPipes); } }; #define _SPIRV_OP(x, ...) \ typedef SPIRVInstTemplate SPIRV##x; // CL 2.0 pipe builtins _SPIRV_OP(ReadPipe, true, 7) _SPIRV_OP(WritePipe, true, 7) _SPIRV_OP(ReservedReadPipe, true, 9) _SPIRV_OP(ReservedWritePipe, true, 9) _SPIRV_OP(ReserveReadPipePackets, true, 7) _SPIRV_OP(ReserveWritePipePackets, true, 7) _SPIRV_OP(CommitReadPipe, false, 5) _SPIRV_OP(CommitWritePipe, false, 5) _SPIRV_OP(IsValidReserveId, true, 4) _SPIRV_OP(GetNumPipePackets, true, 6) _SPIRV_OP(GetMaxPipePackets, true, 6) #undef _SPIRV_OP class SPIRVPipeStorageInstBase : public SPIRVInstTemplateBase { public: SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilityPipeStorage, CapabilityPipes); } }; #define _SPIRV_OP(x, ...) \ typedef SPIRVInstTemplate \ SPIRV##x; _SPIRV_OP(CreatePipeFromPipeStorage, true, 4) #undef _SPIRV_OP class SPIRVGroupInstBase : public SPIRVInstTemplateBase { public: SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilityGroups); } }; #define _SPIRV_OP(x, ...) \ typedef SPIRVInstTemplate SPIRV##x; // Group instructions _SPIRV_OP(GroupWaitEvents, false, 4) _SPIRV_OP(GroupAll, true, 5) _SPIRV_OP(GroupAny, true, 5) _SPIRV_OP(GroupBroadcast, true, 6) _SPIRV_OP(GroupIAdd, true, 6, false, 1) _SPIRV_OP(GroupFAdd, true, 6, false, 1) _SPIRV_OP(GroupFMin, true, 6, false, 1) _SPIRV_OP(GroupUMin, true, 6, false, 1) _SPIRV_OP(GroupSMin, true, 6, false, 1) _SPIRV_OP(GroupFMax, true, 6, false, 1) _SPIRV_OP(GroupUMax, true, 6, false, 1) _SPIRV_OP(GroupSMax, true, 6, false, 1) _SPIRV_OP(GroupReserveReadPipePackets, true, 8) _SPIRV_OP(GroupReserveWritePipePackets, true, 8) _SPIRV_OP(GroupCommitReadPipe, false, 6) _SPIRV_OP(GroupCommitWritePipe, false, 6) #undef _SPIRV_OP class SPIRVBlockingPipesIntelInst : public SPIRVInstTemplateBase { protected: SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilityBlockingPipesINTEL); } SPIRVExtSet getRequiredExtensions() const override { return getSet(ExtensionID::SPV_INTEL_blocking_pipes); } }; #define _SPIRV_OP(x, ...) \ typedef SPIRVInstTemplate \ SPIRV##x; _SPIRV_OP(ReadPipeBlockingINTEL, false, 5) _SPIRV_OP(WritePipeBlockingINTEL, false, 5) #undef _SPIRV_OP class SPIRVAtomicInstBase : public SPIRVInstTemplateBase { public: SPIRVCapVec getRequiredCapability() const override { SPIRVCapVec CapVec; // Most of atomic instructions do not require any capabilities // ... unless they operate on 64-bit integers. if (hasType() && getType()->isTypeInt(64)) { // In SPIRV 1.2 spec only 2 atomic instructions have no result type: // 1. OpAtomicStore - need to check type of the Value operand // 2. OpAtomicFlagClear - doesn't require Int64Atomics capability. CapVec.push_back(CapabilityInt64Atomics); } // Per the spec OpAtomicCompareExchangeWeak, OpAtomicFlagTestAndSet and // OpAtomicFlagClear instructions require kernel capability. But this // capability should be added by setting OpenCL memory model. return CapVec; } // Overriding the following method only because of OpAtomicStore. // We have to declare Int64Atomics capability if the Value operand is int64. void setOpWords(const std::vector &TheOps) override { SPIRVInstTemplateBase::setOpWords(TheOps); static const unsigned ValueOperandIndex = 3; if (getOpCode() == OpAtomicStore && getOperand(ValueOperandIndex)->getType()->isTypeInt(64)) Module->addCapability(CapabilityInt64Atomics); } }; #define _SPIRV_OP(x, ...) \ typedef SPIRVInstTemplate SPIRV##x; // Atomic builtins _SPIRV_OP(AtomicFlagTestAndSet, true, 6) _SPIRV_OP(AtomicFlagClear, false, 4) _SPIRV_OP(AtomicLoad, true, 6) _SPIRV_OP(AtomicStore, false, 5) _SPIRV_OP(AtomicExchange, true, 7) _SPIRV_OP(AtomicCompareExchange, true, 9) _SPIRV_OP(AtomicCompareExchangeWeak, true, 9) _SPIRV_OP(AtomicIIncrement, true, 6) _SPIRV_OP(AtomicIDecrement, true, 6) _SPIRV_OP(AtomicIAdd, true, 7) _SPIRV_OP(AtomicISub, true, 7) _SPIRV_OP(AtomicUMin, true, 7) _SPIRV_OP(AtomicUMax, true, 7) _SPIRV_OP(AtomicSMin, true, 7) _SPIRV_OP(AtomicSMax, true, 7) _SPIRV_OP(AtomicAnd, true, 7) _SPIRV_OP(AtomicOr, true, 7) _SPIRV_OP(AtomicXor, true, 7) _SPIRV_OP(MemoryBarrier, false, 3) #undef _SPIRV_OP class SPIRVImageInstBase : public SPIRVInstTemplateBase { public: SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilityImageBasic); } }; #define _SPIRV_OP(x, ...) \ typedef SPIRVInstTemplate SPIRV##x; // Image instructions _SPIRV_OP(SampledImage, true, 5) _SPIRV_OP(ImageSampleImplicitLod, true, 5, true) _SPIRV_OP(ImageSampleExplicitLod, true, 7, true, 2) _SPIRV_OP(ImageRead, true, 5, true, 2) _SPIRV_OP(ImageWrite, false, 4, true, 3) _SPIRV_OP(ImageQueryFormat, true, 4) _SPIRV_OP(ImageQueryOrder, true, 4) _SPIRV_OP(ImageQuerySizeLod, true, 5) _SPIRV_OP(ImageQuerySize, true, 4) _SPIRV_OP(ImageQueryLod, true, 5) _SPIRV_OP(ImageQueryLevels, true, 4) _SPIRV_OP(ImageQuerySamples, true, 4) #undef _SPIRV_OP #define _SPIRV_OP(x, ...) \ typedef SPIRVInstTemplate SPIRV##x; // Other instructions _SPIRV_OP(SpecConstantOp, true, 4, true, 0) _SPIRV_OP(GenericPtrMemSemantics, true, 4, false) _SPIRV_OP(GenericCastToPtrExplicit, true, 5, false, 1) #undef _SPIRV_OP class SPIRVSubgroupShuffleINTELInstBase : public SPIRVInstTemplateBase { protected: SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilitySubgroupShuffleINTEL); } SPIRVExtSet getRequiredExtensions() const override { return getSet(ExtensionID::SPV_INTEL_subgroups); } }; #define _SPIRV_OP(x, ...) \ typedef SPIRVInstTemplate \ SPIRV##x; // Intel Subgroup Shuffle Instructions _SPIRV_OP(SubgroupShuffleINTEL, true, 5) _SPIRV_OP(SubgroupShuffleDownINTEL, true, 6) _SPIRV_OP(SubgroupShuffleUpINTEL, true, 6) _SPIRV_OP(SubgroupShuffleXorINTEL, true, 5) #undef _SPIRV_OP class SPIRVSubgroupBufferBlockIOINTELInstBase : public SPIRVInstTemplateBase { protected: SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilitySubgroupBufferBlockIOINTEL); } SPIRVExtSet getRequiredExtensions() const override { return getSet(ExtensionID::SPV_INTEL_subgroups); } }; #define _SPIRV_OP(x, ...) \ typedef SPIRVInstTemplate \ SPIRV##x; // Intel Subgroup Buffer Block Read and Write Instructions _SPIRV_OP(SubgroupBlockReadINTEL, true, 4) _SPIRV_OP(SubgroupBlockWriteINTEL, false, 3) #undef _SPIRV_OP class SPIRVSubgroupImageBlockIOINTELInstBase : public SPIRVInstTemplateBase { protected: SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilitySubgroupImageBlockIOINTEL); } SPIRVExtSet getRequiredExtensions() const override { return getSet(ExtensionID::SPV_INTEL_subgroups); } }; #define _SPIRV_OP(x, ...) \ typedef SPIRVInstTemplate \ SPIRV##x; // Intel Subgroup Image Block Read and Write Instructions _SPIRV_OP(SubgroupImageBlockReadINTEL, true, 5) _SPIRV_OP(SubgroupImageBlockWriteINTEL, false, 4) #undef _SPIRV_OP class SPIRVSubgroupImageMediaBlockIOINTELInstBase : public SPIRVInstTemplateBase { protected: SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilitySubgroupImageMediaBlockIOINTEL); } SPIRVExtSet getRequiredExtensions() const override { return getSet(ExtensionID::SPV_INTEL_media_block_io); } }; #define _SPIRV_OP(x, ...) \ typedef SPIRVInstTemplate \ SPIRV##x; // Intel Subgroup Image Media Block Read and Write Instructions _SPIRV_OP(SubgroupImageMediaBlockReadINTEL, true, 7) _SPIRV_OP(SubgroupImageMediaBlockWriteINTEL, false, 6) #undef _SPIRV_OP class SPIRVSubgroupAVCIntelInstBase : public SPIRVInstTemplateBase { protected: SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilitySubgroupAvcMotionEstimationINTEL); } SPIRVExtSet getRequiredExtensions() const override { return getSet(ExtensionID::SPV_INTEL_device_side_avc_motion_estimation); } }; // Intel Subgroup AVC Motion Estimation Instructions typedef SPIRVInstTemplate SPIRVVmeImageINTEL; #define _SPIRV_OP(x, ...) \ typedef SPIRVInstTemplate \ SPIRVSubgroupAvc##x##INTEL; _SPIRV_OP(MceGetDefaultInterBaseMultiReferencePenalty, true, 5) _SPIRV_OP(MceSetInterBaseMultiReferencePenalty, true, 5) _SPIRV_OP(MceGetDefaultInterShapePenalty, true, 5) _SPIRV_OP(MceSetInterShapePenalty, true, 5) _SPIRV_OP(MceGetDefaultInterDirectionPenalty, true, 5) _SPIRV_OP(MceSetInterDirectionPenalty, true, 5) _SPIRV_OP(MceGetDefaultInterMotionVectorCostTable, true, 5) _SPIRV_OP(MceGetDefaultHighPenaltyCostTable, true, 3) _SPIRV_OP(MceGetDefaultMediumPenaltyCostTable, true, 3) _SPIRV_OP(MceGetDefaultLowPenaltyCostTable, true, 3) _SPIRV_OP(MceSetMotionVectorCostFunction, true, 7) _SPIRV_OP(MceSetAcOnlyHaar, true, 4) _SPIRV_OP(MceSetSourceInterlacedFieldPolarity, true, 5) _SPIRV_OP(MceSetSingleReferenceInterlacedFieldPolarity, true, 5) _SPIRV_OP(MceSetDualReferenceInterlacedFieldPolarities, true, 6) _SPIRV_OP(MceConvertToImePayload, true, 4) _SPIRV_OP(MceConvertToImeResult, true, 4) _SPIRV_OP(MceConvertToRefPayload, true, 4) _SPIRV_OP(MceConvertToRefResult, true, 4) _SPIRV_OP(MceConvertToSicPayload, true, 4) _SPIRV_OP(MceConvertToSicResult, true, 4) _SPIRV_OP(MceGetMotionVectors, true, 4) _SPIRV_OP(MceGetInterDistortions, true, 4) _SPIRV_OP(MceGetBestInterDistortions, true, 4) _SPIRV_OP(MceGetInterMajorShape, true, 4) _SPIRV_OP(MceGetInterMinorShape, true, 4) _SPIRV_OP(MceGetInterDirections, true, 4) _SPIRV_OP(MceGetInterMotionVectorCount, true, 4) _SPIRV_OP(MceGetInterReferenceIds, true, 4) _SPIRV_OP(MceGetInterReferenceInterlacedFieldPolarities, true, 6) _SPIRV_OP(ImeInitialize, true, 6) _SPIRV_OP(ImeSetSingleReference, true, 6) _SPIRV_OP(ImeSetDualReference, true, 7) _SPIRV_OP(ImeRefWindowSize, true, 5) _SPIRV_OP(ImeAdjustRefOffset, true, 7) _SPIRV_OP(ImeConvertToMcePayload, true, 4) _SPIRV_OP(ImeSetMaxMotionVectorCount, true, 5) _SPIRV_OP(ImeSetUnidirectionalMixDisable, true, 4) _SPIRV_OP(ImeSetEarlySearchTerminationThreshold, true, 5) _SPIRV_OP(ImeSetWeightedSad, true, 5) _SPIRV_OP(ImeEvaluateWithSingleReference, true, 6) _SPIRV_OP(ImeEvaluateWithDualReference, true, 7) _SPIRV_OP(ImeEvaluateWithSingleReferenceStreamin, true, 7) _SPIRV_OP(ImeEvaluateWithDualReferenceStreamin, true, 8) _SPIRV_OP(ImeEvaluateWithSingleReferenceStreamout, true, 6) _SPIRV_OP(ImeEvaluateWithDualReferenceStreamout, true, 7) _SPIRV_OP(ImeEvaluateWithSingleReferenceStreaminout, true, 7) _SPIRV_OP(ImeEvaluateWithDualReferenceStreaminout, true, 8) _SPIRV_OP(ImeConvertToMceResult, true, 4) _SPIRV_OP(ImeGetSingleReferenceStreamin, true, 4) _SPIRV_OP(ImeGetDualReferenceStreamin, true, 4) _SPIRV_OP(ImeStripSingleReferenceStreamout, true, 4) _SPIRV_OP(ImeStripDualReferenceStreamout, true, 4) _SPIRV_OP(ImeGetStreamoutSingleReferenceMajorShapeMotionVectors, true, 5) _SPIRV_OP(ImeGetStreamoutSingleReferenceMajorShapeDistortions, true, 5) _SPIRV_OP(ImeGetStreamoutSingleReferenceMajorShapeReferenceIds, true, 5) _SPIRV_OP(ImeGetStreamoutDualReferenceMajorShapeMotionVectors, true, 6) _SPIRV_OP(ImeGetStreamoutDualReferenceMajorShapeDistortions, true, 6) _SPIRV_OP(ImeGetStreamoutDualReferenceMajorShapeReferenceIds, true, 6) _SPIRV_OP(ImeGetBorderReached, true, 5) _SPIRV_OP(ImeGetTruncatedSearchIndication, true, 4) _SPIRV_OP(ImeGetUnidirectionalEarlySearchTermination, true, 4) _SPIRV_OP(ImeGetWeightingPatternMinimumMotionVector, true, 4) _SPIRV_OP(ImeGetWeightingPatternMinimumDistortion, true, 4) _SPIRV_OP(FmeInitialize, true, 10) _SPIRV_OP(BmeInitialize, true, 11) _SPIRV_OP(RefConvertToMcePayload, true, 4) _SPIRV_OP(RefSetBidirectionalMixDisable, true, 4) _SPIRV_OP(RefSetBilinearFilterEnable, true, 4) _SPIRV_OP(RefEvaluateWithSingleReference, true, 6) _SPIRV_OP(RefEvaluateWithDualReference, true, 7) _SPIRV_OP(RefEvaluateWithMultiReference, true, 6) _SPIRV_OP(RefEvaluateWithMultiReferenceInterlaced, true, 7) _SPIRV_OP(RefConvertToMceResult, true, 4) _SPIRV_OP(SicInitialize, true, 4) _SPIRV_OP(SicConfigureSkc, true, 9) _SPIRV_OP(SicGetMotionVectorMask, true, 5) _SPIRV_OP(SicConvertToMcePayload, true, 4) _SPIRV_OP(SicSetIntraLumaShapePenalty, true, 5) _SPIRV_OP(SicSetBilinearFilterEnable, true, 4) _SPIRV_OP(SicSetSkcForwardTransformEnable, true, 5) _SPIRV_OP(SicSetBlockBasedRawSkipSad, true, 5) _SPIRV_OP(SicEvaluateWithSingleReference, true, 6) _SPIRV_OP(SicEvaluateWithDualReference, true, 7) _SPIRV_OP(SicEvaluateWithMultiReference, true, 6) _SPIRV_OP(SicEvaluateWithMultiReferenceInterlaced, true, 7) _SPIRV_OP(SicConvertToMceResult, true, 4) _SPIRV_OP(SicGetInterRawSads, true, 4) #undef _SPIRV_OP class SPIRVSubgroupAVCIntelInstBaseIntra : public SPIRVInstTemplateBase { protected: SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilitySubgroupAvcMotionEstimationIntraINTEL); } }; // Intel Subgroup AVC Motion Estimation Intra Instructions #define _SPIRV_OP(x, ...) \ typedef SPIRVInstTemplate \ SPIRVSubgroupAvc##x##INTEL; _SPIRV_OP(MceGetDefaultIntraLumaShapePenalty, true, 5) _SPIRV_OP(MceGetDefaultIntraLumaModePenalty, true, 5) _SPIRV_OP(MceGetDefaultNonDcLumaIntraPenalty, true, 3) _SPIRV_OP(SicConfigureIpeLuma, true, 11) _SPIRV_OP(SicSetIntraLumaModeCostFunction, true, 7) _SPIRV_OP(SicEvaluateIpe, true, 5) _SPIRV_OP(SicGetIpeLumaShape, true, 4) _SPIRV_OP(SicGetBestIpeLumaDistortion, true, 4) _SPIRV_OP(SicGetPackedIpeLumaModes, true, 4) _SPIRV_OP(SicGetPackedSkcLumaCountThreshold, true, 4) _SPIRV_OP(SicGetPackedSkcLumaSumThreshold, true, 4) #undef _SPIRV_OP class SPIRVSubgroupAVCIntelInstBaseChroma : public SPIRVInstTemplateBase { protected: SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilitySubgroupAvcMotionEstimationChromaINTEL); } }; // Intel Subgroup AVC Motion Estimation Chroma Instructions #define _SPIRV_OP(x, ...) \ typedef SPIRVInstTemplate \ SPIRVSubgroupAvc##x##INTEL; _SPIRV_OP(MceGetDefaultIntraChromaModeBasePenalty, true, 3) _SPIRV_OP(SicConfigureIpeLumaChroma, true, 14) _SPIRV_OP(SicSetIntraChromaModeCostFunction, true, 5) _SPIRV_OP(SicGetBestIpeChromaDistortion, true, 4) _SPIRV_OP(SicGetIpeChromaMode, true, 4) #undef _SPIRV_OP SPIRVSpecConstantOp *createSpecConstantOpInst(SPIRVInstruction *Inst); SPIRVInstruction *createInstFromSpecConstantOp(SPIRVSpecConstantOp *C); } // namespace SPIRV #endif // SPIRV_LIBSPIRV_SPIRVINSTRUCTION_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h000066400000000000000000001004071363521741200236200ustar00rootroot00000000000000//===- SPIRVIsValidEnum.h - SPIR-V isValid enums ----------------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines SPIR-V isValid enums. /// //===----------------------------------------------------------------------===// // WARNING: // // This file has been generated using `tools/spirv-tool/gen_spirv.bash` and // should not be modified manually. If the file needs to be updated, edit the // script and any other source file instead, before re-generating this file. //===----------------------------------------------------------------------===// #ifndef SPIRV_LIBSPIRV_SPIRVISVALIDENUM_H #define SPIRV_LIBSPIRV_SPIRVISVALIDENUM_H #include "SPIRVEnum.h" #include "spirv.hpp" using namespace spv; namespace SPIRV { inline bool isValid(spv::SourceLanguage V) { switch (V) { case SourceLanguageUnknown: case SourceLanguageESSL: case SourceLanguageGLSL: case SourceLanguageOpenCL_C: case SourceLanguageOpenCL_CPP: return true; default: return false; } } inline bool isValid(spv::ExecutionModel V) { switch (V) { case ExecutionModelVertex: case ExecutionModelTessellationControl: case ExecutionModelTessellationEvaluation: case ExecutionModelGeometry: case ExecutionModelFragment: case ExecutionModelGLCompute: case ExecutionModelKernel: return true; default: return false; } } inline bool isValid(spv::AddressingModel V) { switch (V) { case AddressingModelLogical: case AddressingModelPhysical32: case AddressingModelPhysical64: return true; default: return false; } } inline bool isValid(spv::MemoryModel V) { switch (V) { case MemoryModelSimple: case MemoryModelGLSL450: case MemoryModelOpenCL: return true; default: return false; } } inline bool isValid(spv::ExecutionMode V) { switch (V) { case ExecutionModeInvocations: case ExecutionModeSpacingEqual: case ExecutionModeSpacingFractionalEven: case ExecutionModeSpacingFractionalOdd: case ExecutionModeVertexOrderCw: case ExecutionModeVertexOrderCcw: case ExecutionModePixelCenterInteger: case ExecutionModeOriginUpperLeft: case ExecutionModeOriginLowerLeft: case ExecutionModeEarlyFragmentTests: case ExecutionModePointMode: case ExecutionModeXfb: case ExecutionModeDepthReplacing: case ExecutionModeDepthGreater: case ExecutionModeDepthLess: case ExecutionModeDepthUnchanged: case ExecutionModeLocalSize: case ExecutionModeLocalSizeHint: case ExecutionModeInputPoints: case ExecutionModeInputLines: case ExecutionModeInputLinesAdjacency: case ExecutionModeTriangles: case ExecutionModeInputTrianglesAdjacency: case ExecutionModeQuads: case ExecutionModeIsolines: case ExecutionModeOutputVertices: case ExecutionModeOutputPoints: case ExecutionModeOutputLineStrip: case ExecutionModeOutputTriangleStrip: case ExecutionModeVecTypeHint: case ExecutionModeContractionOff: case ExecutionModeInitializer: case ExecutionModeFinalizer: case ExecutionModeSubgroupSize: case ExecutionModeSubgroupsPerWorkgroup: case ExecutionModeMaxWorkgroupSizeINTEL: case ExecutionModeMaxWorkDimINTEL: case ExecutionModeNumSIMDWorkitemsINTEL: return true; default: return false; } } inline bool isValid(spv::StorageClass V) { switch (V) { case StorageClassUniformConstant: case StorageClassInput: case StorageClassUniform: case StorageClassOutput: case StorageClassWorkgroup: case StorageClassCrossWorkgroup: case StorageClassPrivate: case StorageClassFunction: case StorageClassGeneric: case StorageClassPushConstant: case StorageClassAtomicCounter: case StorageClassImage: return true; default: return false; } } inline bool isValid(spv::Dim V) { switch (V) { case Dim1D: case Dim2D: case Dim3D: case DimCube: case DimRect: case DimBuffer: case DimSubpassData: return true; default: return false; } } inline bool isValid(spv::SamplerAddressingMode V) { switch (V) { case SamplerAddressingModeNone: case SamplerAddressingModeClampToEdge: case SamplerAddressingModeClamp: case SamplerAddressingModeRepeat: case SamplerAddressingModeRepeatMirrored: return true; default: return false; } } inline bool isValid(spv::SamplerFilterMode V) { switch (V) { case SamplerFilterModeNearest: case SamplerFilterModeLinear: return true; default: return false; } } inline bool isValid(spv::ImageFormat V) { switch (V) { case ImageFormatUnknown: case ImageFormatRgba32f: case ImageFormatRgba16f: case ImageFormatR32f: case ImageFormatRgba8: case ImageFormatRgba8Snorm: case ImageFormatRg32f: case ImageFormatRg16f: case ImageFormatR11fG11fB10f: case ImageFormatR16f: case ImageFormatRgba16: case ImageFormatRgb10A2: case ImageFormatRg16: case ImageFormatRg8: case ImageFormatR16: case ImageFormatR8: case ImageFormatRgba16Snorm: case ImageFormatRg16Snorm: case ImageFormatRg8Snorm: case ImageFormatR16Snorm: case ImageFormatR8Snorm: case ImageFormatRgba32i: case ImageFormatRgba16i: case ImageFormatRgba8i: case ImageFormatR32i: case ImageFormatRg32i: case ImageFormatRg16i: case ImageFormatRg8i: case ImageFormatR16i: case ImageFormatR8i: case ImageFormatRgba32ui: case ImageFormatRgba16ui: case ImageFormatRgba8ui: case ImageFormatR32ui: case ImageFormatRgb10a2ui: case ImageFormatRg32ui: case ImageFormatRg16ui: case ImageFormatRg8ui: case ImageFormatR16ui: case ImageFormatR8ui: return true; default: return false; } } inline bool isValid(spv::ImageChannelOrder V) { switch (V) { case ImageChannelOrderR: case ImageChannelOrderA: case ImageChannelOrderRG: case ImageChannelOrderRA: case ImageChannelOrderRGB: case ImageChannelOrderRGBA: case ImageChannelOrderBGRA: case ImageChannelOrderARGB: case ImageChannelOrderIntensity: case ImageChannelOrderLuminance: case ImageChannelOrderRx: case ImageChannelOrderRGx: case ImageChannelOrderRGBx: case ImageChannelOrderDepth: case ImageChannelOrderDepthStencil: case ImageChannelOrderABGR: return true; default: return false; } } inline bool isValid(spv::ImageChannelDataType V) { switch (V) { case ImageChannelDataTypeSnormInt8: case ImageChannelDataTypeSnormInt16: case ImageChannelDataTypeUnormInt8: case ImageChannelDataTypeUnormInt16: case ImageChannelDataTypeUnormShort565: case ImageChannelDataTypeUnormShort555: case ImageChannelDataTypeUnormInt101010: case ImageChannelDataTypeSignedInt8: case ImageChannelDataTypeSignedInt16: case ImageChannelDataTypeSignedInt32: case ImageChannelDataTypeUnsignedInt8: case ImageChannelDataTypeUnsignedInt16: case ImageChannelDataTypeUnsignedInt32: case ImageChannelDataTypeHalfFloat: case ImageChannelDataTypeFloat: case ImageChannelDataTypeUnormInt24: case ImageChannelDataTypeUnormInt101010_2: return true; default: return false; } } inline bool isValid(spv::FPRoundingMode V) { switch (V) { case FPRoundingModeRTE: case FPRoundingModeRTZ: case FPRoundingModeRTP: case FPRoundingModeRTN: return true; default: return false; } } inline bool isValid(spv::LinkageType V) { switch (V) { case LinkageTypeExport: case LinkageTypeImport: case LinkageTypeInternal: return true; default: return false; } } inline bool isValid(spv::AccessQualifier V) { switch (V) { case AccessQualifierReadOnly: case AccessQualifierWriteOnly: case AccessQualifierReadWrite: return true; default: return false; } } inline bool isValid(spv::FunctionParameterAttribute V) { switch (V) { case FunctionParameterAttributeZext: case FunctionParameterAttributeSext: case FunctionParameterAttributeByVal: case FunctionParameterAttributeSret: case FunctionParameterAttributeNoAlias: case FunctionParameterAttributeNoCapture: case FunctionParameterAttributeNoWrite: case FunctionParameterAttributeNoReadWrite: return true; default: return false; } } inline bool isValid(spv::Decoration V) { switch (V) { case DecorationRelaxedPrecision: case DecorationSpecId: case DecorationBlock: case DecorationBufferBlock: case DecorationRowMajor: case DecorationColMajor: case DecorationArrayStride: case DecorationMatrixStride: case DecorationGLSLShared: case DecorationGLSLPacked: case DecorationCPacked: case DecorationBuiltIn: case DecorationNoPerspective: case DecorationFlat: case DecorationPatch: case DecorationCentroid: case DecorationSample: case DecorationInvariant: case DecorationRestrict: case DecorationAliased: case DecorationVolatile: case DecorationConstant: case DecorationCoherent: case DecorationNonWritable: case DecorationNonReadable: case DecorationUniform: case DecorationSaturatedConversion: case DecorationStream: case DecorationLocation: case DecorationComponent: case DecorationIndex: case DecorationBinding: case DecorationDescriptorSet: case DecorationOffset: case DecorationXfbBuffer: case DecorationXfbStride: case DecorationFuncParamAttr: case DecorationFPRoundingMode: case DecorationFPFastMathMode: case DecorationLinkageAttributes: case DecorationNoContraction: case DecorationInputAttachmentIndex: case DecorationAlignment: case DecorationMaxByteOffset: case DecorationUserSemantic: case DecorationRegisterINTEL: case DecorationMemoryINTEL: case DecorationNumbanksINTEL: case DecorationBankwidthINTEL: case DecorationMaxPrivateCopiesINTEL: case DecorationSinglepumpINTEL: case DecorationDoublepumpINTEL: case DecorationBankBitsINTEL: case DecorationReferencedIndirectlyINTEL: return true; default: return false; } } inline bool isValid(spv::BuiltIn V) { switch (V) { case BuiltInPosition: case BuiltInPointSize: case BuiltInClipDistance: case BuiltInCullDistance: case BuiltInVertexId: case BuiltInInstanceId: case BuiltInPrimitiveId: case BuiltInInvocationId: case BuiltInLayer: case BuiltInViewportIndex: case BuiltInTessLevelOuter: case BuiltInTessLevelInner: case BuiltInTessCoord: case BuiltInPatchVertices: case BuiltInFragCoord: case BuiltInPointCoord: case BuiltInFrontFacing: case BuiltInSampleId: case BuiltInSamplePosition: case BuiltInSampleMask: case BuiltInFragDepth: case BuiltInHelperInvocation: case BuiltInNumWorkgroups: case BuiltInWorkgroupSize: case BuiltInWorkgroupId: case BuiltInLocalInvocationId: case BuiltInGlobalInvocationId: case BuiltInLocalInvocationIndex: case BuiltInWorkDim: case BuiltInGlobalSize: case BuiltInEnqueuedWorkgroupSize: case BuiltInGlobalOffset: case BuiltInGlobalLinearId: case BuiltInSubgroupSize: case BuiltInSubgroupMaxSize: case BuiltInNumSubgroups: case BuiltInNumEnqueuedSubgroups: case BuiltInSubgroupId: case BuiltInSubgroupLocalInvocationId: case BuiltInVertexIndex: case BuiltInInstanceIndex: return true; default: return false; } } inline bool isValid(spv::Scope V) { switch (V) { case ScopeCrossDevice: case ScopeDevice: case ScopeWorkgroup: case ScopeSubgroup: case ScopeInvocation: return true; default: return false; } } inline bool isValid(spv::GroupOperation V) { switch (V) { case GroupOperationReduce: case GroupOperationInclusiveScan: case GroupOperationExclusiveScan: return true; default: return false; } } inline bool isValid(spv::KernelEnqueueFlags V) { switch (V) { case KernelEnqueueFlagsNoWait: case KernelEnqueueFlagsWaitKernel: case KernelEnqueueFlagsWaitWorkGroup: return true; default: return false; } } inline bool isValid(spv::Capability V) { switch (V) { case CapabilityMatrix: case CapabilityShader: case CapabilityGeometry: case CapabilityTessellation: case CapabilityAddresses: case CapabilityLinkage: case CapabilityKernel: case CapabilityVector16: case CapabilityFloat16Buffer: case CapabilityFloat16: case CapabilityFloat64: case CapabilityInt64: case CapabilityInt64Atomics: case CapabilityImageBasic: case CapabilityImageReadWrite: case CapabilityImageMipmap: case CapabilityPipes: case CapabilityGroups: case CapabilityDeviceEnqueue: case CapabilityLiteralSampler: case CapabilityAtomicStorage: case CapabilityInt16: case CapabilityTessellationPointSize: case CapabilityGeometryPointSize: case CapabilityImageGatherExtended: case CapabilityStorageImageMultisample: case CapabilityUniformBufferArrayDynamicIndexing: case CapabilitySampledImageArrayDynamicIndexing: case CapabilityStorageBufferArrayDynamicIndexing: case CapabilityStorageImageArrayDynamicIndexing: case CapabilityClipDistance: case CapabilityCullDistance: case CapabilityImageCubeArray: case CapabilitySampleRateShading: case CapabilityImageRect: case CapabilitySampledRect: case CapabilityGenericPointer: case CapabilityInt8: case CapabilityInputAttachment: case CapabilitySparseResidency: case CapabilityMinLod: case CapabilitySampled1D: case CapabilityImage1D: case CapabilitySampledCubeArray: case CapabilitySampledBuffer: case CapabilityImageBuffer: case CapabilityImageMSArray: case CapabilityStorageImageExtendedFormats: case CapabilityImageQuery: case CapabilityDerivativeControl: case CapabilityInterpolationFunction: case CapabilityTransformFeedback: case CapabilityGeometryStreams: case CapabilityStorageImageReadWithoutFormat: case CapabilityStorageImageWriteWithoutFormat: case CapabilityMultiViewport: case CapabilitySubgroupDispatch: case CapabilityNamedBarrier: case CapabilityPipeStorage: case CapabilityFPGAMemoryAttributesINTEL: case CapabilityFPGALoopControlsINTEL: case CapabilityBlockingPipesINTEL: case CapabilityUnstructuredLoopControlsINTEL: case CapabilityKernelAttributesINTEL: case CapabilityFPGAKernelAttributesINTEL: return true; default: return false; } } inline bool isValid(spv::Op V) { switch (V) { case OpNop: case OpUndef: case OpSourceContinued: case OpSource: case OpSourceExtension: case OpName: case OpMemberName: case OpString: case OpLine: case OpExtension: case OpExtInstImport: case OpExtInst: case OpMemoryModel: case OpEntryPoint: case OpExecutionMode: case OpCapability: case OpTypeVoid: case OpTypeBool: case OpTypeInt: case OpTypeFloat: case OpTypeVector: case OpTypeMatrix: case OpTypeImage: case OpTypeSampler: case OpTypeSampledImage: case OpTypeArray: case OpTypeRuntimeArray: case OpTypeStruct: case OpTypeOpaque: case OpTypePointer: case OpTypeFunction: case OpTypeEvent: case OpTypeDeviceEvent: case OpTypeReserveId: case OpTypeQueue: case OpTypePipe: case OpTypeForwardPointer: case OpConstantTrue: case OpConstantFalse: case OpConstant: case OpConstantComposite: case OpConstantSampler: case OpConstantNull: case OpSpecConstantTrue: case OpSpecConstantFalse: case OpSpecConstant: case OpSpecConstantComposite: case OpSpecConstantOp: case OpFunction: case OpFunctionParameter: case OpFunctionEnd: case OpFunctionCall: case OpVariable: case OpImageTexelPointer: case OpLoad: case OpStore: case OpCopyMemory: case OpCopyMemorySized: case OpAccessChain: case OpInBoundsAccessChain: case OpPtrAccessChain: case OpArrayLength: case OpGenericPtrMemSemantics: case OpInBoundsPtrAccessChain: case OpDecorate: case OpMemberDecorate: case OpDecorationGroup: case OpGroupDecorate: case OpGroupMemberDecorate: case OpVectorExtractDynamic: case OpVectorInsertDynamic: case OpVectorShuffle: case OpCompositeConstruct: case OpCompositeExtract: case OpCompositeInsert: case OpCopyObject: case OpTranspose: case OpSampledImage: case OpImageSampleImplicitLod: case OpImageSampleExplicitLod: case OpImageSampleDrefImplicitLod: case OpImageSampleDrefExplicitLod: case OpImageSampleProjImplicitLod: case OpImageSampleProjExplicitLod: case OpImageSampleProjDrefImplicitLod: case OpImageSampleProjDrefExplicitLod: case OpImageFetch: case OpImageGather: case OpImageDrefGather: case OpImageRead: case OpImageWrite: case OpImage: case OpImageQueryFormat: case OpImageQueryOrder: case OpImageQuerySizeLod: case OpImageQuerySize: case OpImageQueryLod: case OpImageQueryLevels: case OpImageQuerySamples: case OpConvertFToU: case OpConvertFToS: case OpConvertSToF: case OpConvertUToF: case OpUConvert: case OpSConvert: case OpFConvert: case OpQuantizeToF16: case OpConvertPtrToU: case OpSatConvertSToU: case OpSatConvertUToS: case OpConvertUToPtr: case OpPtrCastToGeneric: case OpGenericCastToPtr: case OpGenericCastToPtrExplicit: case OpBitcast: case OpSNegate: case OpFNegate: case OpIAdd: case OpFAdd: case OpISub: case OpFSub: case OpIMul: case OpFMul: case OpUDiv: case OpSDiv: case OpFDiv: case OpUMod: case OpSRem: case OpSMod: case OpFRem: case OpFMod: case OpVectorTimesScalar: case OpMatrixTimesScalar: case OpVectorTimesMatrix: case OpMatrixTimesVector: case OpMatrixTimesMatrix: case OpOuterProduct: case OpDot: case OpIAddCarry: case OpISubBorrow: case OpUMulExtended: case OpSMulExtended: case OpAny: case OpAll: case OpIsNan: case OpIsInf: case OpIsFinite: case OpIsNormal: case OpSignBitSet: case OpLessOrGreater: case OpOrdered: case OpUnordered: case OpLogicalEqual: case OpLogicalNotEqual: case OpLogicalOr: case OpLogicalAnd: case OpLogicalNot: case OpSelect: case OpIEqual: case OpINotEqual: case OpUGreaterThan: case OpSGreaterThan: case OpUGreaterThanEqual: case OpSGreaterThanEqual: case OpULessThan: case OpSLessThan: case OpULessThanEqual: case OpSLessThanEqual: case OpFOrdEqual: case OpFUnordEqual: case OpFOrdNotEqual: case OpFUnordNotEqual: case OpFOrdLessThan: case OpFUnordLessThan: case OpFOrdGreaterThan: case OpFUnordGreaterThan: case OpFOrdLessThanEqual: case OpFUnordLessThanEqual: case OpFOrdGreaterThanEqual: case OpFUnordGreaterThanEqual: case OpShiftRightLogical: case OpShiftRightArithmetic: case OpShiftLeftLogical: case OpBitwiseOr: case OpBitwiseXor: case OpBitwiseAnd: case OpNot: case OpBitFieldInsert: case OpBitFieldSExtract: case OpBitFieldUExtract: case OpBitReverse: case OpBitCount: case OpDPdx: case OpDPdy: case OpFwidth: case OpDPdxFine: case OpDPdyFine: case OpFwidthFine: case OpDPdxCoarse: case OpDPdyCoarse: case OpFwidthCoarse: case OpEmitVertex: case OpEndPrimitive: case OpEmitStreamVertex: case OpEndStreamPrimitive: case OpControlBarrier: case OpMemoryBarrier: case OpAtomicLoad: case OpAtomicStore: case OpAtomicExchange: case OpAtomicCompareExchange: case OpAtomicCompareExchangeWeak: case OpAtomicIIncrement: case OpAtomicIDecrement: case OpAtomicIAdd: case OpAtomicISub: case OpAtomicSMin: case OpAtomicUMin: case OpAtomicSMax: case OpAtomicUMax: case OpAtomicAnd: case OpAtomicOr: case OpAtomicXor: case OpPhi: case OpLoopMerge: case OpSelectionMerge: case OpLabel: case OpBranch: case OpBranchConditional: case OpSwitch: case OpKill: case OpReturn: case OpReturnValue: case OpUnreachable: case OpLifetimeStart: case OpLifetimeStop: case OpGroupAsyncCopy: case OpGroupWaitEvents: case OpGroupAll: case OpGroupAny: case OpGroupBroadcast: case OpGroupIAdd: case OpGroupFAdd: case OpGroupFMin: case OpGroupUMin: case OpGroupSMin: case OpGroupFMax: case OpGroupUMax: case OpGroupSMax: case OpReadPipe: case OpWritePipe: case OpReadPipeBlockingINTEL: case OpWritePipeBlockingINTEL: case OpReservedReadPipe: case OpReservedWritePipe: case OpReserveReadPipePackets: case OpReserveWritePipePackets: case OpCommitReadPipe: case OpCommitWritePipe: case OpIsValidReserveId: case OpGetNumPipePackets: case OpGetMaxPipePackets: case OpGroupReserveReadPipePackets: case OpGroupReserveWritePipePackets: case OpGroupCommitReadPipe: case OpGroupCommitWritePipe: case OpEnqueueMarker: case OpEnqueueKernel: case OpGetKernelNDrangeSubGroupCount: case OpGetKernelNDrangeMaxSubGroupSize: case OpGetKernelWorkGroupSize: case OpGetKernelPreferredWorkGroupSizeMultiple: case OpRetainEvent: case OpReleaseEvent: case OpCreateUserEvent: case OpIsValidEvent: case OpSetUserEventStatus: case OpCaptureEventProfilingInfo: case OpGetDefaultQueue: case OpBuildNDRange: case OpImageSparseSampleImplicitLod: case OpImageSparseSampleExplicitLod: case OpImageSparseSampleDrefImplicitLod: case OpImageSparseSampleDrefExplicitLod: case OpImageSparseSampleProjImplicitLod: case OpImageSparseSampleProjExplicitLod: case OpImageSparseSampleProjDrefImplicitLod: case OpImageSparseSampleProjDrefExplicitLod: case OpImageSparseFetch: case OpImageSparseGather: case OpImageSparseDrefGather: case OpImageSparseTexelsResident: case OpNoLine: case OpAtomicFlagTestAndSet: case OpAtomicFlagClear: case OpImageSparseRead: case OpSizeOf: case OpTypePipeStorage: case OpConstantPipeStorage: case OpCreatePipeFromPipeStorage: case OpGetKernelLocalSizeForSubgroupCount: case OpGetKernelMaxNumSubgroups: case OpTypeNamedBarrier: case OpNamedBarrierInitialize: case OpMemoryNamedBarrier: case OpModuleProcessed: case OpForward: case OpSubgroupShuffleINTEL: case OpSubgroupShuffleDownINTEL: case OpSubgroupShuffleUpINTEL: case OpSubgroupShuffleXorINTEL: case OpSubgroupBlockReadINTEL: case OpSubgroupBlockWriteINTEL: case OpSubgroupImageBlockReadINTEL: case OpSubgroupImageBlockWriteINTEL: case OpSubgroupImageMediaBlockReadINTEL: case OpSubgroupImageMediaBlockWriteINTEL: case OpAsmTargetINTEL: case OpAsmINTEL: case OpAsmCallINTEL: case OpVmeImageINTEL: case OpTypeVmeImageINTEL: case OpTypeAvcImePayloadINTEL: case OpTypeAvcRefPayloadINTEL: case OpTypeAvcSicPayloadINTEL: case OpTypeAvcMcePayloadINTEL: case OpTypeAvcMceResultINTEL: case OpTypeAvcImeResultINTEL: case OpTypeAvcImeResultSingleReferenceStreamoutINTEL: case OpTypeAvcImeResultDualReferenceStreamoutINTEL: case OpTypeAvcImeSingleReferenceStreaminINTEL: case OpTypeAvcImeDualReferenceStreaminINTEL: case OpTypeAvcRefResultINTEL: case OpTypeAvcSicResultINTEL: case OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: case OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: case OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: case OpSubgroupAvcMceSetInterShapePenaltyINTEL: case OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: case OpSubgroupAvcMceSetInterDirectionPenaltyINTEL: case OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: case OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: case OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: case OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: case OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: case OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: case OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: case OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: case OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: case OpSubgroupAvcMceSetAcOnlyHaarINTEL: case OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: case OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: case OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: case OpSubgroupAvcMceConvertToImePayloadINTEL: case OpSubgroupAvcMceConvertToImeResultINTEL: case OpSubgroupAvcMceConvertToRefPayloadINTEL: case OpSubgroupAvcMceConvertToRefResultINTEL: case OpSubgroupAvcMceConvertToSicPayloadINTEL: case OpSubgroupAvcMceConvertToSicResultINTEL: case OpSubgroupAvcMceGetMotionVectorsINTEL: case OpSubgroupAvcMceGetInterDistortionsINTEL: case OpSubgroupAvcMceGetBestInterDistortionsINTEL: case OpSubgroupAvcMceGetInterMajorShapeINTEL: case OpSubgroupAvcMceGetInterMinorShapeINTEL: case OpSubgroupAvcMceGetInterDirectionsINTEL: case OpSubgroupAvcMceGetInterMotionVectorCountINTEL: case OpSubgroupAvcMceGetInterReferenceIdsINTEL: case OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: case OpSubgroupAvcImeInitializeINTEL: case OpSubgroupAvcImeSetSingleReferenceINTEL: case OpSubgroupAvcImeSetDualReferenceINTEL: case OpSubgroupAvcImeRefWindowSizeINTEL: case OpSubgroupAvcImeAdjustRefOffsetINTEL: case OpSubgroupAvcImeConvertToMcePayloadINTEL: case OpSubgroupAvcImeSetMaxMotionVectorCountINTEL: case OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: case OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: case OpSubgroupAvcImeSetWeightedSadINTEL: case OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: case OpSubgroupAvcImeEvaluateWithDualReferenceINTEL: case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: case OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: case OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: case OpSubgroupAvcImeConvertToMceResultINTEL: case OpSubgroupAvcImeGetSingleReferenceStreaminINTEL: case OpSubgroupAvcImeGetDualReferenceStreaminINTEL: case OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: case OpSubgroupAvcImeStripDualReferenceStreamoutINTEL: case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: case OpSubgroupAvcImeGetBorderReachedINTEL: case OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: case OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: case OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: case OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: case OpSubgroupAvcFmeInitializeINTEL: case OpSubgroupAvcBmeInitializeINTEL: case OpSubgroupAvcRefConvertToMcePayloadINTEL: case OpSubgroupAvcRefSetBidirectionalMixDisableINTEL: case OpSubgroupAvcRefSetBilinearFilterEnableINTEL: case OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: case OpSubgroupAvcRefEvaluateWithDualReferenceINTEL: case OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: case OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: case OpSubgroupAvcRefConvertToMceResultINTEL: case OpSubgroupAvcSicInitializeINTEL: case OpSubgroupAvcSicConfigureSkcINTEL: case OpSubgroupAvcSicConfigureIpeLumaINTEL: case OpSubgroupAvcSicConfigureIpeLumaChromaINTEL: case OpSubgroupAvcSicGetMotionVectorMaskINTEL: case OpSubgroupAvcSicConvertToMcePayloadINTEL: case OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: case OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: case OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: case OpSubgroupAvcSicSetBilinearFilterEnableINTEL: case OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: case OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: case OpSubgroupAvcSicEvaluateIpeINTEL: case OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: case OpSubgroupAvcSicEvaluateWithDualReferenceINTEL: case OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: case OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: case OpSubgroupAvcSicConvertToMceResultINTEL: case OpSubgroupAvcSicGetIpeLumaShapeINTEL: case OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: case OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: case OpSubgroupAvcSicGetPackedIpeLumaModesINTEL: case OpSubgroupAvcSicGetIpeChromaModeINTEL: case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: case OpSubgroupAvcSicGetInterRawSadsINTEL: case OpFPGARegINTEL: case OpLoopControlINTEL: return true; default: return false; } } inline bool isValidImageOperandsMask(SPIRVWord Mask) { SPIRVWord ValidMask = 0u; ValidMask |= ImageOperandsBiasMask; ValidMask |= ImageOperandsLodMask; ValidMask |= ImageOperandsGradMask; ValidMask |= ImageOperandsConstOffsetMask; ValidMask |= ImageOperandsOffsetMask; ValidMask |= ImageOperandsConstOffsetsMask; ValidMask |= ImageOperandsSampleMask; ValidMask |= ImageOperandsMinLodMask; return (Mask & ~ValidMask) == 0; } inline bool isValidFPFastMathModeMask(SPIRVWord Mask) { SPIRVWord ValidMask = 0u; ValidMask |= FPFastMathModeNotNaNMask; ValidMask |= FPFastMathModeNotInfMask; ValidMask |= FPFastMathModeNSZMask; ValidMask |= FPFastMathModeAllowRecipMask; ValidMask |= FPFastMathModeFastMask; return (Mask & ~ValidMask) == 0; } inline bool isValidSelectionControlMask(SPIRVWord Mask) { SPIRVWord ValidMask = 0u; ValidMask |= SelectionControlFlattenMask; ValidMask |= SelectionControlDontFlattenMask; return (Mask & ~ValidMask) == 0; } inline bool isValidLoopControlMask(SPIRVWord Mask) { SPIRVWord ValidMask = 0u; ValidMask |= LoopControlUnrollMask; ValidMask |= LoopControlDontUnrollMask; ValidMask |= LoopControlPartialCountMask; ValidMask |= LoopControlDependencyInfiniteMask; ValidMask |= LoopControlDependencyLengthMask; ValidMask |= InitiationIntervalINTEL; ValidMask |= MaxConcurrencyINTEL; ValidMask |= DependencyArrayINTEL; return (Mask & ~ValidMask) == 0; } inline bool isValidFunctionControlMask(SPIRVWord Mask) { SPIRVWord ValidMask = 0u; ValidMask |= FunctionControlInlineMask; ValidMask |= FunctionControlDontInlineMask; ValidMask |= FunctionControlPureMask; ValidMask |= FunctionControlConstMask; return (Mask & ~ValidMask) == 0; } inline bool isValidMemorySemanticsMask(SPIRVWord Mask) { SPIRVWord ValidMask = 0u; ValidMask |= MemorySemanticsAcquireMask; ValidMask |= MemorySemanticsReleaseMask; ValidMask |= MemorySemanticsAcquireReleaseMask; ValidMask |= MemorySemanticsSequentiallyConsistentMask; ValidMask |= MemorySemanticsUniformMemoryMask; ValidMask |= MemorySemanticsSubgroupMemoryMask; ValidMask |= MemorySemanticsWorkgroupMemoryMask; ValidMask |= MemorySemanticsCrossWorkgroupMemoryMask; ValidMask |= MemorySemanticsAtomicCounterMemoryMask; ValidMask |= MemorySemanticsImageMemoryMask; return (Mask & ~ValidMask) == 0; } inline bool isValidMemoryAccessMask(SPIRVWord Mask) { SPIRVWord ValidMask = 0u; ValidMask |= MemoryAccessVolatileMask; ValidMask |= MemoryAccessAlignedMask; ValidMask |= MemoryAccessNontemporalMask; return (Mask & ~ValidMask) == 0; } inline bool isValidKernelProfilingInfoMask(SPIRVWord Mask) { SPIRVWord ValidMask = 0u; ValidMask |= KernelProfilingInfoCmdExecTimeMask; return (Mask & ~ValidMask) == 0; } } /* namespace SPIRV */ #endif // SPIRV_LIBSPIRV_SPIRVISVALIDENUM_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVModule.cpp000066400000000000000000002242561363521741200232310ustar00rootroot00000000000000//===- SPIRVModule.cpp - Class to represent SPIR-V module -------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file implements Module class for SPIR-V. /// //===----------------------------------------------------------------------===// #include "SPIRVModule.h" #include "SPIRVAsm.h" #include "SPIRVDebug.h" #include "SPIRVEntry.h" #include "SPIRVExtInst.h" #include "SPIRVFunction.h" #include "SPIRVInstruction.h" #include "SPIRVStream.h" #include "SPIRVType.h" #include "SPIRVValue.h" #include #include #include namespace SPIRV { SPIRVModule::SPIRVModule() : AutoAddCapability(true), ValidateCapability(false), IsValid(true) {} SPIRVModule::~SPIRVModule() {} class SPIRVModuleImpl : public SPIRVModule { public: SPIRVModuleImpl() : SPIRVModule(), NextId(1), SPIRVVersion(static_cast(VersionNumber::SPIRV_1_0)), GeneratorId(SPIRVGEN_KhronosLLVMSPIRVTranslator), GeneratorVer(0), InstSchema(SPIRVISCH_Default), SrcLang(SourceLanguageOpenCL_C), SrcLangVer(102000) { AddrModel = sizeof(size_t) == 32 ? AddressingModelPhysical32 : AddressingModelPhysical64; // OpenCL memory model requires Kernel capability setMemoryModel(MemoryModelOpenCL); } SPIRVModuleImpl(const SPIRV::TranslatorOpts &Opts) : SPIRVModuleImpl() { TranslationOpts = Opts; } ~SPIRVModuleImpl() override; // Object query functions bool exist(SPIRVId) const override; bool exist(SPIRVId, SPIRVEntry **) const override; SPIRVId getId(SPIRVId Id = SPIRVID_INVALID, unsigned Increment = 1); SPIRVEntry *getEntry(SPIRVId Id) const override; // If we have at least on OpLine in the module the CurrentLine is non-empty bool hasDebugInfo() const override { return CurrentLine.get() || !DebugInstVec.empty(); } // Error handling functions SPIRVErrorLog &getErrorLog() override { return ErrLog; } SPIRVErrorCode getError(std::string &ErrMsg) override { return ErrLog.getError(ErrMsg); } bool checkExtension(ExtensionID Ext, SPIRVErrorCode ErrCode, const std::string &Msg) override { if (ErrLog.checkError(isAllowedToUseExtension(Ext), ErrCode, Msg)) return true; setInvalid(); return false; } // Module query functions SPIRVAddressingModelKind getAddressingModel() override { return AddrModel; } SPIRVExtInstSetKind getBuiltinSet(SPIRVId SetId) const override; const SPIRVCapMap &getCapability() const override { return CapMap; } bool hasCapability(SPIRVCapabilityKind Cap) const override { return CapMap.find(Cap) != CapMap.end(); } std::set &getExtension() override { return SPIRVExt; } SPIRVFunction *getFunction(unsigned I) const override { return FuncVec[I]; } SPIRVVariable *getVariable(unsigned I) const override { return VariableVec[I]; } SPIRVValue *getValue(SPIRVId TheId) const override; std::vector getValues(const std::vector &) const override; std::vector getIds(const std::vector &) const override; std::vector getIds(const std::vector &) const override; SPIRVType *getValueType(SPIRVId TheId) const override; std::vector getValueTypes(const std::vector &) const override; SPIRVMemoryModelKind getMemoryModel() const override { return MemoryModel; } SPIRVConstant *getLiteralAsConstant(unsigned Literal) override; unsigned getNumEntryPoints(SPIRVExecutionModelKind EM) const override { auto Loc = EntryPointVec.find(EM); if (Loc == EntryPointVec.end()) return 0; return Loc->second.size(); } SPIRVFunction *getEntryPoint(SPIRVExecutionModelKind EM, unsigned I) const override { auto Loc = EntryPointVec.find(EM); if (Loc == EntryPointVec.end()) return nullptr; assert(I < Loc->second.size()); return get(Loc->second[I]); } unsigned getNumFunctions() const override { return FuncVec.size(); } unsigned getNumVariables() const override { return VariableVec.size(); } SourceLanguage getSourceLanguage(SPIRVWord *Ver = nullptr) const override { if (Ver) *Ver = SrcLangVer; return SrcLang; } std::set &getSourceExtension() override { return SrcExtension; } bool isEntryPoint(SPIRVExecutionModelKind, SPIRVId EP) const override; unsigned short getGeneratorId() const override { return GeneratorId; } unsigned short getGeneratorVer() const override { return GeneratorVer; } SPIRVWord getSPIRVVersion() const override { return SPIRVVersion; } const std::vector &getDebugInstVec() const override { return DebugInstVec; } const std::vector &getStringVec() const override { return StringVec; } // Module changing functions bool importBuiltinSet(const std::string &, SPIRVId *) override; bool importBuiltinSetWithId(const std::string &, SPIRVId) override; void optimizeDecorates() override; void setAddressingModel(SPIRVAddressingModelKind AM) override { AddrModel = AM; } void setAlignment(SPIRVValue *, SPIRVWord) override; void setMemoryModel(SPIRVMemoryModelKind MM) override { MemoryModel = MM; if (MemoryModel == spv::MemoryModelOpenCL) addCapability(CapabilityKernel); } void setName(SPIRVEntry *E, const std::string &Name) override; void setSourceLanguage(SourceLanguage Lang, SPIRVWord Ver) override { SrcLang = Lang; SrcLangVer = Ver; } void setGeneratorId(unsigned short Id) override { GeneratorId = Id; } void setGeneratorVer(unsigned short Ver) override { GeneratorVer = Ver; } void resolveUnknownStructFields() override; void setSPIRVVersion(SPIRVWord Ver) override { assert(this->isAllowedToUseVersion(static_cast(Ver))); SPIRVVersion = Ver; } // Object creation functions template void addTo(std::vector &V, SPIRVEntry *E); SPIRVEntry *addEntry(SPIRVEntry *E) override; SPIRVBasicBlock *addBasicBlock(SPIRVFunction *, SPIRVId) override; SPIRVString *getString(const std::string &Str) override; SPIRVMemberName *addMemberName(SPIRVTypeStruct *ST, SPIRVWord MemberNumber, const std::string &Name) override; void addUnknownStructField(SPIRVTypeStruct *Struct, unsigned I, SPIRVId ID) override; void addLine(SPIRVEntry *E, SPIRVId FileNameId, SPIRVWord Line, SPIRVWord Column) override; const std::shared_ptr &getCurrentLine() const override; void setCurrentLine(const std::shared_ptr &Line) override; void addCapability(SPIRVCapabilityKind) override; void addCapabilityInternal(SPIRVCapabilityKind) override; void addExtension(ExtensionID) override; const SPIRVDecorateGeneric *addDecorate(SPIRVDecorateGeneric *) override; SPIRVDecorationGroup *addDecorationGroup() override; SPIRVDecorationGroup * addDecorationGroup(SPIRVDecorationGroup *Group) override; SPIRVGroupDecorate * addGroupDecorate(SPIRVDecorationGroup *Group, const std::vector &Targets) override; SPIRVGroupDecorateGeneric * addGroupDecorateGeneric(SPIRVGroupDecorateGeneric *GDec) override; SPIRVGroupMemberDecorate * addGroupMemberDecorate(SPIRVDecorationGroup *Group, const std::vector &Targets) override; void addEntryPoint(SPIRVExecutionModelKind ExecModel, SPIRVId EntryPoint) override; SPIRVForward *addForward(SPIRVType *Ty) override; SPIRVForward *addForward(SPIRVId, SPIRVType *Ty) override; SPIRVFunction *addFunction(SPIRVFunction *) override; SPIRVFunction *addFunction(SPIRVTypeFunction *, SPIRVId) override; SPIRVEntry *replaceForward(SPIRVForward *, SPIRVEntry *) override; void eraseInstruction(SPIRVInstruction *, SPIRVBasicBlock *) override; // Type creation functions template T *addType(T *Ty); SPIRVTypeArray *addArrayType(SPIRVType *, SPIRVConstant *) override; SPIRVTypeBool *addBoolType() override; SPIRVTypeFloat *addFloatType(unsigned BitWidth) override; SPIRVTypeFunction *addFunctionType(SPIRVType *, const std::vector &) override; SPIRVTypeInt *addIntegerType(unsigned BitWidth) override; SPIRVTypeOpaque *addOpaqueType(const std::string &) override; SPIRVTypePointer *addPointerType(SPIRVStorageClassKind, SPIRVType *) override; SPIRVTypeImage *addImageType(SPIRVType *, const SPIRVTypeImageDescriptor &) override; SPIRVTypeImage *addImageType(SPIRVType *, const SPIRVTypeImageDescriptor &, SPIRVAccessQualifierKind) override; SPIRVTypeSampler *addSamplerType() override; SPIRVTypePipeStorage *addPipeStorageType() override; SPIRVTypeSampledImage *addSampledImageType(SPIRVTypeImage *T) override; SPIRVTypeStruct *openStructType(unsigned, const std::string &) override; void closeStructType(SPIRVTypeStruct *T, bool) override; SPIRVTypeVector *addVectorType(SPIRVType *, SPIRVWord) override; SPIRVType *addOpaqueGenericType(Op) override; SPIRVTypeDeviceEvent *addDeviceEventType() override; SPIRVTypeQueue *addQueueType() override; SPIRVTypePipe *addPipeType() override; SPIRVTypeVoid *addVoidType() override; void createForwardPointers() override; SPIRVType *addSubgroupAvcINTELType(Op) override; SPIRVTypeVmeImageINTEL *addVmeImageINTELType(SPIRVTypeImage *T) override; // Constant creation functions SPIRVInstruction *addBranchInst(SPIRVLabel *, SPIRVBasicBlock *) override; SPIRVInstruction *addBranchConditionalInst(SPIRVValue *, SPIRVLabel *, SPIRVLabel *, SPIRVBasicBlock *) override; SPIRVValue *addCompositeConstant(SPIRVType *, const std::vector &) override; SPIRVValue *addConstant(SPIRVValue *) override; SPIRVValue *addConstant(SPIRVType *, uint64_t) override; SPIRVValue *addDoubleConstant(SPIRVTypeFloat *, double) override; SPIRVValue *addFloatConstant(SPIRVTypeFloat *, float) override; SPIRVValue *addIntegerConstant(SPIRVTypeInt *, uint64_t) override; SPIRVValue *addNullConstant(SPIRVType *) override; SPIRVValue *addUndef(SPIRVType *TheType) override; SPIRVValue *addSamplerConstant(SPIRVType *TheType, SPIRVWord AddrMode, SPIRVWord ParametricMode, SPIRVWord FilterMode) override; SPIRVValue *addPipeStorageConstant(SPIRVType *TheType, SPIRVWord PacketSize, SPIRVWord PacketAlign, SPIRVWord Capacity) override; // Instruction creation functions SPIRVInstruction *addPtrAccessChainInst(SPIRVType *, SPIRVValue *, std::vector, SPIRVBasicBlock *, bool) override; SPIRVInstruction *addAsyncGroupCopy(SPIRVValue *Scope, SPIRVValue *Dest, SPIRVValue *Src, SPIRVValue *NumElems, SPIRVValue *Stride, SPIRVValue *Event, SPIRVBasicBlock *BB) override; SPIRVInstruction *addExtInst(SPIRVType *, SPIRVWord, SPIRVWord, const std::vector &, SPIRVBasicBlock *, SPIRVInstruction * = nullptr) override; SPIRVInstruction *addExtInst(SPIRVType *, SPIRVWord, SPIRVWord, const std::vector &, SPIRVBasicBlock *, SPIRVInstruction * = nullptr) override; SPIRVEntry *addDebugInfo(SPIRVWord, SPIRVType *TheType, const std::vector &) override; SPIRVInstruction *addBinaryInst(Op, SPIRVType *, SPIRVValue *, SPIRVValue *, SPIRVBasicBlock *) override; SPIRVInstruction *addCallInst(SPIRVFunction *, const std::vector &, SPIRVBasicBlock *) override; SPIRVInstruction *addIndirectCallInst(SPIRVValue *, SPIRVType *, const std::vector &, SPIRVBasicBlock *) override; SPIRVInstruction *addFunctionPointerINTELInst(SPIRVType *, SPIRVFunction *, SPIRVBasicBlock *) override; SPIRVEntry *getOrAddAsmTargetINTEL(const std::string &) override; SPIRVValue *addAsmINTEL(SPIRVTypeFunction *, SPIRVAsmTargetINTEL *, const std::string &, const std::string &) override; SPIRVInstruction *addAsmCallINTELInst(SPIRVAsmINTEL *, const std::vector &, SPIRVBasicBlock *) override; SPIRVInstruction *addCmpInst(Op, SPIRVType *, SPIRVValue *, SPIRVValue *, SPIRVBasicBlock *) override; SPIRVInstruction *addLoadInst(SPIRVValue *, const std::vector &, SPIRVBasicBlock *) override; SPIRVInstruction *addPhiInst(SPIRVType *, std::vector, SPIRVBasicBlock *) override; SPIRVInstruction *addCompositeConstructInst(SPIRVType *, const std::vector &, SPIRVBasicBlock *) override; SPIRVInstruction *addCompositeExtractInst(SPIRVType *, SPIRVValue *, const std::vector &, SPIRVBasicBlock *) override; SPIRVInstruction * addCompositeInsertInst(SPIRVValue *Object, SPIRVValue *Composite, const std::vector &Indices, SPIRVBasicBlock *BB) override; SPIRVInstruction *addCopyObjectInst(SPIRVType *TheType, SPIRVValue *Operand, SPIRVBasicBlock *BB) override; SPIRVInstruction *addCopyMemoryInst(SPIRVValue *, SPIRVValue *, const std::vector &, SPIRVBasicBlock *) override; SPIRVInstruction *addCopyMemorySizedInst(SPIRVValue *, SPIRVValue *, SPIRVValue *, const std::vector &, SPIRVBasicBlock *) override; SPIRVInstruction *addControlBarrierInst(SPIRVValue *ExecKind, SPIRVValue *MemKind, SPIRVValue *MemSema, SPIRVBasicBlock *BB) override; SPIRVInstruction *addGroupInst(Op OpCode, SPIRVType *Type, Scope Scope, const std::vector &Ops, SPIRVBasicBlock *BB) override; virtual SPIRVInstruction * addInstruction(SPIRVInstruction *Inst, SPIRVBasicBlock *BB, SPIRVInstruction *InsertBefore = nullptr); SPIRVInstTemplateBase *addInstTemplate(Op OC, SPIRVBasicBlock *BB, SPIRVType *Ty) override; SPIRVInstTemplateBase *addInstTemplate(Op OC, const std::vector &Ops, SPIRVBasicBlock *BB, SPIRVType *Ty) override; SPIRVInstruction *addLifetimeInst(Op OC, SPIRVValue *Object, SPIRVWord Size, SPIRVBasicBlock *BB) override; SPIRVInstruction *addMemoryBarrierInst(Scope ScopeKind, SPIRVWord MemFlag, SPIRVBasicBlock *BB) override; SPIRVInstruction *addUnreachableInst(SPIRVBasicBlock *) override; SPIRVInstruction *addReturnInst(SPIRVBasicBlock *) override; SPIRVInstruction *addReturnValueInst(SPIRVValue *, SPIRVBasicBlock *) override; SPIRVInstruction *addSelectInst(SPIRVValue *, SPIRVValue *, SPIRVValue *, SPIRVBasicBlock *) override; SPIRVInstruction * addLoopMergeInst(SPIRVId MergeBlock, SPIRVId ContinueTarget, SPIRVWord LoopControl, std::vector LoopControlParameters, SPIRVBasicBlock *BB) override; SPIRVInstruction * addLoopControlINTELInst(SPIRVWord LoopControl, std::vector LoopControlParameters, SPIRVBasicBlock *BB) override; SPIRVInstruction *addSelectionMergeInst(SPIRVId MergeBlock, SPIRVWord SelectionControl, SPIRVBasicBlock *BB) override; SPIRVInstruction *addStoreInst(SPIRVValue *, SPIRVValue *, const std::vector &, SPIRVBasicBlock *) override; SPIRVInstruction *addSwitchInst( SPIRVValue *, SPIRVBasicBlock *, const std::vector, SPIRVBasicBlock *>> &, SPIRVBasicBlock *) override; SPIRVInstruction *addFModInst(SPIRVType *TheType, SPIRVId TheDividend, SPIRVId TheDivisor, SPIRVBasicBlock *BB) override; SPIRVInstruction *addVectorTimesScalarInst(SPIRVType *TheType, SPIRVId TheVector, SPIRVId TheScalar, SPIRVBasicBlock *BB) override; SPIRVInstruction *addVectorTimesMatrixInst(SPIRVType *TheType, SPIRVId TheVector, SPIRVId TheScalar, SPIRVBasicBlock *BB) override; SPIRVInstruction *addMatrixTimesScalarInst(SPIRVType *TheType, SPIRVId TheMatrix, SPIRVId TheScalar, SPIRVBasicBlock *BB) override; SPIRVInstruction *addMatrixTimesVectorInst(SPIRVType *TheType, SPIRVId TheMatrix, SPIRVId TheVector, SPIRVBasicBlock *BB) override; SPIRVInstruction *addMatrixTimesMatrixInst(SPIRVType *TheType, SPIRVId M1, SPIRVId M2, SPIRVBasicBlock *BB) override; SPIRVInstruction *addTransposeInst(SPIRVType *TheType, SPIRVId TheMatrix, SPIRVBasicBlock *BB) override; SPIRVInstruction *addUnaryInst(Op, SPIRVType *, SPIRVValue *, SPIRVBasicBlock *) override; SPIRVInstruction *addVariable(SPIRVType *, bool, SPIRVLinkageTypeKind, SPIRVValue *, const std::string &, SPIRVStorageClassKind, SPIRVBasicBlock *) override; SPIRVValue *addVectorShuffleInst(SPIRVType *Type, SPIRVValue *Vec1, SPIRVValue *Vec2, const std::vector &Components, SPIRVBasicBlock *BB) override; SPIRVInstruction *addVectorExtractDynamicInst(SPIRVValue *, SPIRVValue *, SPIRVBasicBlock *) override; SPIRVInstruction *addVectorInsertDynamicInst(SPIRVValue *, SPIRVValue *, SPIRVValue *, SPIRVBasicBlock *) override; SPIRVInstruction *addFPGARegINTELInst(SPIRVType *, SPIRVValue *, SPIRVBasicBlock *) override; SPIRVInstruction *addSampledImageInst(SPIRVType *, SPIRVValue *, SPIRVValue *, SPIRVBasicBlock *) override; virtual SPIRVId getExtInstSetId(SPIRVExtInstSetKind Kind) const override; // I/O functions friend spv_ostream &operator<<(spv_ostream &O, SPIRVModule &M); friend std::istream &operator>>(std::istream &I, SPIRVModule &M); private: SPIRVErrorLog ErrLog; SPIRVId NextId; SPIRVWord SPIRVVersion; unsigned short GeneratorId; unsigned short GeneratorVer; SPIRVInstructionSchemaKind InstSchema; SourceLanguage SrcLang; SPIRVWord SrcLangVer; std::set SrcExtension; std::set SPIRVExt; SPIRVAddressingModelKind AddrModel; SPIRVMemoryModelKind MemoryModel; typedef std::map SPIRVIdToEntryMap; typedef std::set SPIRVEntrySet; typedef std::set SPIRVIdSet; typedef std::vector SPIRVIdVec; typedef std::vector SPIRVFunctionVector; typedef std::vector SPIRVForwardPointerVec; typedef std::vector SPIRVTypeVec; typedef std::vector SPIRVConstantVector; typedef std::vector SPIRVVariableVec; typedef std::vector SPIRVStringVec; typedef std::vector SPIRVMemberNameVec; typedef std::vector SPIRVDecGroupVec; typedef std::vector SPIRVGroupDecVec; typedef std::vector SPIRVAsmTargetVector; typedef std::vector SPIRVAsmVector; typedef std::map SPIRVIdToInstructionSetMap; std::map ExtInstSetIds; typedef std::map SPIRVIdToBuiltinSetMap; typedef std::map SPIRVExecModelIdSetMap; typedef std::map SPIRVExecModelIdVecMap; typedef std::unordered_map SPIRVStringMap; typedef std::map>> SPIRVUnknownStructFieldMap; SPIRVForwardPointerVec ForwardPointerVec; SPIRVTypeVec TypeVec; SPIRVIdToEntryMap IdEntryMap; SPIRVFunctionVector FuncVec; SPIRVConstantVector ConstVec; SPIRVVariableVec VariableVec; SPIRVEntrySet EntryNoId; // Entries without id SPIRVIdToInstructionSetMap IdToInstSetMap; SPIRVIdToBuiltinSetMap IdBuiltinMap; SPIRVIdSet NamedId; SPIRVStringVec StringVec; SPIRVMemberNameVec MemberNameVec; std::shared_ptr CurrentLine; SPIRVDecorateSet DecorateSet; SPIRVDecGroupVec DecGroupVec; SPIRVGroupDecVec GroupDecVec; SPIRVAsmTargetVector AsmTargetVec; SPIRVAsmVector AsmVec; SPIRVExecModelIdSetMap EntryPointSet; SPIRVExecModelIdVecMap EntryPointVec; SPIRVStringMap StrMap; SPIRVCapMap CapMap; SPIRVUnknownStructFieldMap UnknownStructFieldMap; std::map IntTypeMap; std::map LiteralMap; std::vector DebugInstVec; void layoutEntry(SPIRVEntry *Entry); }; SPIRVModuleImpl::~SPIRVModuleImpl() { for (auto I : EntryNoId) delete I; for (auto I : IdEntryMap) delete I.second; for (auto C : CapMap) delete C.second; } const std::shared_ptr & SPIRVModuleImpl::getCurrentLine() const { return CurrentLine; } void SPIRVModuleImpl::setCurrentLine( const std::shared_ptr &Line) { CurrentLine = Line; } void SPIRVModuleImpl::addLine(SPIRVEntry *E, SPIRVId FileNameId, SPIRVWord Line, SPIRVWord Column) { if (!(CurrentLine && CurrentLine->equals(FileNameId, Line, Column))) CurrentLine.reset(new SPIRVLine(this, FileNameId, Line, Column)); assert(E && "invalid entry"); E->setLine(CurrentLine); } // Creates decoration group and group decorates from decorates shared by // multiple targets. void SPIRVModuleImpl::optimizeDecorates() { SPIRVDBG(spvdbgs() << "[optimizeDecorates] begin\n"); for (auto I = DecorateSet.begin(), E = DecorateSet.end(); I != E;) { auto D = *I; SPIRVDBG(spvdbgs() << " check " << *D << '\n'); if (D->getOpCode() == OpMemberDecorate) { ++I; continue; } auto ER = DecorateSet.equal_range(D); SPIRVDBG(spvdbgs() << " equal range " << **ER.first << " to "; if (ER.second != DecorateSet.end()) spvdbgs() << **ER.second; else spvdbgs() << "end"; spvdbgs() << '\n'); if (std::distance(ER.first, ER.second) < 2) { I = ER.second; SPIRVDBG(spvdbgs() << " skip equal range \n"); continue; } SPIRVDBG(spvdbgs() << " add deco group. erase equal range\n"); auto G = add(new SPIRVDecorationGroup(this, getId())); std::vector Targets; Targets.push_back(D->getTargetId()); const_cast(D)->setTargetId(G->getId()); G->getDecorations().insert(D); for (I = ER.first; I != ER.second; ++I) { auto E = *I; if (*E == *D) continue; Targets.push_back(E->getTargetId()); } // WordCount is only 16 bits. We can only have 65535 - FixedWC targtets per // group. // For now, just skip using a group if the number of targets to too big if (Targets.size() < 65530) { DecorateSet.erase(ER.first, ER.second); auto GD = add(new SPIRVGroupDecorate(G, Targets)); DecGroupVec.push_back(G); GroupDecVec.push_back(GD); } } } SPIRVValue *SPIRVModuleImpl::addSamplerConstant(SPIRVType *TheType, SPIRVWord AddrMode, SPIRVWord ParametricMode, SPIRVWord FilterMode) { return addConstant(new SPIRVConstantSampler(this, TheType, getId(), AddrMode, ParametricMode, FilterMode)); } SPIRVValue *SPIRVModuleImpl::addPipeStorageConstant(SPIRVType *TheType, SPIRVWord PacketSize, SPIRVWord PacketAlign, SPIRVWord Capacity) { return addConstant(new SPIRVConstantPipeStorage( this, TheType, getId(), PacketSize, PacketAlign, Capacity)); } void SPIRVModuleImpl::addExtension(ExtensionID Ext) { std::string ExtName; SPIRVMap::find(Ext, &ExtName); assert(isAllowedToUseExtension(Ext)); SPIRVExt.insert(ExtName); } void SPIRVModuleImpl::addCapability(SPIRVCapabilityKind Cap) { addCapabilities(SPIRV::getCapability(Cap)); SPIRVDBG(spvdbgs() << "addCapability: " << Cap << '\n'); if (hasCapability(Cap)) return; CapMap.insert(std::make_pair(Cap, new SPIRVCapability(this, Cap))); } void SPIRVModuleImpl::addCapabilityInternal(SPIRVCapabilityKind Cap) { if (AutoAddCapability) { if (hasCapability(Cap)) return; CapMap.insert(std::make_pair(Cap, new SPIRVCapability(this, Cap))); } } SPIRVConstant *SPIRVModuleImpl::getLiteralAsConstant(unsigned Literal) { auto Loc = LiteralMap.find(Literal); if (Loc != LiteralMap.end()) return Loc->second; auto Ty = addIntegerType(32); auto V = new SPIRVConstant(this, Ty, getId(), static_cast(Literal)); LiteralMap[Literal] = V; addConstant(V); return V; } void SPIRVModuleImpl::layoutEntry(SPIRVEntry *E) { auto OC = E->getOpCode(); switch (OC) { case OpString: addTo(StringVec, E); break; case OpMemberName: addTo(MemberNameVec, E); break; case OpVariable: { auto BV = static_cast(E); if (!BV->getParent()) addTo(VariableVec, E); } break; case OpExtInst: { SPIRVExtInst *EI = static_cast(E); if (EI->getExtSetKind() == SPIRVEIS_Debug && EI->getExtOp() != SPIRVDebug::Declare && EI->getExtOp() != SPIRVDebug::Value && EI->getExtOp() != SPIRVDebug::Scope && EI->getExtOp() != SPIRVDebug::NoScope) { DebugInstVec.push_back(EI); } break; } case OpAsmTargetINTEL: { addTo(AsmTargetVec, E); break; } case OpAsmINTEL: { addTo(AsmVec, E); break; } default: if (isTypeOpCode(OC)) TypeVec.push_back(static_cast(E)); else if (isConstantOpCode(OC)) ConstVec.push_back(static_cast(E)); break; } } // Add an entry to the id to entry map. // Assert if the id is mapped to a different entry. // Certain entries need to be add to specific collectors to maintain // logic layout of SPIRV. SPIRVEntry *SPIRVModuleImpl::addEntry(SPIRVEntry *Entry) { assert(Entry && "Invalid entry"); if (Entry->hasId()) { SPIRVId Id = Entry->getId(); assert(Entry->getId() != SPIRVID_INVALID && "Invalid id"); SPIRVEntry *Mapped = nullptr; if (exist(Id, &Mapped)) { if (Mapped->getOpCode() == OpForward) { replaceForward(static_cast(Mapped), Entry); } else { assert(Mapped == Entry && "Id used twice"); } } else IdEntryMap[Id] = Entry; } else { // Entry of OpLine will be deleted by std::shared_ptr automatically. if (Entry->getOpCode() != OpLine) EntryNoId.insert(Entry); } Entry->setModule(this); layoutEntry(Entry); if (AutoAddCapability) { for (auto &I : Entry->getRequiredCapability()) { addCapability(I); } } if (ValidateCapability) { assert(none_of( Entry->getRequiredCapability().begin(), Entry->getRequiredCapability().end(), [this](SPIRVCapabilityKind &val) { return !CapMap.count(val); })); } if (AutoAddExtensions) { // While we are reading existing SPIR-V we need to read it as-is and don't // add required extensions for each entry automatically for (auto &E : Entry->getRequiredExtensions()) { addExtension(E); } } return Entry; } bool SPIRVModuleImpl::exist(SPIRVId Id) const { return exist(Id, nullptr); } bool SPIRVModuleImpl::exist(SPIRVId Id, SPIRVEntry **Entry) const { assert(Id != SPIRVID_INVALID && "Invalid Id"); SPIRVIdToEntryMap::const_iterator Loc = IdEntryMap.find(Id); if (Loc == IdEntryMap.end()) return false; if (Entry) *Entry = Loc->second; return true; } // If Id is invalid, returns the next available id. // Otherwise returns the given id and adjust the next available id by increment. SPIRVId SPIRVModuleImpl::getId(SPIRVId Id, unsigned Increment) { if (!isValidId(Id)) Id = NextId; else NextId = std::max(Id, NextId); NextId += Increment; return Id; } SPIRVEntry *SPIRVModuleImpl::getEntry(SPIRVId Id) const { assert(Id != SPIRVID_INVALID && "Invalid Id"); SPIRVIdToEntryMap::const_iterator Loc = IdEntryMap.find(Id); assert(Loc != IdEntryMap.end() && "Id is not in map"); return Loc->second; } SPIRVExtInstSetKind SPIRVModuleImpl::getBuiltinSet(SPIRVId SetId) const { auto Loc = IdToInstSetMap.find(SetId); assert(Loc != IdToInstSetMap.end() && "Invalid builtin set id"); return Loc->second; } bool SPIRVModuleImpl::isEntryPoint(SPIRVExecutionModelKind ExecModel, SPIRVId EP) const { assert(isValid(ExecModel) && "Invalid execution model"); assert(EP != SPIRVID_INVALID && "Invalid function id"); auto Loc = EntryPointSet.find(ExecModel); if (Loc == EntryPointSet.end()) return false; return Loc->second.count(EP); } // Module change functions bool SPIRVModuleImpl::importBuiltinSet(const std::string &BuiltinSetName, SPIRVId *BuiltinSetId) { SPIRVId TmpBuiltinSetId = getId(); if (!importBuiltinSetWithId(BuiltinSetName, TmpBuiltinSetId)) return false; if (BuiltinSetId) *BuiltinSetId = TmpBuiltinSetId; return true; } bool SPIRVModuleImpl::importBuiltinSetWithId(const std::string &BuiltinSetName, SPIRVId BuiltinSetId) { SPIRVExtInstSetKind BuiltinSet = SPIRVEIS_Count; SPIRVCKRT(SPIRVBuiltinSetNameMap::rfind(BuiltinSetName, &BuiltinSet), InvalidBuiltinSetName, "Actual is " + BuiltinSetName); IdToInstSetMap[BuiltinSetId] = BuiltinSet; ExtInstSetIds[BuiltinSet] = BuiltinSetId; return true; } void SPIRVModuleImpl::setAlignment(SPIRVValue *V, SPIRVWord A) { V->setAlignment(A); } void SPIRVModuleImpl::setName(SPIRVEntry *E, const std::string &Name) { E->setName(Name); if (!E->hasId()) return; if (!Name.empty()) NamedId.insert(E->getId()); else NamedId.erase(E->getId()); } void SPIRVModuleImpl::resolveUnknownStructFields() { for (auto &KV : UnknownStructFieldMap) { auto *Struct = KV.first; for (auto &Indices : KV.second) { unsigned I = Indices.first; SPIRVId ID = Indices.second; auto Ty = static_cast(getEntry(ID)); Struct->setMemberType(I, Ty); } } } // Type creation functions template T *SPIRVModuleImpl::addType(T *Ty) { add(Ty); if (!Ty->getName().empty()) setName(Ty, Ty->getName()); return Ty; } SPIRVTypeVoid *SPIRVModuleImpl::addVoidType() { return addType(new SPIRVTypeVoid(this, getId())); } SPIRVTypeArray *SPIRVModuleImpl::addArrayType(SPIRVType *ElementType, SPIRVConstant *Length) { return addType(new SPIRVTypeArray(this, getId(), ElementType, Length)); } SPIRVTypeBool *SPIRVModuleImpl::addBoolType() { return addType(new SPIRVTypeBool(this, getId())); } SPIRVTypeInt *SPIRVModuleImpl::addIntegerType(unsigned BitWidth) { auto Loc = IntTypeMap.find(BitWidth); if (Loc != IntTypeMap.end()) return Loc->second; auto Ty = new SPIRVTypeInt(this, getId(), BitWidth, false); IntTypeMap[BitWidth] = Ty; return addType(Ty); } SPIRVTypeFloat *SPIRVModuleImpl::addFloatType(unsigned BitWidth) { SPIRVTypeFloat *T = addType(new SPIRVTypeFloat(this, getId(), BitWidth)); return T; } SPIRVTypePointer * SPIRVModuleImpl::addPointerType(SPIRVStorageClassKind StorageClass, SPIRVType *ElementType) { return addType( new SPIRVTypePointer(this, getId(), StorageClass, ElementType)); } SPIRVTypeFunction *SPIRVModuleImpl::addFunctionType( SPIRVType *ReturnType, const std::vector &ParameterTypes) { return addType( new SPIRVTypeFunction(this, getId(), ReturnType, ParameterTypes)); } SPIRVTypeOpaque *SPIRVModuleImpl::addOpaqueType(const std::string &Name) { return addType(new SPIRVTypeOpaque(this, getId(), Name)); } SPIRVTypeStruct *SPIRVModuleImpl::openStructType(unsigned NumMembers, const std::string &Name) { auto T = new SPIRVTypeStruct(this, getId(), NumMembers, Name); return T; } void SPIRVModuleImpl::closeStructType(SPIRVTypeStruct *T, bool Packed) { addType(T); T->setPacked(Packed); } SPIRVTypeVector *SPIRVModuleImpl::addVectorType(SPIRVType *CompType, SPIRVWord CompCount) { return addType(new SPIRVTypeVector(this, getId(), CompType, CompCount)); } SPIRVType *SPIRVModuleImpl::addOpaqueGenericType(Op TheOpCode) { return addType(new SPIRVTypeOpaqueGeneric(TheOpCode, this, getId())); } SPIRVTypeDeviceEvent *SPIRVModuleImpl::addDeviceEventType() { return addType(new SPIRVTypeDeviceEvent(this, getId())); } SPIRVTypeQueue *SPIRVModuleImpl::addQueueType() { return addType(new SPIRVTypeQueue(this, getId())); } SPIRVTypePipe *SPIRVModuleImpl::addPipeType() { return addType(new SPIRVTypePipe(this, getId())); } SPIRVTypeImage * SPIRVModuleImpl::addImageType(SPIRVType *SampledType, const SPIRVTypeImageDescriptor &Desc) { return addType(new SPIRVTypeImage( this, getId(), SampledType ? SampledType->getId() : 0, Desc)); } SPIRVTypeImage * SPIRVModuleImpl::addImageType(SPIRVType *SampledType, const SPIRVTypeImageDescriptor &Desc, SPIRVAccessQualifierKind Acc) { return addType(new SPIRVTypeImage( this, getId(), SampledType ? SampledType->getId() : 0, Desc, Acc)); } SPIRVTypeSampler *SPIRVModuleImpl::addSamplerType() { return addType(new SPIRVTypeSampler(this, getId())); } SPIRVTypePipeStorage *SPIRVModuleImpl::addPipeStorageType() { return addType(new SPIRVTypePipeStorage(this, getId())); } SPIRVTypeSampledImage *SPIRVModuleImpl::addSampledImageType(SPIRVTypeImage *T) { return addType(new SPIRVTypeSampledImage(this, getId(), T)); } void SPIRVModuleImpl::createForwardPointers() { std::unordered_set Seen; for (auto *T : TypeVec) { if (T->hasId()) Seen.insert(T->getId()); if (!T->isTypeStruct()) continue; auto ST = static_cast(T); for (unsigned I = 0; I < ST->getStructMemberCount(); ++I) { auto MemberTy = ST->getStructMemberType(I); if (!MemberTy->isTypePointer()) continue; auto Ptr = static_cast(MemberTy); if (Seen.find(Ptr->getId()) == Seen.end()) { ForwardPointerVec.push_back(new SPIRVTypeForwardPointer( this, Ptr, Ptr->getPointerStorageClass())); } } } } SPIRVTypeVmeImageINTEL * SPIRVModuleImpl::addVmeImageINTELType(SPIRVTypeImage *T) { return addType(new SPIRVTypeVmeImageINTEL(this, getId(), T)); } SPIRVType *SPIRVModuleImpl::addSubgroupAvcINTELType(Op TheOpCode) { return addType(new SPIRVTypeSubgroupAvcINTEL(TheOpCode, this, getId())); } SPIRVFunction *SPIRVModuleImpl::addFunction(SPIRVFunction *Func) { FuncVec.push_back(add(Func)); return Func; } SPIRVFunction *SPIRVModuleImpl::addFunction(SPIRVTypeFunction *FuncType, SPIRVId Id) { return addFunction(new SPIRVFunction( this, FuncType, getId(Id, FuncType->getNumParameters() + 1))); } SPIRVBasicBlock *SPIRVModuleImpl::addBasicBlock(SPIRVFunction *Func, SPIRVId Id) { return Func->addBasicBlock(new SPIRVBasicBlock(getId(Id), Func)); } const SPIRVDecorateGeneric * SPIRVModuleImpl::addDecorate(SPIRVDecorateGeneric *Dec) { add(Dec); SPIRVId Id = Dec->getTargetId(); bool Found = exist(Id); (void)Found; assert(Found && "Decorate target does not exist"); if (!Dec->getOwner()) DecorateSet.insert(Dec); addCapabilities(Dec->getRequiredCapability()); return Dec; } void SPIRVModuleImpl::addEntryPoint(SPIRVExecutionModelKind ExecModel, SPIRVId EntryPoint) { assert(isValid(ExecModel) && "Invalid execution model"); assert(EntryPoint != SPIRVID_INVALID && "Invalid entry point"); EntryPointSet[ExecModel].insert(EntryPoint); EntryPointVec[ExecModel].push_back(EntryPoint); addCapabilities(SPIRV::getCapability(ExecModel)); } SPIRVForward *SPIRVModuleImpl::addForward(SPIRVType *Ty) { return add(new SPIRVForward(this, Ty, getId())); } SPIRVForward *SPIRVModuleImpl::addForward(SPIRVId Id, SPIRVType *Ty) { return add(new SPIRVForward(this, Ty, Id)); } SPIRVEntry *SPIRVModuleImpl::replaceForward(SPIRVForward *Forward, SPIRVEntry *Entry) { SPIRVId Id = Entry->getId(); SPIRVId ForwardId = Forward->getId(); if (ForwardId == Id) IdEntryMap[Id] = Entry; else { auto Loc = IdEntryMap.find(Id); assert(Loc != IdEntryMap.end()); IdEntryMap.erase(Loc); Entry->setId(ForwardId); IdEntryMap[ForwardId] = Entry; } // Annotations include name, decorations, execution modes Entry->takeAnnotations(Forward); delete Forward; return Entry; } void SPIRVModuleImpl::eraseInstruction(SPIRVInstruction *I, SPIRVBasicBlock *BB) { SPIRVId Id = I->getId(); BB->eraseInstruction(I); auto Loc = IdEntryMap.find(Id); assert(Loc != IdEntryMap.end()); IdEntryMap.erase(Loc); delete I; } SPIRVValue *SPIRVModuleImpl::addConstant(SPIRVValue *C) { return add(C); } SPIRVValue *SPIRVModuleImpl::addConstant(SPIRVType *Ty, uint64_t V) { if (Ty->isTypeBool()) { if (V) return addConstant(new SPIRVConstantTrue(this, Ty, getId())); else return addConstant(new SPIRVConstantFalse(this, Ty, getId())); } if (Ty->isTypeInt()) return addIntegerConstant(static_cast(Ty), V); return addConstant(new SPIRVConstant(this, Ty, getId(), V)); } SPIRVValue *SPIRVModuleImpl::addIntegerConstant(SPIRVTypeInt *Ty, uint64_t V) { if (Ty->getBitWidth() == 32) { unsigned I32 = static_cast(V); assert(I32 == V && "Integer value truncated"); return getLiteralAsConstant(I32); } return addConstant(new SPIRVConstant(this, Ty, getId(), V)); } SPIRVValue *SPIRVModuleImpl::addFloatConstant(SPIRVTypeFloat *Ty, float V) { return addConstant(new SPIRVConstant(this, Ty, getId(), V)); } SPIRVValue *SPIRVModuleImpl::addDoubleConstant(SPIRVTypeFloat *Ty, double V) { return addConstant(new SPIRVConstant(this, Ty, getId(), V)); } SPIRVValue *SPIRVModuleImpl::addNullConstant(SPIRVType *Ty) { return addConstant(new SPIRVConstantNull(this, Ty, getId())); } SPIRVValue *SPIRVModuleImpl::addCompositeConstant( SPIRVType *Ty, const std::vector &Elements) { return addConstant(new SPIRVConstantComposite(this, Ty, getId(), Elements)); } SPIRVValue *SPIRVModuleImpl::addUndef(SPIRVType *TheType) { return addConstant(new SPIRVUndef(this, TheType, getId())); } // Instruction creation functions SPIRVInstruction * SPIRVModuleImpl::addStoreInst(SPIRVValue *Target, SPIRVValue *Source, const std::vector &TheMemoryAccess, SPIRVBasicBlock *BB) { return BB->addInstruction( new SPIRVStore(Target->getId(), Source->getId(), TheMemoryAccess, BB)); } SPIRVInstruction *SPIRVModuleImpl::addSwitchInst( SPIRVValue *Select, SPIRVBasicBlock *Default, const std::vector, SPIRVBasicBlock *>> &Pairs, SPIRVBasicBlock *BB) { return BB->addInstruction(new SPIRVSwitch(Select, Default, Pairs, BB)); } SPIRVInstruction *SPIRVModuleImpl::addFModInst(SPIRVType *TheType, SPIRVId TheDividend, SPIRVId TheDivisor, SPIRVBasicBlock *BB) { return BB->addInstruction( new SPIRVFMod(TheType, getId(), TheDividend, TheDivisor, BB)); } SPIRVInstruction * SPIRVModuleImpl::addVectorTimesScalarInst(SPIRVType *TheType, SPIRVId TheVector, SPIRVId TheScalar, SPIRVBasicBlock *BB) { return BB->addInstruction( new SPIRVVectorTimesScalar(TheType, getId(), TheVector, TheScalar, BB)); } SPIRVInstruction * SPIRVModuleImpl::addVectorTimesMatrixInst(SPIRVType *TheType, SPIRVId TheVector, SPIRVId TheMatrix, SPIRVBasicBlock *BB) { return BB->addInstruction( new SPIRVVectorTimesMatrix(TheType, getId(), TheVector, TheMatrix, BB)); } SPIRVInstruction * SPIRVModuleImpl::addMatrixTimesScalarInst(SPIRVType *TheType, SPIRVId TheMatrix, SPIRVId TheScalar, SPIRVBasicBlock *BB) { return BB->addInstruction( new SPIRVMatrixTimesScalar(TheType, getId(), TheMatrix, TheScalar, BB)); } SPIRVInstruction * SPIRVModuleImpl::addMatrixTimesVectorInst(SPIRVType *TheType, SPIRVId TheMatrix, SPIRVId TheVector, SPIRVBasicBlock *BB) { return BB->addInstruction( new SPIRVMatrixTimesVector(TheType, getId(), TheMatrix, TheVector, BB)); } SPIRVInstruction * SPIRVModuleImpl::addMatrixTimesMatrixInst(SPIRVType *TheType, SPIRVId M1, SPIRVId M2, SPIRVBasicBlock *BB) { return BB->addInstruction( new SPIRVMatrixTimesMatrix(TheType, getId(), M1, M2, BB)); } SPIRVInstruction *SPIRVModuleImpl::addTransposeInst(SPIRVType *TheType, SPIRVId TheMatrix, SPIRVBasicBlock *BB) { return BB->addInstruction( new SPIRVTranspose(TheType, getId(), TheMatrix, BB)); } SPIRVInstruction * SPIRVModuleImpl::addGroupInst(Op OpCode, SPIRVType *Type, Scope Scope, const std::vector &Ops, SPIRVBasicBlock *BB) { assert(!Type || !Type->isTypeVoid()); auto WordOps = getIds(Ops); WordOps.insert(WordOps.begin(), Scope); return addInstTemplate(OpCode, WordOps, BB, Type); } SPIRVInstruction * SPIRVModuleImpl::addInstruction(SPIRVInstruction *Inst, SPIRVBasicBlock *BB, SPIRVInstruction *InsertBefore) { if (BB) return BB->addInstruction(Inst, InsertBefore); if (Inst->getOpCode() != OpSpecConstantOp) Inst = createSpecConstantOpInst(Inst); return static_cast(addConstant(Inst)); } SPIRVInstruction * SPIRVModuleImpl::addLoadInst(SPIRVValue *Source, const std::vector &TheMemoryAccess, SPIRVBasicBlock *BB) { return addInstruction( new SPIRVLoad(getId(), Source->getId(), TheMemoryAccess, BB), BB); } SPIRVInstruction * SPIRVModuleImpl::addPhiInst(SPIRVType *Type, std::vector IncomingPairs, SPIRVBasicBlock *BB) { return addInstruction(new SPIRVPhi(Type, getId(), IncomingPairs, BB), BB); } SPIRVInstruction *SPIRVModuleImpl::addExtInst( SPIRVType *TheType, SPIRVWord BuiltinSet, SPIRVWord EntryPoint, const std::vector &Args, SPIRVBasicBlock *BB, SPIRVInstruction *InsertBefore) { return addInstruction( new SPIRVExtInst(TheType, getId(), BuiltinSet, EntryPoint, Args, BB), BB, InsertBefore); } SPIRVInstruction *SPIRVModuleImpl::addExtInst( SPIRVType *TheType, SPIRVWord BuiltinSet, SPIRVWord EntryPoint, const std::vector &Args, SPIRVBasicBlock *BB, SPIRVInstruction *InsertBefore) { return addInstruction( new SPIRVExtInst(TheType, getId(), BuiltinSet, EntryPoint, Args, BB), BB, InsertBefore); } SPIRVEntry *SPIRVModuleImpl::addDebugInfo(SPIRVWord InstId, SPIRVType *TheType, const std::vector &Args) { return addEntry(new SPIRVExtInst(this, getId(), TheType, SPIRVEIS_Debug, ExtInstSetIds[SPIRVEIS_Debug], InstId, Args)); } SPIRVInstruction * SPIRVModuleImpl::addCallInst(SPIRVFunction *TheFunction, const std::vector &TheArguments, SPIRVBasicBlock *BB) { return addInstruction( new SPIRVFunctionCall(getId(), TheFunction, TheArguments, BB), BB); } SPIRVInstruction *SPIRVModuleImpl::addIndirectCallInst( SPIRVValue *TheCalledValue, SPIRVType *TheReturnType, const std::vector &TheArguments, SPIRVBasicBlock *BB) { return addInstruction( new SPIRVFunctionPointerCallINTEL(getId(), TheCalledValue, TheReturnType, TheArguments, BB), BB); } SPIRVInstruction *SPIRVModuleImpl::addFunctionPointerINTELInst( SPIRVType *TheType, SPIRVFunction *TheFunction, SPIRVBasicBlock *BB) { return addInstruction( new SPIRVFunctionPointerINTEL(getId(), TheType, TheFunction, BB), BB); } SPIRVEntry * SPIRVModuleImpl::getOrAddAsmTargetINTEL(const std::string &TheTarget) { auto TargetIt = std::find_if(AsmTargetVec.begin(), AsmTargetVec.end(), [&TheTarget](const SPIRVAsmTargetINTEL *Target) { return Target->getTarget() == TheTarget; }); if (TargetIt == AsmTargetVec.end()) return add(new SPIRVAsmTargetINTEL(this, getId(), TheTarget)); return *TargetIt; } SPIRVValue *SPIRVModuleImpl::addAsmINTEL(SPIRVTypeFunction *TheType, SPIRVAsmTargetINTEL *TheTarget, const std::string &TheInstructions, const std::string &TheConstraints) { auto Asm = new SPIRVAsmINTEL(this, TheType, getId(), TheTarget, TheInstructions, TheConstraints); return add(Asm); } SPIRVInstruction * SPIRVModuleImpl::addAsmCallINTELInst(SPIRVAsmINTEL *TheAsm, const std::vector &TheArguments, SPIRVBasicBlock *BB) { return addInstruction( new SPIRVAsmCallINTEL(getId(), TheAsm, TheArguments, BB), BB); } SPIRVInstruction *SPIRVModuleImpl::addBinaryInst(Op TheOpCode, SPIRVType *Type, SPIRVValue *Op1, SPIRVValue *Op2, SPIRVBasicBlock *BB) { return addInstruction(SPIRVInstTemplateBase::create( TheOpCode, Type, getId(), getVec(Op1->getId(), Op2->getId()), BB, this), BB); } SPIRVInstruction *SPIRVModuleImpl::addUnreachableInst(SPIRVBasicBlock *BB) { return addInstruction(new SPIRVUnreachable(BB), BB); } SPIRVInstruction *SPIRVModuleImpl::addReturnInst(SPIRVBasicBlock *BB) { return addInstruction(new SPIRVReturn(BB), BB); } SPIRVInstruction *SPIRVModuleImpl::addReturnValueInst(SPIRVValue *ReturnValue, SPIRVBasicBlock *BB) { return addInstruction(new SPIRVReturnValue(ReturnValue, BB), BB); } SPIRVInstruction *SPIRVModuleImpl::addUnaryInst(Op TheOpCode, SPIRVType *TheType, SPIRVValue *Op, SPIRVBasicBlock *BB) { return addInstruction( SPIRVInstTemplateBase::create(TheOpCode, TheType, getId(), getVec(Op->getId()), BB, this), BB); } SPIRVInstruction *SPIRVModuleImpl::addVectorExtractDynamicInst( SPIRVValue *TheVector, SPIRVValue *Index, SPIRVBasicBlock *BB) { return addInstruction( new SPIRVVectorExtractDynamic(getId(), TheVector, Index, BB), BB); } SPIRVInstruction *SPIRVModuleImpl::addVectorInsertDynamicInst( SPIRVValue *TheVector, SPIRVValue *TheComponent, SPIRVValue *Index, SPIRVBasicBlock *BB) { return addInstruction( new SPIRVVectorInsertDynamic(getId(), TheVector, TheComponent, Index, BB), BB); } SPIRVValue *SPIRVModuleImpl::addVectorShuffleInst( SPIRVType *Type, SPIRVValue *Vec1, SPIRVValue *Vec2, const std::vector &Components, SPIRVBasicBlock *BB) { return addInstruction( new SPIRVVectorShuffle(getId(), Type, Vec1, Vec2, Components, BB), BB); } SPIRVInstruction *SPIRVModuleImpl::addBranchInst(SPIRVLabel *TargetLabel, SPIRVBasicBlock *BB) { return addInstruction(new SPIRVBranch(TargetLabel, BB), BB); } SPIRVInstruction *SPIRVModuleImpl::addBranchConditionalInst( SPIRVValue *Condition, SPIRVLabel *TrueLabel, SPIRVLabel *FalseLabel, SPIRVBasicBlock *BB) { return addInstruction( new SPIRVBranchConditional(Condition, TrueLabel, FalseLabel, BB), BB); } SPIRVInstruction *SPIRVModuleImpl::addCmpInst(Op TheOpCode, SPIRVType *TheType, SPIRVValue *Op1, SPIRVValue *Op2, SPIRVBasicBlock *BB) { return addInstruction(SPIRVInstTemplateBase::create( TheOpCode, TheType, getId(), getVec(Op1->getId(), Op2->getId()), BB, this), BB); } SPIRVInstruction *SPIRVModuleImpl::addControlBarrierInst(SPIRVValue *ExecKind, SPIRVValue *MemKind, SPIRVValue *MemSema, SPIRVBasicBlock *BB) { return addInstruction(new SPIRVControlBarrier(ExecKind, MemKind, MemSema, BB), BB); } SPIRVInstruction *SPIRVModuleImpl::addLifetimeInst(Op OC, SPIRVValue *Object, SPIRVWord Size, SPIRVBasicBlock *BB) { if (OC == OpLifetimeStart) return BB->addInstruction( new SPIRVLifetimeStart(Object->getId(), Size, BB)); else return BB->addInstruction(new SPIRVLifetimeStop(Object->getId(), Size, BB)); } SPIRVInstruction *SPIRVModuleImpl::addMemoryBarrierInst(Scope ScopeKind, SPIRVWord MemFlag, SPIRVBasicBlock *BB) { return addInstruction(SPIRVInstTemplateBase::create( OpMemoryBarrier, nullptr, SPIRVID_INVALID, getVec(static_cast(ScopeKind), MemFlag), BB, this), BB); } SPIRVInstruction *SPIRVModuleImpl::addSelectInst(SPIRVValue *Condition, SPIRVValue *Op1, SPIRVValue *Op2, SPIRVBasicBlock *BB) { return addInstruction(new SPIRVSelect(getId(), Condition->getId(), Op1->getId(), Op2->getId(), BB), BB); } SPIRVInstruction *SPIRVModuleImpl::addSelectionMergeInst( SPIRVId MergeBlock, SPIRVWord SelectionControl, SPIRVBasicBlock *BB) { return addInstruction( new SPIRVSelectionMerge(MergeBlock, SelectionControl, BB), BB); } SPIRVInstruction *SPIRVModuleImpl::addLoopMergeInst( SPIRVId MergeBlock, SPIRVId ContinueTarget, SPIRVWord LoopControl, std::vector LoopControlParameters, SPIRVBasicBlock *BB) { return addInstruction( new SPIRVLoopMerge(MergeBlock, ContinueTarget, LoopControl, LoopControlParameters, BB), BB, const_cast(BB->getTerminateInstr())); } SPIRVInstruction *SPIRVModuleImpl::addLoopControlINTELInst( SPIRVWord LoopControl, std::vector LoopControlParameters, SPIRVBasicBlock *BB) { addCapability(CapabilityUnstructuredLoopControlsINTEL); addExtension(ExtensionID::SPV_INTEL_unstructured_loop_controls); return addInstruction( new SPIRVLoopControlINTEL(LoopControl, LoopControlParameters, BB), BB, const_cast(BB->getTerminateInstr())); } SPIRVInstruction * SPIRVModuleImpl::addPtrAccessChainInst(SPIRVType *Type, SPIRVValue *Base, std::vector Indices, SPIRVBasicBlock *BB, bool IsInBounds) { return addInstruction( SPIRVInstTemplateBase::create( IsInBounds ? OpInBoundsPtrAccessChain : OpPtrAccessChain, Type, getId(), getVec(Base->getId(), Base->getIds(Indices)), BB, this), BB); } SPIRVInstruction *SPIRVModuleImpl::addAsyncGroupCopy( SPIRVValue *Scope, SPIRVValue *Dest, SPIRVValue *Src, SPIRVValue *NumElems, SPIRVValue *Stride, SPIRVValue *Event, SPIRVBasicBlock *BB) { return addInstruction(new SPIRVGroupAsyncCopy(Scope, getId(), Dest, Src, NumElems, Stride, Event, BB), BB); } SPIRVInstruction *SPIRVModuleImpl::addCompositeConstructInst( SPIRVType *Type, const std::vector &Constituents, SPIRVBasicBlock *BB) { return addInstruction( new SPIRVCompositeConstruct(Type, getId(), Constituents, BB), BB); } SPIRVInstruction * SPIRVModuleImpl::addCompositeExtractInst(SPIRVType *Type, SPIRVValue *TheVector, const std::vector &Indices, SPIRVBasicBlock *BB) { return addInstruction( new SPIRVCompositeExtract(Type, getId(), TheVector, Indices, BB), BB); } SPIRVInstruction *SPIRVModuleImpl::addCompositeInsertInst( SPIRVValue *Object, SPIRVValue *Composite, const std::vector &Indices, SPIRVBasicBlock *BB) { return addInstruction( new SPIRVCompositeInsert(getId(), Object, Composite, Indices, BB), BB); } SPIRVInstruction *SPIRVModuleImpl::addCopyObjectInst(SPIRVType *TheType, SPIRVValue *Operand, SPIRVBasicBlock *BB) { return addInstruction(new SPIRVCopyObject(TheType, getId(), Operand, BB), BB); } SPIRVInstruction *SPIRVModuleImpl::addCopyMemoryInst( SPIRVValue *TheTarget, SPIRVValue *TheSource, const std::vector &TheMemoryAccess, SPIRVBasicBlock *BB) { return addInstruction( new SPIRVCopyMemory(TheTarget, TheSource, TheMemoryAccess, BB), BB); } SPIRVInstruction *SPIRVModuleImpl::addCopyMemorySizedInst( SPIRVValue *TheTarget, SPIRVValue *TheSource, SPIRVValue *TheSize, const std::vector &TheMemoryAccess, SPIRVBasicBlock *BB) { return addInstruction(new SPIRVCopyMemorySized(TheTarget, TheSource, TheSize, TheMemoryAccess, BB), BB); } SPIRVInstruction *SPIRVModuleImpl::addFPGARegINTELInst(SPIRVType *Type, SPIRVValue *V, SPIRVBasicBlock *BB) { return addInstruction( SPIRVInstTemplateBase::create(OpFPGARegINTEL, Type, getId(), getVec(V->getId()), BB, this), BB); } SPIRVInstruction *SPIRVModuleImpl::addSampledImageInst(SPIRVType *ResultTy, SPIRVValue *Image, SPIRVValue *Sampler, SPIRVBasicBlock *BB) { return addInstruction(SPIRVInstTemplateBase::create( OpSampledImage, ResultTy, getId(), getVec(Image->getId(), Sampler->getId()), BB, this), BB); } SPIRVInstruction *SPIRVModuleImpl::addVariable( SPIRVType *Type, bool IsConstant, SPIRVLinkageTypeKind LinkageType, SPIRVValue *Initializer, const std::string &Name, SPIRVStorageClassKind StorageClass, SPIRVBasicBlock *BB) { SPIRVVariable *Variable = new SPIRVVariable(Type, getId(), Initializer, Name, StorageClass, BB, this); if (BB) return addInstruction(Variable, BB); add(Variable); if (LinkageType != LinkageTypeInternal) Variable->setLinkageType(LinkageType); Variable->setIsConstant(IsConstant); return Variable; } template spv_ostream &operator<<(spv_ostream &O, const std::vector &V) { for (auto &I : V) O << *I; return O; } template spv_ostream &operator<<(spv_ostream &O, const std::multiset &V) { for (auto &I : V) O << *I; return O; } // To satisfy SPIR-V spec requirement: // "All operands must be declared before being used", // we do DFS based topological sort // https://en.wikipedia.org/wiki/Topological_sorting#Depth-first_search class TopologicalSort { enum DFSState : char { Unvisited, Discovered, Visited }; typedef std::vector SPIRVTypeVec; typedef std::vector SPIRVConstantVector; typedef std::vector SPIRVVariableVec; typedef std::vector SPIRVConstAndVarVec; typedef std::vector SPIRVForwardPointerVec; typedef std::function IdComp; typedef std::map EntryStateMapTy; SPIRVTypeVec TypeIntVec; SPIRVConstantVector ConstIntVec; SPIRVTypeVec TypeVec; SPIRVConstAndVarVec ConstAndVarVec; const SPIRVForwardPointerVec &ForwardPointerVec; EntryStateMapTy EntryStateMap; friend spv_ostream &operator<<(spv_ostream &O, const TopologicalSort &S); // This method implements recursive depth-first search among all Entries in // EntryStateMap. Traversing entries and adding them to corresponding // container after visiting all dependent entries(post-order traversal) // guarantees that the entry's operands will appear in the container before // the entry itslef. void visit(SPIRVEntry *E) { DFSState &State = EntryStateMap[E]; assert(State != Discovered && "Cyclic dependency detected"); if (State == Visited) return; State = Discovered; for (SPIRVEntry *Op : E->getNonLiteralOperands()) { auto Comp = [&Op](SPIRVTypeForwardPointer *FwdPtr) { return FwdPtr->getPointer() == Op; }; // Skip forward referenced pointers if (Op->getOpCode() == OpTypePointer && find_if(ForwardPointerVec.begin(), ForwardPointerVec.end(), Comp) != ForwardPointerVec.end()) continue; visit(Op); } State = Visited; Op OC = E->getOpCode(); if (OC == OpTypeInt) TypeIntVec.push_back(static_cast(E)); else if (isConstantOpCode(OC)) { SPIRVConstant *C = static_cast(E); if (C->getType()->isTypeInt()) ConstIntVec.push_back(C); else ConstAndVarVec.push_back(E); } else if (isTypeOpCode(OC)) TypeVec.push_back(static_cast(E)); else ConstAndVarVec.push_back(E); } public: TopologicalSort(const SPIRVTypeVec &TypeVec, const SPIRVConstantVector &ConstVec, const SPIRVVariableVec &VariableVec, const SPIRVForwardPointerVec &ForwardPointerVec) : ForwardPointerVec(ForwardPointerVec), EntryStateMap([](SPIRVEntry *A, SPIRVEntry *B) -> bool { return A->getId() < B->getId(); }) { // Collect entries for sorting for (auto *T : TypeVec) EntryStateMap[T] = DFSState::Unvisited; for (auto *C : ConstVec) EntryStateMap[C] = DFSState::Unvisited; for (auto *V : VariableVec) EntryStateMap[V] = DFSState::Unvisited; // Run topoligical sort for (auto ES : EntryStateMap) visit(ES.first); } }; spv_ostream &operator<<(spv_ostream &O, const TopologicalSort &S) { O << S.TypeIntVec << S.ConstIntVec << S.TypeVec << S.ConstAndVarVec; return O; } spv_ostream &operator<<(spv_ostream &O, SPIRVModule &M) { SPIRVModuleImpl &MI = *static_cast(&M); // Start tracking of the current line with no line MI.CurrentLine.reset(); SPIRVEncoder Encoder(O); Encoder << MagicNumber << MI.SPIRVVersion << (((SPIRVWord)MI.GeneratorId << 16) | MI.GeneratorVer) << MI.NextId /* Bound for Id */ << MI.InstSchema; O << SPIRVNL(); for (auto &I : MI.CapMap) O << *I.second; for (auto &I : M.getExtension()) { assert(!I.empty() && "Invalid extension"); O << SPIRVExtension(&M, I); } for (auto &I : MI.IdToInstSetMap) O << SPIRVExtInstImport(&M, I.first, SPIRVBuiltinSetNameMap::map(I.second)); O << SPIRVMemoryModel(&M); for (auto &I : MI.EntryPointVec) for (auto &II : I.second) O << SPIRVEntryPoint(&M, I.first, II, M.get(II)->getName(), M.get(II)->getVariables()); for (auto &I : MI.EntryPointVec) for (auto &II : I.second) MI.get(II)->encodeExecutionModes(O); O << MI.StringVec; for (auto &I : M.getSourceExtension()) { assert(!I.empty() && "Invalid source extension"); O << SPIRVSourceExtension(&M, I); } O << SPIRVSource(&M); for (auto &I : MI.NamedId) { // Don't output name for entry point since it is redundant bool IsEntryPoint = false; for (auto &EPS : MI.EntryPointSet) if (EPS.second.count(I)) { IsEntryPoint = true; break; } if (!IsEntryPoint) M.getEntry(I)->encodeName(O); } O << MI.MemberNameVec << MI.DecGroupVec << MI.DecorateSet << MI.GroupDecVec << MI.ForwardPointerVec << TopologicalSort(MI.TypeVec, MI.ConstVec, MI.VariableVec, MI.ForwardPointerVec); if (M.isAllowedToUseExtension(ExtensionID::SPV_INTEL_inline_assembly)) { O << SPIRVNL() << MI.AsmTargetVec << MI.AsmVec; } O << SPIRVNL() << MI.DebugInstVec << SPIRVNL() << MI.FuncVec; return O; } template void SPIRVModuleImpl::addTo(std::vector &V, SPIRVEntry *E) { V.push_back(static_cast(E)); } // The first decoration group includes all the previously defined decorates. // The second decoration group includes all the decorates defined between the // first and second decoration group. So long so forth. SPIRVDecorationGroup *SPIRVModuleImpl::addDecorationGroup() { return addDecorationGroup(new SPIRVDecorationGroup(this, getId())); } SPIRVDecorationGroup * SPIRVModuleImpl::addDecorationGroup(SPIRVDecorationGroup *Group) { add(Group); Group->takeDecorates(DecorateSet); DecGroupVec.push_back(Group); SPIRVDBG(spvdbgs() << "[addDecorationGroup] {" << *Group << "}\n"; spvdbgs() << " Remaining DecorateSet: {" << DecorateSet << "}\n"); assert(DecorateSet.empty()); return Group; } SPIRVGroupDecorateGeneric * SPIRVModuleImpl::addGroupDecorateGeneric(SPIRVGroupDecorateGeneric *GDec) { add(GDec); GDec->decorateTargets(); GroupDecVec.push_back(GDec); return GDec; } SPIRVGroupDecorate * SPIRVModuleImpl::addGroupDecorate(SPIRVDecorationGroup *Group, const std::vector &Targets) { auto GD = new SPIRVGroupDecorate(Group, getIds(Targets)); addGroupDecorateGeneric(GD); return GD; } SPIRVGroupMemberDecorate *SPIRVModuleImpl::addGroupMemberDecorate( SPIRVDecorationGroup *Group, const std::vector &Targets) { auto GMD = new SPIRVGroupMemberDecorate(Group, getIds(Targets)); addGroupDecorateGeneric(GMD); return GMD; } SPIRVString *SPIRVModuleImpl::getString(const std::string &Str) { auto Loc = StrMap.find(Str); if (Loc != StrMap.end()) return Loc->second; auto S = add(new SPIRVString(this, getId(), Str)); StrMap[Str] = S; return S; } SPIRVMemberName *SPIRVModuleImpl::addMemberName(SPIRVTypeStruct *ST, SPIRVWord MemberNumber, const std::string &Name) { return add(new SPIRVMemberName(ST, MemberNumber, Name)); } void SPIRVModuleImpl::addUnknownStructField(SPIRVTypeStruct *Struct, unsigned I, SPIRVId ID) { UnknownStructFieldMap[Struct].push_back(std::make_pair(I, ID)); } static std::string to_string(uint32_t Version) { std::string Res; switch (Version) { case static_cast(VersionNumber::SPIRV_1_0): Res = "1.0"; break; case static_cast(VersionNumber::SPIRV_1_1): Res = "1.1"; break; default: Res = "unknown"; } Res += " (" + std::to_string(Version) + ")"; return Res; } static std::string to_string(VersionNumber Version) { return to_string(static_cast(Version)); } std::istream &operator>>(std::istream &I, SPIRVModule &M) { SPIRVDecoder Decoder(I, M); SPIRVModuleImpl &MI = *static_cast(&M); // Disable automatic capability filling. MI.setAutoAddCapability(false); MI.setAutoAddExtensions(false); SPIRVWord Magic; Decoder >> Magic; if (!M.getErrorLog().checkError(Magic == MagicNumber, SPIRVEC_InvalidModule, "invalid magic number")) { M.setInvalid(); return I; } Decoder >> MI.SPIRVVersion; bool SPIRVVersionIsKnown = static_cast(VersionNumber::MinimumVersion) <= MI.SPIRVVersion && MI.SPIRVVersion <= static_cast(VersionNumber::MaximumVersion); if (!M.getErrorLog().checkError( SPIRVVersionIsKnown, SPIRVEC_InvalidModule, "unsupported SPIR-V version number '" + to_string(MI.SPIRVVersion) + "'. Range of supported/known SPIR-V " "versions is " + to_string(VersionNumber::MinimumVersion) + " - " + to_string(VersionNumber::MaximumVersion))) { M.setInvalid(); return I; } bool SPIRVVersionIsAllowed = M.isAllowedToUseVersion(MI.SPIRVVersion); if (!M.getErrorLog().checkError( SPIRVVersionIsAllowed, SPIRVEC_InvalidModule, "incorrect SPIR-V version number " + to_string(MI.SPIRVVersion) + " - it conflicts with --spirv-max-version which is set to " + to_string(M.getMaximumAllowedSPIRVVersion()))) { M.setInvalid(); return I; } SPIRVWord Generator = 0; Decoder >> Generator; MI.GeneratorId = Generator >> 16; MI.GeneratorVer = Generator & 0xFFFF; // Bound for Id Decoder >> MI.NextId; Decoder >> MI.InstSchema; if (!M.getErrorLog().checkError(MI.InstSchema == SPIRVISCH_Default, SPIRVEC_InvalidModule, "unsupported instruction schema")) { M.setInvalid(); return I; } while (Decoder.getWordCountAndOpCode() && M.isModuleValid()) { SPIRVEntry *Entry = Decoder.getEntry(); if (Entry != nullptr) M.add(Entry); } MI.optimizeDecorates(); MI.resolveUnknownStructFields(); MI.createForwardPointers(); return I; } SPIRVModule *SPIRVModule::createSPIRVModule() { return new SPIRVModuleImpl(); } SPIRVModule *SPIRVModule::createSPIRVModule(const SPIRV::TranslatorOpts &Opts) { return new SPIRVModuleImpl(Opts); } SPIRVValue *SPIRVModuleImpl::getValue(SPIRVId TheId) const { return get(TheId); } SPIRVType *SPIRVModuleImpl::getValueType(SPIRVId TheId) const { return get(TheId)->getType(); } std::vector SPIRVModuleImpl::getValues(const std::vector &IdVec) const { std::vector ValueVec; for (auto I : IdVec) ValueVec.push_back(getValue(I)); return ValueVec; } std::vector SPIRVModuleImpl::getValueTypes(const std::vector &IdVec) const { std::vector TypeVec; for (auto I : IdVec) TypeVec.push_back(getValue(I)->getType()); return TypeVec; } std::vector SPIRVModuleImpl::getIds(const std::vector &ValueVec) const { std::vector IdVec; for (auto I : ValueVec) IdVec.push_back(I->getId()); return IdVec; } std::vector SPIRVModuleImpl::getIds(const std::vector &ValueVec) const { std::vector IdVec; for (auto I : ValueVec) IdVec.push_back(I->getId()); return IdVec; } SPIRVInstTemplateBase * SPIRVModuleImpl::addInstTemplate(Op OC, SPIRVBasicBlock *BB, SPIRVType *Ty) { assert(!Ty || !Ty->isTypeVoid()); SPIRVId Id = Ty ? getId() : SPIRVID_INVALID; auto Ins = SPIRVInstTemplateBase::create(OC, Ty, Id, BB, this); BB->addInstruction(Ins); return Ins; } SPIRVInstTemplateBase * SPIRVModuleImpl::addInstTemplate(Op OC, const std::vector &Ops, SPIRVBasicBlock *BB, SPIRVType *Ty) { assert(!Ty || !Ty->isTypeVoid()); SPIRVId Id = Ty ? getId() : SPIRVID_INVALID; auto Ins = SPIRVInstTemplateBase::create(OC, Ty, Id, Ops, BB, this); BB->addInstruction(Ins); return Ins; } SPIRVId SPIRVModuleImpl::getExtInstSetId(SPIRVExtInstSetKind Kind) const { assert(Kind < SPIRVEIS_Count && "Unknown extended instruction set!"); auto Res = ExtInstSetIds.find(Kind); assert(Res != ExtInstSetIds.end() && "extended instruction set not found!"); return Res->second; } bool isSpirvBinary(const std::string &Img) { if (Img.size() < sizeof(unsigned)) return false; auto Magic = reinterpret_cast(Img.data()); return *Magic == MagicNumber; } #ifdef _SPIRV_SUPPORT_TEXT_FMT bool convertSpirv(std::istream &IS, std::ostream &OS, std::string &ErrMsg, bool FromText, bool ToText) { auto SaveOpt = SPIRVUseTextFormat; SPIRVUseTextFormat = FromText; // Conversion from/to SPIR-V text representation is a side feature of the // translator which is mostly intended for debug usage. So, this step cannot // be customized to enable/disable particular extensions or restrict/allow // particular SPIR-V versions: all known SPIR-V versions are allowed, all // known SPIR-V extensions are enabled during this conversion SPIRV::TranslatorOpts DefaultOpts; DefaultOpts.enableAllExtensions(); SPIRVModuleImpl M(DefaultOpts); IS >> M; if (M.getError(ErrMsg) != SPIRVEC_Success) { SPIRVUseTextFormat = SaveOpt; return false; } SPIRVUseTextFormat = ToText; OS << M; if (M.getError(ErrMsg) != SPIRVEC_Success) { SPIRVUseTextFormat = SaveOpt; return false; } SPIRVUseTextFormat = SaveOpt; return true; } bool isSpirvText(const std::string &Img) { std::istringstream SS(Img); unsigned Magic = 0; SS >> Magic; if (SS.bad()) return false; return Magic == MagicNumber; } bool convertSpirv(std::string &Input, std::string &Out, std::string &ErrMsg, bool ToText) { auto FromText = isSpirvText(Input); if (ToText == FromText) { Out = Input; return true; } std::istringstream IS(Input); std::ostringstream OS; if (!convertSpirv(IS, OS, ErrMsg, FromText, ToText)) return false; Out = OS.str(); return true; } #endif // _SPIRV_SUPPORT_TEXT_FMT } // namespace SPIRV SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVModule.h000066400000000000000000000606521363521741200226740ustar00rootroot00000000000000//===- SPIRVModule.h - Class to represent a SPIR-V module -------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines Module class for SPIR-V. /// //===----------------------------------------------------------------------===// #ifndef SPIRV_LIBSPIRV_SPIRVMODULE_H #define SPIRV_LIBSPIRV_SPIRVMODULE_H #include "LLVMSPIRVOpts.h" #include "SPIRVEntry.h" #include #include #include #include #include #include namespace SPIRV { template class SPIRVConstantBase; using SPIRVConstant = SPIRVConstantBase; class SPIRVBasicBlock; class SPIRVEntry; class SPIRVFunction; class SPIRVInstruction; class SPIRVType; class SPIRVTypeArray; class SPIRVTypeBool; class SPIRVTypeFloat; class SPIRVTypeFunction; class SPIRVTypeInt; class SPIRVTypeOpaque; class SPIRVTypePointer; class SPIRVTypeImage; class SPIRVTypeSampler; class SPIRVTypeSampledImage; class SPIRVTypePipeStorage; class SPIRVTypeStruct; class SPIRVTypeVector; class SPIRVTypeVoid; class SPIRVTypeDeviceEvent; class SPIRVTypeQueue; class SPIRVTypePipe; class SPIRVTypeVmeImageINTEL; class SPIRVValue; class SPIRVVariable; class SPIRVDecorateGeneric; class SPIRVDecorationGroup; class SPIRVGroupDecorate; class SPIRVGroupMemberDecorate; class SPIRVGroupDecorateGeneric; class SPIRVInstTemplateBase; class SPIRVAsmTargetINTEL; class SPIRVAsmINTEL; class SPIRVAsmCallINTEL; typedef SPIRVBasicBlock SPIRVLabel; struct SPIRVTypeImageDescriptor; class SPIRVModule { public: typedef std::map SPIRVCapMap; static SPIRVModule *createSPIRVModule(); static SPIRVModule *createSPIRVModule(const SPIRV::TranslatorOpts &); SPIRVModule(); virtual ~SPIRVModule(); // Object query functions virtual bool exist(SPIRVId) const = 0; virtual bool exist(SPIRVId, SPIRVEntry **) const = 0; template T *get(SPIRVId Id) const { return static_cast(getEntry(Id)); } virtual SPIRVEntry *getEntry(SPIRVId) const = 0; virtual bool hasDebugInfo() const = 0; // Error handling functions virtual SPIRVErrorLog &getErrorLog() = 0; virtual SPIRVErrorCode getError(std::string &) = 0; // Check if extension is allowed, and set ErrCode and DetailedMsg if not. // Returns true if no error. virtual bool checkExtension(ExtensionID, SPIRVErrorCode, const std::string &) = 0; void setInvalid() { IsValid = false; } bool isModuleValid() { return IsValid; } // Module query functions virtual SPIRVAddressingModelKind getAddressingModel() = 0; virtual const SPIRVCapMap &getCapability() const = 0; virtual bool hasCapability(SPIRVCapabilityKind) const = 0; virtual SPIRVExtInstSetKind getBuiltinSet(SPIRVId) const = 0; virtual SPIRVFunction *getEntryPoint(SPIRVExecutionModelKind, unsigned) const = 0; virtual std::set &getExtension() = 0; virtual SPIRVFunction *getFunction(unsigned) const = 0; virtual SPIRVVariable *getVariable(unsigned) const = 0; virtual SPIRVMemoryModelKind getMemoryModel() const = 0; virtual unsigned getNumFunctions() const = 0; virtual unsigned getNumEntryPoints(SPIRVExecutionModelKind) const = 0; virtual unsigned getNumVariables() const = 0; virtual SourceLanguage getSourceLanguage(SPIRVWord *) const = 0; virtual std::set &getSourceExtension() = 0; virtual SPIRVValue *getValue(SPIRVId TheId) const = 0; virtual std::vector getValues(const std::vector &) const = 0; virtual std::vector getIds(const std::vector &) const = 0; virtual std::vector getIds(const std::vector &) const = 0; virtual SPIRVType *getValueType(SPIRVId TheId) const = 0; virtual std::vector getValueTypes(const std::vector &) const = 0; virtual SPIRVConstant *getLiteralAsConstant(unsigned Literal) = 0; virtual bool isEntryPoint(SPIRVExecutionModelKind, SPIRVId) const = 0; virtual unsigned short getGeneratorId() const = 0; virtual unsigned short getGeneratorVer() const = 0; virtual SPIRVWord getSPIRVVersion() const = 0; virtual const std::vector &getDebugInstVec() const = 0; virtual const std::vector &getStringVec() const = 0; // Module changing functions virtual bool importBuiltinSet(const std::string &, SPIRVId *) = 0; virtual bool importBuiltinSetWithId(const std::string &, SPIRVId) = 0; virtual void setAddressingModel(SPIRVAddressingModelKind) = 0; virtual void setAlignment(SPIRVValue *, SPIRVWord) = 0; virtual void setMemoryModel(SPIRVMemoryModelKind) = 0; virtual void setName(SPIRVEntry *, const std::string &) = 0; virtual void setSourceLanguage(SourceLanguage, SPIRVWord) = 0; virtual void optimizeDecorates() = 0; virtual void setAutoAddCapability(bool E) { AutoAddCapability = E; } virtual void setValidateCapability(bool E) { ValidateCapability = E; } virtual void setAutoAddExtensions(bool E) { AutoAddExtensions = E; } virtual void setGeneratorId(unsigned short) = 0; virtual void setGeneratorVer(unsigned short) = 0; virtual void resolveUnknownStructFields() = 0; virtual void setSPIRVVersion(SPIRVWord) = 0; void setMinSPIRVVersion(SPIRVWord Ver) { setSPIRVVersion(std::max(Ver, getSPIRVVersion())); } // Object creation functions template T *add(T *Entry) { addEntry(Entry); return Entry; } virtual SPIRVEntry *addEntry(SPIRVEntry *) = 0; virtual SPIRVBasicBlock *addBasicBlock(SPIRVFunction *, SPIRVId Id = SPIRVID_INVALID) = 0; virtual SPIRVString *getString(const std::string &Str) = 0; virtual SPIRVMemberName *addMemberName(SPIRVTypeStruct *ST, SPIRVWord MemberNumber, const std::string &Name) = 0; virtual void addUnknownStructField(SPIRVTypeStruct *, unsigned Idx, SPIRVId Id) = 0; virtual void addLine(SPIRVEntry *E, SPIRVId FileNameId, SPIRVWord Line, SPIRVWord Column) = 0; virtual const std::shared_ptr &getCurrentLine() const = 0; virtual void setCurrentLine(const std::shared_ptr &) = 0; virtual const SPIRVDecorateGeneric *addDecorate(SPIRVDecorateGeneric *) = 0; virtual SPIRVDecorationGroup *addDecorationGroup() = 0; virtual SPIRVDecorationGroup * addDecorationGroup(SPIRVDecorationGroup *Group) = 0; virtual SPIRVGroupDecorate * addGroupDecorate(SPIRVDecorationGroup *Group, const std::vector &Targets) = 0; virtual SPIRVGroupMemberDecorate * addGroupMemberDecorate(SPIRVDecorationGroup *Group, const std::vector &Targets) = 0; virtual SPIRVGroupDecorateGeneric * addGroupDecorateGeneric(SPIRVGroupDecorateGeneric *GDec) = 0; virtual void addEntryPoint(SPIRVExecutionModelKind, SPIRVId) = 0; virtual SPIRVForward *addForward(SPIRVType *Ty) = 0; virtual SPIRVForward *addForward(SPIRVId, SPIRVType *Ty) = 0; virtual SPIRVFunction *addFunction(SPIRVFunction *) = 0; virtual SPIRVFunction *addFunction(SPIRVTypeFunction *, SPIRVId Id = SPIRVID_INVALID) = 0; virtual SPIRVEntry *replaceForward(SPIRVForward *, SPIRVEntry *) = 0; virtual void eraseInstruction(SPIRVInstruction *, SPIRVBasicBlock *) = 0; // Type creation functions virtual SPIRVTypeArray *addArrayType(SPIRVType *, SPIRVConstant *) = 0; virtual SPIRVTypeBool *addBoolType() = 0; virtual SPIRVTypeFloat *addFloatType(unsigned) = 0; virtual SPIRVTypeFunction * addFunctionType(SPIRVType *, const std::vector &) = 0; virtual SPIRVTypeImage *addImageType(SPIRVType *, const SPIRVTypeImageDescriptor &) = 0; virtual SPIRVTypeImage *addImageType(SPIRVType *, const SPIRVTypeImageDescriptor &, SPIRVAccessQualifierKind) = 0; virtual SPIRVTypeSampler *addSamplerType() = 0; virtual SPIRVTypePipeStorage *addPipeStorageType() = 0; virtual SPIRVTypeSampledImage *addSampledImageType(SPIRVTypeImage *T) = 0; virtual SPIRVTypeInt *addIntegerType(unsigned) = 0; virtual SPIRVTypeOpaque *addOpaqueType(const std::string &) = 0; virtual SPIRVTypePointer *addPointerType(SPIRVStorageClassKind, SPIRVType *) = 0; virtual SPIRVTypeStruct *openStructType(unsigned, const std::string &) = 0; virtual void closeStructType(SPIRVTypeStruct *, bool) = 0; virtual SPIRVTypeVector *addVectorType(SPIRVType *, SPIRVWord) = 0; virtual SPIRVTypeVoid *addVoidType() = 0; virtual SPIRVType *addOpaqueGenericType(Op) = 0; virtual SPIRVTypeDeviceEvent *addDeviceEventType() = 0; virtual SPIRVTypeQueue *addQueueType() = 0; virtual SPIRVTypePipe *addPipeType() = 0; virtual SPIRVType *addSubgroupAvcINTELType(Op) = 0; virtual SPIRVTypeVmeImageINTEL *addVmeImageINTELType(SPIRVTypeImage *) = 0; virtual void createForwardPointers() = 0; // Constants creation functions virtual SPIRVValue * addCompositeConstant(SPIRVType *, const std::vector &) = 0; virtual SPIRVValue *addConstant(SPIRVValue *) = 0; virtual SPIRVValue *addConstant(SPIRVType *, uint64_t) = 0; virtual SPIRVValue *addDoubleConstant(SPIRVTypeFloat *, double) = 0; virtual SPIRVValue *addFloatConstant(SPIRVTypeFloat *, float) = 0; virtual SPIRVValue *addIntegerConstant(SPIRVTypeInt *, uint64_t) = 0; virtual SPIRVValue *addNullConstant(SPIRVType *) = 0; virtual SPIRVValue *addUndef(SPIRVType *TheType) = 0; virtual SPIRVValue *addSamplerConstant(SPIRVType *TheType, SPIRVWord AddrMode, SPIRVWord ParametricMode, SPIRVWord FilterMode) = 0; virtual SPIRVValue *addPipeStorageConstant(SPIRVType *TheType, SPIRVWord PacketSize, SPIRVWord PacketAlign, SPIRVWord Capacity) = 0; // Instruction creation functions virtual SPIRVInstruction *addPtrAccessChainInst(SPIRVType *, SPIRVValue *, std::vector, SPIRVBasicBlock *, bool) = 0; virtual SPIRVInstruction * addAsyncGroupCopy(SPIRVValue *Scope, SPIRVValue *Dest, SPIRVValue *Src, SPIRVValue *NumElems, SPIRVValue *Stride, SPIRVValue *Event, SPIRVBasicBlock *BB) = 0; virtual SPIRVInstruction *addBinaryInst(Op, SPIRVType *, SPIRVValue *, SPIRVValue *, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addBranchConditionalInst(SPIRVValue *, SPIRVLabel *, SPIRVLabel *, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addBranchInst(SPIRVLabel *, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addExtInst(SPIRVType *, SPIRVWord, SPIRVWord, const std::vector &, SPIRVBasicBlock *, SPIRVInstruction * = nullptr) = 0; virtual SPIRVInstruction *addExtInst(SPIRVType *, SPIRVWord, SPIRVWord, const std::vector &, SPIRVBasicBlock *, SPIRVInstruction * = nullptr) = 0; virtual SPIRVEntry *addDebugInfo(SPIRVWord, SPIRVType *, const std::vector &) = 0; virtual void addCapability(SPIRVCapabilityKind) = 0; template void addCapabilities(const T &Caps) { for (auto I : Caps) addCapability(I); } virtual void addExtension(ExtensionID) = 0; /// Used by SPIRV entries to add required capability internally. /// Should not be used by users directly. virtual void addCapabilityInternal(SPIRVCapabilityKind) = 0; virtual SPIRVInstruction *addCallInst(SPIRVFunction *, const std::vector &, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addIndirectCallInst(SPIRVValue *, SPIRVType *, const std::vector &, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addFunctionPointerINTELInst(SPIRVType *, SPIRVFunction *, SPIRVBasicBlock *) = 0; virtual SPIRVEntry *getOrAddAsmTargetINTEL(const std::string &) = 0; virtual SPIRVValue *addAsmINTEL(SPIRVTypeFunction *, SPIRVAsmTargetINTEL *, const std::string &, const std::string &) = 0; virtual SPIRVInstruction *addAsmCallINTELInst(SPIRVAsmINTEL *, const std::vector &, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction * addCompositeConstructInst(SPIRVType *, const std::vector &, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction * addCompositeExtractInst(SPIRVType *, SPIRVValue *, const std::vector &, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction * addCompositeInsertInst(SPIRVValue *, SPIRVValue *, const std::vector &, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addCopyObjectInst(SPIRVType *, SPIRVValue *, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addCopyMemoryInst(SPIRVValue *, SPIRVValue *, const std::vector &, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction * addCopyMemorySizedInst(SPIRVValue *, SPIRVValue *, SPIRVValue *, const std::vector &, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addCmpInst(Op, SPIRVType *, SPIRVValue *, SPIRVValue *, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addControlBarrierInst(SPIRVValue *ExecKind, SPIRVValue *MemKind, SPIRVValue *MemSema, SPIRVBasicBlock *BB) = 0; virtual SPIRVInstruction *addGroupInst(Op OpCode, SPIRVType *Type, Scope Scope, const std::vector &Ops, SPIRVBasicBlock *BB) = 0; virtual SPIRVInstTemplateBase *addInstTemplate(Op OC, SPIRVBasicBlock *BB, SPIRVType *Ty) = 0; virtual SPIRVInstTemplateBase * addInstTemplate(Op OC, const std::vector &Ops, SPIRVBasicBlock *BB, SPIRVType *Ty) = 0; virtual SPIRVInstruction *addLoadInst(SPIRVValue *, const std::vector &, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addLifetimeInst(Op OC, SPIRVValue *Object, SPIRVWord Size, SPIRVBasicBlock *BB) = 0; virtual SPIRVInstruction *addMemoryBarrierInst(Scope ScopeKind, SPIRVWord MemFlag, SPIRVBasicBlock *BB) = 0; virtual SPIRVInstruction *addPhiInst(SPIRVType *, std::vector, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addUnreachableInst(SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addReturnInst(SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addReturnValueInst(SPIRVValue *, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addSelectInst(SPIRVValue *, SPIRVValue *, SPIRVValue *, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addSelectionMergeInst(SPIRVId MergeBlock, SPIRVWord SelectionControl, SPIRVBasicBlock *BB) = 0; virtual SPIRVInstruction *addLoopMergeInst( SPIRVId MergeBlock, SPIRVId ContinueTarget, SPIRVWord LoopControl, std::vector LoopControlParameters, SPIRVBasicBlock *BB) = 0; virtual SPIRVInstruction * addLoopControlINTELInst(SPIRVWord LoopControl, std::vector LoopControlParameters, SPIRVBasicBlock *BB) = 0; virtual SPIRVInstruction *addStoreInst(SPIRVValue *, SPIRVValue *, const std::vector &, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addSwitchInst( SPIRVValue *, SPIRVBasicBlock *, const std::vector, SPIRVBasicBlock *>> &, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addFModInst(SPIRVType *TheType, SPIRVId TheDividend, SPIRVId TheDivisor, SPIRVBasicBlock *BB) = 0; virtual SPIRVInstruction *addVectorTimesScalarInst(SPIRVType *TheType, SPIRVId TheVector, SPIRVId TheScalar, SPIRVBasicBlock *BB) = 0; virtual SPIRVInstruction *addVectorTimesMatrixInst(SPIRVType *TheType, SPIRVId TheVector, SPIRVId TheMatrix, SPIRVBasicBlock *BB) = 0; virtual SPIRVInstruction *addMatrixTimesScalarInst(SPIRVType *TheType, SPIRVId TheMatrix, SPIRVId TheScalar, SPIRVBasicBlock *BB) = 0; virtual SPIRVInstruction *addMatrixTimesVectorInst(SPIRVType *TheType, SPIRVId TheMatrix, SPIRVId TheVector, SPIRVBasicBlock *BB) = 0; virtual SPIRVInstruction *addMatrixTimesMatrixInst(SPIRVType *TheType, SPIRVId M1, SPIRVId M2, SPIRVBasicBlock *BB) = 0; virtual SPIRVInstruction *addTransposeInst(SPIRVType *TheType, SPIRVId TheMatrix, SPIRVBasicBlock *BB) = 0; virtual SPIRVInstruction *addUnaryInst(Op, SPIRVType *, SPIRVValue *, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addVariable(SPIRVType *, bool, SPIRVLinkageTypeKind, SPIRVValue *, const std::string &, SPIRVStorageClassKind, SPIRVBasicBlock *) = 0; virtual SPIRVValue * addVectorShuffleInst(SPIRVType *Type, SPIRVValue *Vec1, SPIRVValue *Vec2, const std::vector &Components, SPIRVBasicBlock *BB) = 0; virtual SPIRVInstruction *addVectorExtractDynamicInst(SPIRVValue *, SPIRVValue *, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addVectorInsertDynamicInst(SPIRVValue *, SPIRVValue *, SPIRVValue *, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addFPGARegINTELInst(SPIRVType *, SPIRVValue *, SPIRVBasicBlock *) = 0; virtual SPIRVInstruction *addSampledImageInst(SPIRVType *, SPIRVValue *, SPIRVValue *, SPIRVBasicBlock *) = 0; virtual SPIRVId getExtInstSetId(SPIRVExtInstSetKind Kind) const = 0; virtual bool isAllowedToUseVersion(SPIRV::VersionNumber RequestedVersion) const final { return TranslationOpts.isAllowedToUseVersion(RequestedVersion); } virtual bool isAllowedToUseVersion(SPIRVWord RequestedVersion) const final { return TranslationOpts.isAllowedToUseVersion( static_cast(RequestedVersion)); } virtual SPIRV::VersionNumber getMaximumAllowedSPIRVVersion() const final { return TranslationOpts.getMaxVersion(); } virtual bool isAllowedToUseExtension(ExtensionID RequestedExtension) const final { return TranslationOpts.isAllowedToUseExtension(RequestedExtension); } virtual bool isAllowedToUseExtensions(const SPIRVExtSet &RequestedExtensions) const final { for (const auto &Ext : RequestedExtensions) { if (!TranslationOpts.isAllowedToUseExtension(Ext)) return false; } return true; } virtual bool isGenArgNameMDEnabled() const final { return TranslationOpts.isGenArgNameMDEnabled(); } bool getSpecializationConstant(SPIRVWord SpecId, uint64_t &ConstValue) { return TranslationOpts.getSpecializationConstant(SpecId, ConstValue); } // I/O functions friend spv_ostream &operator<<(spv_ostream &O, SPIRVModule &M); friend std::istream &operator>>(std::istream &I, SPIRVModule &M); protected: bool AutoAddCapability; bool ValidateCapability; bool AutoAddExtensions = true; SPIRV::TranslatorOpts TranslationOpts; private: bool IsValid; }; #ifdef _SPIRV_SUPPORT_TEXT_FMT /// Convert SPIR-V between binary and internel text formats. /// This function is not thread safe and should not be used in multi-thread /// applications unless guarded by a critical section. bool ConvertSPIRV(std::istream &IS, spv_ostream &OS, std::string &ErrMsg, bool FromText, bool ToText); /// Convert SPIR-V between binary and internel text formats. /// This function is not thread safe and should not be used in multi-thread /// applications unless guarded by a critical section. bool ConvertSPIRV(std::string &Input, std::string &Out, std::string &ErrMsg, bool ToText); #endif } // namespace SPIRV #endif // SPIRV_LIBSPIRV_SPIRVMODULE_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h000066400000000000000000000537461363521741200236200ustar00rootroot00000000000000//===- SPIRVNameMapEnum.h - SPIR-V NameMap enums ----------------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines SPIR-V NameMap enums. /// //===----------------------------------------------------------------------===// // WARNING: // // This file has been generated using `tools/spirv-tool/gen_spirv.bash` and // should not be modified manually. If the file needs to be updated, edit the // script and any other source file instead, before re-generating this file. //===----------------------------------------------------------------------===// #ifndef SPIRV_LIBSPIRV_SPIRVNAMEMAPENUM_H #define SPIRV_LIBSPIRV_SPIRVNAMEMAPENUM_H #include "SPIRVEnum.h" #include "spirv.hpp" using namespace spv; namespace SPIRV { template <> inline void SPIRVMap::init() { add(SourceLanguageUnknown, "Unknown"); add(SourceLanguageESSL, "ESSL"); add(SourceLanguageGLSL, "GLSL"); add(SourceLanguageOpenCL_C, "OpenCL_C"); add(SourceLanguageOpenCL_CPP, "OpenCL_CPP"); } SPIRV_DEF_NAMEMAP(SourceLanguage, SPIRVSourceLanguageNameMap) template <> inline void SPIRVMap::init() { add(ExecutionModelVertex, "Vertex"); add(ExecutionModelTessellationControl, "TessellationControl"); add(ExecutionModelTessellationEvaluation, "TessellationEvaluation"); add(ExecutionModelGeometry, "Geometry"); add(ExecutionModelFragment, "Fragment"); add(ExecutionModelGLCompute, "GLCompute"); add(ExecutionModelKernel, "Kernel"); } SPIRV_DEF_NAMEMAP(ExecutionModel, SPIRVExecutionModelNameMap) template <> inline void SPIRVMap::init() { add(AddressingModelLogical, "Logical"); add(AddressingModelPhysical32, "Physical32"); add(AddressingModelPhysical64, "Physical64"); } SPIRV_DEF_NAMEMAP(AddressingModel, SPIRVAddressingModelNameMap) template <> inline void SPIRVMap::init() { add(MemoryModelSimple, "Simple"); add(MemoryModelGLSL450, "GLSL450"); add(MemoryModelOpenCL, "OpenCL"); } SPIRV_DEF_NAMEMAP(MemoryModel, SPIRVMemoryModelNameMap) template <> inline void SPIRVMap::init() { add(ExecutionModeInvocations, "Invocations"); add(ExecutionModeSpacingEqual, "SpacingEqual"); add(ExecutionModeSpacingFractionalEven, "SpacingFractionalEven"); add(ExecutionModeSpacingFractionalOdd, "SpacingFractionalOdd"); add(ExecutionModeVertexOrderCw, "VertexOrderCw"); add(ExecutionModeVertexOrderCcw, "VertexOrderCcw"); add(ExecutionModePixelCenterInteger, "PixelCenterInteger"); add(ExecutionModeOriginUpperLeft, "OriginUpperLeft"); add(ExecutionModeOriginLowerLeft, "OriginLowerLeft"); add(ExecutionModeEarlyFragmentTests, "EarlyFragmentTests"); add(ExecutionModePointMode, "PointMode"); add(ExecutionModeXfb, "Xfb"); add(ExecutionModeDepthReplacing, "DepthReplacing"); add(ExecutionModeDepthGreater, "DepthGreater"); add(ExecutionModeDepthLess, "DepthLess"); add(ExecutionModeDepthUnchanged, "DepthUnchanged"); add(ExecutionModeLocalSize, "LocalSize"); add(ExecutionModeLocalSizeHint, "LocalSizeHint"); add(ExecutionModeInputPoints, "InputPoints"); add(ExecutionModeInputLines, "InputLines"); add(ExecutionModeInputLinesAdjacency, "InputLinesAdjacency"); add(ExecutionModeTriangles, "Triangles"); add(ExecutionModeInputTrianglesAdjacency, "InputTrianglesAdjacency"); add(ExecutionModeQuads, "Quads"); add(ExecutionModeIsolines, "Isolines"); add(ExecutionModeOutputVertices, "OutputVertices"); add(ExecutionModeOutputPoints, "OutputPoints"); add(ExecutionModeOutputLineStrip, "OutputLineStrip"); add(ExecutionModeOutputTriangleStrip, "OutputTriangleStrip"); add(ExecutionModeVecTypeHint, "VecTypeHint"); add(ExecutionModeContractionOff, "ContractionOff"); add(ExecutionModeMaxWorkgroupSizeINTEL, "MaxWorkgroupSizeINTEL"); add(ExecutionModeMaxWorkDimINTEL, "MaxWorkDimINTEL"); add(ExecutionModeNumSIMDWorkitemsINTEL, "NumSIMDWorkitemsINTEL"); } SPIRV_DEF_NAMEMAP(ExecutionMode, SPIRVExecutionModeNameMap) template <> inline void SPIRVMap::init() { add(StorageClassUniformConstant, "UniformConstant"); add(StorageClassInput, "Input"); add(StorageClassUniform, "Uniform"); add(StorageClassOutput, "Output"); add(StorageClassWorkgroup, "Workgroup"); add(StorageClassCrossWorkgroup, "CrossWorkgroup"); add(StorageClassPrivate, "Private"); add(StorageClassFunction, "Function"); add(StorageClassGeneric, "Generic"); add(StorageClassPushConstant, "PushConstant"); add(StorageClassAtomicCounter, "AtomicCounter"); add(StorageClassImage, "Image"); } SPIRV_DEF_NAMEMAP(StorageClass, SPIRVStorageClassNameMap) template <> inline void SPIRVMap::init() { add(Dim1D, "1D"); add(Dim2D, "2D"); add(Dim3D, "3D"); add(DimCube, "Cube"); add(DimRect, "Rect"); add(DimBuffer, "Buffer"); add(DimSubpassData, "SubpassData"); } SPIRV_DEF_NAMEMAP(Dim, SPIRVDimNameMap) template <> inline void SPIRVMap::init() { add(SamplerAddressingModeNone, "None"); add(SamplerAddressingModeClampToEdge, "ClampToEdge"); add(SamplerAddressingModeClamp, "Clamp"); add(SamplerAddressingModeRepeat, "Repeat"); add(SamplerAddressingModeRepeatMirrored, "RepeatMirrored"); } SPIRV_DEF_NAMEMAP(SamplerAddressingMode, SPIRVSamplerAddressingModeNameMap) template <> inline void SPIRVMap::init() { add(SamplerFilterModeNearest, "Nearest"); add(SamplerFilterModeLinear, "Linear"); } SPIRV_DEF_NAMEMAP(SamplerFilterMode, SPIRVSamplerFilterModeNameMap) template <> inline void SPIRVMap::init() { add(ImageFormatUnknown, "Unknown"); add(ImageFormatRgba32f, "Rgba32f"); add(ImageFormatRgba16f, "Rgba16f"); add(ImageFormatR32f, "R32f"); add(ImageFormatRgba8, "Rgba8"); add(ImageFormatRgba8Snorm, "Rgba8Snorm"); add(ImageFormatRg32f, "Rg32f"); add(ImageFormatRg16f, "Rg16f"); add(ImageFormatR11fG11fB10f, "R11fG11fB10f"); add(ImageFormatR16f, "R16f"); add(ImageFormatRgba16, "Rgba16"); add(ImageFormatRgb10A2, "Rgb10A2"); add(ImageFormatRg16, "Rg16"); add(ImageFormatRg8, "Rg8"); add(ImageFormatR16, "R16"); add(ImageFormatR8, "R8"); add(ImageFormatRgba16Snorm, "Rgba16Snorm"); add(ImageFormatRg16Snorm, "Rg16Snorm"); add(ImageFormatRg8Snorm, "Rg8Snorm"); add(ImageFormatR16Snorm, "R16Snorm"); add(ImageFormatR8Snorm, "R8Snorm"); add(ImageFormatRgba32i, "Rgba32i"); add(ImageFormatRgba16i, "Rgba16i"); add(ImageFormatRgba8i, "Rgba8i"); add(ImageFormatR32i, "R32i"); add(ImageFormatRg32i, "Rg32i"); add(ImageFormatRg16i, "Rg16i"); add(ImageFormatRg8i, "Rg8i"); add(ImageFormatR16i, "R16i"); add(ImageFormatR8i, "R8i"); add(ImageFormatRgba32ui, "Rgba32ui"); add(ImageFormatRgba16ui, "Rgba16ui"); add(ImageFormatRgba8ui, "Rgba8ui"); add(ImageFormatR32ui, "R32ui"); add(ImageFormatRgb10a2ui, "Rgb10a2ui"); add(ImageFormatRg32ui, "Rg32ui"); add(ImageFormatRg16ui, "Rg16ui"); add(ImageFormatRg8ui, "Rg8ui"); add(ImageFormatR16ui, "R16ui"); add(ImageFormatR8ui, "R8ui"); } SPIRV_DEF_NAMEMAP(ImageFormat, SPIRVImageFormatNameMap) template <> inline void SPIRVMap::init() { add(ImageChannelOrderR, "R"); add(ImageChannelOrderA, "A"); add(ImageChannelOrderRG, "RG"); add(ImageChannelOrderRA, "RA"); add(ImageChannelOrderRGB, "RGB"); add(ImageChannelOrderRGBA, "RGBA"); add(ImageChannelOrderBGRA, "BGRA"); add(ImageChannelOrderARGB, "ARGB"); add(ImageChannelOrderIntensity, "Intensity"); add(ImageChannelOrderLuminance, "Luminance"); add(ImageChannelOrderRx, "Rx"); add(ImageChannelOrderRGx, "RGx"); add(ImageChannelOrderRGBx, "RGBx"); add(ImageChannelOrderDepth, "Depth"); add(ImageChannelOrderDepthStencil, "DepthStencil"); } SPIRV_DEF_NAMEMAP(ImageChannelOrder, SPIRVImageChannelOrderNameMap) template <> inline void SPIRVMap::init() { add(ImageChannelDataTypeSnormInt8, "SnormInt8"); add(ImageChannelDataTypeSnormInt16, "SnormInt16"); add(ImageChannelDataTypeUnormInt8, "UnormInt8"); add(ImageChannelDataTypeUnormInt16, "UnormInt16"); add(ImageChannelDataTypeUnormShort565, "UnormShort565"); add(ImageChannelDataTypeUnormShort555, "UnormShort555"); add(ImageChannelDataTypeUnormInt101010, "UnormInt101010"); add(ImageChannelDataTypeSignedInt8, "SignedInt8"); add(ImageChannelDataTypeSignedInt16, "SignedInt16"); add(ImageChannelDataTypeSignedInt32, "SignedInt32"); add(ImageChannelDataTypeUnsignedInt8, "UnsignedInt8"); add(ImageChannelDataTypeUnsignedInt16, "UnsignedInt16"); add(ImageChannelDataTypeUnsignedInt32, "UnsignedInt32"); add(ImageChannelDataTypeHalfFloat, "HalfFloat"); add(ImageChannelDataTypeFloat, "Float"); add(ImageChannelDataTypeUnormInt24, "UnormInt24"); add(ImageChannelDataTypeUnormInt101010_2, "UnormInt101010_2"); } SPIRV_DEF_NAMEMAP(ImageChannelDataType, SPIRVImageChannelDataTypeNameMap) template <> inline void SPIRVMap::init() { add(FPRoundingModeRTE, "RTE"); add(FPRoundingModeRTZ, "RTZ"); add(FPRoundingModeRTP, "RTP"); add(FPRoundingModeRTN, "RTN"); } SPIRV_DEF_NAMEMAP(FPRoundingMode, SPIRVFPRoundingModeNameMap) template <> inline void SPIRVMap::init() { add(LinkageTypeExport, "Export"); add(LinkageTypeImport, "Import"); add(LinkageTypeInternal, "Internal"); } SPIRV_DEF_NAMEMAP(LinkageType, SPIRVLinkageTypeNameMap) template <> inline void SPIRVMap::init() { add(AccessQualifierReadOnly, "ReadOnly"); add(AccessQualifierWriteOnly, "WriteOnly"); add(AccessQualifierReadWrite, "ReadWrite"); } SPIRV_DEF_NAMEMAP(AccessQualifier, SPIRVAccessQualifierNameMap) template <> inline void SPIRVMap::init() { add(FunctionParameterAttributeZext, "Zext"); add(FunctionParameterAttributeSext, "Sext"); add(FunctionParameterAttributeByVal, "ByVal"); add(FunctionParameterAttributeSret, "Sret"); add(FunctionParameterAttributeNoAlias, "NoAlias"); add(FunctionParameterAttributeNoCapture, "NoCapture"); add(FunctionParameterAttributeNoWrite, "NoWrite"); add(FunctionParameterAttributeNoReadWrite, "NoReadWrite"); } SPIRV_DEF_NAMEMAP(FunctionParameterAttribute, SPIRVFunctionParameterAttributeNameMap) template <> inline void SPIRVMap::init() { add(DecorationRelaxedPrecision, "RelaxedPrecision"); add(DecorationSpecId, "SpecId"); add(DecorationBlock, "Block"); add(DecorationBufferBlock, "BufferBlock"); add(DecorationRowMajor, "RowMajor"); add(DecorationColMajor, "ColMajor"); add(DecorationArrayStride, "ArrayStride"); add(DecorationMatrixStride, "MatrixStride"); add(DecorationGLSLShared, "GLSLShared"); add(DecorationGLSLPacked, "GLSLPacked"); add(DecorationCPacked, "CPacked"); add(DecorationBuiltIn, "BuiltIn"); add(DecorationNoPerspective, "NoPerspective"); add(DecorationFlat, "Flat"); add(DecorationPatch, "Patch"); add(DecorationCentroid, "Centroid"); add(DecorationSample, "Sample"); add(DecorationInvariant, "Invariant"); add(DecorationRestrict, "Restrict"); add(DecorationAliased, "Aliased"); add(DecorationVolatile, "Volatile"); add(DecorationConstant, "Constant"); add(DecorationCoherent, "Coherent"); add(DecorationNonWritable, "NonWritable"); add(DecorationNonReadable, "NonReadable"); add(DecorationUniform, "Uniform"); add(DecorationSaturatedConversion, "SaturatedConversion"); add(DecorationStream, "Stream"); add(DecorationLocation, "Location"); add(DecorationComponent, "Component"); add(DecorationIndex, "Index"); add(DecorationBinding, "Binding"); add(DecorationDescriptorSet, "DescriptorSet"); add(DecorationOffset, "Offset"); add(DecorationXfbBuffer, "XfbBuffer"); add(DecorationXfbStride, "XfbStride"); add(DecorationFuncParamAttr, "FuncParamAttr"); add(DecorationFPRoundingMode, "FPRoundingMode"); add(DecorationFPFastMathMode, "FPFastMathMode"); add(DecorationLinkageAttributes, "LinkageAttributes"); add(DecorationNoContraction, "NoContraction"); add(DecorationInputAttachmentIndex, "InputAttachmentIndex"); add(DecorationAlignment, "Alignment"); add(DecorationMaxByteOffset, "MaxByteOffset"); add(DecorationNoSignedWrap, "NoSignedWrap"); add(DecorationNoUnsignedWrap, "NoUnsignedWrap"); add(DecorationSideEffectsINTEL, "SideEffectsINTEL"); add(DecorationUserSemantic, "UserSemantic"); add(DecorationRegisterINTEL, "RegisterINTEL"); add(DecorationMemoryINTEL, "MemoryINTEL"); add(DecorationNumbanksINTEL, "NumbanksINTEL"); add(DecorationBankwidthINTEL, "BankwidthINTEL"); add(DecorationMaxPrivateCopiesINTEL, "MaxPrivateCopiesINTEL"); add(DecorationSinglepumpINTEL, "SinglepumpINTEL"); add(DecorationDoublepumpINTEL, "DoublepumpINTEL"); add(DecorationMaxReplicatesINTEL, "MaxReplicatesINTEL"); add(DecorationSimpleDualPortINTEL, "SimpleDualPortINTEL"); add(DecorationMergeINTEL, "MergeINTEL"); add(DecorationBankBitsINTEL, "BankBitsINTEL"); add(DecorationReferencedIndirectlyINTEL, "ReferencedIndirectlyINTEL"); } SPIRV_DEF_NAMEMAP(Decoration, SPIRVDecorationNameMap) template <> inline void SPIRVMap::init() { add(BuiltInPosition, "BuiltInPosition"); add(BuiltInPointSize, "BuiltInPointSize"); add(BuiltInClipDistance, "BuiltInClipDistance"); add(BuiltInCullDistance, "BuiltInCullDistance"); add(BuiltInVertexId, "BuiltInVertexId"); add(BuiltInInstanceId, "BuiltInInstanceId"); add(BuiltInPrimitiveId, "BuiltInPrimitiveId"); add(BuiltInInvocationId, "BuiltInInvocationId"); add(BuiltInLayer, "BuiltInLayer"); add(BuiltInViewportIndex, "BuiltInViewportIndex"); add(BuiltInTessLevelOuter, "BuiltInTessLevelOuter"); add(BuiltInTessLevelInner, "BuiltInTessLevelInner"); add(BuiltInTessCoord, "BuiltInTessCoord"); add(BuiltInPatchVertices, "BuiltInPatchVertices"); add(BuiltInFragCoord, "BuiltInFragCoord"); add(BuiltInPointCoord, "BuiltInPointCoord"); add(BuiltInFrontFacing, "BuiltInFrontFacing"); add(BuiltInSampleId, "BuiltInSampleId"); add(BuiltInSamplePosition, "BuiltInSamplePosition"); add(BuiltInSampleMask, "BuiltInSampleMask"); add(BuiltInFragDepth, "BuiltInFragDepth"); add(BuiltInHelperInvocation, "BuiltInHelperInvocation"); add(BuiltInNumWorkgroups, "BuiltInNumWorkgroups"); add(BuiltInWorkgroupSize, "BuiltInWorkgroupSize"); add(BuiltInWorkgroupId, "BuiltInWorkgroupId"); add(BuiltInLocalInvocationId, "BuiltInLocalInvocationId"); add(BuiltInGlobalInvocationId, "BuiltInGlobalInvocationId"); add(BuiltInLocalInvocationIndex, "BuiltInLocalInvocationIndex"); add(BuiltInWorkDim, "BuiltInWorkDim"); add(BuiltInGlobalSize, "BuiltInGlobalSize"); add(BuiltInEnqueuedWorkgroupSize, "BuiltInEnqueuedWorkgroupSize"); add(BuiltInGlobalOffset, "BuiltInGlobalOffset"); add(BuiltInGlobalLinearId, "BuiltInGlobalLinearId"); add(BuiltInSubgroupSize, "BuiltInSubgroupSize"); add(BuiltInSubgroupMaxSize, "BuiltInSubgroupMaxSize"); add(BuiltInNumSubgroups, "BuiltInNumSubgroups"); add(BuiltInNumEnqueuedSubgroups, "BuiltInNumEnqueuedSubgroups"); add(BuiltInSubgroupId, "BuiltInSubgroupId"); add(BuiltInSubgroupLocalInvocationId, "BuiltInSubgroupLocalInvocationId"); add(BuiltInVertexIndex, "BuiltInVertexIndex"); add(BuiltInInstanceIndex, "BuiltInInstanceIndex"); } SPIRV_DEF_NAMEMAP(BuiltIn, SPIRVBuiltInNameMap) template <> inline void SPIRVMap::init() { add(ScopeCrossDevice, "CrossDevice"); add(ScopeDevice, "Device"); add(ScopeWorkgroup, "Workgroup"); add(ScopeSubgroup, "Subgroup"); add(ScopeInvocation, "Invocation"); } SPIRV_DEF_NAMEMAP(Scope, SPIRVScopeNameMap) template <> inline void SPIRVMap::init() { add(GroupOperationReduce, "Reduce"); add(GroupOperationInclusiveScan, "InclusiveScan"); add(GroupOperationExclusiveScan, "ExclusiveScan"); } SPIRV_DEF_NAMEMAP(GroupOperation, SPIRVGroupOperationNameMap) template <> inline void SPIRVMap::init() { add(KernelEnqueueFlagsNoWait, "NoWait"); add(KernelEnqueueFlagsWaitKernel, "WaitKernel"); add(KernelEnqueueFlagsWaitWorkGroup, "WaitWorkGroup"); } SPIRV_DEF_NAMEMAP(KernelEnqueueFlags, SPIRVKernelEnqueueFlagsNameMap) template <> inline void SPIRVMap::init() { add(CapabilityMatrix, "Matrix"); add(CapabilityShader, "Shader"); add(CapabilityGeometry, "Geometry"); add(CapabilityTessellation, "Tessellation"); add(CapabilityAddresses, "Addresses"); add(CapabilityLinkage, "Linkage"); add(CapabilityKernel, "Kernel"); add(CapabilityVector16, "Vector16"); add(CapabilityFloat16Buffer, "Float16Buffer"); add(CapabilityFloat16, "Float16"); add(CapabilityFloat64, "Float64"); add(CapabilityInt64, "Int64"); add(CapabilityInt64Atomics, "Int64Atomics"); add(CapabilityImageBasic, "ImageBasic"); add(CapabilityImageReadWrite, "ImageReadWrite"); add(CapabilityImageMipmap, "ImageMipmap"); add(CapabilityPipes, "Pipes"); add(CapabilityPipeStorage, "PipeStorage"); add(CapabilityGroups, "Groups"); add(CapabilityDeviceEnqueue, "DeviceEnqueue"); add(CapabilityLiteralSampler, "LiteralSampler"); add(CapabilityAtomicStorage, "AtomicStorage"); add(CapabilityInt16, "Int16"); add(CapabilityTessellationPointSize, "TessellationPointSize"); add(CapabilityGeometryPointSize, "GeometryPointSize"); add(CapabilityImageGatherExtended, "ImageGatherExtended"); add(CapabilityStorageImageMultisample, "StorageImageMultisample"); add(CapabilityUniformBufferArrayDynamicIndexing, "UniformBufferArrayDynamicIndexing"); add(CapabilitySampledImageArrayDynamicIndexing, "SampledImageArrayDynamicIndexing"); add(CapabilityStorageBufferArrayDynamicIndexing, "StorageBufferArrayDynamicIndexing"); add(CapabilityStorageImageArrayDynamicIndexing, "StorageImageArrayDynamicIndexing"); add(CapabilityClipDistance, "ClipDistance"); add(CapabilityCullDistance, "CullDistance"); add(CapabilityImageCubeArray, "ImageCubeArray"); add(CapabilitySampleRateShading, "SampleRateShading"); add(CapabilityImageRect, "ImageRect"); add(CapabilitySampledRect, "SampledRect"); add(CapabilityGenericPointer, "GenericPointer"); add(CapabilityInt8, "Int8"); add(CapabilityInputAttachment, "InputAttachment"); add(CapabilitySparseResidency, "SparseResidency"); add(CapabilityMinLod, "MinLod"); add(CapabilitySampled1D, "Sampled1D"); add(CapabilityImage1D, "Image1D"); add(CapabilitySampledCubeArray, "SampledCubeArray"); add(CapabilitySampledBuffer, "SampledBuffer"); add(CapabilityImageBuffer, "ImageBuffer"); add(CapabilityImageMSArray, "ImageMSArray"); add(CapabilityStorageImageExtendedFormats, "StorageImageExtendedFormats"); add(CapabilityImageQuery, "ImageQuery"); add(CapabilityDerivativeControl, "DerivativeControl"); add(CapabilityInterpolationFunction, "InterpolationFunction"); add(CapabilityTransformFeedback, "TransformFeedback"); add(CapabilityGeometryStreams, "GeometryStreams"); add(CapabilityStorageImageReadWithoutFormat, "StorageImageReadWithoutFormat"); add(CapabilityStorageImageWriteWithoutFormat, "StorageImageWriteWithoutFormat"); add(CapabilityMultiViewport, "MultiViewport"); add(CapabilitySubgroupShuffleINTEL, "SubgroupShuffleINTEL"); add(CapabilitySubgroupBufferBlockIOINTEL, "SubgroupBufferBlockIOINTEL"); add(CapabilitySubgroupImageBlockIOINTEL, "SubgroupImageBlockIOINTEL"); add(CapabilitySubgroupImageMediaBlockIOINTEL, "SubgroupImageMediaBlockIOINTEL"); add(CapabilityAsmINTEL, "AsmINTEL"); add(CapabilitySubgroupAvcMotionEstimationINTEL, "SubgroupAvcMotionEstimationINTEL"); add(CapabilitySubgroupAvcMotionEstimationIntraINTEL, "SubgroupAvcMotionEstimationIntraINTEL"); add(CapabilitySubgroupAvcMotionEstimationChromaINTEL, "SubgroupAvcMotionEstimationChromaINTEL"); add(CapabilityFPGAMemoryAttributesINTEL, "FPGAMemoryAttributesINTEL"); add(CapabilityFPGALoopControlsINTEL, "FPGALoopControlsINTEL"); add(CapabilityFPGARegINTEL, "FPGARegINTEL"); add(CapabilityBlockingPipesINTEL, "BlockingPipesINTEL"); add(CapabilityUnstructuredLoopControlsINTEL, "UnstructuredLoopControlsINTEL"); add(CapabilityFunctionPointersINTEL, "FunctionPointersINTEL"); add(CapabilityIndirectReferencesINTEL, "IndirectReferencesINTEL"); add(CapabilityKernelAttributesINTEL, "KernelAttributesINTEL"); add(CapabilityFPGAKernelAttributesINTEL, "FPGAKernelAttributesINTEL"); } SPIRV_DEF_NAMEMAP(Capability, SPIRVCapabilityNameMap) } /* namespace SPIRV */ #endif // SPIRV_LIBSPIRV_SPIRVNAMEMAPENUM_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVOpCode.h000066400000000000000000000155401363521741200226140ustar00rootroot00000000000000//===- SPIRVOpCode.h - Class to represent SPIR-V Operation Codes -*- C++ -*-==// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines Operation Code class for SPIR-V. /// //===----------------------------------------------------------------------===// #ifndef SPIRV_LIBSPIRV_SPIRVOPCODE_H #define SPIRV_LIBSPIRV_SPIRVOPCODE_H #include "SPIRVUtil.h" #include "spirv.hpp" #include using namespace spv; namespace SPIRV { template <> inline void SPIRVMap::init() { #define _SPIRV_OP(x, ...) add(Op##x, #x); #include "SPIRVOpCodeEnum.h" #undef _SPIRV_OP } SPIRV_DEF_NAMEMAP(Op, OpCodeNameMap) inline bool isAtomicOpCode(Op OpCode) { static_assert(OpAtomicLoad < OpAtomicXor, ""); return ((unsigned)OpCode >= OpAtomicLoad && (unsigned)OpCode <= OpAtomicXor) || OpCode == OpAtomicFlagTestAndSet || OpCode == OpAtomicFlagClear; } inline bool isBinaryOpCode(Op OpCode) { return ((unsigned)OpCode >= OpIAdd && (unsigned)OpCode <= OpFMod) || OpCode == OpDot; } inline bool isShiftOpCode(Op OpCode) { return (unsigned)OpCode >= OpShiftRightLogical && (unsigned)OpCode <= OpShiftLeftLogical; } inline bool isLogicalOpCode(Op OpCode) { return (unsigned)OpCode >= OpLogicalEqual && (unsigned)OpCode <= OpLogicalNot; } inline bool isBitwiseOpCode(Op OpCode) { return (unsigned)OpCode >= OpBitwiseOr && (unsigned)OpCode <= OpBitwiseAnd; } inline bool isBinaryShiftLogicalBitwiseOpCode(Op OpCode) { return (((unsigned)OpCode >= OpShiftRightLogical && (unsigned)OpCode <= OpBitwiseAnd) || isBinaryOpCode(OpCode)); } inline bool isCmpOpCode(Op OpCode) { return ((unsigned)OpCode >= OpIEqual && (unsigned)OpCode <= OpFUnordGreaterThanEqual) || (OpCode >= OpLessOrGreater && OpCode <= OpLogicalNotEqual); } inline bool isCvtOpCode(Op OpCode) { return ((unsigned)OpCode >= OpConvertFToU && (unsigned)OpCode <= OpBitcast) || OpCode == OpSatConvertSToU || OpCode == OpSatConvertUToS; } inline bool isCvtToUnsignedOpCode(Op OpCode) { return OpCode == OpConvertFToU || OpCode == OpUConvert || OpCode == OpSatConvertSToU; } inline bool isCvtFromUnsignedOpCode(Op OpCode) { return OpCode == OpConvertUToF || OpCode == OpUConvert || OpCode == OpSatConvertUToS; } inline bool isOpaqueGenericTypeOpCode(Op OpCode) { return ((unsigned)OpCode >= OpTypeEvent && (unsigned)OpCode <= OpTypeQueue) || OpCode == OpTypeSampler; } inline bool isGenericNegateOpCode(Op OpCode) { return (unsigned)OpCode == OpSNegate || (unsigned)OpCode == OpFNegate || (unsigned)OpCode == OpNot; } inline bool isAccessChainOpCode(Op OpCode) { return OpCode == OpAccessChain || OpCode == OpInBoundsAccessChain; } inline bool hasExecScope(Op OpCode) { unsigned OC = OpCode; return (OpGroupWaitEvents <= OC && OC <= OpGroupSMax) || (OpGroupReserveReadPipePackets <= OC && OC <= OpGroupCommitWritePipe); } inline bool hasGroupOperation(Op OpCode) { unsigned OC = OpCode; return OpGroupIAdd <= OC && OC <= OpGroupSMax; } inline bool isGroupOpCode(Op OpCode) { unsigned OC = OpCode; return OpGroupAll <= OC && OC <= OpGroupSMax; } inline bool isMediaBlockINTELOpcode(Op OpCode) { return OpCode == OpSubgroupImageMediaBlockReadINTEL || OpCode == OpSubgroupImageMediaBlockWriteINTEL; } inline bool isPipeOpCode(Op OpCode) { unsigned OC = OpCode; return (OpReadPipe <= OC && OC <= OpGroupCommitWritePipe) || (OpReadPipeBlockingINTEL <= OC && OC <= OpWritePipeBlockingINTEL); } inline bool isSubgroupAvcINTELTypeOpCode(Op OpCode) { unsigned OC = OpCode; return OpTypeAvcImePayloadINTEL <= OC && OC <= OpTypeAvcSicResultINTEL; } inline bool isSubgroupAvcINTELInstructionOpCode(Op OpCode) { unsigned OC = OpCode; return OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL <= OC && OC <= OpSubgroupAvcSicGetInterRawSadsINTEL; } inline bool isSubgroupAvcINTELEvaluateOpcode(Op OpCode) { unsigned OC = OpCode; return (OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL <= OC && OC <= OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL) || (OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL <= OC && OC <= OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL) || (OpSubgroupAvcSicEvaluateIpeINTEL <= OC && OC <= OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL); } inline bool isTypeOpCode(Op OpCode) { unsigned OC = OpCode; return (OpTypeVoid <= OC && OC <= OpTypePipe) || OC == OpTypePipeStorage || isSubgroupAvcINTELTypeOpCode(OpCode) || OC == OpTypeVmeImageINTEL; } inline bool isConstantOpCode(Op OpCode) { unsigned OC = OpCode; return (OpConstantTrue <= OC && OC <= OpSpecConstantOp) || OC == OpUndef || OC == OpConstantPipeStorage; } inline bool isModuleScopeAllowedOpCode(Op OpCode) { return OpCode == OpVariable || OpCode == OpExtInst || isConstantOpCode(OpCode); } inline bool isIntelSubgroupOpCode(Op OpCode) { unsigned OC = OpCode; return OpSubgroupShuffleINTEL <= OC && OC <= OpSubgroupImageBlockWriteINTEL; } } // namespace SPIRV #endif // SPIRV_LIBSPIRV_SPIRVOPCODE_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h000066400000000000000000000406511363521741200234420ustar00rootroot00000000000000_SPIRV_OP(Nop, 0) _SPIRV_OP(Undef, 1) _SPIRV_OP(SourceContinued, 2) _SPIRV_OP(Source, 3) _SPIRV_OP(SourceExtension, 4) _SPIRV_OP(Name, 5) _SPIRV_OP(MemberName, 6) _SPIRV_OP(String, 7) _SPIRV_OP(Line, 8) _SPIRV_OP(Extension, 10) _SPIRV_OP(ExtInstImport, 11) _SPIRV_OP(ExtInst, 12) _SPIRV_OP(MemoryModel, 14) _SPIRV_OP(EntryPoint, 15) _SPIRV_OP(ExecutionMode, 16) _SPIRV_OP(Capability, 17) _SPIRV_OP(TypeVoid, 19) _SPIRV_OP(TypeBool, 20) _SPIRV_OP(TypeInt, 21) _SPIRV_OP(TypeFloat, 22) _SPIRV_OP(TypeVector, 23) _SPIRV_OP(TypeMatrix, 24) _SPIRV_OP(TypeImage, 25) _SPIRV_OP(TypeSampler, 26) _SPIRV_OP(TypeSampledImage, 27) _SPIRV_OP(TypeArray, 28) _SPIRV_OP(TypeRuntimeArray, 29) _SPIRV_OP(TypeStruct, 30) _SPIRV_OP(TypeOpaque, 31) _SPIRV_OP(TypePointer, 32) _SPIRV_OP(TypeFunction, 33) _SPIRV_OP(TypeEvent, 34) _SPIRV_OP(TypeDeviceEvent, 35) _SPIRV_OP(TypeReserveId, 36) _SPIRV_OP(TypeQueue, 37) _SPIRV_OP(TypePipe, 38) _SPIRV_OP(TypeForwardPointer, 39) _SPIRV_OP(ConstantTrue, 41) _SPIRV_OP(ConstantFalse, 42) _SPIRV_OP(Constant, 43) _SPIRV_OP(ConstantComposite, 44) _SPIRV_OP(ConstantSampler, 45) _SPIRV_OP(ConstantNull, 46) _SPIRV_OP(SpecConstantTrue, 48) _SPIRV_OP(SpecConstantFalse, 49) _SPIRV_OP(SpecConstant, 50) _SPIRV_OP(SpecConstantComposite, 51) _SPIRV_OP(SpecConstantOp, 52) _SPIRV_OP(Function, 54) _SPIRV_OP(FunctionParameter, 55) _SPIRV_OP(FunctionEnd, 56) _SPIRV_OP(FunctionCall, 57) _SPIRV_OP(Variable, 59) _SPIRV_OP(ImageTexelPointer, 60) _SPIRV_OP(Load, 61) _SPIRV_OP(Store, 62) _SPIRV_OP(CopyMemory, 63) _SPIRV_OP(CopyMemorySized, 64) _SPIRV_OP(AccessChain, 65) _SPIRV_OP(InBoundsAccessChain, 66) _SPIRV_OP(PtrAccessChain, 67) _SPIRV_OP(ArrayLength, 68) _SPIRV_OP(GenericPtrMemSemantics, 69) _SPIRV_OP(InBoundsPtrAccessChain, 70) _SPIRV_OP(Decorate, 71) _SPIRV_OP(MemberDecorate, 72) _SPIRV_OP(DecorationGroup, 73) _SPIRV_OP(GroupDecorate, 74) _SPIRV_OP(GroupMemberDecorate, 75) _SPIRV_OP(VectorExtractDynamic, 77) _SPIRV_OP(VectorInsertDynamic, 78) _SPIRV_OP(VectorShuffle, 79) _SPIRV_OP(CompositeConstruct, 80) _SPIRV_OP(CompositeExtract, 81) _SPIRV_OP(CompositeInsert, 82) _SPIRV_OP(CopyObject, 83) _SPIRV_OP(Transpose, 84) _SPIRV_OP(SampledImage, 86) _SPIRV_OP(ImageSampleImplicitLod, 87) _SPIRV_OP(ImageSampleExplicitLod, 88) _SPIRV_OP(ImageSampleDrefImplicitLod, 89) _SPIRV_OP(ImageSampleDrefExplicitLod, 90) _SPIRV_OP(ImageSampleProjImplicitLod, 91) _SPIRV_OP(ImageSampleProjExplicitLod, 92) _SPIRV_OP(ImageSampleProjDrefImplicitLod, 93) _SPIRV_OP(ImageSampleProjDrefExplicitLod, 94) _SPIRV_OP(ImageFetch, 95) _SPIRV_OP(ImageGather, 96) _SPIRV_OP(ImageDrefGather, 97) _SPIRV_OP(ImageRead, 98) _SPIRV_OP(ImageWrite, 99) _SPIRV_OP(Image, 100) _SPIRV_OP(ImageQueryFormat, 101) _SPIRV_OP(ImageQueryOrder, 102) _SPIRV_OP(ImageQuerySizeLod, 103) _SPIRV_OP(ImageQuerySize, 104) _SPIRV_OP(ImageQueryLod, 105) _SPIRV_OP(ImageQueryLevels, 106) _SPIRV_OP(ImageQuerySamples, 107) _SPIRV_OP(ConvertFToU, 109) _SPIRV_OP(ConvertFToS, 110) _SPIRV_OP(ConvertSToF, 111) _SPIRV_OP(ConvertUToF, 112) _SPIRV_OP(UConvert, 113) _SPIRV_OP(SConvert, 114) _SPIRV_OP(FConvert, 115) _SPIRV_OP(QuantizeToF16, 116) _SPIRV_OP(ConvertPtrToU, 117) _SPIRV_OP(SatConvertSToU, 118) _SPIRV_OP(SatConvertUToS, 119) _SPIRV_OP(ConvertUToPtr, 120) _SPIRV_OP(PtrCastToGeneric, 121) _SPIRV_OP(GenericCastToPtr, 122) _SPIRV_OP(GenericCastToPtrExplicit, 123) _SPIRV_OP(Bitcast, 124) _SPIRV_OP(SNegate, 126) _SPIRV_OP(FNegate, 127) _SPIRV_OP(IAdd, 128) _SPIRV_OP(FAdd, 129) _SPIRV_OP(ISub, 130) _SPIRV_OP(FSub, 131) _SPIRV_OP(IMul, 132) _SPIRV_OP(FMul, 133) _SPIRV_OP(UDiv, 134) _SPIRV_OP(SDiv, 135) _SPIRV_OP(FDiv, 136) _SPIRV_OP(UMod, 137) _SPIRV_OP(SRem, 138) _SPIRV_OP(SMod, 139) _SPIRV_OP(FRem, 140) _SPIRV_OP(FMod, 141) _SPIRV_OP(VectorTimesScalar, 142) _SPIRV_OP(MatrixTimesScalar, 143) _SPIRV_OP(VectorTimesMatrix, 144) _SPIRV_OP(MatrixTimesVector, 145) _SPIRV_OP(MatrixTimesMatrix, 146) _SPIRV_OP(OuterProduct, 147) _SPIRV_OP(Dot, 148) _SPIRV_OP(IAddCarry, 149) _SPIRV_OP(ISubBorrow, 150) _SPIRV_OP(UMulExtended, 151) _SPIRV_OP(SMulExtended, 152) _SPIRV_OP(Any, 154) _SPIRV_OP(All, 155) _SPIRV_OP(IsNan, 156) _SPIRV_OP(IsInf, 157) _SPIRV_OP(IsFinite, 158) _SPIRV_OP(IsNormal, 159) _SPIRV_OP(SignBitSet, 160) _SPIRV_OP(LessOrGreater, 161) _SPIRV_OP(Ordered, 162) _SPIRV_OP(Unordered, 163) _SPIRV_OP(LogicalEqual, 164) _SPIRV_OP(LogicalNotEqual, 165) _SPIRV_OP(LogicalOr, 166) _SPIRV_OP(LogicalAnd, 167) _SPIRV_OP(LogicalNot, 168) _SPIRV_OP(Select, 169) _SPIRV_OP(IEqual, 170) _SPIRV_OP(INotEqual, 171) _SPIRV_OP(UGreaterThan, 172) _SPIRV_OP(SGreaterThan, 173) _SPIRV_OP(UGreaterThanEqual, 174) _SPIRV_OP(SGreaterThanEqual, 175) _SPIRV_OP(ULessThan, 176) _SPIRV_OP(SLessThan, 177) _SPIRV_OP(ULessThanEqual, 178) _SPIRV_OP(SLessThanEqual, 179) _SPIRV_OP(FOrdEqual, 180) _SPIRV_OP(FUnordEqual, 181) _SPIRV_OP(FOrdNotEqual, 182) _SPIRV_OP(FUnordNotEqual, 183) _SPIRV_OP(FOrdLessThan, 184) _SPIRV_OP(FUnordLessThan, 185) _SPIRV_OP(FOrdGreaterThan, 186) _SPIRV_OP(FUnordGreaterThan, 187) _SPIRV_OP(FOrdLessThanEqual, 188) _SPIRV_OP(FUnordLessThanEqual, 189) _SPIRV_OP(FOrdGreaterThanEqual, 190) _SPIRV_OP(FUnordGreaterThanEqual, 191) _SPIRV_OP(ShiftRightLogical, 194) _SPIRV_OP(ShiftRightArithmetic, 195) _SPIRV_OP(ShiftLeftLogical, 196) _SPIRV_OP(BitwiseOr, 197) _SPIRV_OP(BitwiseXor, 198) _SPIRV_OP(BitwiseAnd, 199) _SPIRV_OP(Not, 200) _SPIRV_OP(BitFieldInsert, 201) _SPIRV_OP(BitFieldSExtract, 202) _SPIRV_OP(BitFieldUExtract, 203) _SPIRV_OP(BitReverse, 204) _SPIRV_OP(BitCount, 205) _SPIRV_OP(DPdx, 207) _SPIRV_OP(DPdy, 208) _SPIRV_OP(Fwidth, 209) _SPIRV_OP(DPdxFine, 210) _SPIRV_OP(DPdyFine, 211) _SPIRV_OP(FwidthFine, 212) _SPIRV_OP(DPdxCoarse, 213) _SPIRV_OP(DPdyCoarse, 214) _SPIRV_OP(FwidthCoarse, 215) _SPIRV_OP(EmitVertex, 218) _SPIRV_OP(EndPrimitive, 219) _SPIRV_OP(EmitStreamVertex, 220) _SPIRV_OP(EndStreamPrimitive, 221) _SPIRV_OP(ControlBarrier, 224) _SPIRV_OP(MemoryBarrier, 225) _SPIRV_OP(AtomicLoad, 227) _SPIRV_OP(AtomicStore, 228) _SPIRV_OP(AtomicExchange, 229) _SPIRV_OP(AtomicCompareExchange, 230) _SPIRV_OP(AtomicCompareExchangeWeak, 231) _SPIRV_OP(AtomicIIncrement, 232) _SPIRV_OP(AtomicIDecrement, 233) _SPIRV_OP(AtomicIAdd, 234) _SPIRV_OP(AtomicISub, 235) _SPIRV_OP(AtomicSMin, 236) _SPIRV_OP(AtomicUMin, 237) _SPIRV_OP(AtomicSMax, 238) _SPIRV_OP(AtomicUMax, 239) _SPIRV_OP(AtomicAnd, 240) _SPIRV_OP(AtomicOr, 241) _SPIRV_OP(AtomicXor, 242) _SPIRV_OP(Phi, 245) _SPIRV_OP(LoopMerge, 246) _SPIRV_OP(SelectionMerge, 247) _SPIRV_OP(Label, 248) _SPIRV_OP(Branch, 249) _SPIRV_OP(BranchConditional, 250) _SPIRV_OP(Switch, 251) _SPIRV_OP(Kill, 252) _SPIRV_OP(Return, 253) _SPIRV_OP(ReturnValue, 254) _SPIRV_OP(Unreachable, 255) _SPIRV_OP(LifetimeStart, 256) _SPIRV_OP(LifetimeStop, 257) _SPIRV_OP(GroupAsyncCopy, 259) _SPIRV_OP(GroupWaitEvents, 260) _SPIRV_OP(GroupAll, 261) _SPIRV_OP(GroupAny, 262) _SPIRV_OP(GroupBroadcast, 263) _SPIRV_OP(GroupIAdd, 264) _SPIRV_OP(GroupFAdd, 265) _SPIRV_OP(GroupFMin, 266) _SPIRV_OP(GroupUMin, 267) _SPIRV_OP(GroupSMin, 268) _SPIRV_OP(GroupFMax, 269) _SPIRV_OP(GroupUMax, 270) _SPIRV_OP(GroupSMax, 271) _SPIRV_OP(ReadPipe, 274) _SPIRV_OP(WritePipe, 275) _SPIRV_OP(ReservedReadPipe, 276) _SPIRV_OP(ReservedWritePipe, 277) _SPIRV_OP(ReserveReadPipePackets, 278) _SPIRV_OP(ReserveWritePipePackets, 279) _SPIRV_OP(CommitReadPipe, 280) _SPIRV_OP(CommitWritePipe, 281) _SPIRV_OP(IsValidReserveId, 282) _SPIRV_OP(GetNumPipePackets, 283) _SPIRV_OP(GetMaxPipePackets, 284) _SPIRV_OP(GroupReserveReadPipePackets, 285) _SPIRV_OP(GroupReserveWritePipePackets, 286) _SPIRV_OP(GroupCommitReadPipe, 287) _SPIRV_OP(GroupCommitWritePipe, 288) _SPIRV_OP(EnqueueMarker, 291) _SPIRV_OP(EnqueueKernel, 292) _SPIRV_OP(GetKernelNDrangeSubGroupCount, 293) _SPIRV_OP(GetKernelNDrangeMaxSubGroupSize, 294) _SPIRV_OP(GetKernelWorkGroupSize, 295) _SPIRV_OP(GetKernelPreferredWorkGroupSizeMultiple, 296) _SPIRV_OP(RetainEvent, 297) _SPIRV_OP(ReleaseEvent, 298) _SPIRV_OP(CreateUserEvent, 299) _SPIRV_OP(IsValidEvent, 300) _SPIRV_OP(SetUserEventStatus, 301) _SPIRV_OP(CaptureEventProfilingInfo, 302) _SPIRV_OP(GetDefaultQueue, 303) _SPIRV_OP(BuildNDRange, 304) _SPIRV_OP(ImageSparseSampleImplicitLod, 305) _SPIRV_OP(ImageSparseSampleExplicitLod, 306) _SPIRV_OP(ImageSparseSampleDrefImplicitLod, 307) _SPIRV_OP(ImageSparseSampleDrefExplicitLod, 308) _SPIRV_OP(ImageSparseSampleProjImplicitLod, 309) _SPIRV_OP(ImageSparseSampleProjExplicitLod, 310) _SPIRV_OP(ImageSparseSampleProjDrefImplicitLod, 311) _SPIRV_OP(ImageSparseSampleProjDrefExplicitLod, 312) _SPIRV_OP(ImageSparseFetch, 313) _SPIRV_OP(ImageSparseGather, 314) _SPIRV_OP(ImageSparseDrefGather, 315) _SPIRV_OP(ImageSparseTexelsResident, 316) _SPIRV_OP(NoLine, 317) _SPIRV_OP(AtomicFlagTestAndSet, 318) _SPIRV_OP(AtomicFlagClear, 319) _SPIRV_OP(TypePipeStorage, 322) _SPIRV_OP(ConstantPipeStorage, 323) _SPIRV_OP(CreatePipeFromPipeStorage, 324) _SPIRV_OP(Forward, 1024) _SPIRV_OP(SubgroupShuffleINTEL, 5571) _SPIRV_OP(SubgroupShuffleDownINTEL, 5572) _SPIRV_OP(SubgroupShuffleUpINTEL, 5573) _SPIRV_OP(SubgroupShuffleXorINTEL, 5574) _SPIRV_OP(SubgroupBlockReadINTEL, 5575) _SPIRV_OP(SubgroupBlockWriteINTEL, 5576) _SPIRV_OP(SubgroupImageBlockReadINTEL, 5577) _SPIRV_OP(SubgroupImageBlockWriteINTEL, 5578) _SPIRV_OP(SubgroupImageMediaBlockReadINTEL, 5580) _SPIRV_OP(SubgroupImageMediaBlockWriteINTEL, 5581) _SPIRV_OP(FunctionPointerINTEL, 5600) _SPIRV_OP(FunctionPointerCallINTEL, 5601) _SPIRV_OP(AsmTargetINTEL, 5609) _SPIRV_OP(AsmINTEL, 5610) _SPIRV_OP(AsmCallINTEL, 5611) _SPIRV_OP(VmeImageINTEL, 5699) _SPIRV_OP(TypeVmeImageINTEL, 5700) _SPIRV_OP(TypeAvcImePayloadINTEL, 5701) _SPIRV_OP(TypeAvcRefPayloadINTEL, 5702) _SPIRV_OP(TypeAvcSicPayloadINTEL, 5703) _SPIRV_OP(TypeAvcMcePayloadINTEL, 5704) _SPIRV_OP(TypeAvcMceResultINTEL, 5705) _SPIRV_OP(TypeAvcImeResultINTEL, 5706) _SPIRV_OP(TypeAvcImeResultSingleReferenceStreamoutINTEL, 5707) _SPIRV_OP(TypeAvcImeResultDualReferenceStreamoutINTEL, 5708) _SPIRV_OP(TypeAvcImeSingleReferenceStreaminINTEL, 5709) _SPIRV_OP(TypeAvcImeDualReferenceStreaminINTEL, 5710) _SPIRV_OP(TypeAvcRefResultINTEL, 5711) _SPIRV_OP(TypeAvcSicResultINTEL, 5712) _SPIRV_OP(SubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL, 5713) _SPIRV_OP(SubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL, 5714) _SPIRV_OP(SubgroupAvcMceGetDefaultInterShapePenaltyINTEL, 5715) _SPIRV_OP(SubgroupAvcMceSetInterShapePenaltyINTEL, 5716) _SPIRV_OP(SubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL, 5717) _SPIRV_OP(SubgroupAvcMceSetInterDirectionPenaltyINTEL, 5718) _SPIRV_OP(SubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL, 5719) _SPIRV_OP(SubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL, 5720) _SPIRV_OP(SubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL, 5721) _SPIRV_OP(SubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL, 5722) _SPIRV_OP(SubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL, 5723) _SPIRV_OP(SubgroupAvcMceSetMotionVectorCostFunctionINTEL, 5724) _SPIRV_OP(SubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL, 5725) _SPIRV_OP(SubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL, 5726) _SPIRV_OP(SubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL, 5727) _SPIRV_OP(SubgroupAvcMceSetAcOnlyHaarINTEL, 5728) _SPIRV_OP(SubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL, 5729) _SPIRV_OP(SubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL, 5730) _SPIRV_OP(SubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL, 5731) _SPIRV_OP(SubgroupAvcMceConvertToImePayloadINTEL, 5732) _SPIRV_OP(SubgroupAvcMceConvertToImeResultINTEL, 5733) _SPIRV_OP(SubgroupAvcMceConvertToRefPayloadINTEL, 5734) _SPIRV_OP(SubgroupAvcMceConvertToRefResultINTEL, 5735) _SPIRV_OP(SubgroupAvcMceConvertToSicPayloadINTEL, 5736) _SPIRV_OP(SubgroupAvcMceConvertToSicResultINTEL, 5737) _SPIRV_OP(SubgroupAvcMceGetMotionVectorsINTEL, 5738) _SPIRV_OP(SubgroupAvcMceGetInterDistortionsINTEL, 5739) _SPIRV_OP(SubgroupAvcMceGetBestInterDistortionsINTEL, 5740) _SPIRV_OP(SubgroupAvcMceGetInterMajorShapeINTEL, 5741) _SPIRV_OP(SubgroupAvcMceGetInterMinorShapeINTEL, 5742) _SPIRV_OP(SubgroupAvcMceGetInterDirectionsINTEL, 5743) _SPIRV_OP(SubgroupAvcMceGetInterMotionVectorCountINTEL, 5744) _SPIRV_OP(SubgroupAvcMceGetInterReferenceIdsINTEL, 5745) _SPIRV_OP(SubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL, 5746) _SPIRV_OP(SubgroupAvcImeInitializeINTEL, 5747) _SPIRV_OP(SubgroupAvcImeSetSingleReferenceINTEL, 5748) _SPIRV_OP(SubgroupAvcImeSetDualReferenceINTEL, 5749) _SPIRV_OP(SubgroupAvcImeRefWindowSizeINTEL, 5750) _SPIRV_OP(SubgroupAvcImeAdjustRefOffsetINTEL, 5751) _SPIRV_OP(SubgroupAvcImeConvertToMcePayloadINTEL, 5752) _SPIRV_OP(SubgroupAvcImeSetMaxMotionVectorCountINTEL, 5753) _SPIRV_OP(SubgroupAvcImeSetUnidirectionalMixDisableINTEL, 5754) _SPIRV_OP(SubgroupAvcImeSetEarlySearchTerminationThresholdINTEL, 5755) _SPIRV_OP(SubgroupAvcImeSetWeightedSadINTEL, 5756) _SPIRV_OP(SubgroupAvcImeEvaluateWithSingleReferenceINTEL, 5757) _SPIRV_OP(SubgroupAvcImeEvaluateWithDualReferenceINTEL, 5758) _SPIRV_OP(SubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL, 5759) _SPIRV_OP(SubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL, 5760) _SPIRV_OP(SubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL, 5761) _SPIRV_OP(SubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL, 5762) _SPIRV_OP(SubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL, 5763) _SPIRV_OP(SubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL, 5764) _SPIRV_OP(SubgroupAvcImeConvertToMceResultINTEL, 5765) _SPIRV_OP(SubgroupAvcImeGetSingleReferenceStreaminINTEL, 5766) _SPIRV_OP(SubgroupAvcImeGetDualReferenceStreaminINTEL, 5767) _SPIRV_OP(SubgroupAvcImeStripSingleReferenceStreamoutINTEL, 5768) _SPIRV_OP(SubgroupAvcImeStripDualReferenceStreamoutINTEL, 5769) _SPIRV_OP(SubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL, 5770) _SPIRV_OP(SubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL, 5771) _SPIRV_OP(SubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL, 5772) _SPIRV_OP(SubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL, 5773) _SPIRV_OP(SubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL, 5774) _SPIRV_OP(SubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL, 5775) _SPIRV_OP(SubgroupAvcImeGetBorderReachedINTEL, 5776) _SPIRV_OP(SubgroupAvcImeGetTruncatedSearchIndicationINTEL, 5777) _SPIRV_OP(SubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL, 5778) _SPIRV_OP(SubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL, 5779) _SPIRV_OP(SubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL, 5780) _SPIRV_OP(SubgroupAvcFmeInitializeINTEL, 5781) _SPIRV_OP(SubgroupAvcBmeInitializeINTEL, 5782) _SPIRV_OP(SubgroupAvcRefConvertToMcePayloadINTEL, 5783) _SPIRV_OP(SubgroupAvcRefSetBidirectionalMixDisableINTEL, 5784) _SPIRV_OP(SubgroupAvcRefSetBilinearFilterEnableINTEL, 5785) _SPIRV_OP(SubgroupAvcRefEvaluateWithSingleReferenceINTEL, 5786) _SPIRV_OP(SubgroupAvcRefEvaluateWithDualReferenceINTEL, 5787) _SPIRV_OP(SubgroupAvcRefEvaluateWithMultiReferenceINTEL, 5788) _SPIRV_OP(SubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL, 5789) _SPIRV_OP(SubgroupAvcRefConvertToMceResultINTEL, 5790) _SPIRV_OP(SubgroupAvcSicInitializeINTEL, 5791) _SPIRV_OP(SubgroupAvcSicConfigureSkcINTEL, 5792) _SPIRV_OP(SubgroupAvcSicConfigureIpeLumaINTEL, 5793) _SPIRV_OP(SubgroupAvcSicConfigureIpeLumaChromaINTEL, 5794) _SPIRV_OP(SubgroupAvcSicGetMotionVectorMaskINTEL, 5795) _SPIRV_OP(SubgroupAvcSicConvertToMcePayloadINTEL, 5796) _SPIRV_OP(SubgroupAvcSicSetIntraLumaShapePenaltyINTEL, 5797) _SPIRV_OP(SubgroupAvcSicSetIntraLumaModeCostFunctionINTEL, 5798) _SPIRV_OP(SubgroupAvcSicSetIntraChromaModeCostFunctionINTEL, 5799) _SPIRV_OP(SubgroupAvcSicSetBilinearFilterEnableINTEL, 5800) _SPIRV_OP(SubgroupAvcSicSetSkcForwardTransformEnableINTEL, 5801) _SPIRV_OP(SubgroupAvcSicSetBlockBasedRawSkipSadINTEL, 5802) _SPIRV_OP(SubgroupAvcSicEvaluateIpeINTEL, 5803) _SPIRV_OP(SubgroupAvcSicEvaluateWithSingleReferenceINTEL, 5804) _SPIRV_OP(SubgroupAvcSicEvaluateWithDualReferenceINTEL, 5805) _SPIRV_OP(SubgroupAvcSicEvaluateWithMultiReferenceINTEL, 5806) _SPIRV_OP(SubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL, 5807) _SPIRV_OP(SubgroupAvcSicConvertToMceResultINTEL, 5808) _SPIRV_OP(SubgroupAvcSicGetIpeLumaShapeINTEL, 5809) _SPIRV_OP(SubgroupAvcSicGetBestIpeLumaDistortionINTEL, 5810) _SPIRV_OP(SubgroupAvcSicGetBestIpeChromaDistortionINTEL, 5811) _SPIRV_OP(SubgroupAvcSicGetPackedIpeLumaModesINTEL, 5812) _SPIRV_OP(SubgroupAvcSicGetIpeChromaModeINTEL, 5813) _SPIRV_OP(SubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL, 5814) _SPIRV_OP(SubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL, 5815) _SPIRV_OP(SubgroupAvcSicGetInterRawSadsINTEL, 5816) _SPIRV_OP(LoopControlINTEL, 5887) _SPIRV_OP(ReadPipeBlockingINTEL, 5946) _SPIRV_OP(WritePipeBlockingINTEL, 5947) _SPIRV_OP(FPGARegINTEL, 5949) SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVStream.cpp000066400000000000000000000223221363521741200232250ustar00rootroot00000000000000//===- SPIRVStream.cpp - Class to represent a SPIR-V Stream -----*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file implements SPIR-V stream class. /// //===----------------------------------------------------------------------===// #include "SPIRVStream.h" #include "SPIRVDebug.h" #include "SPIRVFunction.h" #include "SPIRVNameMapEnum.h" #include "SPIRVOpCode.h" #include // std::numeric_limits namespace SPIRV { /// Write string with quote. Replace " with \". static void writeQuotedString(spv_ostream &O, const std::string &Str) { O << '"'; for (auto I : Str) { if (I == '"') O << '\\'; O << I; } O << '"'; } /// Read quoted string. Replace \" with ". static void readQuotedString(std::istream &IS, std::string &Str) { char Ch = ' '; char PreCh = ' '; while (IS >> Ch && Ch != '"') ; if (IS >> PreCh && PreCh != '"') { while (IS >> Ch) { if (Ch == '"') { if (PreCh != '\\') { Str += PreCh; break; } else PreCh = Ch; } else { Str += PreCh; PreCh = Ch; } } } } #ifdef _SPIRV_SUPPORT_TEXT_FMT bool SPIRVUseTextFormat = false; #endif SPIRVDecoder::SPIRVDecoder(std::istream &InputStream, SPIRVFunction &F) : IS(InputStream), M(*F.getModule()), WordCount(0), OpCode(OpNop), Scope(&F) {} SPIRVDecoder::SPIRVDecoder(std::istream &InputStream, SPIRVBasicBlock &BB) : IS(InputStream), M(*BB.getModule()), WordCount(0), OpCode(OpNop), Scope(&BB) {} void SPIRVDecoder::setScope(SPIRVEntry *TheScope) { assert(TheScope && (TheScope->getOpCode() == OpFunction || TheScope->getOpCode() == OpLabel)); Scope = TheScope; } template const SPIRVDecoder &decode(const SPIRVDecoder &I, T &V) { #ifdef _SPIRV_SUPPORT_TEXT_FMT if (SPIRVUseTextFormat) { std::string W; I.IS >> W; V = getNameMap(V).rmap(W); SPIRVDBG(spvdbgs() << "Read word: W = " << W << " V = " << V << '\n'); return I; } #endif return decodeBinary(I, V); } template const SPIRVEncoder &encode(const SPIRVEncoder &O, T V) { #ifdef _SPIRV_SUPPORT_TEXT_FMT if (SPIRVUseTextFormat) { O.OS << getNameMap(V).map(V) << " "; return O; } #endif return O << static_cast(V); } #define SPIRV_DEF_ENCDEC(Type) \ const SPIRVDecoder &operator>>(const SPIRVDecoder &I, Type &V) { \ return decode(I, V); \ } \ const SPIRVEncoder &operator<<(const SPIRVEncoder &O, Type V) { \ return encode(O, V); \ } SPIRV_DEF_ENCDEC(Op) SPIRV_DEF_ENCDEC(Capability) SPIRV_DEF_ENCDEC(Decoration) SPIRV_DEF_ENCDEC(OCLExtOpKind) SPIRV_DEF_ENCDEC(SPIRVDebugExtOpKind) SPIRV_DEF_ENCDEC(LinkageType) // Read a string with padded 0's at the end so that they form a stream of // words. const SPIRVDecoder &operator>>(const SPIRVDecoder &I, std::string &Str) { #ifdef _SPIRV_SUPPORT_TEXT_FMT if (SPIRVUseTextFormat) { readQuotedString(I.IS, Str); SPIRVDBG(spvdbgs() << "Read string: \"" << Str << "\"\n"); return I; } #endif uint64_t Count = 0; char Ch; while (I.IS.get(Ch) && Ch != '\0') { Str += Ch; ++Count; } Count = (Count + 1) % 4; Count = Count ? 4 - Count : 0; for (; Count; --Count) { I.IS >> Ch; assert(Ch == '\0' && "Invalid string in SPIRV"); } SPIRVDBG(spvdbgs() << "Read string: \"" << Str << "\"\n"); return I; } // Write a string with padded 0's at the end so that they form a stream of // words. const SPIRVEncoder &operator<<(const SPIRVEncoder &O, const std::string &Str) { #ifdef _SPIRV_SUPPORT_TEXT_FMT if (SPIRVUseTextFormat) { writeQuotedString(O.OS, Str); return O; } #endif size_t L = Str.length(); O.OS.write(Str.c_str(), L); char Zeros[4] = {0, 0, 0, 0}; O.OS.write(Zeros, 4 - L % 4); return O; } bool SPIRVDecoder::getWordCountAndOpCode() { if (IS.eof()) { WordCount = 0; OpCode = OpNop; SPIRVDBG(spvdbgs() << "[SPIRVDecoder] getWordCountAndOpCode EOF " << WordCount << " " << OpCode << '\n'); return false; } #ifdef _SPIRV_SUPPORT_TEXT_FMT if (SPIRVUseTextFormat) { *this >> WordCount; assert(!IS.bad() && "SPIRV stream is bad"); if (IS.fail()) { WordCount = 0; OpCode = OpNop; SPIRVDBG(spvdbgs() << "[SPIRVDecoder] getWordCountAndOpCode FAIL " << WordCount << " " << OpCode << '\n'); return false; } *this >> OpCode; } else { #endif SPIRVWord WordCountAndOpCode; *this >> WordCountAndOpCode; WordCount = WordCountAndOpCode >> 16; OpCode = static_cast(WordCountAndOpCode & 0xFFFF); #ifdef _SPIRV_SUPPORT_TEXT_FMT } #endif assert(!IS.bad() && "SPIRV stream is bad"); if (IS.fail()) { WordCount = 0; OpCode = OpNop; SPIRVDBG(spvdbgs() << "[SPIRVDecoder] getWordCountAndOpCode FAIL " << WordCount << " " << OpCode << '\n'); return false; } SPIRVDBG(spvdbgs() << "[SPIRVDecoder] getWordCountAndOpCode " << WordCount << " " << OpCodeNameMap::map(OpCode) << '\n'); return true; } SPIRVEntry *SPIRVDecoder::getEntry() { if (WordCount == 0 || OpCode == OpNop) return nullptr; SPIRVEntry *Entry = SPIRVEntry::create(OpCode); assert(Entry); Entry->setModule(&M); if (isModuleScopeAllowedOpCode(OpCode) && !Scope) { } else Entry->setScope(Scope); Entry->setWordCount(WordCount); if (OpCode != OpLine) Entry->setLine(M.getCurrentLine()); IS >> *Entry; if (Entry->isEndOfBlock() || OpCode == OpNoLine) M.setCurrentLine(nullptr); if (OpExtension == OpCode) { auto *OpExt = static_cast(Entry); ExtensionID ExtID; bool ExtIsKnown = SPIRVMap::rfind( OpExt->getExtensionName(), &ExtID); if (!M.getErrorLog().checkError( ExtIsKnown, SPIRVEC_InvalidModule, "input SPIR-V module uses unknown extension '" + OpExt->getExtensionName() + "'")) { M.setInvalid(); } if (!M.getErrorLog().checkError( M.isAllowedToUseExtension(ExtID), SPIRVEC_InvalidModule, "input SPIR-V module uses extension '" + OpExt->getExtensionName() + "' which were disabled by --spirv-ext option")) { M.setInvalid(); } } if (!M.getErrorLog().checkError(Entry->isImplemented(), SPIRVEC_UnimplementedOpCode, std::to_string(Entry->getOpCode()))) { M.setInvalid(); } assert(!IS.bad() && !IS.fail() && "SPIRV stream fails"); return Entry; } void SPIRVDecoder::validate() const { assert(OpCode != OpNop && "Invalid op code"); assert(WordCount && "Invalid word count"); assert(!IS.bad() && "Bad iInput stream"); } // Skip \param n words in SPIR-V binary stream. // In case of SPIR-V text format always skip until the end of the line. void SPIRVDecoder::ignore(size_t N) { #ifdef _SPIRV_SUPPORT_TEXT_FMT if (SPIRVUseTextFormat) { IS.ignore(std::numeric_limits::max(), '\n'); return; } #endif IS.ignore(N * sizeof(SPIRVWord)); } void SPIRVDecoder::ignoreInstruction() { ignore(WordCount - 1); } spv_ostream &operator<<(spv_ostream &O, const SPIRVNL &E) { #ifdef _SPIRV_SUPPORT_TEXT_FMT if (SPIRVUseTextFormat) O << '\n'; #endif return O; } } // namespace SPIRV SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVStream.h000066400000000000000000000151451363521741200226770ustar00rootroot00000000000000//===- SPIRVStream.h - Class to represent a SPIR-V Stream -------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines Word class for SPIR-V. /// //===----------------------------------------------------------------------===// #ifndef SPIRV_LIBSPIRV_SPIRVSTREAM_H #define SPIRV_LIBSPIRV_SPIRVSTREAM_H #include "SPIRVDebug.h" #include "SPIRVExtInst.h" #include "SPIRVModule.h" #include #include #include #include #include #include #include namespace SPIRV { #ifndef _SPIRV_SUPPORT_TEXT_FMT #define _SPIRV_SUPPORT_TEXT_FMT #endif #ifdef _SPIRV_SUPPORT_TEXT_FMT // Use textual format for SPIRV. extern bool SPIRVUseTextFormat; #endif class SPIRVFunction; class SPIRVBasicBlock; class SPIRVDecoder { public: SPIRVDecoder(std::istream &InputStream, SPIRVModule &Module) : IS(InputStream), M(Module), WordCount(0), OpCode(OpNop), Scope(NULL) {} SPIRVDecoder(std::istream &InputStream, SPIRVFunction &F); SPIRVDecoder(std::istream &InputStream, SPIRVBasicBlock &BB); void setScope(SPIRVEntry *); bool getWordCountAndOpCode(); SPIRVEntry *getEntry(); void validate() const; void ignore(size_t N); void ignoreInstruction(); std::istream &IS; SPIRVModule &M; SPIRVWord WordCount; Op OpCode; SPIRVEntry *Scope; // A function or basic block }; class SPIRVEncoder { public: explicit SPIRVEncoder(spv_ostream &OutputStream) : OS(OutputStream) {} spv_ostream &OS; }; /// Output a new line in text mode. Do nothing in binary mode. class SPIRVNL { friend spv_ostream &operator<<(spv_ostream &O, const SPIRVNL &E); }; template const SPIRVDecoder &decodeBinary(const SPIRVDecoder &I, T &V) { uint32_t W; I.IS.read(reinterpret_cast(&W), sizeof(W)); V = static_cast(W); SPIRVDBG(spvdbgs() << "Read word: W = " << W << " V = " << V << '\n'); return I; } #ifdef _SPIRV_SUPPORT_TEXT_FMT /// Skip comment and whitespace. Comment starts with ';', ends with '\n'. inline std::istream &skipcomment(std::istream &IS) { if (IS.eof() || IS.bad()) return IS; char C = IS.peek(); while (std::char_traits::not_eof(C) && std::isspace(C)) { IS.get(); C = IS.peek(); } while (std::char_traits::not_eof(C) && C == ';') { IS.ignore(std::numeric_limits::max(), '\n'); C = IS.peek(); while (std::char_traits::not_eof(C) && std::isspace(C)) { IS.get(); C = IS.peek(); } } return IS; } #endif template const SPIRVDecoder &operator>>(const SPIRVDecoder &I, T &V) { #ifdef _SPIRV_SUPPORT_TEXT_FMT if (SPIRVUseTextFormat) { uint32_t W; I.IS >> skipcomment >> W; V = static_cast(W); SPIRVDBG(spvdbgs() << "Read word: W = " << W << " V = " << V << '\n'); return I; } #endif return decodeBinary(I, V); } template const SPIRVDecoder &operator>>(const SPIRVDecoder &I, T *&P) { SPIRVId Id; I >> Id; P = static_cast(I.M.getEntry(Id)); return I; } template const SPIRVDecoder &operator>>(const SPIRVDecoder &Decoder, const std::pair &Range) { for (IterTy I = Range.first, E = Range.second; I != E; ++I) Decoder >> *I; return Decoder; } template const SPIRVDecoder &operator>>(const SPIRVDecoder &I, std::vector &V) { for (size_t J = 0, E = V.size(); J != E; ++J) I >> V[J]; return I; } template const SPIRVEncoder &operator<<(const SPIRVEncoder &O, T V) { #ifdef _SPIRV_SUPPORT_TEXT_FMT if (SPIRVUseTextFormat) { O.OS << V << " "; return O; } #endif uint32_t W = static_cast(V); O.OS.write(reinterpret_cast(&W), sizeof(W)); return O; } template const SPIRVEncoder &operator<<(const SPIRVEncoder &O, T *P) { return O << P->getId(); } template const SPIRVEncoder &operator<<(const SPIRVEncoder &O, const std::vector &V) { for (size_t I = 0, E = V.size(); I != E; ++I) O << V[I]; return O; } template const SPIRVEncoder &operator<<(const SPIRVEncoder &Encoder, const std::pair &Range) { for (IterTy I = Range.first, E = Range.second; I != E; ++I) Encoder << *I; return Encoder; } #define SPIRV_DEC_ENCDEC(Type) \ const SPIRVEncoder &operator<<(const SPIRVEncoder &O, Type V); \ const SPIRVDecoder &operator>>(const SPIRVDecoder &I, Type &V); SPIRV_DEC_ENCDEC(Op) SPIRV_DEC_ENCDEC(Capability) SPIRV_DEC_ENCDEC(Decoration) SPIRV_DEC_ENCDEC(OCLExtOpKind) SPIRV_DEC_ENCDEC(SPIRVDebugExtOpKind) SPIRV_DEC_ENCDEC(LinkageType) const SPIRVEncoder &operator<<(const SPIRVEncoder &O, const std::string &Str); const SPIRVDecoder &operator>>(const SPIRVDecoder &I, std::string &Str); } // namespace SPIRV #endif // SPIRV_LIBSPIRV_SPIRVSTREAM_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVType.cpp000066400000000000000000000212541363521741200227160ustar00rootroot00000000000000//===- SPIRVtype.cpp – Class to represent a SPIR-V type ---------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file implements the types defined in SPIRV spec with op codes. /// //===----------------------------------------------------------------------===// #include "SPIRVType.h" #include "SPIRVDecorate.h" #include "SPIRVModule.h" #include "SPIRVValue.h" #include namespace SPIRV { SPIRVType *SPIRVType::getArrayElementType() const { assert(OpCode == OpTypeArray && "Not array type"); return static_cast(this)->getElementType(); } uint64_t SPIRVType::getArrayLength() const { assert(OpCode == OpTypeArray && "Not array type"); return static_cast(this) ->getLength() ->getZExtIntValue(); } SPIRVWord SPIRVType::getBitWidth() const { if (isTypeVector()) return getVectorComponentType()->getBitWidth(); if (isTypeBool()) return 1; return isTypeInt() ? getIntegerBitWidth() : getFloatBitWidth(); } SPIRVWord SPIRVType::getFloatBitWidth() const { assert(OpCode == OpTypeFloat && "Not a float type"); return static_cast(this)->getBitWidth(); } SPIRVWord SPIRVType::getIntegerBitWidth() const { assert((OpCode == OpTypeInt || OpCode == OpTypeBool) && "Not an integer type"); if (isTypeBool()) return 1; return static_cast(this)->getBitWidth(); } SPIRVType *SPIRVType::getFunctionReturnType() const { assert(OpCode == OpTypeFunction); return static_cast(this)->getReturnType(); } SPIRVType *SPIRVType::getPointerElementType() const { assert(OpCode == OpTypePointer && "Not a pointer type"); return static_cast(this)->getElementType(); } SPIRVStorageClassKind SPIRVType::getPointerStorageClass() const { assert(OpCode == OpTypePointer && "Not a pointer type"); return static_cast(this)->getStorageClass(); } SPIRVType *SPIRVType::getStructMemberType(size_t Index) const { assert(OpCode == OpTypeStruct && "Not struct type"); return static_cast(this)->getMemberType(Index); } SPIRVWord SPIRVType::getStructMemberCount() const { assert(OpCode == OpTypeStruct && "Not struct type"); return static_cast(this)->getMemberCount(); } SPIRVWord SPIRVType::getVectorComponentCount() const { assert(OpCode == OpTypeVector && "Not vector type"); return static_cast(this)->getComponentCount(); } SPIRVType *SPIRVType::getVectorComponentType() const { assert(OpCode == OpTypeVector && "Not vector type"); return static_cast(this)->getComponentType(); } SPIRVWord SPIRVType::getMatrixColumnCount() const { assert(OpCode == OpTypeMatrix && "Not matrix type"); return static_cast(this)->getColumnCount(); } SPIRVType *SPIRVType::getMatrixColumnType() const { assert(OpCode == OpTypeMatrix && "Not matrix type"); return static_cast(this)->getColumnType(); } SPIRVType *SPIRVType::getScalarType() const { switch (OpCode) { case OpTypePointer: return getPointerElementType()->getScalarType(); case OpTypeArray: return getArrayElementType(); case OpTypeVector: return getVectorComponentType(); case OpTypeMatrix: return getMatrixColumnType()->getVectorComponentType(); case OpTypeInt: case OpTypeFloat: case OpTypeBool: return const_cast(this); default: break; } return nullptr; } bool SPIRVType::isTypeVoid() const { return OpCode == OpTypeVoid; } bool SPIRVType::isTypeArray() const { return OpCode == OpTypeArray; } bool SPIRVType::isTypeBool() const { return OpCode == OpTypeBool; } bool SPIRVType::isTypeComposite() const { return isTypeVector() || isTypeArray() || isTypeStruct(); } bool SPIRVType::isTypeFloat(unsigned Bits) const { return isType(this, Bits); } bool SPIRVType::isTypeOCLImage() const { return isTypeImage() && static_cast(this)->isOCLImage(); } bool SPIRVType::isTypePipe() const { return OpCode == OpTypePipe; } bool SPIRVType::isTypePipeStorage() const { return OpCode == OpTypePipeStorage; } bool SPIRVType::isTypeReserveId() const { return OpCode == OpTypeReserveId; } bool SPIRVType::isTypeInt(unsigned Bits) const { return isType(this, Bits); } bool SPIRVType::isTypePointer() const { return OpCode == OpTypePointer; } bool SPIRVType::isTypeOpaque() const { return OpCode == OpTypeOpaque; } bool SPIRVType::isTypeEvent() const { return OpCode == OpTypeEvent; } bool SPIRVType::isTypeDeviceEvent() const { return OpCode == OpTypeDeviceEvent; } bool SPIRVType::isTypeSampler() const { return OpCode == OpTypeSampler; } bool SPIRVType::isTypeImage() const { return OpCode == OpTypeImage; } bool SPIRVType::isTypeStruct() const { return OpCode == OpTypeStruct; } bool SPIRVType::isTypeVector() const { return OpCode == OpTypeVector; } bool SPIRVType::isTypeVectorBool() const { return isTypeVector() && getVectorComponentType()->isTypeBool(); } bool SPIRVType::isTypeVectorInt() const { return isTypeVector() && getVectorComponentType()->isTypeInt(); } bool SPIRVType::isTypeVectorFloat() const { return isTypeVector() && getVectorComponentType()->isTypeFloat(); } bool SPIRVType::isTypeVectorOrScalarBool() const { return isTypeBool() || isTypeVectorBool(); } bool SPIRVType::isTypeSubgroupAvcINTEL() const { return isSubgroupAvcINTELTypeOpCode(OpCode); } bool SPIRVType::isTypeSubgroupAvcMceINTEL() const { return OpCode == OpTypeAvcMcePayloadINTEL || OpCode == OpTypeAvcMceResultINTEL; } bool SPIRVType::isTypeVectorOrScalarInt() const { return isTypeInt() || isTypeVectorInt(); } bool SPIRVType::isTypeVectorOrScalarFloat() const { return isTypeFloat() || isTypeVectorFloat(); } bool SPIRVTypeStruct::isPacked() const { return hasDecorate(DecorationCPacked); } void SPIRVTypeStruct::setPacked(bool Packed) { if (Packed) addDecorate(new SPIRVDecorate(DecorationCPacked, this)); else eraseDecorate(DecorationCPacked); } SPIRVTypeArray::SPIRVTypeArray(SPIRVModule *M, SPIRVId TheId, SPIRVType *TheElemType, SPIRVConstant *TheLength) : SPIRVType(M, 4, OpTypeArray, TheId), ElemType(TheElemType), Length(TheLength->getId()) { validate(); } void SPIRVTypeArray::validate() const { SPIRVEntry::validate(); ElemType->validate(); assert(getValue(Length)->getType()->isTypeInt() && get(Length)->getZExtIntValue() > 0); } SPIRVConstant *SPIRVTypeArray::getLength() const { return get(Length); } _SPIRV_IMP_ENCDEC3(SPIRVTypeArray, Id, ElemType, Length) void SPIRVTypeForwardPointer::encode(spv_ostream &O) const { getEncoder(O) << Pointer << SC; } void SPIRVTypeForwardPointer::decode(std::istream &I) { auto Decoder = getDecoder(I); SPIRVId PointerId; Decoder >> PointerId >> SC; } } // namespace SPIRV SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVType.h000066400000000000000000000720711363521741200223660ustar00rootroot00000000000000//===- SPIRVType.h - Class to represent a SPIR-V Type -----------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines the types defined in SPIRV spec with op codes. /// /// The name of the SPIR-V types follow the op code name in the spec, e.g. /// SPIR-V type with op code name OpTypeInt is named as SPIRVTypeInt. This is /// for readability and ease of using macro to handle types. /// //===----------------------------------------------------------------------===// #ifndef SPIRV_LIBSPIRV_SPIRVTYPE_H #define SPIRV_LIBSPIRV_SPIRVTYPE_H #include "SPIRVEntry.h" #include "SPIRVStream.h" #include #include #include #include #include namespace SPIRV { class SPIRVType : public SPIRVEntry { public: // Complete constructor SPIRVType(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode, SPIRVId TheId) : SPIRVEntry(M, TheWordCount, TheOpCode, TheId) {} // Incomplete constructor SPIRVType(Op TheOpCode) : SPIRVEntry(TheOpCode) {} SPIRVType *getArrayElementType() const; uint64_t getArrayLength() const; unsigned getBitWidth() const; unsigned getFloatBitWidth() const; SPIRVType *getFunctionReturnType() const; unsigned getIntegerBitWidth() const; SPIRVType *getPointerElementType() const; SPIRVStorageClassKind getPointerStorageClass() const; SPIRVType *getStructMemberType(size_t) const; SPIRVWord getStructMemberCount() const; SPIRVWord getVectorComponentCount() const; SPIRVType *getVectorComponentType() const; SPIRVWord getMatrixColumnCount() const; SPIRVType *getMatrixColumnType() const; SPIRVType *getScalarType() const; bool isTypeVoid() const; bool isTypeArray() const; bool isTypeBool() const; bool isTypeComposite() const; bool isTypeEvent() const; bool isTypeDeviceEvent() const; bool isTypeReserveId() const; bool isTypeFloat(unsigned Bits = 0) const; bool isTypeImage() const; bool isTypeOCLImage() const; bool isTypePipe() const; bool isTypePipeStorage() const; bool isTypeInt(unsigned Bits = 0) const; bool isTypeOpaque() const; bool isTypePointer() const; bool isTypeSampler() const; bool isTypeStruct() const; bool isTypeVector() const; bool isTypeVectorInt() const; bool isTypeVectorFloat() const; bool isTypeVectorBool() const; bool isTypeVectorOrScalarInt() const; bool isTypeVectorOrScalarFloat() const; bool isTypeVectorOrScalarBool() const; bool isTypeSubgroupAvcINTEL() const; bool isTypeSubgroupAvcMceINTEL() const; }; class SPIRVTypeVoid : public SPIRVType { public: // Complete constructor SPIRVTypeVoid(SPIRVModule *M, SPIRVId TheId) : SPIRVType(M, 2, OpTypeVoid, TheId) {} // Incomplete constructor SPIRVTypeVoid() : SPIRVType(OpTypeVoid) {} protected: _SPIRV_DEF_ENCDEC1(Id) }; class SPIRVTypeBool : public SPIRVType { public: // Complete constructor SPIRVTypeBool(SPIRVModule *M, SPIRVId TheId) : SPIRVType(M, 2, OpTypeBool, TheId) {} // Incomplete constructor SPIRVTypeBool() : SPIRVType(OpTypeBool) {} protected: _SPIRV_DEF_ENCDEC1(Id) }; class SPIRVTypeInt : public SPIRVType { public: static const Op OC = OpTypeInt; // Complete constructor SPIRVTypeInt(SPIRVModule *M, SPIRVId TheId, unsigned TheBitWidth, bool ItIsSigned) : SPIRVType(M, 4, OC, TheId), BitWidth(TheBitWidth), IsSigned(ItIsSigned) { validate(); } // Incomplete constructor SPIRVTypeInt() : SPIRVType(OC), BitWidth(0), IsSigned(false) {} unsigned getBitWidth() const { return BitWidth; } bool isSigned() const { return IsSigned; } SPIRVCapVec getRequiredCapability() const override { SPIRVCapVec CV; switch (BitWidth) { case 8: CV.push_back(CapabilityInt8); break; case 16: CV.push_back(CapabilityInt16); break; case 64: CV.push_back(CapabilityInt64); break; default: break; } return CV; } protected: _SPIRV_DEF_ENCDEC3(Id, BitWidth, IsSigned) void validate() const override { SPIRVEntry::validate(); assert(BitWidth > 1 && BitWidth <= 64 && "Invalid bit width"); } private: unsigned BitWidth; // Bit width bool IsSigned; // Whether it is signed }; class SPIRVTypeFloat : public SPIRVType { public: static const Op OC = OpTypeFloat; // Complete constructor SPIRVTypeFloat(SPIRVModule *M, SPIRVId TheId, unsigned TheBitWidth) : SPIRVType(M, 3, OC, TheId), BitWidth(TheBitWidth) {} // Incomplete constructor SPIRVTypeFloat() : SPIRVType(OC), BitWidth(0) {} unsigned getBitWidth() const { return BitWidth; } SPIRVCapVec getRequiredCapability() const override { SPIRVCapVec CV; if (isTypeFloat(16)) { CV.push_back(CapabilityFloat16Buffer); auto Extensions = getModule()->getExtension(); if (std::any_of(Extensions.begin(), Extensions.end(), [](const std::string &I) { return I == "cl_khr_fp16"; })) CV.push_back(CapabilityFloat16); } else if (isTypeFloat(64)) CV.push_back(CapabilityFloat64); return CV; } protected: _SPIRV_DEF_ENCDEC2(Id, BitWidth) void validate() const override { SPIRVEntry::validate(); assert(BitWidth >= 16 && BitWidth <= 64 && "Invalid bit width"); } private: unsigned BitWidth; // Bit width }; class SPIRVTypePointer : public SPIRVType { public: // Complete constructor SPIRVTypePointer(SPIRVModule *M, SPIRVId TheId, SPIRVStorageClassKind TheStorageClass, SPIRVType *ElementType) : SPIRVType(M, 4, OpTypePointer, TheId), ElemStorageClass(TheStorageClass), ElemTypeId(ElementType->getId()) { validate(); } // Incomplete constructor SPIRVTypePointer() : SPIRVType(OpTypePointer), ElemStorageClass(StorageClassFunction), ElemTypeId(0) {} SPIRVType *getElementType() const { return static_cast(getEntry(ElemTypeId)); } SPIRVStorageClassKind getStorageClass() const { return ElemStorageClass; } SPIRVCapVec getRequiredCapability() const override { auto Cap = getVec(CapabilityAddresses); if (getElementType()->isTypeFloat(16)) Cap.push_back(CapabilityFloat16Buffer); auto C = getCapability(ElemStorageClass); Cap.insert(Cap.end(), C.begin(), C.end()); return Cap; } std::vector getNonLiteralOperands() const override { return std::vector(1, getEntry(ElemTypeId)); } protected: _SPIRV_DEF_ENCDEC3(Id, ElemStorageClass, ElemTypeId) void validate() const override { SPIRVEntry::validate(); assert(isValid(ElemStorageClass)); } private: SPIRVStorageClassKind ElemStorageClass; // Storage Class SPIRVId ElemTypeId; }; class SPIRVTypeForwardPointer : public SPIRVEntryNoId { public: SPIRVTypeForwardPointer(SPIRVModule *M, SPIRVTypePointer *Pointer, SPIRVStorageClassKind SC) : SPIRVEntryNoId(M, 3), Pointer(Pointer), SC(SC) {} SPIRVTypeForwardPointer() : Pointer(nullptr), SC(StorageClassUniformConstant) {} SPIRVTypePointer *getPointer() const { return Pointer; } _SPIRV_DCL_ENCDEC private: SPIRVTypePointer *Pointer; SPIRVStorageClassKind SC; }; class SPIRVTypeVector : public SPIRVType { public: // Complete constructor SPIRVTypeVector(SPIRVModule *M, SPIRVId TheId, SPIRVType *TheCompType, SPIRVWord TheCompCount) : SPIRVType(M, 4, OpTypeVector, TheId), CompType(TheCompType), CompCount(TheCompCount) { validate(); } // Incomplete constructor SPIRVTypeVector() : SPIRVType(OpTypeVector), CompType(nullptr), CompCount(0) {} SPIRVType *getComponentType() const { return CompType; } SPIRVWord getComponentCount() const { return CompCount; } bool isValidIndex(SPIRVWord Index) const { return Index < CompCount; } SPIRVCapVec getRequiredCapability() const override { SPIRVCapVec V(getComponentType()->getRequiredCapability()); // Even though the capability name is "Vector16", it describes // usage of 8-component or 16-component vectors. if (CompCount >= 8) V.push_back(CapabilityVector16); return V; } std::vector getNonLiteralOperands() const override { return std::vector(1, CompType); } protected: _SPIRV_DEF_ENCDEC3(Id, CompType, CompCount) void validate() const override { SPIRVEntry::validate(); CompType->validate(); assert(CompCount == 2 || CompCount == 3 || CompCount == 4 || CompCount == 8 || CompCount == 16); } private: SPIRVType *CompType; // Component Type SPIRVWord CompCount; // Component Count }; class SPIRVTypeMatrix : public SPIRVType { public: // Complete constructor SPIRVTypeMatrix(SPIRVModule *M, SPIRVId TheId, SPIRVType *TheColType, SPIRVWord TheColCount) : SPIRVType(M, 4, OpTypeMatrix, TheId), ColType(TheColType), ColCount(TheColCount) { validate(); } // Incomplete constructor SPIRVTypeMatrix() : SPIRVType(OpTypeMatrix), ColType(nullptr), ColCount(0) {} SPIRVType *getColumnType() const { return ColType; } SPIRVWord getColumnCount() const { return ColCount; } bool isValidIndex(SPIRVWord Index) const { return Index < ColCount; } SPIRVCapVec getRequiredCapability() const override { SPIRVCapVec V(getColumnType()->getRequiredCapability()); if (ColCount >= 8) V.push_back(CapabilityVector16); return V; } virtual std::vector getNonLiteralOperands() const override { return std::vector(1, ColType); } void validate() const override { SPIRVEntry::validate(); ColType->validate(); assert(ColCount >= 2); } protected: _SPIRV_DEF_ENCDEC3(Id, ColType, ColCount) private: SPIRVType *ColType; // Column Type SPIRVWord ColCount; // Column Count }; class SPIRVTypeArray : public SPIRVType { public: // Complete constructor SPIRVTypeArray(SPIRVModule *M, SPIRVId TheId, SPIRVType *TheElemType, SPIRVConstant *TheLength); // Incomplete constructor SPIRVTypeArray() : SPIRVType(OpTypeArray), ElemType(nullptr), Length(SPIRVID_INVALID) {} SPIRVType *getElementType() const { return ElemType; } SPIRVConstant *getLength() const; SPIRVCapVec getRequiredCapability() const override { return getElementType()->getRequiredCapability(); } std::vector getNonLiteralOperands() const override { std::vector Operands(2, ElemType); Operands[1] = (SPIRVEntry *)getLength(); return Operands; } protected: _SPIRV_DCL_ENCDEC void validate() const override; private: SPIRVType *ElemType; // Element Type SPIRVId Length; // Array Length }; class SPIRVTypeOpaque : public SPIRVType { public: // Complete constructor SPIRVTypeOpaque(SPIRVModule *M, SPIRVId TheId, const std::string &TheName) : SPIRVType(M, 2 + getSizeInWords(TheName), OpTypeOpaque, TheId) { Name = TheName; validate(); } // Incomplete constructor SPIRVTypeOpaque() : SPIRVType(OpTypeOpaque) {} protected: _SPIRV_DEF_ENCDEC2(Id, Name) void validate() const override { SPIRVEntry::validate(); } }; struct SPIRVTypeImageDescriptor { SPIRVImageDimKind Dim; SPIRVWord Depth; SPIRVWord Arrayed; SPIRVWord MS; SPIRVWord Sampled; SPIRVWord Format; static std::tuple< std::tuple, SPIRVWord> getAsTuple(const SPIRVTypeImageDescriptor &Desc) { return std::make_tuple(std::make_tuple(Desc.Dim, Desc.Depth, Desc.Arrayed, Desc.MS, Desc.Sampled), Desc.Format); } SPIRVTypeImageDescriptor() : Dim(Dim1D), Depth(0), Arrayed(0), MS(0), Sampled(0), Format(0) {} SPIRVTypeImageDescriptor(SPIRVImageDimKind Dim, SPIRVWord Cont, SPIRVWord Arr, SPIRVWord Comp, SPIRVWord Mult, SPIRVWord F) : Dim(Dim), Depth(Cont), Arrayed(Arr), MS(Comp), Sampled(Mult), Format(F) {} }; template <> inline void SPIRVMap::init() { #define _SPIRV_OP(x, ...) \ { \ SPIRVTypeImageDescriptor S(__VA_ARGS__); \ add(#x, S); \ } _SPIRV_OP(image1d_t, Dim1D, 0, 0, 0, 0, 0) _SPIRV_OP(image1d_buffer_t, DimBuffer, 0, 0, 0, 0, 0) _SPIRV_OP(image1d_array_t, Dim1D, 0, 1, 0, 0, 0) _SPIRV_OP(image2d_t, Dim2D, 0, 0, 0, 0, 0) _SPIRV_OP(image2d_array_t, Dim2D, 0, 1, 0, 0, 0) _SPIRV_OP(image2d_depth_t, Dim2D, 1, 0, 0, 0, 0) _SPIRV_OP(image2d_array_depth_t, Dim2D, 1, 1, 0, 0, 0) _SPIRV_OP(image2d_msaa_t, Dim2D, 0, 0, 1, 0, 0) _SPIRV_OP(image2d_array_msaa_t, Dim2D, 0, 1, 1, 0, 0) _SPIRV_OP(image2d_msaa_depth_t, Dim2D, 1, 0, 1, 0, 0) _SPIRV_OP(image2d_array_msaa_depth_t, Dim2D, 1, 1, 1, 0, 0) _SPIRV_OP(image3d_t, Dim3D, 0, 0, 0, 0, 0) #undef _SPIRV_OP } typedef SPIRVMap OCLSPIRVImageTypeMap; // Comparision function required to use the struct as map key. inline bool operator<(const SPIRVTypeImageDescriptor &A, const SPIRVTypeImageDescriptor &B) { return SPIRVTypeImageDescriptor::getAsTuple(A) < SPIRVTypeImageDescriptor::getAsTuple(B); } class SPIRVTypeImage : public SPIRVType { public: const static Op OC = OpTypeImage; const static SPIRVWord FixedWC = 9; SPIRVTypeImage(SPIRVModule *M, SPIRVId TheId, SPIRVId TheSampledType, const SPIRVTypeImageDescriptor &TheDesc) : SPIRVType(M, FixedWC, OC, TheId), SampledType(TheSampledType), Desc(TheDesc) { validate(); } SPIRVTypeImage(SPIRVModule *M, SPIRVId TheId, SPIRVId TheSampledType, const SPIRVTypeImageDescriptor &TheDesc, SPIRVAccessQualifierKind TheAcc) : SPIRVType(M, FixedWC + 1, OC, TheId), SampledType(TheSampledType), Desc(TheDesc) { Acc.push_back(TheAcc); validate(); } SPIRVTypeImage() : SPIRVType(OC), SampledType(SPIRVID_INVALID), Desc() {} const SPIRVTypeImageDescriptor &getDescriptor() const { return Desc; } bool isOCLImage() const { return Desc.Sampled == 0 && Desc.Format == 0; } bool hasAccessQualifier() const { return !Acc.empty(); } SPIRVAccessQualifierKind getAccessQualifier() const { assert(hasAccessQualifier()); return Acc[0]; } SPIRVCapVec getRequiredCapability() const override { SPIRVCapVec CV; CV.push_back(CapabilityImageBasic); if (Desc.Dim == SPIRVImageDimKind::Dim1D) CV.push_back(CapabilitySampled1D); else if (Desc.Dim == SPIRVImageDimKind::DimBuffer) CV.push_back(CapabilitySampledBuffer); if (Acc.size() > 0 && Acc[0] == AccessQualifierReadWrite) CV.push_back(CapabilityImageReadWrite); if (Desc.MS) CV.push_back(CapabilityImageMipmap); return CV; } SPIRVType *getSampledType() const { return get(SampledType); } std::vector getNonLiteralOperands() const override { return std::vector(1, get(SampledType)); } protected: _SPIRV_DEF_ENCDEC9(Id, SampledType, Desc.Dim, Desc.Depth, Desc.Arrayed, Desc.MS, Desc.Sampled, Desc.Format, Acc) // The validation assumes OpenCL image or sampler type. void validate() const override { assert(OpCode == OC); assert(WordCount == FixedWC + Acc.size()); assert(SampledType != SPIRVID_INVALID && "Invalid sampled type"); assert(Desc.Dim <= 5); assert(Desc.Depth <= 1); assert(Desc.Arrayed <= 1); assert(Desc.MS <= 1); assert(Desc.Sampled == 0); // For OCL only assert(Desc.Format == 0); // For OCL only assert(Acc.size() <= 1); } void setWordCount(SPIRVWord TheWC) override { WordCount = TheWC; Acc.resize(WordCount - FixedWC); } private: SPIRVId SampledType; SPIRVTypeImageDescriptor Desc; std::vector Acc; }; class SPIRVTypeSampler : public SPIRVType { public: const static Op OC = OpTypeSampler; const static SPIRVWord FixedWC = 2; SPIRVTypeSampler(SPIRVModule *M, SPIRVId TheId) : SPIRVType(M, FixedWC, OC, TheId) { validate(); } SPIRVTypeSampler() : SPIRVType(OC) {} protected: _SPIRV_DEF_ENCDEC1(Id) void validate() const override { assert(OpCode == OC); assert(WordCount == FixedWC); } }; class SPIRVTypeSampledImage : public SPIRVType { public: const static Op OC = OpTypeSampledImage; const static SPIRVWord FixedWC = 3; SPIRVTypeSampledImage(SPIRVModule *M, SPIRVId TheId, SPIRVTypeImage *TheImgTy) : SPIRVType(M, FixedWC, OC, TheId), ImgTy(TheImgTy) { validate(); } SPIRVTypeSampledImage() : SPIRVType(OC), ImgTy(nullptr) {} const SPIRVTypeImage *getImageType() const { return ImgTy; } void setImageType(SPIRVTypeImage *TheImgTy) { ImgTy = TheImgTy; } std::vector getNonLiteralOperands() const override { return std::vector(1, ImgTy); } protected: SPIRVTypeImage *ImgTy; _SPIRV_DEF_ENCDEC2(Id, ImgTy) void validate() const override { assert(OpCode == OC); assert(WordCount == FixedWC); assert(ImgTy && ImgTy->isTypeImage()); } }; class SPIRVTypePipeStorage : public SPIRVType { public: const static Op OC = OpTypePipeStorage; const static SPIRVWord FixedWC = 2; SPIRVTypePipeStorage(SPIRVModule *M, SPIRVId TheId) : SPIRVType(M, FixedWC, OC, TheId) { validate(); } SPIRVTypePipeStorage() : SPIRVType(OC) {} protected: _SPIRV_DEF_ENCDEC1(Id) void validate() const override { assert(OpCode == OC); assert(WordCount == FixedWC); } }; class SPIRVTypeStruct : public SPIRVType { public: // Complete constructor SPIRVTypeStruct(SPIRVModule *M, SPIRVId TheId, const std::vector &TheMemberTypes, const std::string &TheName) : SPIRVType(M, 2 + TheMemberTypes.size(), OpTypeStruct, TheId) { MemberTypeIdVec.resize(TheMemberTypes.size()); for (auto &T : TheMemberTypes) MemberTypeIdVec.push_back(T->getId()); Name = TheName; validate(); } SPIRVTypeStruct(SPIRVModule *M, SPIRVId TheId, unsigned NumMembers, const std::string &TheName) : SPIRVType(M, 2 + NumMembers, OpTypeStruct, TheId) { Name = TheName; validate(); MemberTypeIdVec.resize(NumMembers); } // Incomplete constructor SPIRVTypeStruct() : SPIRVType(OpTypeStruct) {} SPIRVWord getMemberCount() const { return MemberTypeIdVec.size(); } SPIRVType *getMemberType(size_t I) const { return static_cast(getEntry(MemberTypeIdVec[I])); } void setMemberType(size_t I, SPIRVType *Ty) { MemberTypeIdVec[I] = Ty->getId(); } bool isPacked() const; void setPacked(bool Packed); void setWordCount(SPIRVWord WordCount) override { SPIRVType::setWordCount(WordCount); MemberTypeIdVec.resize(WordCount - 2); } std::vector getNonLiteralOperands() const override { std::vector Operands(MemberTypeIdVec.size()); for (size_t I = 0, E = MemberTypeIdVec.size(); I < E; ++I) Operands[I] = getEntry(MemberTypeIdVec[I]); return Operands; } protected: _SPIRV_DEF_ENCDEC2(Id, MemberTypeIdVec) void validate() const override { SPIRVEntry::validate(); } private: std::vector MemberTypeIdVec; // Member Type Ids }; class SPIRVTypeFunction : public SPIRVType { public: // Complete constructor SPIRVTypeFunction(SPIRVModule *M, SPIRVId TheId, SPIRVType *TheReturnType, const std::vector &TheParameterTypes) : SPIRVType(M, 3 + TheParameterTypes.size(), OpTypeFunction, TheId), ReturnType(TheReturnType), ParamTypeVec(TheParameterTypes) { validate(); } // Incomplete constructor SPIRVTypeFunction() : SPIRVType(OpTypeFunction), ReturnType(NULL) {} SPIRVType *getReturnType() const { return ReturnType; } SPIRVWord getNumParameters() const { return ParamTypeVec.size(); } SPIRVType *getParameterType(unsigned I) const { return ParamTypeVec[I]; } std::vector getNonLiteralOperands() const override { std::vector Operands(1 + ParamTypeVec.size(), ReturnType); std::copy(ParamTypeVec.begin(), ParamTypeVec.end(), ++Operands.begin()); return Operands; } protected: _SPIRV_DEF_ENCDEC3(Id, ReturnType, ParamTypeVec) void setWordCount(SPIRVWord WordCount) override { SPIRVType::setWordCount(WordCount); ParamTypeVec.resize(WordCount - 3); } void validate() const override { SPIRVEntry::validate(); ReturnType->validate(); for (auto T : ParamTypeVec) T->validate(); } private: SPIRVType *ReturnType; // Return Type std::vector ParamTypeVec; // Parameter Types }; class SPIRVTypeOpaqueGeneric : public SPIRVType { public: // Complete constructor SPIRVTypeOpaqueGeneric(Op TheOpCode, SPIRVModule *M, SPIRVId TheId) : SPIRVType(M, 2, TheOpCode, TheId) { validate(); } // Incomplete constructor SPIRVTypeOpaqueGeneric(Op TheOpCode) : SPIRVType(TheOpCode), Opn(SPIRVID_INVALID) {} SPIRVValue *getOperand() { return getValue(Opn); } protected: _SPIRV_DEF_ENCDEC1(Id) void validate() const override { SPIRVEntry::validate(); } SPIRVId Opn; }; template class SPIRVOpaqueGenericType : public SPIRVTypeOpaqueGeneric { public: // Complete constructor SPIRVOpaqueGenericType(SPIRVModule *M, SPIRVId TheId) : SPIRVTypeOpaqueGeneric(TheOpCode, M, TheId) {} // Incomplete constructor SPIRVOpaqueGenericType() : SPIRVTypeOpaqueGeneric(TheOpCode) {} }; #define _SPIRV_OP(x) typedef SPIRVOpaqueGenericType SPIRVType##x; _SPIRV_OP(Event) _SPIRV_OP(ReserveId) #undef _SPIRV_OP class SPIRVTypeDeviceEvent : public SPIRVType { public: // Complete constructor SPIRVTypeDeviceEvent(SPIRVModule *M, SPIRVId TheId) : SPIRVType(M, 2, OpTypeDeviceEvent, TheId) { validate(); } // Incomplete constructor SPIRVTypeDeviceEvent() : SPIRVType(OpTypeDeviceEvent) {} SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilityDeviceEnqueue); } protected: _SPIRV_DEF_ENCDEC1(Id) void validate() const override { SPIRVEntry::validate(); } }; class SPIRVTypeQueue : public SPIRVType { public: // Complete constructor SPIRVTypeQueue(SPIRVModule *M, SPIRVId TheId) : SPIRVType(M, 2, OpTypeQueue, TheId) { validate(); } // Incomplete constructor SPIRVTypeQueue() : SPIRVType(OpTypeQueue) {} SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilityDeviceEnqueue); } protected: _SPIRV_DEF_ENCDEC1(Id) }; class SPIRVTypePipe : public SPIRVType { public: // Complete constructor SPIRVTypePipe(SPIRVModule *M, SPIRVId TheId, SPIRVAccessQualifierKind AccessQual = AccessQualifierReadOnly) : SPIRVType(M, 3, OpTypePipe, TheId), AccessQualifier(AccessQual) { validate(); } // Incomplete constructor SPIRVTypePipe() : SPIRVType(OpTypePipe), AccessQualifier(AccessQualifierReadOnly) {} SPIRVAccessQualifierKind getAccessQualifier() const { return AccessQualifier; } void setPipeAcessQualifier(SPIRVAccessQualifierKind AccessQual) { AccessQualifier = AccessQual; assert(isValid(AccessQualifier)); } SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilityPipes); } protected: _SPIRV_DEF_ENCDEC2(Id, AccessQualifier) void validate() const override { SPIRVEntry::validate(); } private: SPIRVAccessQualifierKind AccessQualifier; // Access Qualifier }; template bool isType(const T1 *Ty, unsigned Bits = 0) { bool Is = Ty->getOpCode() == T2::OC; if (!Is) return false; if (Bits == 0) return true; return static_cast(Ty)->getBitWidth() == Bits; } // SPV_INTEL_device_side_avc_motion_estimation extension types class SPIRVTypeVmeImageINTEL : public SPIRVType { public: const static Op OC = OpTypeVmeImageINTEL; const static SPIRVWord FixedWC = 3; SPIRVTypeVmeImageINTEL(SPIRVModule *M, SPIRVId TheId, SPIRVTypeImage *TheImgTy) : SPIRVType(M, FixedWC, OC, TheId), ImgTy(TheImgTy) { validate(); } SPIRVTypeVmeImageINTEL() : SPIRVType(OC), ImgTy(nullptr) {} const SPIRVTypeImage *getImageType() const { return ImgTy; } void setImageType(SPIRVTypeImage *TheImgTy) { ImgTy = TheImgTy; } virtual std::vector getNonLiteralOperands() const override { return std::vector(1, ImgTy); } SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilitySubgroupAvcMotionEstimationINTEL); } SPIRVExtSet getRequiredExtensions() const override { return getSet(ExtensionID::SPV_INTEL_device_side_avc_motion_estimation); } protected: SPIRVTypeImage *ImgTy; _SPIRV_DEF_ENCDEC2(Id, ImgTy) void validate() const override { assert(OpCode == OC); assert(WordCount == FixedWC); assert(ImgTy && ImgTy->isTypeImage()); } }; class SPIRVTypeSubgroupINTEL; template <> inline void SPIRVMap::init() { #define _SPIRV_OP(x, y) \ add("opencl.intel_sub_group_avc_" #x, OpTypeAvc##y##INTEL); _SPIRV_OP(mce_payload_t, McePayload) _SPIRV_OP(mce_result_t, MceResult) _SPIRV_OP(sic_payload_t, SicPayload) _SPIRV_OP(sic_result_t, SicResult) _SPIRV_OP(ime_result_single_reference_streamout_t, ImeResultSingleReferenceStreamout) _SPIRV_OP(ime_result_dual_reference_streamout_t, ImeResultDualReferenceStreamout) _SPIRV_OP(ime_single_reference_streamin_t, ImeSingleReferenceStreamin) _SPIRV_OP(ime_dual_reference_streamin_t, ImeDualReferenceStreamin) _SPIRV_OP(ime_payload_t, ImePayload) _SPIRV_OP(ime_result_t, ImeResult) _SPIRV_OP(ref_payload_t, RefPayload) _SPIRV_OP(ref_result_t, RefResult); #undef _SPIRV_OP } typedef SPIRVMap OCLSubgroupINTELTypeOpCodeMap; class SPIRVTypeSubgroupAvcINTEL : public SPIRVType { public: // Complete constructor SPIRVTypeSubgroupAvcINTEL(Op TheOpCode, SPIRVModule *M, SPIRVId TheId) : SPIRVType(M, 2, TheOpCode, TheId) { validate(); } // Incomplete constructor SPIRVTypeSubgroupAvcINTEL(Op TheOpCode) : SPIRVType(TheOpCode), Opn(SPIRVID_INVALID) {} SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilitySubgroupAvcMotionEstimationINTEL); } SPIRVExtSet getRequiredExtensions() const override { return getSet(ExtensionID::SPV_INTEL_device_side_avc_motion_estimation); } SPIRVValue *getOperand() { return getValue(Opn); } protected: _SPIRV_DEF_ENCDEC1(Id) void validate() const override { SPIRVEntry::validate(); } SPIRVId Opn; }; template class SPIRVSubgroupAvcINTELType : public SPIRVTypeSubgroupAvcINTEL { public: // Complete constructor SPIRVSubgroupAvcINTELType(SPIRVModule *M, SPIRVId TheId) : SPIRVTypeSubgroupAvcINTEL(TheOpCode, M, TheId) {} // Incomplete constructor SPIRVSubgroupAvcINTELType() : SPIRVTypeSubgroupAvcINTEL(TheOpCode) {} }; #define _SPIRV_OP(x) \ typedef SPIRVSubgroupAvcINTELType SPIRVType##x##INTEL; _SPIRV_OP(AvcMcePayload) _SPIRV_OP(AvcImePayload) _SPIRV_OP(AvcRefPayload) _SPIRV_OP(AvcSicPayload) _SPIRV_OP(AvcMceResult) _SPIRV_OP(AvcImeResult) _SPIRV_OP(AvcImeResultSingleReferenceStreamout) _SPIRV_OP(AvcImeResultDualReferenceStreamout) _SPIRV_OP(AvcImeSingleReferenceStreamin) _SPIRV_OP(AvcImeDualReferenceStreamin) _SPIRV_OP(AvcRefResult) _SPIRV_OP(AvcSicResult) #undef _SPIRV_OP } // namespace SPIRV #endif // SPIRV_LIBSPIRV_SPIRVTYPE_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVUtil.h000066400000000000000000000271521363521741200223620ustar00rootroot00000000000000//===- SPIRVUtil.h - SPIR-V Utility Functions -------------------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines SPIR-V utility functions. /// //===----------------------------------------------------------------------===// #ifndef SPIRV_LIBSPIRV_SPIRVUTIL_H #define SPIRV_LIBSPIRV_SPIRVUTIL_H #include #define spv_ostream std::ostream #include #include #include #include #include #include #include #include #include #include #include // MSVC supports "magic statics" since MSVS 2015. // For the previous version of MSVS we should guard // initialization of local static variables. #if defined(_MSC_VER) && (_MSC_VER < 1900) #include "llvm/Support/Mutex.h" #include "llvm/Support/MutexGuard.h" #endif // LLVM_MSC_PREREQ(1900) namespace SPIRV { #if defined(_MSC_VER) && (_MSC_VER < 1900) static llvm::sys::Mutex MapLock; #endif // LLVM_MSC_PREREQ(1900) #define SPIRV_DEF_NAMEMAP(Type, MapType) \ typedef SPIRVMap(MapType); \ inline MapType getNameMap(Type) { \ MapType MT; \ return MT; \ } // A bi-way map template struct SPIRVMap { public: typedef Ty1 KeyTy; typedef Ty2 ValueTy; // Initialize map entries void init(); static Ty2 map(Ty1 Key) { Ty2 Val; bool Found = find(Key, &Val); (void)Found; assert(Found && "Invalid key"); return Val; } static Ty1 rmap(Ty2 Key) { Ty1 Val; bool Found = rfind(Key, &Val); (void)Found; assert(Found && "Invalid key"); return Val; } static const SPIRVMap &getMap() { #if defined(_MSC_VER) && (_MSC_VER < 1900) llvm::sys::ScopedLock mapGuard(MapLock); #endif // LLVM_MSC_PREREQ(1900) static const SPIRVMap Map(false); return Map; } static const SPIRVMap &getRMap() { #if defined(_MSC_VER) && (_MSC_VER < 1900) llvm::sys::ScopedLock mapGuard(MapLock); #endif // LLVM_MSC_PREREQ(1900) static const SPIRVMap Map(true); return Map; } static void foreach (std::function F) { for (auto &I : getMap().Map) F(I.first, I.second); } // For each key/value in the map executes function \p F. // If \p F returns false break the iteration. static void foreachConditional(std::function F) { for (auto &I : getMap().Map) { if (!F(I.first, I.second)) break; } } static bool find(Ty1 Key, Ty2 *Val = nullptr) { const SPIRVMap &Map = getMap(); typename MapTy::const_iterator Loc = Map.Map.find(Key); if (Loc == Map.Map.end()) return false; if (Val) *Val = Loc->second; return true; } static bool rfind(Ty2 Key, Ty1 *Val = nullptr) { const SPIRVMap &Map = getRMap(); typename RevMapTy::const_iterator Loc = Map.RevMap.find(Key); if (Loc == Map.RevMap.end()) return false; if (Val) *Val = Loc->second; return true; } SPIRVMap() : IsReverse(false) {} protected: SPIRVMap(bool Reverse) : IsReverse(Reverse) { init(); } typedef std::map MapTy; typedef std::map RevMapTy; void add(Ty1 V1, Ty2 V2) { if (IsReverse) { RevMap[V2] = V1; return; } Map[V1] = V2; } MapTy Map; RevMapTy RevMap; bool IsReverse; }; inline std::vector getVec(const std::string &S, char Delim) { std::vector Strs; std::stringstream SS(S); std::string Item; while (std::getline(SS, Item, Delim)) Strs.push_back(Item); return Strs; } inline std::unordered_set getUnordSet(const std::string &S, char Delim = ' ') { std::unordered_set Strs; std::stringstream SS(S); std::string Item; while (std::getline(SS, Item, Delim)) Strs.insert(Item); return Strs; } inline std::set getSet(const std::string &S, char Delim = ' ') { std::set Strs; std::stringstream SS(S); std::string Item; while (std::getline(SS, Item, Delim)) Strs.insert(Item); return Strs; } template VT map(KT Key) { return SPIRVMap::map(Key); } template KT rmap(VT V) { return SPIRVMap::rmap(V); } template std::unordered_set map(const std::unordered_set &KSet) { VT V; std::unordered_set VSet; for (auto &I : KSet) if (SPIRVMap::find(I, &V)) VSet.insert(V); return VSet; } template std::set map(const std::set &KSet) { VT V; std::set VSet; for (auto &I : KSet) if (SPIRVMap::find(I, &V)) VSet.insert(V); return VSet; } template std::unordered_set rmap(const std::unordered_set &KSet) { KT V; std::unordered_set VSet; for (auto &I : KSet) if (SPIRVMap::rfind(I, &V)) VSet.insert(V); return VSet; } template std::set rmap(const std::set &KSet) { KT V; std::set VSet; for (auto &I : KSet) if (SPIRVMap::rfind(I, &V)) VSet.insert(V); return VSet; } template std::set rmap(const std::map &KMap) { KT V; std::set VSet; for (auto &I : KMap) if (SPIRVMap::rfind(I.first, &V)) VSet.insert(V); return VSet; } template std::string getName(K Key) { std::string Name; if (SPIRVMap::find(Key, &Name)) return Name; return ""; } template bool getByName(const std::string &Name, K &Key) { return SPIRVMap::rfind(Name, &Key); } // Add a number as a string to a string template std::string concat(const std::string &S, const T &N) { std::stringstream Ss; Ss << S << N; return Ss.str(); } inline std::string concat(const std::string &S1, const std::string &S2, char Delim = ' ') { std::string S; if (S1.empty()) S = S2; else if (!S2.empty()) S = S1 + Delim + S2; return S; } inline std::string operator+(const std::string &S, int N) { return concat(S, N); } inline std::string operator+(const std::string &S, unsigned N) { return concat(S, N); } template std::string getStr(const T &C, char Delim = ' ') { std::stringstream SS; bool First = true; for (auto &I : C) { if (!First) SS << Delim; else First = false; SS << I; } return SS.str(); } template unsigned mapBitMask(unsigned BM) { unsigned Res = 0; MapTy::foreach ([&](typename MapTy::KeyTy K, typename MapTy::ValueTy V) { Res |= BM & (unsigned)K ? (unsigned)V : 0; }); return Res; } template unsigned rmapBitMask(unsigned BM) { unsigned Res = 0; MapTy::foreach ([&](typename MapTy::KeyTy K, typename MapTy::ValueTy V) { Res |= BM & (unsigned)V ? (unsigned)K : 0; }); return Res; } // Get the number of words used for encoding a string literal in SPIRV inline unsigned getSizeInWords(const std::string &Str) { assert(Str.length() / 4 + 1 <= std::numeric_limits::max()); return static_cast(Str.length() / 4 + 1); } inline std::string getString(std::vector::const_iterator Begin, std::vector::const_iterator End) { std::string Str = std::string(); for (auto I = Begin; I != End; ++I) { uint32_t Word = *I; for (unsigned J = 0u; J < 32u; J += 8u) { char Char = (char)((Word >> J) & 0xff); if (Char == '\0') return Str; Str += Char; } } return Str; } inline std::string getString(const std::vector &V) { return getString(V.cbegin(), V.cend()); } // if vector of Literals is expected to contain more than one Literal String inline std::vector getVecString(const std::vector &V) { std::vector Result; std::string Str; for (auto It = V.cbegin(); It < V.cend(); It += getSizeInWords(Str)) { Str.clear(); Str = getString(It, V.cend()); Result.push_back(Str); } return Result; } inline std::vector getVec(const std::string &Str) { std::vector V; auto StrSize = Str.size(); uint32_t CurrentWord = 0u; for (unsigned I = 0u; I < StrSize; ++I) { if (I % 4u == 0u && I != 0u) { V.push_back(CurrentWord); CurrentWord = 0u; } assert(Str[I] && "0 is not allowed in string"); CurrentWord += ((uint32_t)Str[I]) << ((I % 4u) * 8u); } if (CurrentWord != 0u) V.push_back(CurrentWord); if (StrSize % 4 == 0) V.push_back(0); return V; } template inline std::set getSet(T Op1) { std::set S; S.insert(Op1); return S; } template inline std::vector getVec(T Op1) { std::vector V; V.push_back(Op1); return V; } template inline std::vector getVec(T Op1, T Op2) { std::vector V; V.push_back(Op1); V.push_back(Op2); return V; } template inline std::vector getVec(T Op1, T Op2, T Op3) { std::vector V; V.push_back(Op1); V.push_back(Op2); V.push_back(Op3); return V; } template inline std::vector getVec(T Op1, const std::vector &Ops2) { std::vector V; V.push_back(Op1); V.insert(V.end(), Ops2.begin(), Ops2.end()); return V; } template typename MapTy::mapped_type getOrInsert(MapTy &Map, typename MapTy::key_type Key, FuncTy Func) { typename MapTy::iterator Loc = Map.find(Key); if (Loc != Map.end()) return Loc->second; typename MapTy::mapped_type NF = Func(); Map[Key] = NF; return NF; } } // namespace SPIRV #endif // SPIRV_LIBSPIRV_SPIRVUTIL_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVValue.cpp000066400000000000000000000110661363521741200230510ustar00rootroot00000000000000//===- SPIRVValue.cpp - Class to represent a SPIR-V Value -------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines the values defined in SPIR-V spec with op codes. /// /// The name of the SPIR-V values follow the op code name in the spec. /// This is for readability and ease of using macro to handle types. // //===----------------------------------------------------------------------===// #include "SPIRVValue.h" #include "SPIRVEnum.h" namespace SPIRV { void SPIRVValue::setAlignment(SPIRVWord A) { if (A == 0) { eraseDecorate(DecorationAlignment); return; } addDecorate(new SPIRVDecorate(DecorationAlignment, this, A)); SPIRVDBG(spvdbgs() << "Set alignment " << A << " for obj " << Id << "\n") } bool SPIRVValue::hasAlignment(SPIRVWord *Result) const { return hasDecorate(DecorationAlignment, 0, Result); } bool SPIRVValue::isVolatile() const { return hasDecorate(DecorationVolatile); } void SPIRVValue::setVolatile(bool IsVolatile) { if (!IsVolatile) { eraseDecorate(DecorationVolatile); return; } addDecorate(new SPIRVDecorate(DecorationVolatile, this)); SPIRVDBG(spvdbgs() << "Set volatile " << " for obj " << Id << "\n") } bool SPIRVValue::hasNoSignedWrap() const { return hasDecorate(DecorationNoSignedWrap); } void SPIRVValue::setNoSignedWrap(bool HasNoSignedWrap) { if (!HasNoSignedWrap) { eraseDecorate(DecorationNoSignedWrap); } if (Module->isAllowedToUseExtension( ExtensionID::SPV_KHR_no_integer_wrap_decoration)) { // NoSignedWrap decoration is available only if it is allowed to use SPIR-V // 1.4 or if SPV_KHR_no_integer_wrap_decoration extension is allowed // FIXME: update this 'if' to include check for SPIR-V 1.4 once translator // support this version addDecorate(new SPIRVDecorate(DecorationNoSignedWrap, this)); SPIRVDBG(spvdbgs() << "Set nsw for obj " << Id << "\n") } else { SPIRVDBG(spvdbgs() << "Skip setting nsw for obj " << Id << "\n") } } bool SPIRVValue::hasNoUnsignedWrap() const { return hasDecorate(DecorationNoUnsignedWrap); } void SPIRVValue::setNoUnsignedWrap(bool HasNoUnsignedWrap) { if (!HasNoUnsignedWrap) { eraseDecorate(DecorationNoUnsignedWrap); return; } if (Module->isAllowedToUseExtension( ExtensionID::SPV_KHR_no_integer_wrap_decoration)) { // NoUnsignedWrap decoration is available only if it is allowed to use // SPIR-V 1.4 or if SPV_KHR_no_integer_wrap_decoration extension is allowed // FIXME: update this 'if' to include check for SPIR-V 1.4 once translator // support this version addDecorate(new SPIRVDecorate(DecorationNoUnsignedWrap, this)); SPIRVDBG(spvdbgs() << "Set nuw for obj " << Id << "\n") } else { SPIRVDBG(spvdbgs() << "Skip setting nuw for obj " << Id << "\n") } } } // namespace SPIRV SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/SPIRVValue.h000066400000000000000000000327701363521741200225230ustar00rootroot00000000000000//===- SPIRVValue.h - Class to represent a SPIR-V Value ---------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines the values defined in SPIR-V spec with op codes. /// /// The name of the SPIR-V values follow the op code name in the spec. /// This is for readability and ease of using macro to handle types. // //===----------------------------------------------------------------------===// #ifndef SPIRV_LIBSPIRV_SPIRVVALUE_H #define SPIRV_LIBSPIRV_SPIRVVALUE_H #include "SPIRVDecorate.h" #include "SPIRVEntry.h" #include "SPIRVType.h" #include #include #include namespace SPIRV { class SPIRVValue : public SPIRVEntry { public: // Complete constructor for value with id and type SPIRVValue(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode, SPIRVType *TheType, SPIRVId TheId) : SPIRVEntry(M, TheWordCount, TheOpCode, TheId), Type(TheType) { validate(); } // Complete constructor for value with type but without id SPIRVValue(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode, SPIRVType *TheType) : SPIRVEntry(M, TheWordCount, TheOpCode), Type(TheType) { setHasNoId(); SPIRVValue::validate(); } // Complete constructor for value with id but without type SPIRVValue(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode, SPIRVId TheId) : SPIRVEntry(M, TheWordCount, TheOpCode, TheId), Type(NULL) { setHasNoType(); SPIRVValue::validate(); } // Complete constructor for value without id and type SPIRVValue(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode) : SPIRVEntry(M, TheWordCount, TheOpCode), Type(NULL) { setHasNoId(); setHasNoType(); SPIRVValue::validate(); } // Incomplete constructor SPIRVValue(Op TheOpCode) : SPIRVEntry(TheOpCode), Type(NULL) {} bool hasType() const { return !(Attrib & SPIRVEA_NOTYPE); } SPIRVType *getType() const { assert(hasType() && "value has no type"); return Type; } bool isVolatile() const; bool hasAlignment(SPIRVWord *Result = 0) const; bool hasNoSignedWrap() const; bool hasNoUnsignedWrap() const; void setAlignment(SPIRVWord); void setVolatile(bool IsVolatile); void setNoSignedWrap(bool HasNoSignedWrap); void setNoUnsignedWrap(bool HasNoUnsignedWrap); void validate() const override { SPIRVEntry::validate(); assert((!hasType() || Type) && "Invalid type"); } void setType(SPIRVType *Ty) { Type = Ty; assert(!Ty || !Ty->isTypeVoid() || OpCode == OpFunction); if (Ty && (!Ty->isTypeVoid() || OpCode == OpFunction)) setHasType(); else setHasNoType(); } SPIRVCapVec getRequiredCapability() const override { SPIRVCapVec CV; if (!hasType()) return CV; return Type->getRequiredCapability(); } SPIRVExtSet getRequiredExtensions() const override { SPIRVExtSet EV; if (!hasType()) return EV; EV = Type->getRequiredExtensions(); assert(!Module || Module->isAllowedToUseExtensions(EV)); return EV; } protected: void setHasNoType() { Attrib |= SPIRVEA_NOTYPE; } void setHasType() { Attrib &= ~SPIRVEA_NOTYPE; } SPIRVType *Type; // Value Type }; template class SPIRVConstantBase : public SPIRVValue { public: // Complete constructor for integer constant SPIRVConstantBase(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId, uint64_t TheValue) : SPIRVValue(M, 0, OC, TheType, TheId) { Union.UInt64Val = TheValue; recalculateWordCount(); validate(); } // Complete constructor for float constant SPIRVConstantBase(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId, float TheValue) : SPIRVValue(M, 0, OC, TheType, TheId) { Union.FloatVal = TheValue; recalculateWordCount(); validate(); } // Complete constructor for double constant SPIRVConstantBase(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId, double TheValue) : SPIRVValue(M, 0, OC, TheType, TheId) { Union.DoubleVal = TheValue; recalculateWordCount(); validate(); } // Incomplete constructor SPIRVConstantBase() : SPIRVValue(OC), NumWords(0) {} uint64_t getZExtIntValue() const { return Union.UInt64Val; } float getFloatValue() const { return Union.FloatVal; } double getDoubleValue() const { return Union.DoubleVal; } protected: void recalculateWordCount() { NumWords = Type->getBitWidth() / 32; if (NumWords < 1) NumWords = 1; WordCount = 3 + NumWords; } void validate() const override { SPIRVValue::validate(); assert(NumWords >= 1 && NumWords <= 2 && "Invalid constant size"); } void encode(spv_ostream &O) const override { getEncoder(O) << Type << Id; for (unsigned I = 0; I < NumWords; ++I) getEncoder(O) << Union.Words[I]; } void setWordCount(SPIRVWord WordCount) override { SPIRVValue::setWordCount(WordCount); NumWords = WordCount - 3; } void decode(std::istream &I) override { getDecoder(I) >> Type >> Id; for (unsigned J = 0; J < NumWords; ++J) getDecoder(I) >> Union.Words[J]; } unsigned NumWords; union UnionType { uint64_t UInt64Val; float FloatVal; double DoubleVal; SPIRVWord Words[2]; UnionType() { UInt64Val = 0; } } Union; }; using SPIRVConstant = SPIRVConstantBase; using SPIRVSpecConstant = SPIRVConstantBase; template class SPIRVConstantEmpty : public SPIRVValue { public: // Complete constructor SPIRVConstantEmpty(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId) : SPIRVValue(M, 3, OC, TheType, TheId) { validate(); } // Incomplete constructor SPIRVConstantEmpty() : SPIRVValue(OC) {} protected: void validate() const override { SPIRVValue::validate(); } _SPIRV_DEF_ENCDEC2(Type, Id) }; template class SPIRVConstantBool : public SPIRVConstantEmpty { public: // Complete constructor SPIRVConstantBool(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId) : SPIRVConstantEmpty(M, TheType, TheId) {} // Incomplete constructor SPIRVConstantBool() {} protected: void validate() const override { SPIRVConstantEmpty::validate(); assert(this->Type->isTypeBool() && "Invalid type"); } }; typedef SPIRVConstantBool SPIRVConstantTrue; typedef SPIRVConstantBool SPIRVConstantFalse; typedef SPIRVConstantBool SPIRVSpecConstantTrue; typedef SPIRVConstantBool SPIRVSpecConstantFalse; class SPIRVConstantNull : public SPIRVConstantEmpty { public: // Complete constructor SPIRVConstantNull(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId) : SPIRVConstantEmpty(M, TheType, TheId) { validate(); } // Incomplete constructor SPIRVConstantNull() {} protected: void validate() const override { SPIRVConstantEmpty::validate(); assert((Type->isTypeComposite() || Type->isTypeOpaque() || Type->isTypeEvent() || Type->isTypePointer() || Type->isTypeReserveId() || Type->isTypeDeviceEvent() || (Type->isTypeSubgroupAvcINTEL() && !Type->isTypeSubgroupAvcMceINTEL())) && "Invalid type"); } }; class SPIRVUndef : public SPIRVConstantEmpty { public: // Complete constructor SPIRVUndef(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId) : SPIRVConstantEmpty(M, TheType, TheId) { validate(); } // Incomplete constructor SPIRVUndef() {} protected: void validate() const override { SPIRVConstantEmpty::validate(); } }; template class SPIRVConstantCompositeBase : public SPIRVValue { public: // Complete constructor for composite constant SPIRVConstantCompositeBase(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId, const std::vector TheElements) : SPIRVValue(M, TheElements.size() + 3, OpConstantComposite, TheType, TheId) { Elements = getIds(TheElements); validate(); } // Incomplete constructor SPIRVConstantCompositeBase() : SPIRVValue(OpConstantComposite) {} std::vector getElements() const { return getValues(Elements); } std::vector getNonLiteralOperands() const override { std::vector Elements = getElements(); return std::vector(Elements.begin(), Elements.end()); } protected: void validate() const override { SPIRVValue::validate(); for (auto &I : Elements) getValue(I)->validate(); } void setWordCount(SPIRVWord WordCount) override { SPIRVEntry::setWordCount(WordCount); Elements.resize(WordCount - 3); } _SPIRV_DEF_ENCDEC3(Type, Id, Elements) std::vector Elements; }; using SPIRVConstantComposite = SPIRVConstantCompositeBase; using SPIRVSpecConstantComposite = SPIRVConstantCompositeBase; class SPIRVConstantSampler : public SPIRVValue { public: const static Op OC = OpConstantSampler; const static SPIRVWord WC = 6; // Complete constructor SPIRVConstantSampler(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId, SPIRVWord TheAddrMode, SPIRVWord TheNormalized, SPIRVWord TheFilterMode) : SPIRVValue(M, WC, OC, TheType, TheId), AddrMode(TheAddrMode), Normalized(TheNormalized), FilterMode(TheFilterMode) { validate(); } // Incomplete constructor SPIRVConstantSampler() : SPIRVValue(OC), AddrMode(SPIRVSAM_Invalid), Normalized(SPIRVWORD_MAX), FilterMode(SPIRVSFM_Invalid) {} SPIRVWord getAddrMode() const { return AddrMode; } SPIRVWord getFilterMode() const { return FilterMode; } SPIRVWord getNormalized() const { return Normalized; } SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilityLiteralSampler); } protected: SPIRVWord AddrMode; SPIRVWord Normalized; SPIRVWord FilterMode; void validate() const override { SPIRVValue::validate(); assert(OpCode == OC); assert(WordCount == WC); assert(Type->isTypeSampler()); } _SPIRV_DEF_ENCDEC5(Type, Id, AddrMode, Normalized, FilterMode) }; class SPIRVConstantPipeStorage : public SPIRVValue { public: const static Op OC = OpConstantPipeStorage; const static SPIRVWord WC = 6; // Complete constructor SPIRVConstantPipeStorage(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId, SPIRVWord ThePacketSize, SPIRVWord ThePacketAlign, SPIRVWord TheCapacity) : SPIRVValue(M, WC, OC, TheType, TheId), PacketSize(ThePacketSize), PacketAlign(ThePacketAlign), Capacity(TheCapacity) { validate(); } // Incomplete constructor SPIRVConstantPipeStorage() : SPIRVValue(OC), PacketSize(0), PacketAlign(0), Capacity(0) {} SPIRVWord getPacketSize() const { return PacketSize; } SPIRVWord getPacketAlign() const { return PacketAlign; } SPIRVWord getCapacity() const { return Capacity; } SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilityPipes, CapabilityPipeStorage); } protected: SPIRVWord PacketSize; SPIRVWord PacketAlign; SPIRVWord Capacity; void validate() const override { SPIRVValue::validate(); assert(OpCode == OC); assert(WordCount == WC); assert(Type->isTypePipeStorage()); } _SPIRV_DEF_ENCDEC5(Type, Id, PacketSize, PacketAlign, Capacity) }; class SPIRVForward : public SPIRVValue, public SPIRVComponentExecutionModes { public: const static Op OC = OpForward; // Complete constructor SPIRVForward(SPIRVModule *TheModule, SPIRVType *TheTy, SPIRVId TheId) : SPIRVValue(TheModule, 0, OC, TheId) { if (TheTy) setType(TheTy); } SPIRVForward() : SPIRVValue(OC) { assert(0 && "should never be called"); } _SPIRV_DEF_ENCDEC1(Id) friend class SPIRVFunction; protected: void validate() const override {} }; } // namespace SPIRV #endif // SPIRV_LIBSPIRV_SPIRVVALUE_H SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/libSPIRV.h000066400000000000000000000044271363521741200222130ustar00rootroot00000000000000//===- libSPIRV.h - SPIR-V Header files -------------------------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // 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 Advanced Micro Devices, Inc., 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. // //===----------------------------------------------------------------------===// /// \file /// /// This file includes all SPIRV header files. /// //===----------------------------------------------------------------------===// #ifndef LIBSPIRV_H_ #define LIBSPIRV_H_ #include "SPIRVBasicBlock.h" #include "SPIRVEntry.h" #include "SPIRVFunction.h" #include "SPIRVInstruction.h" #include "SPIRVModule.h" #include "SPIRVOpCode.h" #include "SPIRVType.h" #include "SPIRVValue.h" #endif // LIBSPIRV_H_ SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/libSPIRV/spirv.hpp000066400000000000000000001130611363521741200223170ustar00rootroot00000000000000// Copyright (c) 2014-2017 The Khronos Group Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and/or associated documentation files (the "Materials"), // to deal in the Materials without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Materials, and to permit persons to whom the // Materials are furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Materials. // // MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS // STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND // HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ // // THE MATERIALS ARE 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 AUTHORS 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 MATERIALS OR THE USE OR OTHER DEALINGS // IN THE MATERIALS. // This header is automatically generated by the same tool that creates // the Binary Section of the SPIR-V specification. // Enumeration tokens for SPIR-V, in various styles: // C, C++, C++11, JSON, Lua, Python // // - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL // - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL // - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL // - Lua will use tables, e.g.: spv.SourceLanguage.GLSL // - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] // // Some tokens act like mask values, which can be OR'd together, // while others are mutually exclusive. The mask-like ones have // "Mask" in their name, and a parallel enum that has the shift // amount (1 << x) for each corresponding enumerant. #ifndef spirv_HPP #define spirv_HPP namespace spv { typedef unsigned int Id; #define SPV_VERSION 0x10100 #define SPV_REVISION 7 static const unsigned int MagicNumber = 0x07230203; static const unsigned int Version = 0x00010100; static const unsigned int Revision = 7; static const unsigned int OpCodeMask = 0xffff; static const unsigned int WordCountShift = 16; enum SourceLanguage { SourceLanguageUnknown = 0, SourceLanguageESSL = 1, SourceLanguageGLSL = 2, SourceLanguageOpenCL_C = 3, SourceLanguageOpenCL_CPP = 4, SourceLanguageHLSL = 5, SourceLanguageMax = 0x7fffffff, }; enum ExecutionModel { ExecutionModelVertex = 0, ExecutionModelTessellationControl = 1, ExecutionModelTessellationEvaluation = 2, ExecutionModelGeometry = 3, ExecutionModelFragment = 4, ExecutionModelGLCompute = 5, ExecutionModelKernel = 6, ExecutionModelMax = 0x7fffffff, }; enum AddressingModel { AddressingModelLogical = 0, AddressingModelPhysical32 = 1, AddressingModelPhysical64 = 2, AddressingModelMax = 0x7fffffff, }; enum MemoryModel { MemoryModelSimple = 0, MemoryModelGLSL450 = 1, MemoryModelOpenCL = 2, MemoryModelMax = 0x7fffffff, }; enum ExecutionMode { ExecutionModeInvocations = 0, ExecutionModeSpacingEqual = 1, ExecutionModeSpacingFractionalEven = 2, ExecutionModeSpacingFractionalOdd = 3, ExecutionModeVertexOrderCw = 4, ExecutionModeVertexOrderCcw = 5, ExecutionModePixelCenterInteger = 6, ExecutionModeOriginUpperLeft = 7, ExecutionModeOriginLowerLeft = 8, ExecutionModeEarlyFragmentTests = 9, ExecutionModePointMode = 10, ExecutionModeXfb = 11, ExecutionModeDepthReplacing = 12, ExecutionModeDepthGreater = 14, ExecutionModeDepthLess = 15, ExecutionModeDepthUnchanged = 16, ExecutionModeLocalSize = 17, ExecutionModeLocalSizeHint = 18, ExecutionModeInputPoints = 19, ExecutionModeInputLines = 20, ExecutionModeInputLinesAdjacency = 21, ExecutionModeTriangles = 22, ExecutionModeInputTrianglesAdjacency = 23, ExecutionModeQuads = 24, ExecutionModeIsolines = 25, ExecutionModeOutputVertices = 26, ExecutionModeOutputPoints = 27, ExecutionModeOutputLineStrip = 28, ExecutionModeOutputTriangleStrip = 29, ExecutionModeVecTypeHint = 30, ExecutionModeContractionOff = 31, ExecutionModeInitializer = 33, ExecutionModeFinalizer = 34, ExecutionModeSubgroupSize = 35, ExecutionModeSubgroupsPerWorkgroup = 36, ExecutionModeMaxWorkgroupSizeINTEL = 5893, ExecutionModeMaxWorkDimINTEL = 5894, ExecutionModeNoGlobalOffsetINTEL = 5895, ExecutionModeNumSIMDWorkitemsINTEL = 5896, ExecutionModeMax = 0x7fffffff, }; enum StorageClass { StorageClassUniformConstant = 0, StorageClassInput = 1, StorageClassUniform = 2, StorageClassOutput = 3, StorageClassWorkgroup = 4, StorageClassCrossWorkgroup = 5, StorageClassPrivate = 6, StorageClassFunction = 7, StorageClassGeneric = 8, StorageClassPushConstant = 9, StorageClassAtomicCounter = 10, StorageClassImage = 11, StorageClassStorageBuffer = 12, StorageClassMax = 0x7fffffff, }; enum Dim { Dim1D = 0, Dim2D = 1, Dim3D = 2, DimCube = 3, DimRect = 4, DimBuffer = 5, DimSubpassData = 6, DimMax = 0x7fffffff, }; enum SamplerAddressingMode { SamplerAddressingModeNone = 0, SamplerAddressingModeClampToEdge = 1, SamplerAddressingModeClamp = 2, SamplerAddressingModeRepeat = 3, SamplerAddressingModeRepeatMirrored = 4, SamplerAddressingModeMax = 0x7fffffff, }; enum SamplerFilterMode { SamplerFilterModeNearest = 0, SamplerFilterModeLinear = 1, SamplerFilterModeMax = 0x7fffffff, }; enum ImageFormat { ImageFormatUnknown = 0, ImageFormatRgba32f = 1, ImageFormatRgba16f = 2, ImageFormatR32f = 3, ImageFormatRgba8 = 4, ImageFormatRgba8Snorm = 5, ImageFormatRg32f = 6, ImageFormatRg16f = 7, ImageFormatR11fG11fB10f = 8, ImageFormatR16f = 9, ImageFormatRgba16 = 10, ImageFormatRgb10A2 = 11, ImageFormatRg16 = 12, ImageFormatRg8 = 13, ImageFormatR16 = 14, ImageFormatR8 = 15, ImageFormatRgba16Snorm = 16, ImageFormatRg16Snorm = 17, ImageFormatRg8Snorm = 18, ImageFormatR16Snorm = 19, ImageFormatR8Snorm = 20, ImageFormatRgba32i = 21, ImageFormatRgba16i = 22, ImageFormatRgba8i = 23, ImageFormatR32i = 24, ImageFormatRg32i = 25, ImageFormatRg16i = 26, ImageFormatRg8i = 27, ImageFormatR16i = 28, ImageFormatR8i = 29, ImageFormatRgba32ui = 30, ImageFormatRgba16ui = 31, ImageFormatRgba8ui = 32, ImageFormatR32ui = 33, ImageFormatRgb10a2ui = 34, ImageFormatRg32ui = 35, ImageFormatRg16ui = 36, ImageFormatRg8ui = 37, ImageFormatR16ui = 38, ImageFormatR8ui = 39, ImageFormatMax = 0x7fffffff, }; enum ImageChannelOrder { ImageChannelOrderR = 0, ImageChannelOrderA = 1, ImageChannelOrderRG = 2, ImageChannelOrderRA = 3, ImageChannelOrderRGB = 4, ImageChannelOrderRGBA = 5, ImageChannelOrderBGRA = 6, ImageChannelOrderARGB = 7, ImageChannelOrderIntensity = 8, ImageChannelOrderLuminance = 9, ImageChannelOrderRx = 10, ImageChannelOrderRGx = 11, ImageChannelOrderRGBx = 12, ImageChannelOrderDepth = 13, ImageChannelOrderDepthStencil = 14, ImageChannelOrdersRGB = 15, ImageChannelOrdersRGBx = 16, ImageChannelOrdersRGBA = 17, ImageChannelOrdersBGRA = 18, ImageChannelOrderABGR = 19, ImageChannelOrderMax = 0x7fffffff, }; enum ImageChannelDataType { ImageChannelDataTypeSnormInt8 = 0, ImageChannelDataTypeSnormInt16 = 1, ImageChannelDataTypeUnormInt8 = 2, ImageChannelDataTypeUnormInt16 = 3, ImageChannelDataTypeUnormShort565 = 4, ImageChannelDataTypeUnormShort555 = 5, ImageChannelDataTypeUnormInt101010 = 6, ImageChannelDataTypeSignedInt8 = 7, ImageChannelDataTypeSignedInt16 = 8, ImageChannelDataTypeSignedInt32 = 9, ImageChannelDataTypeUnsignedInt8 = 10, ImageChannelDataTypeUnsignedInt16 = 11, ImageChannelDataTypeUnsignedInt32 = 12, ImageChannelDataTypeHalfFloat = 13, ImageChannelDataTypeFloat = 14, ImageChannelDataTypeUnormInt24 = 15, ImageChannelDataTypeUnormInt101010_2 = 16, ImageChannelDataTypeMax = 0x7fffffff, }; enum ImageOperandsShift { ImageOperandsBiasShift = 0, ImageOperandsLodShift = 1, ImageOperandsGradShift = 2, ImageOperandsConstOffsetShift = 3, ImageOperandsOffsetShift = 4, ImageOperandsConstOffsetsShift = 5, ImageOperandsSampleShift = 6, ImageOperandsMinLodShift = 7, ImageOperandsMax = 0x7fffffff, }; enum ImageOperandsMask { ImageOperandsMaskNone = 0, ImageOperandsBiasMask = 0x00000001, ImageOperandsLodMask = 0x00000002, ImageOperandsGradMask = 0x00000004, ImageOperandsConstOffsetMask = 0x00000008, ImageOperandsOffsetMask = 0x00000010, ImageOperandsConstOffsetsMask = 0x00000020, ImageOperandsSampleMask = 0x00000040, ImageOperandsMinLodMask = 0x00000080, }; enum FPFastMathModeShift { FPFastMathModeNotNaNShift = 0, FPFastMathModeNotInfShift = 1, FPFastMathModeNSZShift = 2, FPFastMathModeAllowRecipShift = 3, FPFastMathModeFastShift = 4, FPFastMathModeMax = 0x7fffffff, }; enum FPFastMathModeMask { FPFastMathModeMaskNone = 0, FPFastMathModeNotNaNMask = 0x00000001, FPFastMathModeNotInfMask = 0x00000002, FPFastMathModeNSZMask = 0x00000004, FPFastMathModeAllowRecipMask = 0x00000008, FPFastMathModeFastMask = 0x00000010, }; enum FPRoundingMode { FPRoundingModeRTE = 0, FPRoundingModeRTZ = 1, FPRoundingModeRTP = 2, FPRoundingModeRTN = 3, FPRoundingModeMax = 0x7fffffff, }; enum LinkageType { LinkageTypeExport = 0, LinkageTypeImport = 1, LinkageTypeInternal, /* internal use only */ LinkageTypeMax = 0x7fffffff, }; enum AccessQualifier { AccessQualifierReadOnly = 0, AccessQualifierWriteOnly = 1, AccessQualifierReadWrite = 2, AccessQualifierMax = 0x7fffffff, }; enum FunctionParameterAttribute { FunctionParameterAttributeZext = 0, FunctionParameterAttributeSext = 1, FunctionParameterAttributeByVal = 2, FunctionParameterAttributeSret = 3, FunctionParameterAttributeNoAlias = 4, FunctionParameterAttributeNoCapture = 5, FunctionParameterAttributeNoWrite = 6, FunctionParameterAttributeNoReadWrite = 7, FunctionParameterAttributeMax = 0x7fffffff, }; enum Decoration { DecorationRelaxedPrecision = 0, DecorationSpecId = 1, DecorationBlock = 2, DecorationBufferBlock = 3, DecorationRowMajor = 4, DecorationColMajor = 5, DecorationArrayStride = 6, DecorationMatrixStride = 7, DecorationGLSLShared = 8, DecorationGLSLPacked = 9, DecorationCPacked = 10, DecorationBuiltIn = 11, DecorationNoPerspective = 13, DecorationFlat = 14, DecorationPatch = 15, DecorationCentroid = 16, DecorationSample = 17, DecorationInvariant = 18, DecorationRestrict = 19, DecorationAliased = 20, DecorationVolatile = 21, DecorationConstant = 22, DecorationCoherent = 23, DecorationNonWritable = 24, DecorationNonReadable = 25, DecorationUniform = 26, DecorationSaturatedConversion = 28, DecorationStream = 29, DecorationLocation = 30, DecorationComponent = 31, DecorationIndex = 32, DecorationBinding = 33, DecorationDescriptorSet = 34, DecorationOffset = 35, DecorationXfbBuffer = 36, DecorationXfbStride = 37, DecorationFuncParamAttr = 38, DecorationFPRoundingMode = 39, DecorationFPFastMathMode = 40, DecorationLinkageAttributes = 41, DecorationNoContraction = 42, DecorationInputAttachmentIndex = 43, DecorationAlignment = 44, DecorationMaxByteOffset = 45, DecorationNoSignedWrap = 4469, DecorationNoUnsignedWrap = 4470, DecorationOverrideCoverageNV = 5248, DecorationPassthroughNV = 5250, DecorationViewportRelativeNV = 5252, DecorationSecondaryViewportRelativeNV = 5256, DecorationReferencedIndirectlyINTEL = 5602, DecorationSideEffectsINTEL = 5608, DecorationUserSemantic = 5635, DecorationRegisterINTEL = 5825, DecorationMemoryINTEL = 5826, DecorationNumbanksINTEL = 5827, DecorationBankwidthINTEL = 5828, DecorationMaxPrivateCopiesINTEL = 5829, DecorationSinglepumpINTEL = 5830, DecorationDoublepumpINTEL = 5831, DecorationMaxReplicatesINTEL = 5832, DecorationSimpleDualPortINTEL = 5833, DecorationMergeINTEL = 5834, DecorationBankBitsINTEL = 5835, DecorationMax = 0x7fffffff, }; enum BuiltIn { BuiltInPosition = 0, BuiltInPointSize = 1, BuiltInClipDistance = 3, BuiltInCullDistance = 4, BuiltInVertexId = 5, BuiltInInstanceId = 6, BuiltInPrimitiveId = 7, BuiltInInvocationId = 8, BuiltInLayer = 9, BuiltInViewportIndex = 10, BuiltInTessLevelOuter = 11, BuiltInTessLevelInner = 12, BuiltInTessCoord = 13, BuiltInPatchVertices = 14, BuiltInFragCoord = 15, BuiltInPointCoord = 16, BuiltInFrontFacing = 17, BuiltInSampleId = 18, BuiltInSamplePosition = 19, BuiltInSampleMask = 20, BuiltInFragDepth = 22, BuiltInHelperInvocation = 23, BuiltInNumWorkgroups = 24, BuiltInWorkgroupSize = 25, BuiltInWorkgroupId = 26, BuiltInLocalInvocationId = 27, BuiltInGlobalInvocationId = 28, BuiltInLocalInvocationIndex = 29, BuiltInWorkDim = 30, BuiltInGlobalSize = 31, BuiltInEnqueuedWorkgroupSize = 32, BuiltInGlobalOffset = 33, BuiltInGlobalLinearId = 34, BuiltInSubgroupSize = 36, BuiltInSubgroupMaxSize = 37, BuiltInNumSubgroups = 38, BuiltInNumEnqueuedSubgroups = 39, BuiltInSubgroupId = 40, BuiltInSubgroupLocalInvocationId = 41, BuiltInVertexIndex = 42, BuiltInInstanceIndex = 43, BuiltInSubgroupEqMaskKHR = 4416, BuiltInSubgroupGeMaskKHR = 4417, BuiltInSubgroupGtMaskKHR = 4418, BuiltInSubgroupLeMaskKHR = 4419, BuiltInSubgroupLtMaskKHR = 4420, BuiltInBaseVertex = 4424, BuiltInBaseInstance = 4425, BuiltInDrawIndex = 4426, BuiltInDeviceIndex = 4438, BuiltInViewIndex = 4440, BuiltInViewportMaskNV = 5253, BuiltInSecondaryPositionNV = 5257, BuiltInSecondaryViewportMaskNV = 5258, BuiltInPositionPerViewNV = 5261, BuiltInViewportMaskPerViewNV = 5262, BuiltInMax = 0x7fffffff, }; enum SelectionControlShift { SelectionControlFlattenShift = 0, SelectionControlDontFlattenShift = 1, SelectionControlMax = 0x7fffffff, }; enum SelectionControlMask { SelectionControlMaskNone = 0, SelectionControlFlattenMask = 0x00000001, SelectionControlDontFlattenMask = 0x00000002, }; enum LoopControlShift { LoopControlUnrollShift = 0, LoopControlDontUnrollShift = 1, LoopControlDependencyInfiniteShift = 2, LoopControlDependencyLengthShift = 3, LoopControlMax = 0x7fffffff, }; enum LoopControlMask { LoopControlMaskNone = 0, LoopControlUnrollMask = 0x00000001, LoopControlDontUnrollMask = 0x00000002, LoopControlDependencyInfiniteMask = 0x00000004, LoopControlDependencyLengthMask = 0x00000008, LoopControlMinIterationsMask = 0x00000010, LoopControlMaxIterationsMask = 0x00000020, LoopControlIterationMultipleMask = 0x00000040, LoopControlPeelCountMask = 0x00000080, LoopControlPartialCountMask = 0x00000100, InitiationIntervalINTEL = 0x10000, MaxConcurrencyINTEL = 0x20000, DependencyArrayINTEL = 0x40000, }; enum FunctionControlShift { FunctionControlInlineShift = 0, FunctionControlDontInlineShift = 1, FunctionControlPureShift = 2, FunctionControlConstShift = 3, FunctionControlMax = 0x7fffffff, }; enum FunctionControlMask { FunctionControlMaskNone = 0, FunctionControlInlineMask = 0x00000001, FunctionControlDontInlineMask = 0x00000002, FunctionControlPureMask = 0x00000004, FunctionControlConstMask = 0x00000008, }; enum MemorySemanticsShift { MemorySemanticsAcquireShift = 1, MemorySemanticsReleaseShift = 2, MemorySemanticsAcquireReleaseShift = 3, MemorySemanticsSequentiallyConsistentShift = 4, MemorySemanticsUniformMemoryShift = 6, MemorySemanticsSubgroupMemoryShift = 7, MemorySemanticsWorkgroupMemoryShift = 8, MemorySemanticsCrossWorkgroupMemoryShift = 9, MemorySemanticsAtomicCounterMemoryShift = 10, MemorySemanticsImageMemoryShift = 11, MemorySemanticsMax = 0x7fffffff, }; enum MemorySemanticsMask { MemorySemanticsMaskNone = 0, MemorySemanticsAcquireMask = 0x00000002, MemorySemanticsReleaseMask = 0x00000004, MemorySemanticsAcquireReleaseMask = 0x00000008, MemorySemanticsSequentiallyConsistentMask = 0x00000010, MemorySemanticsUniformMemoryMask = 0x00000040, MemorySemanticsSubgroupMemoryMask = 0x00000080, MemorySemanticsWorkgroupMemoryMask = 0x00000100, MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, MemorySemanticsAtomicCounterMemoryMask = 0x00000400, MemorySemanticsImageMemoryMask = 0x00000800, }; enum MemoryAccessShift { MemoryAccessVolatileShift = 0, MemoryAccessAlignedShift = 1, MemoryAccessNontemporalShift = 2, MemoryAccessMax = 0x7fffffff, }; enum MemoryAccessMask { MemoryAccessMaskNone = 0, MemoryAccessVolatileMask = 0x00000001, MemoryAccessAlignedMask = 0x00000002, MemoryAccessNontemporalMask = 0x00000004, }; enum Scope { ScopeCrossDevice = 0, ScopeDevice = 1, ScopeWorkgroup = 2, ScopeSubgroup = 3, ScopeInvocation = 4, ScopeMax = 0x7fffffff, }; enum GroupOperation { GroupOperationReduce = 0, GroupOperationInclusiveScan = 1, GroupOperationExclusiveScan = 2, GroupOperationMax = 0x7fffffff, }; enum KernelEnqueueFlags { KernelEnqueueFlagsNoWait = 0, KernelEnqueueFlagsWaitKernel = 1, KernelEnqueueFlagsWaitWorkGroup = 2, KernelEnqueueFlagsMax = 0x7fffffff, }; enum KernelProfilingInfoShift { KernelProfilingInfoCmdExecTimeShift = 0, KernelProfilingInfoMax = 0x7fffffff, }; enum KernelProfilingInfoMask { KernelProfilingInfoMaskNone = 0, KernelProfilingInfoCmdExecTimeMask = 0x00000001, }; enum Capability { CapabilityMatrix = 0, CapabilityShader = 1, CapabilityGeometry = 2, CapabilityTessellation = 3, CapabilityAddresses = 4, CapabilityLinkage = 5, CapabilityKernel = 6, CapabilityVector16 = 7, CapabilityFloat16Buffer = 8, CapabilityFloat16 = 9, CapabilityFloat64 = 10, CapabilityInt64 = 11, CapabilityInt64Atomics = 12, CapabilityImageBasic = 13, CapabilityImageReadWrite = 14, CapabilityImageMipmap = 15, CapabilityPipes = 17, CapabilityGroups = 18, CapabilityDeviceEnqueue = 19, CapabilityLiteralSampler = 20, CapabilityAtomicStorage = 21, CapabilityInt16 = 22, CapabilityTessellationPointSize = 23, CapabilityGeometryPointSize = 24, CapabilityImageGatherExtended = 25, CapabilityStorageImageMultisample = 27, CapabilityUniformBufferArrayDynamicIndexing = 28, CapabilitySampledImageArrayDynamicIndexing = 29, CapabilityStorageBufferArrayDynamicIndexing = 30, CapabilityStorageImageArrayDynamicIndexing = 31, CapabilityClipDistance = 32, CapabilityCullDistance = 33, CapabilityImageCubeArray = 34, CapabilitySampleRateShading = 35, CapabilityImageRect = 36, CapabilitySampledRect = 37, CapabilityGenericPointer = 38, CapabilityInt8 = 39, CapabilityInputAttachment = 40, CapabilitySparseResidency = 41, CapabilityMinLod = 42, CapabilitySampled1D = 43, CapabilityImage1D = 44, CapabilitySampledCubeArray = 45, CapabilitySampledBuffer = 46, CapabilityImageBuffer = 47, CapabilityImageMSArray = 48, CapabilityStorageImageExtendedFormats = 49, CapabilityImageQuery = 50, CapabilityDerivativeControl = 51, CapabilityInterpolationFunction = 52, CapabilityTransformFeedback = 53, CapabilityGeometryStreams = 54, CapabilityStorageImageReadWithoutFormat = 55, CapabilityStorageImageWriteWithoutFormat = 56, CapabilityMultiViewport = 57, CapabilitySubgroupDispatch = 58, CapabilityNamedBarrier = 59, CapabilityPipeStorage = 60, CapabilitySubgroupBallotKHR = 4423, CapabilityDrawParameters = 4427, CapabilitySubgroupVoteKHR = 4431, CapabilityStorageBuffer16BitAccess = 4433, CapabilityStorageUniformBufferBlock16 = 4433, CapabilityStorageUniform16 = 4434, CapabilityUniformAndStorageBuffer16BitAccess = 4434, CapabilityStoragePushConstant16 = 4435, CapabilityStorageInputOutput16 = 4436, CapabilityDeviceGroup = 4437, CapabilityMultiView = 4439, CapabilityVariablePointersStorageBuffer = 4441, CapabilityVariablePointers = 4442, CapabilitySampleMaskOverrideCoverageNV = 5249, CapabilityGeometryShaderPassthroughNV = 5251, CapabilityShaderViewportIndexLayerNV = 5254, CapabilityShaderViewportMaskNV = 5255, CapabilityShaderStereoViewNV = 5259, CapabilityPerViewAttributesNV = 5260, CapabilitySubgroupShuffleINTEL = 5568, CapabilitySubgroupBufferBlockIOINTEL = 5569, CapabilitySubgroupImageBlockIOINTEL = 5570, CapabilitySubgroupImageMediaBlockIOINTEL = 5579, CapabilityFunctionPointersINTEL = 5603, CapabilityIndirectReferencesINTEL = 5604, CapabilityAsmINTEL = 5606, CapabilitySubgroupAvcMotionEstimationINTEL = 5696, CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, CapabilityFPGAMemoryAttributesINTEL = 5824, CapabilityUnstructuredLoopControlsINTEL = 5886, CapabilityFPGALoopControlsINTEL = 5888, CapabilityBlockingPipesINTEL = 5945, CapabilityFPGARegINTEL = 5948, CapabilityKernelAttributesINTEL= 5892, CapabilityFPGAKernelAttributesINTEL= 5897, CapabilityMax = 0x7fffffff, }; enum Op { OpNop = 0, OpUndef = 1, OpSourceContinued = 2, OpSource = 3, OpSourceExtension = 4, OpName = 5, OpMemberName = 6, OpString = 7, OpLine = 8, OpExtension = 10, OpExtInstImport = 11, OpExtInst = 12, OpMemoryModel = 14, OpEntryPoint = 15, OpExecutionMode = 16, OpCapability = 17, OpTypeVoid = 19, OpTypeBool = 20, OpTypeInt = 21, OpTypeFloat = 22, OpTypeVector = 23, OpTypeMatrix = 24, OpTypeImage = 25, OpTypeSampler = 26, OpTypeSampledImage = 27, OpTypeArray = 28, OpTypeRuntimeArray = 29, OpTypeStruct = 30, OpTypeOpaque = 31, OpTypePointer = 32, OpTypeFunction = 33, OpTypeEvent = 34, OpTypeDeviceEvent = 35, OpTypeReserveId = 36, OpTypeQueue = 37, OpTypePipe = 38, OpTypeForwardPointer = 39, OpConstantTrue = 41, OpConstantFalse = 42, OpConstant = 43, OpConstantComposite = 44, OpConstantSampler = 45, OpConstantNull = 46, OpSpecConstantTrue = 48, OpSpecConstantFalse = 49, OpSpecConstant = 50, OpSpecConstantComposite = 51, OpSpecConstantOp = 52, OpFunction = 54, OpFunctionParameter = 55, OpFunctionEnd = 56, OpFunctionCall = 57, OpVariable = 59, OpImageTexelPointer = 60, OpLoad = 61, OpStore = 62, OpCopyMemory = 63, OpCopyMemorySized = 64, OpAccessChain = 65, OpInBoundsAccessChain = 66, OpPtrAccessChain = 67, OpArrayLength = 68, OpGenericPtrMemSemantics = 69, OpInBoundsPtrAccessChain = 70, OpDecorate = 71, OpMemberDecorate = 72, OpDecorationGroup = 73, OpGroupDecorate = 74, OpGroupMemberDecorate = 75, OpVectorExtractDynamic = 77, OpVectorInsertDynamic = 78, OpVectorShuffle = 79, OpCompositeConstruct = 80, OpCompositeExtract = 81, OpCompositeInsert = 82, OpCopyObject = 83, OpTranspose = 84, OpSampledImage = 86, OpImageSampleImplicitLod = 87, OpImageSampleExplicitLod = 88, OpImageSampleDrefImplicitLod = 89, OpImageSampleDrefExplicitLod = 90, OpImageSampleProjImplicitLod = 91, OpImageSampleProjExplicitLod = 92, OpImageSampleProjDrefImplicitLod = 93, OpImageSampleProjDrefExplicitLod = 94, OpImageFetch = 95, OpImageGather = 96, OpImageDrefGather = 97, OpImageRead = 98, OpImageWrite = 99, OpImage = 100, OpImageQueryFormat = 101, OpImageQueryOrder = 102, OpImageQuerySizeLod = 103, OpImageQuerySize = 104, OpImageQueryLod = 105, OpImageQueryLevels = 106, OpImageQuerySamples = 107, OpConvertFToU = 109, OpConvertFToS = 110, OpConvertSToF = 111, OpConvertUToF = 112, OpUConvert = 113, OpSConvert = 114, OpFConvert = 115, OpQuantizeToF16 = 116, OpConvertPtrToU = 117, OpSatConvertSToU = 118, OpSatConvertUToS = 119, OpConvertUToPtr = 120, OpPtrCastToGeneric = 121, OpGenericCastToPtr = 122, OpGenericCastToPtrExplicit = 123, OpBitcast = 124, OpSNegate = 126, OpFNegate = 127, OpIAdd = 128, OpFAdd = 129, OpISub = 130, OpFSub = 131, OpIMul = 132, OpFMul = 133, OpUDiv = 134, OpSDiv = 135, OpFDiv = 136, OpUMod = 137, OpSRem = 138, OpSMod = 139, OpFRem = 140, OpFMod = 141, OpVectorTimesScalar = 142, OpMatrixTimesScalar = 143, OpVectorTimesMatrix = 144, OpMatrixTimesVector = 145, OpMatrixTimesMatrix = 146, OpOuterProduct = 147, OpDot = 148, OpIAddCarry = 149, OpISubBorrow = 150, OpUMulExtended = 151, OpSMulExtended = 152, OpAny = 154, OpAll = 155, OpIsNan = 156, OpIsInf = 157, OpIsFinite = 158, OpIsNormal = 159, OpSignBitSet = 160, OpLessOrGreater = 161, OpOrdered = 162, OpUnordered = 163, OpLogicalEqual = 164, OpLogicalNotEqual = 165, OpLogicalOr = 166, OpLogicalAnd = 167, OpLogicalNot = 168, OpSelect = 169, OpIEqual = 170, OpINotEqual = 171, OpUGreaterThan = 172, OpSGreaterThan = 173, OpUGreaterThanEqual = 174, OpSGreaterThanEqual = 175, OpULessThan = 176, OpSLessThan = 177, OpULessThanEqual = 178, OpSLessThanEqual = 179, OpFOrdEqual = 180, OpFUnordEqual = 181, OpFOrdNotEqual = 182, OpFUnordNotEqual = 183, OpFOrdLessThan = 184, OpFUnordLessThan = 185, OpFOrdGreaterThan = 186, OpFUnordGreaterThan = 187, OpFOrdLessThanEqual = 188, OpFUnordLessThanEqual = 189, OpFOrdGreaterThanEqual = 190, OpFUnordGreaterThanEqual = 191, OpShiftRightLogical = 194, OpShiftRightArithmetic = 195, OpShiftLeftLogical = 196, OpBitwiseOr = 197, OpBitwiseXor = 198, OpBitwiseAnd = 199, OpNot = 200, OpBitFieldInsert = 201, OpBitFieldSExtract = 202, OpBitFieldUExtract = 203, OpBitReverse = 204, OpBitCount = 205, OpDPdx = 207, OpDPdy = 208, OpFwidth = 209, OpDPdxFine = 210, OpDPdyFine = 211, OpFwidthFine = 212, OpDPdxCoarse = 213, OpDPdyCoarse = 214, OpFwidthCoarse = 215, OpEmitVertex = 218, OpEndPrimitive = 219, OpEmitStreamVertex = 220, OpEndStreamPrimitive = 221, OpControlBarrier = 224, OpMemoryBarrier = 225, OpAtomicLoad = 227, OpAtomicStore = 228, OpAtomicExchange = 229, OpAtomicCompareExchange = 230, OpAtomicCompareExchangeWeak = 231, OpAtomicIIncrement = 232, OpAtomicIDecrement = 233, OpAtomicIAdd = 234, OpAtomicISub = 235, OpAtomicSMin = 236, OpAtomicUMin = 237, OpAtomicSMax = 238, OpAtomicUMax = 239, OpAtomicAnd = 240, OpAtomicOr = 241, OpAtomicXor = 242, OpPhi = 245, OpLoopMerge = 246, OpSelectionMerge = 247, OpLabel = 248, OpBranch = 249, OpBranchConditional = 250, OpSwitch = 251, OpKill = 252, OpReturn = 253, OpReturnValue = 254, OpUnreachable = 255, OpLifetimeStart = 256, OpLifetimeStop = 257, OpGroupAsyncCopy = 259, OpGroupWaitEvents = 260, OpGroupAll = 261, OpGroupAny = 262, OpGroupBroadcast = 263, OpGroupIAdd = 264, OpGroupFAdd = 265, OpGroupFMin = 266, OpGroupUMin = 267, OpGroupSMin = 268, OpGroupFMax = 269, OpGroupUMax = 270, OpGroupSMax = 271, OpReadPipe = 274, OpWritePipe = 275, OpReservedReadPipe = 276, OpReservedWritePipe = 277, OpReserveReadPipePackets = 278, OpReserveWritePipePackets = 279, OpCommitReadPipe = 280, OpCommitWritePipe = 281, OpIsValidReserveId = 282, OpGetNumPipePackets = 283, OpGetMaxPipePackets = 284, OpGroupReserveReadPipePackets = 285, OpGroupReserveWritePipePackets = 286, OpGroupCommitReadPipe = 287, OpGroupCommitWritePipe = 288, OpEnqueueMarker = 291, OpEnqueueKernel = 292, OpGetKernelNDrangeSubGroupCount = 293, OpGetKernelNDrangeMaxSubGroupSize = 294, OpGetKernelWorkGroupSize = 295, OpGetKernelPreferredWorkGroupSizeMultiple = 296, OpRetainEvent = 297, OpReleaseEvent = 298, OpCreateUserEvent = 299, OpIsValidEvent = 300, OpSetUserEventStatus = 301, OpCaptureEventProfilingInfo = 302, OpGetDefaultQueue = 303, OpBuildNDRange = 304, OpImageSparseSampleImplicitLod = 305, OpImageSparseSampleExplicitLod = 306, OpImageSparseSampleDrefImplicitLod = 307, OpImageSparseSampleDrefExplicitLod = 308, OpImageSparseSampleProjImplicitLod = 309, OpImageSparseSampleProjExplicitLod = 310, OpImageSparseSampleProjDrefImplicitLod = 311, OpImageSparseSampleProjDrefExplicitLod = 312, OpImageSparseFetch = 313, OpImageSparseGather = 314, OpImageSparseDrefGather = 315, OpImageSparseTexelsResident = 316, OpNoLine = 317, OpAtomicFlagTestAndSet = 318, OpAtomicFlagClear = 319, OpImageSparseRead = 320, OpSizeOf = 321, OpTypePipeStorage = 322, OpConstantPipeStorage = 323, OpCreatePipeFromPipeStorage = 324, OpGetKernelLocalSizeForSubgroupCount = 325, OpGetKernelMaxNumSubgroups = 326, OpTypeNamedBarrier = 327, OpNamedBarrierInitialize = 328, OpMemoryNamedBarrier = 329, OpModuleProcessed = 330, OpForward = 1024, /* internal use only */ OpSubgroupBallotKHR = 4421, OpSubgroupFirstInvocationKHR = 4422, OpSubgroupAllKHR = 4428, OpSubgroupAnyKHR = 4429, OpSubgroupAllEqualKHR = 4430, OpSubgroupReadInvocationKHR = 4432, OpSubgroupShuffleINTEL = 5571, OpSubgroupShuffleDownINTEL = 5572, OpSubgroupShuffleUpINTEL = 5573, OpSubgroupShuffleXorINTEL = 5574, OpSubgroupBlockReadINTEL = 5575, OpSubgroupBlockWriteINTEL = 5576, OpSubgroupImageBlockReadINTEL = 5577, OpSubgroupImageBlockWriteINTEL = 5578, OpSubgroupImageMediaBlockReadINTEL = 5580, OpSubgroupImageMediaBlockWriteINTEL = 5581, OpFunctionPointerINTEL = 5600, OpFunctionPointerCallINTEL = 5601, OpAsmTargetINTEL = 5609, OpAsmINTEL = 5610, OpAsmCallINTEL = 5611, OpVmeImageINTEL = 5699, OpTypeVmeImageINTEL = 5700, OpTypeAvcImePayloadINTEL = 5701, OpTypeAvcRefPayloadINTEL = 5702, OpTypeAvcSicPayloadINTEL = 5703, OpTypeAvcMcePayloadINTEL = 5704, OpTypeAvcMceResultINTEL = 5705, OpTypeAvcImeResultINTEL = 5706, OpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707, OpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708, OpTypeAvcImeSingleReferenceStreaminINTEL = 5709, OpTypeAvcImeDualReferenceStreaminINTEL = 5710, OpTypeAvcRefResultINTEL = 5711, OpTypeAvcSicResultINTEL = 5712, OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713, OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714, OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715, OpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716, OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717, OpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718, OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719, OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720, OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721, OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722, OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723, OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724, OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725, OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726, OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727, OpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728, OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729, OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730, OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731, OpSubgroupAvcMceConvertToImePayloadINTEL = 5732, OpSubgroupAvcMceConvertToImeResultINTEL = 5733, OpSubgroupAvcMceConvertToRefPayloadINTEL = 5734, OpSubgroupAvcMceConvertToRefResultINTEL = 5735, OpSubgroupAvcMceConvertToSicPayloadINTEL = 5736, OpSubgroupAvcMceConvertToSicResultINTEL = 5737, OpSubgroupAvcMceGetMotionVectorsINTEL = 5738, OpSubgroupAvcMceGetInterDistortionsINTEL = 5739, OpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740, OpSubgroupAvcMceGetInterMajorShapeINTEL = 5741, OpSubgroupAvcMceGetInterMinorShapeINTEL = 5742, OpSubgroupAvcMceGetInterDirectionsINTEL = 5743, OpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744, OpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745, OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746, OpSubgroupAvcImeInitializeINTEL = 5747, OpSubgroupAvcImeSetSingleReferenceINTEL = 5748, OpSubgroupAvcImeSetDualReferenceINTEL = 5749, OpSubgroupAvcImeRefWindowSizeINTEL = 5750, OpSubgroupAvcImeAdjustRefOffsetINTEL = 5751, OpSubgroupAvcImeConvertToMcePayloadINTEL = 5752, OpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753, OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754, OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755, OpSubgroupAvcImeSetWeightedSadINTEL = 5756, OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757, OpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758, OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759, OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760, OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761, OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762, OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763, OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764, OpSubgroupAvcImeConvertToMceResultINTEL = 5765, OpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766, OpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767, OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768, OpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769, OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770, OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771, OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772, OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773, OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774, OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775, OpSubgroupAvcImeGetBorderReachedINTEL = 5776, OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777, OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778, OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779, OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780, OpSubgroupAvcFmeInitializeINTEL = 5781, OpSubgroupAvcBmeInitializeINTEL = 5782, OpSubgroupAvcRefConvertToMcePayloadINTEL = 5783, OpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784, OpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785, OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786, OpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787, OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788, OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789, OpSubgroupAvcRefConvertToMceResultINTEL = 5790, OpSubgroupAvcSicInitializeINTEL = 5791, OpSubgroupAvcSicConfigureSkcINTEL = 5792, OpSubgroupAvcSicConfigureIpeLumaINTEL = 5793, OpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794, OpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795, OpSubgroupAvcSicConvertToMcePayloadINTEL = 5796, OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797, OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798, OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799, OpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800, OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801, OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802, OpSubgroupAvcSicEvaluateIpeINTEL = 5803, OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804, OpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805, OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806, OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807, OpSubgroupAvcSicConvertToMceResultINTEL = 5808, OpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809, OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810, OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811, OpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812, OpSubgroupAvcSicGetIpeChromaModeINTEL = 5813, OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, OpLoopControlINTEL = 5887, OpReadPipeBlockingINTEL = 5946, OpWritePipeBlockingINTEL = 5947, OpFPGARegINTEL = 5949, OpMax = 0x7fffffff, }; // Overload operator| for mask bit combining inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } } // end namespace spv #endif // #ifndef spirv_HPP SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/runtime/000077500000000000000000000000001363521741200205325ustar00rootroot00000000000000SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/runtime/OpenCL/000077500000000000000000000000001363521741200216525ustar00rootroot00000000000000SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/runtime/OpenCL/inc/000077500000000000000000000000001363521741200224235ustar00rootroot00000000000000SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/runtime/OpenCL/inc/spirv.h000066400000000000000000000024341363521741200237420ustar00rootroot00000000000000__attribute__((overloadable, always_inline)) int __spirv_ImageQuerySize(image1d_buffer_t img); __attribute__((overloadable, always_inline)) int2 __spirv_ImageQuerySize(image1d_array_t img); __attribute__((overloadable, always_inline)) int2 __spirv_ImageQuerySize(image2d_t img); __attribute__((overloadable, always_inline)) int2 __spirv_ImageQuerySize(image2d_depth_t img); __attribute__((overloadable, always_inline)) int3 __spirv_ImageQuerySize(image2d_array_t img); __attribute__((overloadable, always_inline)) int3 __spirv_ImageQuerySize(image2d_array_depth_t img); __attribute__((overloadable, always_inline)) int __spirv_ImageQuerySizeLod(image1d_t img, int lod); __attribute__((overloadable, always_inline)) int2 __spirv_ImageQuerySizeLod(image1d_array_t img, int lod); __attribute__((overloadable, always_inline)) int2 __spirv_ImageQuerySizeLod(image2d_t img, int lod); __attribute__((overloadable, always_inline)) int2 __spirv_ImageQuerySizeLod(image2d_depth_t img, int lod); __attribute__((overloadable, always_inline)) int3 __spirv_ImageQuerySizeLod(image2d_array_t img, int lod); __attribute__((overloadable, always_inline)) int3 __spirv_ImageQuerySizeLod(image2d_array_depth_t img, int lod); __attribute__((overloadable, always_inline)) int3 __spirv_ImageQuerySizeLod(image3d_t img, int lod); SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/runtime/OpenCL/inc/spirv_convert.h000066400000000000000000016655731363521741200255260ustar00rootroot00000000000000__attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar(half); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_rtz(half); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_rte(half); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_rtp(half); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_rtn(half); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_sat(half); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_sat_rtz(half); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_sat_rte(half); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_sat_rtp(half); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_sat_rtn(half); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar(float); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_rtz(float); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_rte(float); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_rtp(float); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_rtn(float); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_sat(float); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_sat_rtz(float); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_sat_rte(float); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_sat_rtp(float); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_sat_rtn(float); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar(double); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_rtz(double); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_rte(double); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_rtp(double); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_rtn(double); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_sat(double); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_sat_rtz(double); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_sat_rte(double); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_sat_rtp(double); __attribute__((overloadable)) uchar __spirv_ConvertFToU_Ruchar_sat_rtn(double); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2(half2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_rtz(half2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_rte(half2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_rtp(half2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_rtn(half2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_sat(half2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_sat_rtz(half2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_sat_rte(half2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_sat_rtp(half2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_sat_rtn(half2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2(float2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_rtz(float2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_rte(float2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_rtp(float2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_rtn(float2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_sat(float2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_sat_rtz(float2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_sat_rte(float2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_sat_rtp(float2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_sat_rtn(float2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2(double2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_rtz(double2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_rte(double2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_rtp(double2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_rtn(double2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_sat(double2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_sat_rtz(double2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_sat_rte(double2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_sat_rtp(double2); __attribute__((overloadable)) uchar2 __spirv_ConvertFToU_Ruchar2_sat_rtn(double2); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3(half3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_rtz(half3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_rte(half3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_rtp(half3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_rtn(half3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_sat(half3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_sat_rtz(half3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_sat_rte(half3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_sat_rtp(half3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_sat_rtn(half3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3(float3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_rtz(float3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_rte(float3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_rtp(float3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_rtn(float3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_sat(float3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_sat_rtz(float3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_sat_rte(float3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_sat_rtp(float3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_sat_rtn(float3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3(double3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_rtz(double3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_rte(double3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_rtp(double3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_rtn(double3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_sat(double3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_sat_rtz(double3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_sat_rte(double3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_sat_rtp(double3); __attribute__((overloadable)) uchar3 __spirv_ConvertFToU_Ruchar3_sat_rtn(double3); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4(half4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_rtz(half4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_rte(half4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_rtp(half4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_rtn(half4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_sat(half4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_sat_rtz(half4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_sat_rte(half4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_sat_rtp(half4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_sat_rtn(half4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4(float4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_rtz(float4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_rte(float4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_rtp(float4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_rtn(float4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_sat(float4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_sat_rtz(float4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_sat_rte(float4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_sat_rtp(float4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_sat_rtn(float4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4(double4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_rtz(double4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_rte(double4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_rtp(double4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_rtn(double4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_sat(double4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_sat_rtz(double4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_sat_rte(double4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_sat_rtp(double4); __attribute__((overloadable)) uchar4 __spirv_ConvertFToU_Ruchar4_sat_rtn(double4); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8(half8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_rtz(half8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_rte(half8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_rtp(half8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_rtn(half8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_sat(half8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_sat_rtz(half8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_sat_rte(half8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_sat_rtp(half8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_sat_rtn(half8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8(float8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_rtz(float8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_rte(float8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_rtp(float8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_rtn(float8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_sat(float8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_sat_rtz(float8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_sat_rte(float8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_sat_rtp(float8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_sat_rtn(float8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8(double8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_rtz(double8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_rte(double8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_rtp(double8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_rtn(double8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_sat(double8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_sat_rtz(double8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_sat_rte(double8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_sat_rtp(double8); __attribute__((overloadable)) uchar8 __spirv_ConvertFToU_Ruchar8_sat_rtn(double8); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16(half16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_rtz(half16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_rte(half16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_rtp(half16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_rtn(half16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_sat(half16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_sat_rtz(half16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_sat_rte(half16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_sat_rtp(half16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_sat_rtn(half16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16(float16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_rtz(float16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_rte(float16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_rtp(float16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_rtn(float16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_sat(float16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_sat_rtz(float16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_sat_rte(float16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_sat_rtp(float16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_sat_rtn(float16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16(double16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_rtz(double16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_rte(double16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_rtp(double16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_rtn(double16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_sat(double16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_sat_rtz(double16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_sat_rte(double16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_sat_rtp(double16); __attribute__((overloadable)) uchar16 __spirv_ConvertFToU_Ruchar16_sat_rtn(double16); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort(half); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_rtz(half); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_rte(half); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_rtp(half); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_rtn(half); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_sat(half); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_sat_rtz(half); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_sat_rte(half); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_sat_rtp(half); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_sat_rtn(half); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort(float); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_rtz(float); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_rte(float); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_rtp(float); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_rtn(float); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_sat(float); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_sat_rtz(float); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_sat_rte(float); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_sat_rtp(float); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_sat_rtn(float); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort(double); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_rtz(double); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_rte(double); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_rtp(double); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_rtn(double); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_sat(double); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_sat_rtz(double); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_sat_rte(double); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_sat_rtp(double); __attribute__((overloadable)) ushort __spirv_ConvertFToU_Rushort_sat_rtn(double); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2(half2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_rtz(half2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_rte(half2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_rtp(half2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_rtn(half2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_sat(half2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_sat_rtz(half2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_sat_rte(half2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_sat_rtp(half2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_sat_rtn(half2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2(float2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_rtz(float2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_rte(float2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_rtp(float2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_rtn(float2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_sat(float2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_sat_rtz(float2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_sat_rte(float2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_sat_rtp(float2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_sat_rtn(float2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2(double2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_rtz(double2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_rte(double2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_rtp(double2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_rtn(double2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_sat(double2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_sat_rtz(double2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_sat_rte(double2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_sat_rtp(double2); __attribute__((overloadable)) ushort2 __spirv_ConvertFToU_Rushort2_sat_rtn(double2); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3(half3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_rtz(half3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_rte(half3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_rtp(half3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_rtn(half3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_sat(half3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_sat_rtz(half3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_sat_rte(half3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_sat_rtp(half3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_sat_rtn(half3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3(float3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_rtz(float3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_rte(float3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_rtp(float3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_rtn(float3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_sat(float3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_sat_rtz(float3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_sat_rte(float3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_sat_rtp(float3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_sat_rtn(float3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3(double3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_rtz(double3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_rte(double3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_rtp(double3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_rtn(double3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_sat(double3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_sat_rtz(double3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_sat_rte(double3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_sat_rtp(double3); __attribute__((overloadable)) ushort3 __spirv_ConvertFToU_Rushort3_sat_rtn(double3); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4(half4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_rtz(half4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_rte(half4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_rtp(half4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_rtn(half4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_sat(half4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_sat_rtz(half4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_sat_rte(half4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_sat_rtp(half4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_sat_rtn(half4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4(float4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_rtz(float4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_rte(float4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_rtp(float4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_rtn(float4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_sat(float4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_sat_rtz(float4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_sat_rte(float4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_sat_rtp(float4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_sat_rtn(float4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4(double4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_rtz(double4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_rte(double4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_rtp(double4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_rtn(double4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_sat(double4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_sat_rtz(double4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_sat_rte(double4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_sat_rtp(double4); __attribute__((overloadable)) ushort4 __spirv_ConvertFToU_Rushort4_sat_rtn(double4); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8(half8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_rtz(half8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_rte(half8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_rtp(half8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_rtn(half8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_sat(half8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_sat_rtz(half8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_sat_rte(half8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_sat_rtp(half8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_sat_rtn(half8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8(float8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_rtz(float8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_rte(float8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_rtp(float8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_rtn(float8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_sat(float8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_sat_rtz(float8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_sat_rte(float8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_sat_rtp(float8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_sat_rtn(float8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8(double8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_rtz(double8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_rte(double8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_rtp(double8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_rtn(double8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_sat(double8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_sat_rtz(double8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_sat_rte(double8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_sat_rtp(double8); __attribute__((overloadable)) ushort8 __spirv_ConvertFToU_Rushort8_sat_rtn(double8); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16(half16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_rtz(half16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_rte(half16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_rtp(half16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_rtn(half16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_sat(half16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_sat_rtz(half16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_sat_rte(half16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_sat_rtp(half16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_sat_rtn(half16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16(float16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_rtz(float16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_rte(float16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_rtp(float16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_rtn(float16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_sat(float16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_sat_rtz(float16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_sat_rte(float16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_sat_rtp(float16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_sat_rtn(float16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16(double16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_rtz(double16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_rte(double16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_rtp(double16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_rtn(double16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_sat(double16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_sat_rtz(double16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_sat_rte(double16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_sat_rtp(double16); __attribute__((overloadable)) ushort16 __spirv_ConvertFToU_Rushort16_sat_rtn(double16); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint(half); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_rtz(half); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_rte(half); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_rtp(half); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_rtn(half); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_sat(half); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_sat_rtz(half); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_sat_rte(half); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_sat_rtp(half); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_sat_rtn(half); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint(float); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_rtz(float); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_rte(float); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_rtp(float); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_rtn(float); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_sat(float); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_sat_rtz(float); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_sat_rte(float); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_sat_rtp(float); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_sat_rtn(float); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint(double); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_rtz(double); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_rte(double); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_rtp(double); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_rtn(double); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_sat(double); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_sat_rtz(double); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_sat_rte(double); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_sat_rtp(double); __attribute__((overloadable)) uint __spirv_ConvertFToU_Ruint_sat_rtn(double); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2(half2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_rtz(half2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_rte(half2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_rtp(half2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_rtn(half2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_sat(half2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_sat_rtz(half2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_sat_rte(half2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_sat_rtp(half2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_sat_rtn(half2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2(float2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_rtz(float2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_rte(float2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_rtp(float2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_rtn(float2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_sat(float2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_sat_rtz(float2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_sat_rte(float2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_sat_rtp(float2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_sat_rtn(float2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2(double2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_rtz(double2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_rte(double2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_rtp(double2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_rtn(double2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_sat(double2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_sat_rtz(double2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_sat_rte(double2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_sat_rtp(double2); __attribute__((overloadable)) uint2 __spirv_ConvertFToU_Ruint2_sat_rtn(double2); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3(half3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_rtz(half3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_rte(half3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_rtp(half3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_rtn(half3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_sat(half3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_sat_rtz(half3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_sat_rte(half3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_sat_rtp(half3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_sat_rtn(half3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3(float3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_rtz(float3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_rte(float3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_rtp(float3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_rtn(float3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_sat(float3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_sat_rtz(float3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_sat_rte(float3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_sat_rtp(float3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_sat_rtn(float3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3(double3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_rtz(double3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_rte(double3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_rtp(double3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_rtn(double3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_sat(double3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_sat_rtz(double3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_sat_rte(double3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_sat_rtp(double3); __attribute__((overloadable)) uint3 __spirv_ConvertFToU_Ruint3_sat_rtn(double3); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4(half4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_rtz(half4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_rte(half4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_rtp(half4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_rtn(half4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_sat(half4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_sat_rtz(half4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_sat_rte(half4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_sat_rtp(half4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_sat_rtn(half4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4(float4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_rtz(float4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_rte(float4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_rtp(float4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_rtn(float4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_sat(float4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_sat_rtz(float4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_sat_rte(float4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_sat_rtp(float4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_sat_rtn(float4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4(double4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_rtz(double4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_rte(double4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_rtp(double4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_rtn(double4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_sat(double4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_sat_rtz(double4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_sat_rte(double4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_sat_rtp(double4); __attribute__((overloadable)) uint4 __spirv_ConvertFToU_Ruint4_sat_rtn(double4); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8(half8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_rtz(half8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_rte(half8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_rtp(half8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_rtn(half8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_sat(half8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_sat_rtz(half8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_sat_rte(half8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_sat_rtp(half8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_sat_rtn(half8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8(float8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_rtz(float8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_rte(float8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_rtp(float8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_rtn(float8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_sat(float8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_sat_rtz(float8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_sat_rte(float8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_sat_rtp(float8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_sat_rtn(float8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8(double8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_rtz(double8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_rte(double8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_rtp(double8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_rtn(double8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_sat(double8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_sat_rtz(double8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_sat_rte(double8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_sat_rtp(double8); __attribute__((overloadable)) uint8 __spirv_ConvertFToU_Ruint8_sat_rtn(double8); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16(half16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_rtz(half16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_rte(half16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_rtp(half16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_rtn(half16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_sat(half16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_sat_rtz(half16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_sat_rte(half16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_sat_rtp(half16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_sat_rtn(half16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16(float16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_rtz(float16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_rte(float16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_rtp(float16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_rtn(float16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_sat(float16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_sat_rtz(float16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_sat_rte(float16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_sat_rtp(float16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_sat_rtn(float16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16(double16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_rtz(double16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_rte(double16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_rtp(double16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_rtn(double16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_sat(double16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_sat_rtz(double16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_sat_rte(double16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_sat_rtp(double16); __attribute__((overloadable)) uint16 __spirv_ConvertFToU_Ruint16_sat_rtn(double16); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong(half); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_rtz(half); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_rte(half); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_rtp(half); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_rtn(half); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_sat(half); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_sat_rtz(half); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_sat_rte(half); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_sat_rtp(half); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_sat_rtn(half); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong(float); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_rtz(float); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_rte(float); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_rtp(float); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_rtn(float); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_sat(float); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_sat_rtz(float); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_sat_rte(float); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_sat_rtp(float); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_sat_rtn(float); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong(double); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_rtz(double); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_rte(double); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_rtp(double); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_rtn(double); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_sat(double); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_sat_rtz(double); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_sat_rte(double); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_sat_rtp(double); __attribute__((overloadable)) ulong __spirv_ConvertFToU_Rulong_sat_rtn(double); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2(half2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_rtz(half2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_rte(half2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_rtp(half2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_rtn(half2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_sat(half2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_sat_rtz(half2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_sat_rte(half2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_sat_rtp(half2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_sat_rtn(half2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2(float2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_rtz(float2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_rte(float2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_rtp(float2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_rtn(float2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_sat(float2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_sat_rtz(float2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_sat_rte(float2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_sat_rtp(float2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_sat_rtn(float2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2(double2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_rtz(double2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_rte(double2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_rtp(double2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_rtn(double2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_sat(double2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_sat_rtz(double2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_sat_rte(double2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_sat_rtp(double2); __attribute__((overloadable)) ulong2 __spirv_ConvertFToU_Rulong2_sat_rtn(double2); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3(half3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_rtz(half3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_rte(half3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_rtp(half3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_rtn(half3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_sat(half3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_sat_rtz(half3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_sat_rte(half3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_sat_rtp(half3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_sat_rtn(half3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3(float3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_rtz(float3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_rte(float3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_rtp(float3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_rtn(float3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_sat(float3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_sat_rtz(float3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_sat_rte(float3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_sat_rtp(float3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_sat_rtn(float3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3(double3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_rtz(double3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_rte(double3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_rtp(double3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_rtn(double3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_sat(double3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_sat_rtz(double3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_sat_rte(double3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_sat_rtp(double3); __attribute__((overloadable)) ulong3 __spirv_ConvertFToU_Rulong3_sat_rtn(double3); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4(half4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_rtz(half4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_rte(half4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_rtp(half4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_rtn(half4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_sat(half4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_sat_rtz(half4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_sat_rte(half4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_sat_rtp(half4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_sat_rtn(half4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4(float4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_rtz(float4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_rte(float4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_rtp(float4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_rtn(float4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_sat(float4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_sat_rtz(float4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_sat_rte(float4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_sat_rtp(float4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_sat_rtn(float4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4(double4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_rtz(double4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_rte(double4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_rtp(double4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_rtn(double4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_sat(double4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_sat_rtz(double4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_sat_rte(double4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_sat_rtp(double4); __attribute__((overloadable)) ulong4 __spirv_ConvertFToU_Rulong4_sat_rtn(double4); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8(half8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_rtz(half8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_rte(half8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_rtp(half8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_rtn(half8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_sat(half8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_sat_rtz(half8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_sat_rte(half8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_sat_rtp(half8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_sat_rtn(half8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8(float8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_rtz(float8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_rte(float8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_rtp(float8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_rtn(float8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_sat(float8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_sat_rtz(float8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_sat_rte(float8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_sat_rtp(float8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_sat_rtn(float8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8(double8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_rtz(double8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_rte(double8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_rtp(double8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_rtn(double8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_sat(double8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_sat_rtz(double8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_sat_rte(double8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_sat_rtp(double8); __attribute__((overloadable)) ulong8 __spirv_ConvertFToU_Rulong8_sat_rtn(double8); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16(half16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_rtz(half16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_rte(half16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_rtp(half16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_rtn(half16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_sat(half16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_sat_rtz(half16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_sat_rte(half16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_sat_rtp(half16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_sat_rtn(half16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16(float16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_rtz(float16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_rte(float16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_rtp(float16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_rtn(float16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_sat(float16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_sat_rtz(float16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_sat_rte(float16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_sat_rtp(float16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_sat_rtn(float16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16(double16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_rtz(double16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_rte(double16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_rtp(double16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_rtn(double16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_sat(double16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_sat_rtz(double16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_sat_rte(double16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_sat_rtp(double16); __attribute__((overloadable)) ulong16 __spirv_ConvertFToU_Rulong16_sat_rtn(double16); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar(half); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_rtz(half); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_rte(half); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_rtp(half); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_rtn(half); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_sat(half); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_sat_rtz(half); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_sat_rte(half); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_sat_rtp(half); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_sat_rtn(half); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar(float); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_rtz(float); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_rte(float); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_rtp(float); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_rtn(float); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_sat(float); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_sat_rtz(float); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_sat_rte(float); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_sat_rtp(float); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_sat_rtn(float); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar(double); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_rtz(double); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_rte(double); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_rtp(double); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_rtn(double); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_sat(double); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_sat_rtz(double); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_sat_rte(double); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_sat_rtp(double); __attribute__((overloadable)) char __spirv_ConvertFToS_Rchar_sat_rtn(double); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2(half2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_rtz(half2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_rte(half2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_rtp(half2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_rtn(half2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_sat(half2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_sat_rtz(half2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_sat_rte(half2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_sat_rtp(half2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_sat_rtn(half2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2(float2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_rtz(float2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_rte(float2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_rtp(float2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_rtn(float2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_sat(float2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_sat_rtz(float2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_sat_rte(float2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_sat_rtp(float2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_sat_rtn(float2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2(double2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_rtz(double2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_rte(double2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_rtp(double2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_rtn(double2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_sat(double2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_sat_rtz(double2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_sat_rte(double2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_sat_rtp(double2); __attribute__((overloadable)) char2 __spirv_ConvertFToS_Rchar2_sat_rtn(double2); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3(half3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_rtz(half3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_rte(half3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_rtp(half3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_rtn(half3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_sat(half3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_sat_rtz(half3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_sat_rte(half3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_sat_rtp(half3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_sat_rtn(half3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3(float3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_rtz(float3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_rte(float3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_rtp(float3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_rtn(float3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_sat(float3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_sat_rtz(float3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_sat_rte(float3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_sat_rtp(float3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_sat_rtn(float3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3(double3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_rtz(double3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_rte(double3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_rtp(double3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_rtn(double3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_sat(double3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_sat_rtz(double3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_sat_rte(double3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_sat_rtp(double3); __attribute__((overloadable)) char3 __spirv_ConvertFToS_Rchar3_sat_rtn(double3); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4(half4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_rtz(half4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_rte(half4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_rtp(half4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_rtn(half4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_sat(half4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_sat_rtz(half4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_sat_rte(half4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_sat_rtp(half4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_sat_rtn(half4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4(float4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_rtz(float4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_rte(float4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_rtp(float4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_rtn(float4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_sat(float4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_sat_rtz(float4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_sat_rte(float4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_sat_rtp(float4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_sat_rtn(float4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4(double4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_rtz(double4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_rte(double4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_rtp(double4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_rtn(double4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_sat(double4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_sat_rtz(double4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_sat_rte(double4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_sat_rtp(double4); __attribute__((overloadable)) char4 __spirv_ConvertFToS_Rchar4_sat_rtn(double4); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8(half8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_rtz(half8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_rte(half8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_rtp(half8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_rtn(half8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_sat(half8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_sat_rtz(half8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_sat_rte(half8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_sat_rtp(half8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_sat_rtn(half8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8(float8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_rtz(float8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_rte(float8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_rtp(float8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_rtn(float8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_sat(float8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_sat_rtz(float8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_sat_rte(float8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_sat_rtp(float8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_sat_rtn(float8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8(double8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_rtz(double8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_rte(double8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_rtp(double8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_rtn(double8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_sat(double8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_sat_rtz(double8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_sat_rte(double8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_sat_rtp(double8); __attribute__((overloadable)) char8 __spirv_ConvertFToS_Rchar8_sat_rtn(double8); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16(half16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_rtz(half16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_rte(half16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_rtp(half16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_rtn(half16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_sat(half16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_sat_rtz(half16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_sat_rte(half16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_sat_rtp(half16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_sat_rtn(half16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16(float16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_rtz(float16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_rte(float16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_rtp(float16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_rtn(float16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_sat(float16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_sat_rtz(float16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_sat_rte(float16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_sat_rtp(float16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_sat_rtn(float16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16(double16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_rtz(double16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_rte(double16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_rtp(double16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_rtn(double16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_sat(double16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_sat_rtz(double16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_sat_rte(double16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_sat_rtp(double16); __attribute__((overloadable)) char16 __spirv_ConvertFToS_Rchar16_sat_rtn(double16); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort(half); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_rtz(half); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_rte(half); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_rtp(half); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_rtn(half); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_sat(half); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_sat_rtz(half); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_sat_rte(half); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_sat_rtp(half); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_sat_rtn(half); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort(float); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_rtz(float); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_rte(float); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_rtp(float); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_rtn(float); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_sat(float); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_sat_rtz(float); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_sat_rte(float); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_sat_rtp(float); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_sat_rtn(float); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort(double); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_rtz(double); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_rte(double); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_rtp(double); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_rtn(double); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_sat(double); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_sat_rtz(double); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_sat_rte(double); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_sat_rtp(double); __attribute__((overloadable)) short __spirv_ConvertFToS_Rshort_sat_rtn(double); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2(half2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_rtz(half2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_rte(half2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_rtp(half2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_rtn(half2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_sat(half2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_sat_rtz(half2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_sat_rte(half2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_sat_rtp(half2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_sat_rtn(half2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2(float2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_rtz(float2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_rte(float2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_rtp(float2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_rtn(float2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_sat(float2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_sat_rtz(float2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_sat_rte(float2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_sat_rtp(float2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_sat_rtn(float2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2(double2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_rtz(double2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_rte(double2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_rtp(double2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_rtn(double2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_sat(double2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_sat_rtz(double2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_sat_rte(double2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_sat_rtp(double2); __attribute__((overloadable)) short2 __spirv_ConvertFToS_Rshort2_sat_rtn(double2); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3(half3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_rtz(half3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_rte(half3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_rtp(half3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_rtn(half3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_sat(half3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_sat_rtz(half3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_sat_rte(half3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_sat_rtp(half3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_sat_rtn(half3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3(float3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_rtz(float3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_rte(float3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_rtp(float3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_rtn(float3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_sat(float3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_sat_rtz(float3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_sat_rte(float3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_sat_rtp(float3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_sat_rtn(float3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3(double3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_rtz(double3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_rte(double3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_rtp(double3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_rtn(double3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_sat(double3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_sat_rtz(double3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_sat_rte(double3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_sat_rtp(double3); __attribute__((overloadable)) short3 __spirv_ConvertFToS_Rshort3_sat_rtn(double3); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4(half4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_rtz(half4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_rte(half4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_rtp(half4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_rtn(half4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_sat(half4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_sat_rtz(half4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_sat_rte(half4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_sat_rtp(half4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_sat_rtn(half4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4(float4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_rtz(float4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_rte(float4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_rtp(float4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_rtn(float4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_sat(float4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_sat_rtz(float4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_sat_rte(float4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_sat_rtp(float4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_sat_rtn(float4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4(double4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_rtz(double4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_rte(double4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_rtp(double4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_rtn(double4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_sat(double4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_sat_rtz(double4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_sat_rte(double4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_sat_rtp(double4); __attribute__((overloadable)) short4 __spirv_ConvertFToS_Rshort4_sat_rtn(double4); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8(half8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_rtz(half8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_rte(half8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_rtp(half8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_rtn(half8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_sat(half8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_sat_rtz(half8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_sat_rte(half8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_sat_rtp(half8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_sat_rtn(half8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8(float8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_rtz(float8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_rte(float8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_rtp(float8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_rtn(float8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_sat(float8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_sat_rtz(float8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_sat_rte(float8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_sat_rtp(float8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_sat_rtn(float8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8(double8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_rtz(double8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_rte(double8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_rtp(double8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_rtn(double8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_sat(double8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_sat_rtz(double8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_sat_rte(double8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_sat_rtp(double8); __attribute__((overloadable)) short8 __spirv_ConvertFToS_Rshort8_sat_rtn(double8); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16(half16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_rtz(half16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_rte(half16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_rtp(half16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_rtn(half16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_sat(half16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_sat_rtz(half16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_sat_rte(half16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_sat_rtp(half16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_sat_rtn(half16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16(float16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_rtz(float16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_rte(float16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_rtp(float16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_rtn(float16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_sat(float16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_sat_rtz(float16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_sat_rte(float16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_sat_rtp(float16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_sat_rtn(float16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16(double16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_rtz(double16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_rte(double16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_rtp(double16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_rtn(double16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_sat(double16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_sat_rtz(double16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_sat_rte(double16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_sat_rtp(double16); __attribute__((overloadable)) short16 __spirv_ConvertFToS_Rshort16_sat_rtn(double16); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint(half); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_rtz(half); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_rte(half); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_rtp(half); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_rtn(half); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_sat(half); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_sat_rtz(half); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_sat_rte(half); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_sat_rtp(half); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_sat_rtn(half); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint(float); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_rtz(float); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_rte(float); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_rtp(float); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_rtn(float); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_sat(float); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_sat_rtz(float); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_sat_rte(float); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_sat_rtp(float); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_sat_rtn(float); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint(double); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_rtz(double); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_rte(double); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_rtp(double); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_rtn(double); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_sat(double); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_sat_rtz(double); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_sat_rte(double); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_sat_rtp(double); __attribute__((overloadable)) int __spirv_ConvertFToS_Rint_sat_rtn(double); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2(half2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_rtz(half2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_rte(half2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_rtp(half2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_rtn(half2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_sat(half2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_sat_rtz(half2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_sat_rte(half2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_sat_rtp(half2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_sat_rtn(half2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2(float2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_rtz(float2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_rte(float2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_rtp(float2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_rtn(float2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_sat(float2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_sat_rtz(float2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_sat_rte(float2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_sat_rtp(float2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_sat_rtn(float2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2(double2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_rtz(double2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_rte(double2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_rtp(double2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_rtn(double2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_sat(double2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_sat_rtz(double2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_sat_rte(double2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_sat_rtp(double2); __attribute__((overloadable)) int2 __spirv_ConvertFToS_Rint2_sat_rtn(double2); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3(half3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_rtz(half3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_rte(half3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_rtp(half3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_rtn(half3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_sat(half3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_sat_rtz(half3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_sat_rte(half3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_sat_rtp(half3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_sat_rtn(half3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3(float3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_rtz(float3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_rte(float3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_rtp(float3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_rtn(float3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_sat(float3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_sat_rtz(float3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_sat_rte(float3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_sat_rtp(float3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_sat_rtn(float3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3(double3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_rtz(double3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_rte(double3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_rtp(double3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_rtn(double3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_sat(double3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_sat_rtz(double3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_sat_rte(double3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_sat_rtp(double3); __attribute__((overloadable)) int3 __spirv_ConvertFToS_Rint3_sat_rtn(double3); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4(half4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_rtz(half4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_rte(half4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_rtp(half4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_rtn(half4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_sat(half4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_sat_rtz(half4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_sat_rte(half4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_sat_rtp(half4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_sat_rtn(half4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4(float4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_rtz(float4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_rte(float4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_rtp(float4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_rtn(float4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_sat(float4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_sat_rtz(float4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_sat_rte(float4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_sat_rtp(float4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_sat_rtn(float4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4(double4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_rtz(double4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_rte(double4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_rtp(double4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_rtn(double4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_sat(double4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_sat_rtz(double4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_sat_rte(double4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_sat_rtp(double4); __attribute__((overloadable)) int4 __spirv_ConvertFToS_Rint4_sat_rtn(double4); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8(half8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_rtz(half8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_rte(half8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_rtp(half8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_rtn(half8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_sat(half8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_sat_rtz(half8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_sat_rte(half8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_sat_rtp(half8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_sat_rtn(half8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8(float8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_rtz(float8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_rte(float8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_rtp(float8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_rtn(float8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_sat(float8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_sat_rtz(float8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_sat_rte(float8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_sat_rtp(float8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_sat_rtn(float8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8(double8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_rtz(double8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_rte(double8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_rtp(double8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_rtn(double8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_sat(double8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_sat_rtz(double8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_sat_rte(double8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_sat_rtp(double8); __attribute__((overloadable)) int8 __spirv_ConvertFToS_Rint8_sat_rtn(double8); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16(half16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_rtz(half16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_rte(half16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_rtp(half16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_rtn(half16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_sat(half16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_sat_rtz(half16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_sat_rte(half16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_sat_rtp(half16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_sat_rtn(half16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16(float16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_rtz(float16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_rte(float16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_rtp(float16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_rtn(float16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_sat(float16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_sat_rtz(float16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_sat_rte(float16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_sat_rtp(float16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_sat_rtn(float16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16(double16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_rtz(double16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_rte(double16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_rtp(double16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_rtn(double16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_sat(double16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_sat_rtz(double16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_sat_rte(double16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_sat_rtp(double16); __attribute__((overloadable)) int16 __spirv_ConvertFToS_Rint16_sat_rtn(double16); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong(half); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_rtz(half); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_rte(half); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_rtp(half); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_rtn(half); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_sat(half); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_sat_rtz(half); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_sat_rte(half); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_sat_rtp(half); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_sat_rtn(half); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong(float); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_rtz(float); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_rte(float); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_rtp(float); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_rtn(float); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_sat(float); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_sat_rtz(float); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_sat_rte(float); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_sat_rtp(float); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_sat_rtn(float); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong(double); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_rtz(double); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_rte(double); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_rtp(double); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_rtn(double); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_sat(double); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_sat_rtz(double); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_sat_rte(double); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_sat_rtp(double); __attribute__((overloadable)) long __spirv_ConvertFToS_Rlong_sat_rtn(double); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2(half2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_rtz(half2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_rte(half2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_rtp(half2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_rtn(half2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_sat(half2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_sat_rtz(half2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_sat_rte(half2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_sat_rtp(half2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_sat_rtn(half2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2(float2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_rtz(float2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_rte(float2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_rtp(float2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_rtn(float2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_sat(float2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_sat_rtz(float2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_sat_rte(float2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_sat_rtp(float2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_sat_rtn(float2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2(double2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_rtz(double2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_rte(double2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_rtp(double2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_rtn(double2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_sat(double2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_sat_rtz(double2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_sat_rte(double2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_sat_rtp(double2); __attribute__((overloadable)) long2 __spirv_ConvertFToS_Rlong2_sat_rtn(double2); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3(half3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_rtz(half3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_rte(half3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_rtp(half3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_rtn(half3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_sat(half3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_sat_rtz(half3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_sat_rte(half3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_sat_rtp(half3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_sat_rtn(half3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3(float3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_rtz(float3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_rte(float3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_rtp(float3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_rtn(float3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_sat(float3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_sat_rtz(float3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_sat_rte(float3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_sat_rtp(float3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_sat_rtn(float3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3(double3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_rtz(double3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_rte(double3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_rtp(double3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_rtn(double3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_sat(double3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_sat_rtz(double3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_sat_rte(double3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_sat_rtp(double3); __attribute__((overloadable)) long3 __spirv_ConvertFToS_Rlong3_sat_rtn(double3); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4(half4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_rtz(half4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_rte(half4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_rtp(half4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_rtn(half4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_sat(half4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_sat_rtz(half4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_sat_rte(half4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_sat_rtp(half4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_sat_rtn(half4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4(float4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_rtz(float4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_rte(float4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_rtp(float4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_rtn(float4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_sat(float4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_sat_rtz(float4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_sat_rte(float4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_sat_rtp(float4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_sat_rtn(float4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4(double4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_rtz(double4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_rte(double4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_rtp(double4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_rtn(double4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_sat(double4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_sat_rtz(double4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_sat_rte(double4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_sat_rtp(double4); __attribute__((overloadable)) long4 __spirv_ConvertFToS_Rlong4_sat_rtn(double4); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8(half8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_rtz(half8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_rte(half8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_rtp(half8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_rtn(half8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_sat(half8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_sat_rtz(half8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_sat_rte(half8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_sat_rtp(half8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_sat_rtn(half8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8(float8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_rtz(float8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_rte(float8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_rtp(float8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_rtn(float8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_sat(float8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_sat_rtz(float8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_sat_rte(float8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_sat_rtp(float8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_sat_rtn(float8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8(double8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_rtz(double8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_rte(double8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_rtp(double8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_rtn(double8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_sat(double8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_sat_rtz(double8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_sat_rte(double8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_sat_rtp(double8); __attribute__((overloadable)) long8 __spirv_ConvertFToS_Rlong8_sat_rtn(double8); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16(half16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_rtz(half16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_rte(half16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_rtp(half16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_rtn(half16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_sat(half16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_sat_rtz(half16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_sat_rte(half16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_sat_rtp(half16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_sat_rtn(half16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16(float16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_rtz(float16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_rte(float16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_rtp(float16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_rtn(float16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_sat(float16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_sat_rtz(float16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_sat_rte(float16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_sat_rtp(float16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_sat_rtn(float16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16(double16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_rtz(double16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_rte(double16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_rtp(double16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_rtn(double16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_sat(double16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_sat_rtz(double16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_sat_rte(double16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_sat_rtp(double16); __attribute__((overloadable)) long16 __spirv_ConvertFToS_Rlong16_sat_rtn(double16); __attribute__((overloadable)) half __spirv_ConvertUToF_Rhalf(uchar); __attribute__((overloadable)) half __spirv_ConvertUToF_Rhalf_rtz(uchar); __attribute__((overloadable)) half __spirv_ConvertUToF_Rhalf_rte(uchar); __attribute__((overloadable)) half __spirv_ConvertUToF_Rhalf_rtp(uchar); __attribute__((overloadable)) half __spirv_ConvertUToF_Rhalf_rtn(uchar); __attribute__((overloadable)) half __spirv_ConvertUToF_Rhalf(ushort); __attribute__((overloadable)) half __spirv_ConvertUToF_Rhalf_rtz(ushort); __attribute__((overloadable)) half __spirv_ConvertUToF_Rhalf_rte(ushort); __attribute__((overloadable)) half __spirv_ConvertUToF_Rhalf_rtp(ushort); __attribute__((overloadable)) half __spirv_ConvertUToF_Rhalf_rtn(ushort); __attribute__((overloadable)) half __spirv_ConvertUToF_Rhalf(uint); __attribute__((overloadable)) half __spirv_ConvertUToF_Rhalf_rtz(uint); __attribute__((overloadable)) half __spirv_ConvertUToF_Rhalf_rte(uint); __attribute__((overloadable)) half __spirv_ConvertUToF_Rhalf_rtp(uint); __attribute__((overloadable)) half __spirv_ConvertUToF_Rhalf_rtn(uint); __attribute__((overloadable)) half __spirv_ConvertUToF_Rhalf(ulong); __attribute__((overloadable)) half __spirv_ConvertUToF_Rhalf_rtz(ulong); __attribute__((overloadable)) half __spirv_ConvertUToF_Rhalf_rte(ulong); __attribute__((overloadable)) half __spirv_ConvertUToF_Rhalf_rtp(ulong); __attribute__((overloadable)) half __spirv_ConvertUToF_Rhalf_rtn(ulong); __attribute__((overloadable)) half2 __spirv_ConvertUToF_Rhalf2(uchar2); __attribute__((overloadable)) half2 __spirv_ConvertUToF_Rhalf2_rtz(uchar2); __attribute__((overloadable)) half2 __spirv_ConvertUToF_Rhalf2_rte(uchar2); __attribute__((overloadable)) half2 __spirv_ConvertUToF_Rhalf2_rtp(uchar2); __attribute__((overloadable)) half2 __spirv_ConvertUToF_Rhalf2_rtn(uchar2); __attribute__((overloadable)) half2 __spirv_ConvertUToF_Rhalf2(ushort2); __attribute__((overloadable)) half2 __spirv_ConvertUToF_Rhalf2_rtz(ushort2); __attribute__((overloadable)) half2 __spirv_ConvertUToF_Rhalf2_rte(ushort2); __attribute__((overloadable)) half2 __spirv_ConvertUToF_Rhalf2_rtp(ushort2); __attribute__((overloadable)) half2 __spirv_ConvertUToF_Rhalf2_rtn(ushort2); __attribute__((overloadable)) half2 __spirv_ConvertUToF_Rhalf2(uint2); __attribute__((overloadable)) half2 __spirv_ConvertUToF_Rhalf2_rtz(uint2); __attribute__((overloadable)) half2 __spirv_ConvertUToF_Rhalf2_rte(uint2); __attribute__((overloadable)) half2 __spirv_ConvertUToF_Rhalf2_rtp(uint2); __attribute__((overloadable)) half2 __spirv_ConvertUToF_Rhalf2_rtn(uint2); __attribute__((overloadable)) half2 __spirv_ConvertUToF_Rhalf2(ulong2); __attribute__((overloadable)) half2 __spirv_ConvertUToF_Rhalf2_rtz(ulong2); __attribute__((overloadable)) half2 __spirv_ConvertUToF_Rhalf2_rte(ulong2); __attribute__((overloadable)) half2 __spirv_ConvertUToF_Rhalf2_rtp(ulong2); __attribute__((overloadable)) half2 __spirv_ConvertUToF_Rhalf2_rtn(ulong2); __attribute__((overloadable)) half3 __spirv_ConvertUToF_Rhalf3(uchar3); __attribute__((overloadable)) half3 __spirv_ConvertUToF_Rhalf3_rtz(uchar3); __attribute__((overloadable)) half3 __spirv_ConvertUToF_Rhalf3_rte(uchar3); __attribute__((overloadable)) half3 __spirv_ConvertUToF_Rhalf3_rtp(uchar3); __attribute__((overloadable)) half3 __spirv_ConvertUToF_Rhalf3_rtn(uchar3); __attribute__((overloadable)) half3 __spirv_ConvertUToF_Rhalf3(ushort3); __attribute__((overloadable)) half3 __spirv_ConvertUToF_Rhalf3_rtz(ushort3); __attribute__((overloadable)) half3 __spirv_ConvertUToF_Rhalf3_rte(ushort3); __attribute__((overloadable)) half3 __spirv_ConvertUToF_Rhalf3_rtp(ushort3); __attribute__((overloadable)) half3 __spirv_ConvertUToF_Rhalf3_rtn(ushort3); __attribute__((overloadable)) half3 __spirv_ConvertUToF_Rhalf3(uint3); __attribute__((overloadable)) half3 __spirv_ConvertUToF_Rhalf3_rtz(uint3); __attribute__((overloadable)) half3 __spirv_ConvertUToF_Rhalf3_rte(uint3); __attribute__((overloadable)) half3 __spirv_ConvertUToF_Rhalf3_rtp(uint3); __attribute__((overloadable)) half3 __spirv_ConvertUToF_Rhalf3_rtn(uint3); __attribute__((overloadable)) half3 __spirv_ConvertUToF_Rhalf3(ulong3); __attribute__((overloadable)) half3 __spirv_ConvertUToF_Rhalf3_rtz(ulong3); __attribute__((overloadable)) half3 __spirv_ConvertUToF_Rhalf3_rte(ulong3); __attribute__((overloadable)) half3 __spirv_ConvertUToF_Rhalf3_rtp(ulong3); __attribute__((overloadable)) half3 __spirv_ConvertUToF_Rhalf3_rtn(ulong3); __attribute__((overloadable)) half4 __spirv_ConvertUToF_Rhalf4(uchar4); __attribute__((overloadable)) half4 __spirv_ConvertUToF_Rhalf4_rtz(uchar4); __attribute__((overloadable)) half4 __spirv_ConvertUToF_Rhalf4_rte(uchar4); __attribute__((overloadable)) half4 __spirv_ConvertUToF_Rhalf4_rtp(uchar4); __attribute__((overloadable)) half4 __spirv_ConvertUToF_Rhalf4_rtn(uchar4); __attribute__((overloadable)) half4 __spirv_ConvertUToF_Rhalf4(ushort4); __attribute__((overloadable)) half4 __spirv_ConvertUToF_Rhalf4_rtz(ushort4); __attribute__((overloadable)) half4 __spirv_ConvertUToF_Rhalf4_rte(ushort4); __attribute__((overloadable)) half4 __spirv_ConvertUToF_Rhalf4_rtp(ushort4); __attribute__((overloadable)) half4 __spirv_ConvertUToF_Rhalf4_rtn(ushort4); __attribute__((overloadable)) half4 __spirv_ConvertUToF_Rhalf4(uint4); __attribute__((overloadable)) half4 __spirv_ConvertUToF_Rhalf4_rtz(uint4); __attribute__((overloadable)) half4 __spirv_ConvertUToF_Rhalf4_rte(uint4); __attribute__((overloadable)) half4 __spirv_ConvertUToF_Rhalf4_rtp(uint4); __attribute__((overloadable)) half4 __spirv_ConvertUToF_Rhalf4_rtn(uint4); __attribute__((overloadable)) half4 __spirv_ConvertUToF_Rhalf4(ulong4); __attribute__((overloadable)) half4 __spirv_ConvertUToF_Rhalf4_rtz(ulong4); __attribute__((overloadable)) half4 __spirv_ConvertUToF_Rhalf4_rte(ulong4); __attribute__((overloadable)) half4 __spirv_ConvertUToF_Rhalf4_rtp(ulong4); __attribute__((overloadable)) half4 __spirv_ConvertUToF_Rhalf4_rtn(ulong4); __attribute__((overloadable)) half8 __spirv_ConvertUToF_Rhalf8(uchar8); __attribute__((overloadable)) half8 __spirv_ConvertUToF_Rhalf8_rtz(uchar8); __attribute__((overloadable)) half8 __spirv_ConvertUToF_Rhalf8_rte(uchar8); __attribute__((overloadable)) half8 __spirv_ConvertUToF_Rhalf8_rtp(uchar8); __attribute__((overloadable)) half8 __spirv_ConvertUToF_Rhalf8_rtn(uchar8); __attribute__((overloadable)) half8 __spirv_ConvertUToF_Rhalf8(ushort8); __attribute__((overloadable)) half8 __spirv_ConvertUToF_Rhalf8_rtz(ushort8); __attribute__((overloadable)) half8 __spirv_ConvertUToF_Rhalf8_rte(ushort8); __attribute__((overloadable)) half8 __spirv_ConvertUToF_Rhalf8_rtp(ushort8); __attribute__((overloadable)) half8 __spirv_ConvertUToF_Rhalf8_rtn(ushort8); __attribute__((overloadable)) half8 __spirv_ConvertUToF_Rhalf8(uint8); __attribute__((overloadable)) half8 __spirv_ConvertUToF_Rhalf8_rtz(uint8); __attribute__((overloadable)) half8 __spirv_ConvertUToF_Rhalf8_rte(uint8); __attribute__((overloadable)) half8 __spirv_ConvertUToF_Rhalf8_rtp(uint8); __attribute__((overloadable)) half8 __spirv_ConvertUToF_Rhalf8_rtn(uint8); __attribute__((overloadable)) half8 __spirv_ConvertUToF_Rhalf8(ulong8); __attribute__((overloadable)) half8 __spirv_ConvertUToF_Rhalf8_rtz(ulong8); __attribute__((overloadable)) half8 __spirv_ConvertUToF_Rhalf8_rte(ulong8); __attribute__((overloadable)) half8 __spirv_ConvertUToF_Rhalf8_rtp(ulong8); __attribute__((overloadable)) half8 __spirv_ConvertUToF_Rhalf8_rtn(ulong8); __attribute__((overloadable)) half16 __spirv_ConvertUToF_Rhalf16(uchar16); __attribute__((overloadable)) half16 __spirv_ConvertUToF_Rhalf16_rtz(uchar16); __attribute__((overloadable)) half16 __spirv_ConvertUToF_Rhalf16_rte(uchar16); __attribute__((overloadable)) half16 __spirv_ConvertUToF_Rhalf16_rtp(uchar16); __attribute__((overloadable)) half16 __spirv_ConvertUToF_Rhalf16_rtn(uchar16); __attribute__((overloadable)) half16 __spirv_ConvertUToF_Rhalf16(ushort16); __attribute__((overloadable)) half16 __spirv_ConvertUToF_Rhalf16_rtz(ushort16); __attribute__((overloadable)) half16 __spirv_ConvertUToF_Rhalf16_rte(ushort16); __attribute__((overloadable)) half16 __spirv_ConvertUToF_Rhalf16_rtp(ushort16); __attribute__((overloadable)) half16 __spirv_ConvertUToF_Rhalf16_rtn(ushort16); __attribute__((overloadable)) half16 __spirv_ConvertUToF_Rhalf16(uint16); __attribute__((overloadable)) half16 __spirv_ConvertUToF_Rhalf16_rtz(uint16); __attribute__((overloadable)) half16 __spirv_ConvertUToF_Rhalf16_rte(uint16); __attribute__((overloadable)) half16 __spirv_ConvertUToF_Rhalf16_rtp(uint16); __attribute__((overloadable)) half16 __spirv_ConvertUToF_Rhalf16_rtn(uint16); __attribute__((overloadable)) half16 __spirv_ConvertUToF_Rhalf16(ulong16); __attribute__((overloadable)) half16 __spirv_ConvertUToF_Rhalf16_rtz(ulong16); __attribute__((overloadable)) half16 __spirv_ConvertUToF_Rhalf16_rte(ulong16); __attribute__((overloadable)) half16 __spirv_ConvertUToF_Rhalf16_rtp(ulong16); __attribute__((overloadable)) half16 __spirv_ConvertUToF_Rhalf16_rtn(ulong16); __attribute__((overloadable)) float __spirv_ConvertUToF_Rfloat(uchar); __attribute__((overloadable)) float __spirv_ConvertUToF_Rfloat_rtz(uchar); __attribute__((overloadable)) float __spirv_ConvertUToF_Rfloat_rte(uchar); __attribute__((overloadable)) float __spirv_ConvertUToF_Rfloat_rtp(uchar); __attribute__((overloadable)) float __spirv_ConvertUToF_Rfloat_rtn(uchar); __attribute__((overloadable)) float __spirv_ConvertUToF_Rfloat(ushort); __attribute__((overloadable)) float __spirv_ConvertUToF_Rfloat_rtz(ushort); __attribute__((overloadable)) float __spirv_ConvertUToF_Rfloat_rte(ushort); __attribute__((overloadable)) float __spirv_ConvertUToF_Rfloat_rtp(ushort); __attribute__((overloadable)) float __spirv_ConvertUToF_Rfloat_rtn(ushort); __attribute__((overloadable)) float __spirv_ConvertUToF_Rfloat(uint); __attribute__((overloadable)) float __spirv_ConvertUToF_Rfloat_rtz(uint); __attribute__((overloadable)) float __spirv_ConvertUToF_Rfloat_rte(uint); __attribute__((overloadable)) float __spirv_ConvertUToF_Rfloat_rtp(uint); __attribute__((overloadable)) float __spirv_ConvertUToF_Rfloat_rtn(uint); __attribute__((overloadable)) float __spirv_ConvertUToF_Rfloat(ulong); __attribute__((overloadable)) float __spirv_ConvertUToF_Rfloat_rtz(ulong); __attribute__((overloadable)) float __spirv_ConvertUToF_Rfloat_rte(ulong); __attribute__((overloadable)) float __spirv_ConvertUToF_Rfloat_rtp(ulong); __attribute__((overloadable)) float __spirv_ConvertUToF_Rfloat_rtn(ulong); __attribute__((overloadable)) float2 __spirv_ConvertUToF_Rfloat2(uchar2); __attribute__((overloadable)) float2 __spirv_ConvertUToF_Rfloat2_rtz(uchar2); __attribute__((overloadable)) float2 __spirv_ConvertUToF_Rfloat2_rte(uchar2); __attribute__((overloadable)) float2 __spirv_ConvertUToF_Rfloat2_rtp(uchar2); __attribute__((overloadable)) float2 __spirv_ConvertUToF_Rfloat2_rtn(uchar2); __attribute__((overloadable)) float2 __spirv_ConvertUToF_Rfloat2(ushort2); __attribute__((overloadable)) float2 __spirv_ConvertUToF_Rfloat2_rtz(ushort2); __attribute__((overloadable)) float2 __spirv_ConvertUToF_Rfloat2_rte(ushort2); __attribute__((overloadable)) float2 __spirv_ConvertUToF_Rfloat2_rtp(ushort2); __attribute__((overloadable)) float2 __spirv_ConvertUToF_Rfloat2_rtn(ushort2); __attribute__((overloadable)) float2 __spirv_ConvertUToF_Rfloat2(uint2); __attribute__((overloadable)) float2 __spirv_ConvertUToF_Rfloat2_rtz(uint2); __attribute__((overloadable)) float2 __spirv_ConvertUToF_Rfloat2_rte(uint2); __attribute__((overloadable)) float2 __spirv_ConvertUToF_Rfloat2_rtp(uint2); __attribute__((overloadable)) float2 __spirv_ConvertUToF_Rfloat2_rtn(uint2); __attribute__((overloadable)) float2 __spirv_ConvertUToF_Rfloat2(ulong2); __attribute__((overloadable)) float2 __spirv_ConvertUToF_Rfloat2_rtz(ulong2); __attribute__((overloadable)) float2 __spirv_ConvertUToF_Rfloat2_rte(ulong2); __attribute__((overloadable)) float2 __spirv_ConvertUToF_Rfloat2_rtp(ulong2); __attribute__((overloadable)) float2 __spirv_ConvertUToF_Rfloat2_rtn(ulong2); __attribute__((overloadable)) float3 __spirv_ConvertUToF_Rfloat3(uchar3); __attribute__((overloadable)) float3 __spirv_ConvertUToF_Rfloat3_rtz(uchar3); __attribute__((overloadable)) float3 __spirv_ConvertUToF_Rfloat3_rte(uchar3); __attribute__((overloadable)) float3 __spirv_ConvertUToF_Rfloat3_rtp(uchar3); __attribute__((overloadable)) float3 __spirv_ConvertUToF_Rfloat3_rtn(uchar3); __attribute__((overloadable)) float3 __spirv_ConvertUToF_Rfloat3(ushort3); __attribute__((overloadable)) float3 __spirv_ConvertUToF_Rfloat3_rtz(ushort3); __attribute__((overloadable)) float3 __spirv_ConvertUToF_Rfloat3_rte(ushort3); __attribute__((overloadable)) float3 __spirv_ConvertUToF_Rfloat3_rtp(ushort3); __attribute__((overloadable)) float3 __spirv_ConvertUToF_Rfloat3_rtn(ushort3); __attribute__((overloadable)) float3 __spirv_ConvertUToF_Rfloat3(uint3); __attribute__((overloadable)) float3 __spirv_ConvertUToF_Rfloat3_rtz(uint3); __attribute__((overloadable)) float3 __spirv_ConvertUToF_Rfloat3_rte(uint3); __attribute__((overloadable)) float3 __spirv_ConvertUToF_Rfloat3_rtp(uint3); __attribute__((overloadable)) float3 __spirv_ConvertUToF_Rfloat3_rtn(uint3); __attribute__((overloadable)) float3 __spirv_ConvertUToF_Rfloat3(ulong3); __attribute__((overloadable)) float3 __spirv_ConvertUToF_Rfloat3_rtz(ulong3); __attribute__((overloadable)) float3 __spirv_ConvertUToF_Rfloat3_rte(ulong3); __attribute__((overloadable)) float3 __spirv_ConvertUToF_Rfloat3_rtp(ulong3); __attribute__((overloadable)) float3 __spirv_ConvertUToF_Rfloat3_rtn(ulong3); __attribute__((overloadable)) float4 __spirv_ConvertUToF_Rfloat4(uchar4); __attribute__((overloadable)) float4 __spirv_ConvertUToF_Rfloat4_rtz(uchar4); __attribute__((overloadable)) float4 __spirv_ConvertUToF_Rfloat4_rte(uchar4); __attribute__((overloadable)) float4 __spirv_ConvertUToF_Rfloat4_rtp(uchar4); __attribute__((overloadable)) float4 __spirv_ConvertUToF_Rfloat4_rtn(uchar4); __attribute__((overloadable)) float4 __spirv_ConvertUToF_Rfloat4(ushort4); __attribute__((overloadable)) float4 __spirv_ConvertUToF_Rfloat4_rtz(ushort4); __attribute__((overloadable)) float4 __spirv_ConvertUToF_Rfloat4_rte(ushort4); __attribute__((overloadable)) float4 __spirv_ConvertUToF_Rfloat4_rtp(ushort4); __attribute__((overloadable)) float4 __spirv_ConvertUToF_Rfloat4_rtn(ushort4); __attribute__((overloadable)) float4 __spirv_ConvertUToF_Rfloat4(uint4); __attribute__((overloadable)) float4 __spirv_ConvertUToF_Rfloat4_rtz(uint4); __attribute__((overloadable)) float4 __spirv_ConvertUToF_Rfloat4_rte(uint4); __attribute__((overloadable)) float4 __spirv_ConvertUToF_Rfloat4_rtp(uint4); __attribute__((overloadable)) float4 __spirv_ConvertUToF_Rfloat4_rtn(uint4); __attribute__((overloadable)) float4 __spirv_ConvertUToF_Rfloat4(ulong4); __attribute__((overloadable)) float4 __spirv_ConvertUToF_Rfloat4_rtz(ulong4); __attribute__((overloadable)) float4 __spirv_ConvertUToF_Rfloat4_rte(ulong4); __attribute__((overloadable)) float4 __spirv_ConvertUToF_Rfloat4_rtp(ulong4); __attribute__((overloadable)) float4 __spirv_ConvertUToF_Rfloat4_rtn(ulong4); __attribute__((overloadable)) float8 __spirv_ConvertUToF_Rfloat8(uchar8); __attribute__((overloadable)) float8 __spirv_ConvertUToF_Rfloat8_rtz(uchar8); __attribute__((overloadable)) float8 __spirv_ConvertUToF_Rfloat8_rte(uchar8); __attribute__((overloadable)) float8 __spirv_ConvertUToF_Rfloat8_rtp(uchar8); __attribute__((overloadable)) float8 __spirv_ConvertUToF_Rfloat8_rtn(uchar8); __attribute__((overloadable)) float8 __spirv_ConvertUToF_Rfloat8(ushort8); __attribute__((overloadable)) float8 __spirv_ConvertUToF_Rfloat8_rtz(ushort8); __attribute__((overloadable)) float8 __spirv_ConvertUToF_Rfloat8_rte(ushort8); __attribute__((overloadable)) float8 __spirv_ConvertUToF_Rfloat8_rtp(ushort8); __attribute__((overloadable)) float8 __spirv_ConvertUToF_Rfloat8_rtn(ushort8); __attribute__((overloadable)) float8 __spirv_ConvertUToF_Rfloat8(uint8); __attribute__((overloadable)) float8 __spirv_ConvertUToF_Rfloat8_rtz(uint8); __attribute__((overloadable)) float8 __spirv_ConvertUToF_Rfloat8_rte(uint8); __attribute__((overloadable)) float8 __spirv_ConvertUToF_Rfloat8_rtp(uint8); __attribute__((overloadable)) float8 __spirv_ConvertUToF_Rfloat8_rtn(uint8); __attribute__((overloadable)) float8 __spirv_ConvertUToF_Rfloat8(ulong8); __attribute__((overloadable)) float8 __spirv_ConvertUToF_Rfloat8_rtz(ulong8); __attribute__((overloadable)) float8 __spirv_ConvertUToF_Rfloat8_rte(ulong8); __attribute__((overloadable)) float8 __spirv_ConvertUToF_Rfloat8_rtp(ulong8); __attribute__((overloadable)) float8 __spirv_ConvertUToF_Rfloat8_rtn(ulong8); __attribute__((overloadable)) float16 __spirv_ConvertUToF_Rfloat16(uchar16); __attribute__((overloadable)) float16 __spirv_ConvertUToF_Rfloat16_rtz(uchar16); __attribute__((overloadable)) float16 __spirv_ConvertUToF_Rfloat16_rte(uchar16); __attribute__((overloadable)) float16 __spirv_ConvertUToF_Rfloat16_rtp(uchar16); __attribute__((overloadable)) float16 __spirv_ConvertUToF_Rfloat16_rtn(uchar16); __attribute__((overloadable)) float16 __spirv_ConvertUToF_Rfloat16(ushort16); __attribute__((overloadable)) float16 __spirv_ConvertUToF_Rfloat16_rtz(ushort16); __attribute__((overloadable)) float16 __spirv_ConvertUToF_Rfloat16_rte(ushort16); __attribute__((overloadable)) float16 __spirv_ConvertUToF_Rfloat16_rtp(ushort16); __attribute__((overloadable)) float16 __spirv_ConvertUToF_Rfloat16_rtn(ushort16); __attribute__((overloadable)) float16 __spirv_ConvertUToF_Rfloat16(uint16); __attribute__((overloadable)) float16 __spirv_ConvertUToF_Rfloat16_rtz(uint16); __attribute__((overloadable)) float16 __spirv_ConvertUToF_Rfloat16_rte(uint16); __attribute__((overloadable)) float16 __spirv_ConvertUToF_Rfloat16_rtp(uint16); __attribute__((overloadable)) float16 __spirv_ConvertUToF_Rfloat16_rtn(uint16); __attribute__((overloadable)) float16 __spirv_ConvertUToF_Rfloat16(ulong16); __attribute__((overloadable)) float16 __spirv_ConvertUToF_Rfloat16_rtz(ulong16); __attribute__((overloadable)) float16 __spirv_ConvertUToF_Rfloat16_rte(ulong16); __attribute__((overloadable)) float16 __spirv_ConvertUToF_Rfloat16_rtp(ulong16); __attribute__((overloadable)) float16 __spirv_ConvertUToF_Rfloat16_rtn(ulong16); __attribute__((overloadable)) double __spirv_ConvertUToF_Rdouble(uchar); __attribute__((overloadable)) double __spirv_ConvertUToF_Rdouble_rtz(uchar); __attribute__((overloadable)) double __spirv_ConvertUToF_Rdouble_rte(uchar); __attribute__((overloadable)) double __spirv_ConvertUToF_Rdouble_rtp(uchar); __attribute__((overloadable)) double __spirv_ConvertUToF_Rdouble_rtn(uchar); __attribute__((overloadable)) double __spirv_ConvertUToF_Rdouble(ushort); __attribute__((overloadable)) double __spirv_ConvertUToF_Rdouble_rtz(ushort); __attribute__((overloadable)) double __spirv_ConvertUToF_Rdouble_rte(ushort); __attribute__((overloadable)) double __spirv_ConvertUToF_Rdouble_rtp(ushort); __attribute__((overloadable)) double __spirv_ConvertUToF_Rdouble_rtn(ushort); __attribute__((overloadable)) double __spirv_ConvertUToF_Rdouble(uint); __attribute__((overloadable)) double __spirv_ConvertUToF_Rdouble_rtz(uint); __attribute__((overloadable)) double __spirv_ConvertUToF_Rdouble_rte(uint); __attribute__((overloadable)) double __spirv_ConvertUToF_Rdouble_rtp(uint); __attribute__((overloadable)) double __spirv_ConvertUToF_Rdouble_rtn(uint); __attribute__((overloadable)) double __spirv_ConvertUToF_Rdouble(ulong); __attribute__((overloadable)) double __spirv_ConvertUToF_Rdouble_rtz(ulong); __attribute__((overloadable)) double __spirv_ConvertUToF_Rdouble_rte(ulong); __attribute__((overloadable)) double __spirv_ConvertUToF_Rdouble_rtp(ulong); __attribute__((overloadable)) double __spirv_ConvertUToF_Rdouble_rtn(ulong); __attribute__((overloadable)) double2 __spirv_ConvertUToF_Rdouble2(uchar2); __attribute__((overloadable)) double2 __spirv_ConvertUToF_Rdouble2_rtz(uchar2); __attribute__((overloadable)) double2 __spirv_ConvertUToF_Rdouble2_rte(uchar2); __attribute__((overloadable)) double2 __spirv_ConvertUToF_Rdouble2_rtp(uchar2); __attribute__((overloadable)) double2 __spirv_ConvertUToF_Rdouble2_rtn(uchar2); __attribute__((overloadable)) double2 __spirv_ConvertUToF_Rdouble2(ushort2); __attribute__((overloadable)) double2 __spirv_ConvertUToF_Rdouble2_rtz(ushort2); __attribute__((overloadable)) double2 __spirv_ConvertUToF_Rdouble2_rte(ushort2); __attribute__((overloadable)) double2 __spirv_ConvertUToF_Rdouble2_rtp(ushort2); __attribute__((overloadable)) double2 __spirv_ConvertUToF_Rdouble2_rtn(ushort2); __attribute__((overloadable)) double2 __spirv_ConvertUToF_Rdouble2(uint2); __attribute__((overloadable)) double2 __spirv_ConvertUToF_Rdouble2_rtz(uint2); __attribute__((overloadable)) double2 __spirv_ConvertUToF_Rdouble2_rte(uint2); __attribute__((overloadable)) double2 __spirv_ConvertUToF_Rdouble2_rtp(uint2); __attribute__((overloadable)) double2 __spirv_ConvertUToF_Rdouble2_rtn(uint2); __attribute__((overloadable)) double2 __spirv_ConvertUToF_Rdouble2(ulong2); __attribute__((overloadable)) double2 __spirv_ConvertUToF_Rdouble2_rtz(ulong2); __attribute__((overloadable)) double2 __spirv_ConvertUToF_Rdouble2_rte(ulong2); __attribute__((overloadable)) double2 __spirv_ConvertUToF_Rdouble2_rtp(ulong2); __attribute__((overloadable)) double2 __spirv_ConvertUToF_Rdouble2_rtn(ulong2); __attribute__((overloadable)) double3 __spirv_ConvertUToF_Rdouble3(uchar3); __attribute__((overloadable)) double3 __spirv_ConvertUToF_Rdouble3_rtz(uchar3); __attribute__((overloadable)) double3 __spirv_ConvertUToF_Rdouble3_rte(uchar3); __attribute__((overloadable)) double3 __spirv_ConvertUToF_Rdouble3_rtp(uchar3); __attribute__((overloadable)) double3 __spirv_ConvertUToF_Rdouble3_rtn(uchar3); __attribute__((overloadable)) double3 __spirv_ConvertUToF_Rdouble3(ushort3); __attribute__((overloadable)) double3 __spirv_ConvertUToF_Rdouble3_rtz(ushort3); __attribute__((overloadable)) double3 __spirv_ConvertUToF_Rdouble3_rte(ushort3); __attribute__((overloadable)) double3 __spirv_ConvertUToF_Rdouble3_rtp(ushort3); __attribute__((overloadable)) double3 __spirv_ConvertUToF_Rdouble3_rtn(ushort3); __attribute__((overloadable)) double3 __spirv_ConvertUToF_Rdouble3(uint3); __attribute__((overloadable)) double3 __spirv_ConvertUToF_Rdouble3_rtz(uint3); __attribute__((overloadable)) double3 __spirv_ConvertUToF_Rdouble3_rte(uint3); __attribute__((overloadable)) double3 __spirv_ConvertUToF_Rdouble3_rtp(uint3); __attribute__((overloadable)) double3 __spirv_ConvertUToF_Rdouble3_rtn(uint3); __attribute__((overloadable)) double3 __spirv_ConvertUToF_Rdouble3(ulong3); __attribute__((overloadable)) double3 __spirv_ConvertUToF_Rdouble3_rtz(ulong3); __attribute__((overloadable)) double3 __spirv_ConvertUToF_Rdouble3_rte(ulong3); __attribute__((overloadable)) double3 __spirv_ConvertUToF_Rdouble3_rtp(ulong3); __attribute__((overloadable)) double3 __spirv_ConvertUToF_Rdouble3_rtn(ulong3); __attribute__((overloadable)) double4 __spirv_ConvertUToF_Rdouble4(uchar4); __attribute__((overloadable)) double4 __spirv_ConvertUToF_Rdouble4_rtz(uchar4); __attribute__((overloadable)) double4 __spirv_ConvertUToF_Rdouble4_rte(uchar4); __attribute__((overloadable)) double4 __spirv_ConvertUToF_Rdouble4_rtp(uchar4); __attribute__((overloadable)) double4 __spirv_ConvertUToF_Rdouble4_rtn(uchar4); __attribute__((overloadable)) double4 __spirv_ConvertUToF_Rdouble4(ushort4); __attribute__((overloadable)) double4 __spirv_ConvertUToF_Rdouble4_rtz(ushort4); __attribute__((overloadable)) double4 __spirv_ConvertUToF_Rdouble4_rte(ushort4); __attribute__((overloadable)) double4 __spirv_ConvertUToF_Rdouble4_rtp(ushort4); __attribute__((overloadable)) double4 __spirv_ConvertUToF_Rdouble4_rtn(ushort4); __attribute__((overloadable)) double4 __spirv_ConvertUToF_Rdouble4(uint4); __attribute__((overloadable)) double4 __spirv_ConvertUToF_Rdouble4_rtz(uint4); __attribute__((overloadable)) double4 __spirv_ConvertUToF_Rdouble4_rte(uint4); __attribute__((overloadable)) double4 __spirv_ConvertUToF_Rdouble4_rtp(uint4); __attribute__((overloadable)) double4 __spirv_ConvertUToF_Rdouble4_rtn(uint4); __attribute__((overloadable)) double4 __spirv_ConvertUToF_Rdouble4(ulong4); __attribute__((overloadable)) double4 __spirv_ConvertUToF_Rdouble4_rtz(ulong4); __attribute__((overloadable)) double4 __spirv_ConvertUToF_Rdouble4_rte(ulong4); __attribute__((overloadable)) double4 __spirv_ConvertUToF_Rdouble4_rtp(ulong4); __attribute__((overloadable)) double4 __spirv_ConvertUToF_Rdouble4_rtn(ulong4); __attribute__((overloadable)) double8 __spirv_ConvertUToF_Rdouble8(uchar8); __attribute__((overloadable)) double8 __spirv_ConvertUToF_Rdouble8_rtz(uchar8); __attribute__((overloadable)) double8 __spirv_ConvertUToF_Rdouble8_rte(uchar8); __attribute__((overloadable)) double8 __spirv_ConvertUToF_Rdouble8_rtp(uchar8); __attribute__((overloadable)) double8 __spirv_ConvertUToF_Rdouble8_rtn(uchar8); __attribute__((overloadable)) double8 __spirv_ConvertUToF_Rdouble8(ushort8); __attribute__((overloadable)) double8 __spirv_ConvertUToF_Rdouble8_rtz(ushort8); __attribute__((overloadable)) double8 __spirv_ConvertUToF_Rdouble8_rte(ushort8); __attribute__((overloadable)) double8 __spirv_ConvertUToF_Rdouble8_rtp(ushort8); __attribute__((overloadable)) double8 __spirv_ConvertUToF_Rdouble8_rtn(ushort8); __attribute__((overloadable)) double8 __spirv_ConvertUToF_Rdouble8(uint8); __attribute__((overloadable)) double8 __spirv_ConvertUToF_Rdouble8_rtz(uint8); __attribute__((overloadable)) double8 __spirv_ConvertUToF_Rdouble8_rte(uint8); __attribute__((overloadable)) double8 __spirv_ConvertUToF_Rdouble8_rtp(uint8); __attribute__((overloadable)) double8 __spirv_ConvertUToF_Rdouble8_rtn(uint8); __attribute__((overloadable)) double8 __spirv_ConvertUToF_Rdouble8(ulong8); __attribute__((overloadable)) double8 __spirv_ConvertUToF_Rdouble8_rtz(ulong8); __attribute__((overloadable)) double8 __spirv_ConvertUToF_Rdouble8_rte(ulong8); __attribute__((overloadable)) double8 __spirv_ConvertUToF_Rdouble8_rtp(ulong8); __attribute__((overloadable)) double8 __spirv_ConvertUToF_Rdouble8_rtn(ulong8); __attribute__((overloadable)) double16 __spirv_ConvertUToF_Rdouble16(uchar16); __attribute__((overloadable)) double16 __spirv_ConvertUToF_Rdouble16_rtz(uchar16); __attribute__((overloadable)) double16 __spirv_ConvertUToF_Rdouble16_rte(uchar16); __attribute__((overloadable)) double16 __spirv_ConvertUToF_Rdouble16_rtp(uchar16); __attribute__((overloadable)) double16 __spirv_ConvertUToF_Rdouble16_rtn(uchar16); __attribute__((overloadable)) double16 __spirv_ConvertUToF_Rdouble16(ushort16); __attribute__((overloadable)) double16 __spirv_ConvertUToF_Rdouble16_rtz(ushort16); __attribute__((overloadable)) double16 __spirv_ConvertUToF_Rdouble16_rte(ushort16); __attribute__((overloadable)) double16 __spirv_ConvertUToF_Rdouble16_rtp(ushort16); __attribute__((overloadable)) double16 __spirv_ConvertUToF_Rdouble16_rtn(ushort16); __attribute__((overloadable)) double16 __spirv_ConvertUToF_Rdouble16(uint16); __attribute__((overloadable)) double16 __spirv_ConvertUToF_Rdouble16_rtz(uint16); __attribute__((overloadable)) double16 __spirv_ConvertUToF_Rdouble16_rte(uint16); __attribute__((overloadable)) double16 __spirv_ConvertUToF_Rdouble16_rtp(uint16); __attribute__((overloadable)) double16 __spirv_ConvertUToF_Rdouble16_rtn(uint16); __attribute__((overloadable)) double16 __spirv_ConvertUToF_Rdouble16(ulong16); __attribute__((overloadable)) double16 __spirv_ConvertUToF_Rdouble16_rtz(ulong16); __attribute__((overloadable)) double16 __spirv_ConvertUToF_Rdouble16_rte(ulong16); __attribute__((overloadable)) double16 __spirv_ConvertUToF_Rdouble16_rtp(ulong16); __attribute__((overloadable)) double16 __spirv_ConvertUToF_Rdouble16_rtn(ulong16); __attribute__((overloadable)) half __spirv_ConvertSToF_Rhalf(char); __attribute__((overloadable)) half __spirv_ConvertSToF_Rhalf_rtz(char); __attribute__((overloadable)) half __spirv_ConvertSToF_Rhalf_rte(char); __attribute__((overloadable)) half __spirv_ConvertSToF_Rhalf_rtp(char); __attribute__((overloadable)) half __spirv_ConvertSToF_Rhalf_rtn(char); __attribute__((overloadable)) half __spirv_ConvertSToF_Rhalf(short); __attribute__((overloadable)) half __spirv_ConvertSToF_Rhalf_rtz(short); __attribute__((overloadable)) half __spirv_ConvertSToF_Rhalf_rte(short); __attribute__((overloadable)) half __spirv_ConvertSToF_Rhalf_rtp(short); __attribute__((overloadable)) half __spirv_ConvertSToF_Rhalf_rtn(short); __attribute__((overloadable)) half __spirv_ConvertSToF_Rhalf(int); __attribute__((overloadable)) half __spirv_ConvertSToF_Rhalf_rtz(int); __attribute__((overloadable)) half __spirv_ConvertSToF_Rhalf_rte(int); __attribute__((overloadable)) half __spirv_ConvertSToF_Rhalf_rtp(int); __attribute__((overloadable)) half __spirv_ConvertSToF_Rhalf_rtn(int); __attribute__((overloadable)) half __spirv_ConvertSToF_Rhalf(long); __attribute__((overloadable)) half __spirv_ConvertSToF_Rhalf_rtz(long); __attribute__((overloadable)) half __spirv_ConvertSToF_Rhalf_rte(long); __attribute__((overloadable)) half __spirv_ConvertSToF_Rhalf_rtp(long); __attribute__((overloadable)) half __spirv_ConvertSToF_Rhalf_rtn(long); __attribute__((overloadable)) half2 __spirv_ConvertSToF_Rhalf2(char2); __attribute__((overloadable)) half2 __spirv_ConvertSToF_Rhalf2_rtz(char2); __attribute__((overloadable)) half2 __spirv_ConvertSToF_Rhalf2_rte(char2); __attribute__((overloadable)) half2 __spirv_ConvertSToF_Rhalf2_rtp(char2); __attribute__((overloadable)) half2 __spirv_ConvertSToF_Rhalf2_rtn(char2); __attribute__((overloadable)) half2 __spirv_ConvertSToF_Rhalf2(short2); __attribute__((overloadable)) half2 __spirv_ConvertSToF_Rhalf2_rtz(short2); __attribute__((overloadable)) half2 __spirv_ConvertSToF_Rhalf2_rte(short2); __attribute__((overloadable)) half2 __spirv_ConvertSToF_Rhalf2_rtp(short2); __attribute__((overloadable)) half2 __spirv_ConvertSToF_Rhalf2_rtn(short2); __attribute__((overloadable)) half2 __spirv_ConvertSToF_Rhalf2(int2); __attribute__((overloadable)) half2 __spirv_ConvertSToF_Rhalf2_rtz(int2); __attribute__((overloadable)) half2 __spirv_ConvertSToF_Rhalf2_rte(int2); __attribute__((overloadable)) half2 __spirv_ConvertSToF_Rhalf2_rtp(int2); __attribute__((overloadable)) half2 __spirv_ConvertSToF_Rhalf2_rtn(int2); __attribute__((overloadable)) half2 __spirv_ConvertSToF_Rhalf2(long2); __attribute__((overloadable)) half2 __spirv_ConvertSToF_Rhalf2_rtz(long2); __attribute__((overloadable)) half2 __spirv_ConvertSToF_Rhalf2_rte(long2); __attribute__((overloadable)) half2 __spirv_ConvertSToF_Rhalf2_rtp(long2); __attribute__((overloadable)) half2 __spirv_ConvertSToF_Rhalf2_rtn(long2); __attribute__((overloadable)) half3 __spirv_ConvertSToF_Rhalf3(char3); __attribute__((overloadable)) half3 __spirv_ConvertSToF_Rhalf3_rtz(char3); __attribute__((overloadable)) half3 __spirv_ConvertSToF_Rhalf3_rte(char3); __attribute__((overloadable)) half3 __spirv_ConvertSToF_Rhalf3_rtp(char3); __attribute__((overloadable)) half3 __spirv_ConvertSToF_Rhalf3_rtn(char3); __attribute__((overloadable)) half3 __spirv_ConvertSToF_Rhalf3(short3); __attribute__((overloadable)) half3 __spirv_ConvertSToF_Rhalf3_rtz(short3); __attribute__((overloadable)) half3 __spirv_ConvertSToF_Rhalf3_rte(short3); __attribute__((overloadable)) half3 __spirv_ConvertSToF_Rhalf3_rtp(short3); __attribute__((overloadable)) half3 __spirv_ConvertSToF_Rhalf3_rtn(short3); __attribute__((overloadable)) half3 __spirv_ConvertSToF_Rhalf3(int3); __attribute__((overloadable)) half3 __spirv_ConvertSToF_Rhalf3_rtz(int3); __attribute__((overloadable)) half3 __spirv_ConvertSToF_Rhalf3_rte(int3); __attribute__((overloadable)) half3 __spirv_ConvertSToF_Rhalf3_rtp(int3); __attribute__((overloadable)) half3 __spirv_ConvertSToF_Rhalf3_rtn(int3); __attribute__((overloadable)) half3 __spirv_ConvertSToF_Rhalf3(long3); __attribute__((overloadable)) half3 __spirv_ConvertSToF_Rhalf3_rtz(long3); __attribute__((overloadable)) half3 __spirv_ConvertSToF_Rhalf3_rte(long3); __attribute__((overloadable)) half3 __spirv_ConvertSToF_Rhalf3_rtp(long3); __attribute__((overloadable)) half3 __spirv_ConvertSToF_Rhalf3_rtn(long3); __attribute__((overloadable)) half4 __spirv_ConvertSToF_Rhalf4(char4); __attribute__((overloadable)) half4 __spirv_ConvertSToF_Rhalf4_rtz(char4); __attribute__((overloadable)) half4 __spirv_ConvertSToF_Rhalf4_rte(char4); __attribute__((overloadable)) half4 __spirv_ConvertSToF_Rhalf4_rtp(char4); __attribute__((overloadable)) half4 __spirv_ConvertSToF_Rhalf4_rtn(char4); __attribute__((overloadable)) half4 __spirv_ConvertSToF_Rhalf4(short4); __attribute__((overloadable)) half4 __spirv_ConvertSToF_Rhalf4_rtz(short4); __attribute__((overloadable)) half4 __spirv_ConvertSToF_Rhalf4_rte(short4); __attribute__((overloadable)) half4 __spirv_ConvertSToF_Rhalf4_rtp(short4); __attribute__((overloadable)) half4 __spirv_ConvertSToF_Rhalf4_rtn(short4); __attribute__((overloadable)) half4 __spirv_ConvertSToF_Rhalf4(int4); __attribute__((overloadable)) half4 __spirv_ConvertSToF_Rhalf4_rtz(int4); __attribute__((overloadable)) half4 __spirv_ConvertSToF_Rhalf4_rte(int4); __attribute__((overloadable)) half4 __spirv_ConvertSToF_Rhalf4_rtp(int4); __attribute__((overloadable)) half4 __spirv_ConvertSToF_Rhalf4_rtn(int4); __attribute__((overloadable)) half4 __spirv_ConvertSToF_Rhalf4(long4); __attribute__((overloadable)) half4 __spirv_ConvertSToF_Rhalf4_rtz(long4); __attribute__((overloadable)) half4 __spirv_ConvertSToF_Rhalf4_rte(long4); __attribute__((overloadable)) half4 __spirv_ConvertSToF_Rhalf4_rtp(long4); __attribute__((overloadable)) half4 __spirv_ConvertSToF_Rhalf4_rtn(long4); __attribute__((overloadable)) half8 __spirv_ConvertSToF_Rhalf8(char8); __attribute__((overloadable)) half8 __spirv_ConvertSToF_Rhalf8_rtz(char8); __attribute__((overloadable)) half8 __spirv_ConvertSToF_Rhalf8_rte(char8); __attribute__((overloadable)) half8 __spirv_ConvertSToF_Rhalf8_rtp(char8); __attribute__((overloadable)) half8 __spirv_ConvertSToF_Rhalf8_rtn(char8); __attribute__((overloadable)) half8 __spirv_ConvertSToF_Rhalf8(short8); __attribute__((overloadable)) half8 __spirv_ConvertSToF_Rhalf8_rtz(short8); __attribute__((overloadable)) half8 __spirv_ConvertSToF_Rhalf8_rte(short8); __attribute__((overloadable)) half8 __spirv_ConvertSToF_Rhalf8_rtp(short8); __attribute__((overloadable)) half8 __spirv_ConvertSToF_Rhalf8_rtn(short8); __attribute__((overloadable)) half8 __spirv_ConvertSToF_Rhalf8(int8); __attribute__((overloadable)) half8 __spirv_ConvertSToF_Rhalf8_rtz(int8); __attribute__((overloadable)) half8 __spirv_ConvertSToF_Rhalf8_rte(int8); __attribute__((overloadable)) half8 __spirv_ConvertSToF_Rhalf8_rtp(int8); __attribute__((overloadable)) half8 __spirv_ConvertSToF_Rhalf8_rtn(int8); __attribute__((overloadable)) half8 __spirv_ConvertSToF_Rhalf8(long8); __attribute__((overloadable)) half8 __spirv_ConvertSToF_Rhalf8_rtz(long8); __attribute__((overloadable)) half8 __spirv_ConvertSToF_Rhalf8_rte(long8); __attribute__((overloadable)) half8 __spirv_ConvertSToF_Rhalf8_rtp(long8); __attribute__((overloadable)) half8 __spirv_ConvertSToF_Rhalf8_rtn(long8); __attribute__((overloadable)) half16 __spirv_ConvertSToF_Rhalf16(char16); __attribute__((overloadable)) half16 __spirv_ConvertSToF_Rhalf16_rtz(char16); __attribute__((overloadable)) half16 __spirv_ConvertSToF_Rhalf16_rte(char16); __attribute__((overloadable)) half16 __spirv_ConvertSToF_Rhalf16_rtp(char16); __attribute__((overloadable)) half16 __spirv_ConvertSToF_Rhalf16_rtn(char16); __attribute__((overloadable)) half16 __spirv_ConvertSToF_Rhalf16(short16); __attribute__((overloadable)) half16 __spirv_ConvertSToF_Rhalf16_rtz(short16); __attribute__((overloadable)) half16 __spirv_ConvertSToF_Rhalf16_rte(short16); __attribute__((overloadable)) half16 __spirv_ConvertSToF_Rhalf16_rtp(short16); __attribute__((overloadable)) half16 __spirv_ConvertSToF_Rhalf16_rtn(short16); __attribute__((overloadable)) half16 __spirv_ConvertSToF_Rhalf16(int16); __attribute__((overloadable)) half16 __spirv_ConvertSToF_Rhalf16_rtz(int16); __attribute__((overloadable)) half16 __spirv_ConvertSToF_Rhalf16_rte(int16); __attribute__((overloadable)) half16 __spirv_ConvertSToF_Rhalf16_rtp(int16); __attribute__((overloadable)) half16 __spirv_ConvertSToF_Rhalf16_rtn(int16); __attribute__((overloadable)) half16 __spirv_ConvertSToF_Rhalf16(long16); __attribute__((overloadable)) half16 __spirv_ConvertSToF_Rhalf16_rtz(long16); __attribute__((overloadable)) half16 __spirv_ConvertSToF_Rhalf16_rte(long16); __attribute__((overloadable)) half16 __spirv_ConvertSToF_Rhalf16_rtp(long16); __attribute__((overloadable)) half16 __spirv_ConvertSToF_Rhalf16_rtn(long16); __attribute__((overloadable)) float __spirv_ConvertSToF_Rfloat(char); __attribute__((overloadable)) float __spirv_ConvertSToF_Rfloat_rtz(char); __attribute__((overloadable)) float __spirv_ConvertSToF_Rfloat_rte(char); __attribute__((overloadable)) float __spirv_ConvertSToF_Rfloat_rtp(char); __attribute__((overloadable)) float __spirv_ConvertSToF_Rfloat_rtn(char); __attribute__((overloadable)) float __spirv_ConvertSToF_Rfloat(short); __attribute__((overloadable)) float __spirv_ConvertSToF_Rfloat_rtz(short); __attribute__((overloadable)) float __spirv_ConvertSToF_Rfloat_rte(short); __attribute__((overloadable)) float __spirv_ConvertSToF_Rfloat_rtp(short); __attribute__((overloadable)) float __spirv_ConvertSToF_Rfloat_rtn(short); __attribute__((overloadable)) float __spirv_ConvertSToF_Rfloat(int); __attribute__((overloadable)) float __spirv_ConvertSToF_Rfloat_rtz(int); __attribute__((overloadable)) float __spirv_ConvertSToF_Rfloat_rte(int); __attribute__((overloadable)) float __spirv_ConvertSToF_Rfloat_rtp(int); __attribute__((overloadable)) float __spirv_ConvertSToF_Rfloat_rtn(int); __attribute__((overloadable)) float __spirv_ConvertSToF_Rfloat(long); __attribute__((overloadable)) float __spirv_ConvertSToF_Rfloat_rtz(long); __attribute__((overloadable)) float __spirv_ConvertSToF_Rfloat_rte(long); __attribute__((overloadable)) float __spirv_ConvertSToF_Rfloat_rtp(long); __attribute__((overloadable)) float __spirv_ConvertSToF_Rfloat_rtn(long); __attribute__((overloadable)) float2 __spirv_ConvertSToF_Rfloat2(char2); __attribute__((overloadable)) float2 __spirv_ConvertSToF_Rfloat2_rtz(char2); __attribute__((overloadable)) float2 __spirv_ConvertSToF_Rfloat2_rte(char2); __attribute__((overloadable)) float2 __spirv_ConvertSToF_Rfloat2_rtp(char2); __attribute__((overloadable)) float2 __spirv_ConvertSToF_Rfloat2_rtn(char2); __attribute__((overloadable)) float2 __spirv_ConvertSToF_Rfloat2(short2); __attribute__((overloadable)) float2 __spirv_ConvertSToF_Rfloat2_rtz(short2); __attribute__((overloadable)) float2 __spirv_ConvertSToF_Rfloat2_rte(short2); __attribute__((overloadable)) float2 __spirv_ConvertSToF_Rfloat2_rtp(short2); __attribute__((overloadable)) float2 __spirv_ConvertSToF_Rfloat2_rtn(short2); __attribute__((overloadable)) float2 __spirv_ConvertSToF_Rfloat2(int2); __attribute__((overloadable)) float2 __spirv_ConvertSToF_Rfloat2_rtz(int2); __attribute__((overloadable)) float2 __spirv_ConvertSToF_Rfloat2_rte(int2); __attribute__((overloadable)) float2 __spirv_ConvertSToF_Rfloat2_rtp(int2); __attribute__((overloadable)) float2 __spirv_ConvertSToF_Rfloat2_rtn(int2); __attribute__((overloadable)) float2 __spirv_ConvertSToF_Rfloat2(long2); __attribute__((overloadable)) float2 __spirv_ConvertSToF_Rfloat2_rtz(long2); __attribute__((overloadable)) float2 __spirv_ConvertSToF_Rfloat2_rte(long2); __attribute__((overloadable)) float2 __spirv_ConvertSToF_Rfloat2_rtp(long2); __attribute__((overloadable)) float2 __spirv_ConvertSToF_Rfloat2_rtn(long2); __attribute__((overloadable)) float3 __spirv_ConvertSToF_Rfloat3(char3); __attribute__((overloadable)) float3 __spirv_ConvertSToF_Rfloat3_rtz(char3); __attribute__((overloadable)) float3 __spirv_ConvertSToF_Rfloat3_rte(char3); __attribute__((overloadable)) float3 __spirv_ConvertSToF_Rfloat3_rtp(char3); __attribute__((overloadable)) float3 __spirv_ConvertSToF_Rfloat3_rtn(char3); __attribute__((overloadable)) float3 __spirv_ConvertSToF_Rfloat3(short3); __attribute__((overloadable)) float3 __spirv_ConvertSToF_Rfloat3_rtz(short3); __attribute__((overloadable)) float3 __spirv_ConvertSToF_Rfloat3_rte(short3); __attribute__((overloadable)) float3 __spirv_ConvertSToF_Rfloat3_rtp(short3); __attribute__((overloadable)) float3 __spirv_ConvertSToF_Rfloat3_rtn(short3); __attribute__((overloadable)) float3 __spirv_ConvertSToF_Rfloat3(int3); __attribute__((overloadable)) float3 __spirv_ConvertSToF_Rfloat3_rtz(int3); __attribute__((overloadable)) float3 __spirv_ConvertSToF_Rfloat3_rte(int3); __attribute__((overloadable)) float3 __spirv_ConvertSToF_Rfloat3_rtp(int3); __attribute__((overloadable)) float3 __spirv_ConvertSToF_Rfloat3_rtn(int3); __attribute__((overloadable)) float3 __spirv_ConvertSToF_Rfloat3(long3); __attribute__((overloadable)) float3 __spirv_ConvertSToF_Rfloat3_rtz(long3); __attribute__((overloadable)) float3 __spirv_ConvertSToF_Rfloat3_rte(long3); __attribute__((overloadable)) float3 __spirv_ConvertSToF_Rfloat3_rtp(long3); __attribute__((overloadable)) float3 __spirv_ConvertSToF_Rfloat3_rtn(long3); __attribute__((overloadable)) float4 __spirv_ConvertSToF_Rfloat4(char4); __attribute__((overloadable)) float4 __spirv_ConvertSToF_Rfloat4_rtz(char4); __attribute__((overloadable)) float4 __spirv_ConvertSToF_Rfloat4_rte(char4); __attribute__((overloadable)) float4 __spirv_ConvertSToF_Rfloat4_rtp(char4); __attribute__((overloadable)) float4 __spirv_ConvertSToF_Rfloat4_rtn(char4); __attribute__((overloadable)) float4 __spirv_ConvertSToF_Rfloat4(short4); __attribute__((overloadable)) float4 __spirv_ConvertSToF_Rfloat4_rtz(short4); __attribute__((overloadable)) float4 __spirv_ConvertSToF_Rfloat4_rte(short4); __attribute__((overloadable)) float4 __spirv_ConvertSToF_Rfloat4_rtp(short4); __attribute__((overloadable)) float4 __spirv_ConvertSToF_Rfloat4_rtn(short4); __attribute__((overloadable)) float4 __spirv_ConvertSToF_Rfloat4(int4); __attribute__((overloadable)) float4 __spirv_ConvertSToF_Rfloat4_rtz(int4); __attribute__((overloadable)) float4 __spirv_ConvertSToF_Rfloat4_rte(int4); __attribute__((overloadable)) float4 __spirv_ConvertSToF_Rfloat4_rtp(int4); __attribute__((overloadable)) float4 __spirv_ConvertSToF_Rfloat4_rtn(int4); __attribute__((overloadable)) float4 __spirv_ConvertSToF_Rfloat4(long4); __attribute__((overloadable)) float4 __spirv_ConvertSToF_Rfloat4_rtz(long4); __attribute__((overloadable)) float4 __spirv_ConvertSToF_Rfloat4_rte(long4); __attribute__((overloadable)) float4 __spirv_ConvertSToF_Rfloat4_rtp(long4); __attribute__((overloadable)) float4 __spirv_ConvertSToF_Rfloat4_rtn(long4); __attribute__((overloadable)) float8 __spirv_ConvertSToF_Rfloat8(char8); __attribute__((overloadable)) float8 __spirv_ConvertSToF_Rfloat8_rtz(char8); __attribute__((overloadable)) float8 __spirv_ConvertSToF_Rfloat8_rte(char8); __attribute__((overloadable)) float8 __spirv_ConvertSToF_Rfloat8_rtp(char8); __attribute__((overloadable)) float8 __spirv_ConvertSToF_Rfloat8_rtn(char8); __attribute__((overloadable)) float8 __spirv_ConvertSToF_Rfloat8(short8); __attribute__((overloadable)) float8 __spirv_ConvertSToF_Rfloat8_rtz(short8); __attribute__((overloadable)) float8 __spirv_ConvertSToF_Rfloat8_rte(short8); __attribute__((overloadable)) float8 __spirv_ConvertSToF_Rfloat8_rtp(short8); __attribute__((overloadable)) float8 __spirv_ConvertSToF_Rfloat8_rtn(short8); __attribute__((overloadable)) float8 __spirv_ConvertSToF_Rfloat8(int8); __attribute__((overloadable)) float8 __spirv_ConvertSToF_Rfloat8_rtz(int8); __attribute__((overloadable)) float8 __spirv_ConvertSToF_Rfloat8_rte(int8); __attribute__((overloadable)) float8 __spirv_ConvertSToF_Rfloat8_rtp(int8); __attribute__((overloadable)) float8 __spirv_ConvertSToF_Rfloat8_rtn(int8); __attribute__((overloadable)) float8 __spirv_ConvertSToF_Rfloat8(long8); __attribute__((overloadable)) float8 __spirv_ConvertSToF_Rfloat8_rtz(long8); __attribute__((overloadable)) float8 __spirv_ConvertSToF_Rfloat8_rte(long8); __attribute__((overloadable)) float8 __spirv_ConvertSToF_Rfloat8_rtp(long8); __attribute__((overloadable)) float8 __spirv_ConvertSToF_Rfloat8_rtn(long8); __attribute__((overloadable)) float16 __spirv_ConvertSToF_Rfloat16(char16); __attribute__((overloadable)) float16 __spirv_ConvertSToF_Rfloat16_rtz(char16); __attribute__((overloadable)) float16 __spirv_ConvertSToF_Rfloat16_rte(char16); __attribute__((overloadable)) float16 __spirv_ConvertSToF_Rfloat16_rtp(char16); __attribute__((overloadable)) float16 __spirv_ConvertSToF_Rfloat16_rtn(char16); __attribute__((overloadable)) float16 __spirv_ConvertSToF_Rfloat16(short16); __attribute__((overloadable)) float16 __spirv_ConvertSToF_Rfloat16_rtz(short16); __attribute__((overloadable)) float16 __spirv_ConvertSToF_Rfloat16_rte(short16); __attribute__((overloadable)) float16 __spirv_ConvertSToF_Rfloat16_rtp(short16); __attribute__((overloadable)) float16 __spirv_ConvertSToF_Rfloat16_rtn(short16); __attribute__((overloadable)) float16 __spirv_ConvertSToF_Rfloat16(int16); __attribute__((overloadable)) float16 __spirv_ConvertSToF_Rfloat16_rtz(int16); __attribute__((overloadable)) float16 __spirv_ConvertSToF_Rfloat16_rte(int16); __attribute__((overloadable)) float16 __spirv_ConvertSToF_Rfloat16_rtp(int16); __attribute__((overloadable)) float16 __spirv_ConvertSToF_Rfloat16_rtn(int16); __attribute__((overloadable)) float16 __spirv_ConvertSToF_Rfloat16(long16); __attribute__((overloadable)) float16 __spirv_ConvertSToF_Rfloat16_rtz(long16); __attribute__((overloadable)) float16 __spirv_ConvertSToF_Rfloat16_rte(long16); __attribute__((overloadable)) float16 __spirv_ConvertSToF_Rfloat16_rtp(long16); __attribute__((overloadable)) float16 __spirv_ConvertSToF_Rfloat16_rtn(long16); __attribute__((overloadable)) double __spirv_ConvertSToF_Rdouble(char); __attribute__((overloadable)) double __spirv_ConvertSToF_Rdouble_rtz(char); __attribute__((overloadable)) double __spirv_ConvertSToF_Rdouble_rte(char); __attribute__((overloadable)) double __spirv_ConvertSToF_Rdouble_rtp(char); __attribute__((overloadable)) double __spirv_ConvertSToF_Rdouble_rtn(char); __attribute__((overloadable)) double __spirv_ConvertSToF_Rdouble(short); __attribute__((overloadable)) double __spirv_ConvertSToF_Rdouble_rtz(short); __attribute__((overloadable)) double __spirv_ConvertSToF_Rdouble_rte(short); __attribute__((overloadable)) double __spirv_ConvertSToF_Rdouble_rtp(short); __attribute__((overloadable)) double __spirv_ConvertSToF_Rdouble_rtn(short); __attribute__((overloadable)) double __spirv_ConvertSToF_Rdouble(int); __attribute__((overloadable)) double __spirv_ConvertSToF_Rdouble_rtz(int); __attribute__((overloadable)) double __spirv_ConvertSToF_Rdouble_rte(int); __attribute__((overloadable)) double __spirv_ConvertSToF_Rdouble_rtp(int); __attribute__((overloadable)) double __spirv_ConvertSToF_Rdouble_rtn(int); __attribute__((overloadable)) double __spirv_ConvertSToF_Rdouble(long); __attribute__((overloadable)) double __spirv_ConvertSToF_Rdouble_rtz(long); __attribute__((overloadable)) double __spirv_ConvertSToF_Rdouble_rte(long); __attribute__((overloadable)) double __spirv_ConvertSToF_Rdouble_rtp(long); __attribute__((overloadable)) double __spirv_ConvertSToF_Rdouble_rtn(long); __attribute__((overloadable)) double2 __spirv_ConvertSToF_Rdouble2(char2); __attribute__((overloadable)) double2 __spirv_ConvertSToF_Rdouble2_rtz(char2); __attribute__((overloadable)) double2 __spirv_ConvertSToF_Rdouble2_rte(char2); __attribute__((overloadable)) double2 __spirv_ConvertSToF_Rdouble2_rtp(char2); __attribute__((overloadable)) double2 __spirv_ConvertSToF_Rdouble2_rtn(char2); __attribute__((overloadable)) double2 __spirv_ConvertSToF_Rdouble2(short2); __attribute__((overloadable)) double2 __spirv_ConvertSToF_Rdouble2_rtz(short2); __attribute__((overloadable)) double2 __spirv_ConvertSToF_Rdouble2_rte(short2); __attribute__((overloadable)) double2 __spirv_ConvertSToF_Rdouble2_rtp(short2); __attribute__((overloadable)) double2 __spirv_ConvertSToF_Rdouble2_rtn(short2); __attribute__((overloadable)) double2 __spirv_ConvertSToF_Rdouble2(int2); __attribute__((overloadable)) double2 __spirv_ConvertSToF_Rdouble2_rtz(int2); __attribute__((overloadable)) double2 __spirv_ConvertSToF_Rdouble2_rte(int2); __attribute__((overloadable)) double2 __spirv_ConvertSToF_Rdouble2_rtp(int2); __attribute__((overloadable)) double2 __spirv_ConvertSToF_Rdouble2_rtn(int2); __attribute__((overloadable)) double2 __spirv_ConvertSToF_Rdouble2(long2); __attribute__((overloadable)) double2 __spirv_ConvertSToF_Rdouble2_rtz(long2); __attribute__((overloadable)) double2 __spirv_ConvertSToF_Rdouble2_rte(long2); __attribute__((overloadable)) double2 __spirv_ConvertSToF_Rdouble2_rtp(long2); __attribute__((overloadable)) double2 __spirv_ConvertSToF_Rdouble2_rtn(long2); __attribute__((overloadable)) double3 __spirv_ConvertSToF_Rdouble3(char3); __attribute__((overloadable)) double3 __spirv_ConvertSToF_Rdouble3_rtz(char3); __attribute__((overloadable)) double3 __spirv_ConvertSToF_Rdouble3_rte(char3); __attribute__((overloadable)) double3 __spirv_ConvertSToF_Rdouble3_rtp(char3); __attribute__((overloadable)) double3 __spirv_ConvertSToF_Rdouble3_rtn(char3); __attribute__((overloadable)) double3 __spirv_ConvertSToF_Rdouble3(short3); __attribute__((overloadable)) double3 __spirv_ConvertSToF_Rdouble3_rtz(short3); __attribute__((overloadable)) double3 __spirv_ConvertSToF_Rdouble3_rte(short3); __attribute__((overloadable)) double3 __spirv_ConvertSToF_Rdouble3_rtp(short3); __attribute__((overloadable)) double3 __spirv_ConvertSToF_Rdouble3_rtn(short3); __attribute__((overloadable)) double3 __spirv_ConvertSToF_Rdouble3(int3); __attribute__((overloadable)) double3 __spirv_ConvertSToF_Rdouble3_rtz(int3); __attribute__((overloadable)) double3 __spirv_ConvertSToF_Rdouble3_rte(int3); __attribute__((overloadable)) double3 __spirv_ConvertSToF_Rdouble3_rtp(int3); __attribute__((overloadable)) double3 __spirv_ConvertSToF_Rdouble3_rtn(int3); __attribute__((overloadable)) double3 __spirv_ConvertSToF_Rdouble3(long3); __attribute__((overloadable)) double3 __spirv_ConvertSToF_Rdouble3_rtz(long3); __attribute__((overloadable)) double3 __spirv_ConvertSToF_Rdouble3_rte(long3); __attribute__((overloadable)) double3 __spirv_ConvertSToF_Rdouble3_rtp(long3); __attribute__((overloadable)) double3 __spirv_ConvertSToF_Rdouble3_rtn(long3); __attribute__((overloadable)) double4 __spirv_ConvertSToF_Rdouble4(char4); __attribute__((overloadable)) double4 __spirv_ConvertSToF_Rdouble4_rtz(char4); __attribute__((overloadable)) double4 __spirv_ConvertSToF_Rdouble4_rte(char4); __attribute__((overloadable)) double4 __spirv_ConvertSToF_Rdouble4_rtp(char4); __attribute__((overloadable)) double4 __spirv_ConvertSToF_Rdouble4_rtn(char4); __attribute__((overloadable)) double4 __spirv_ConvertSToF_Rdouble4(short4); __attribute__((overloadable)) double4 __spirv_ConvertSToF_Rdouble4_rtz(short4); __attribute__((overloadable)) double4 __spirv_ConvertSToF_Rdouble4_rte(short4); __attribute__((overloadable)) double4 __spirv_ConvertSToF_Rdouble4_rtp(short4); __attribute__((overloadable)) double4 __spirv_ConvertSToF_Rdouble4_rtn(short4); __attribute__((overloadable)) double4 __spirv_ConvertSToF_Rdouble4(int4); __attribute__((overloadable)) double4 __spirv_ConvertSToF_Rdouble4_rtz(int4); __attribute__((overloadable)) double4 __spirv_ConvertSToF_Rdouble4_rte(int4); __attribute__((overloadable)) double4 __spirv_ConvertSToF_Rdouble4_rtp(int4); __attribute__((overloadable)) double4 __spirv_ConvertSToF_Rdouble4_rtn(int4); __attribute__((overloadable)) double4 __spirv_ConvertSToF_Rdouble4(long4); __attribute__((overloadable)) double4 __spirv_ConvertSToF_Rdouble4_rtz(long4); __attribute__((overloadable)) double4 __spirv_ConvertSToF_Rdouble4_rte(long4); __attribute__((overloadable)) double4 __spirv_ConvertSToF_Rdouble4_rtp(long4); __attribute__((overloadable)) double4 __spirv_ConvertSToF_Rdouble4_rtn(long4); __attribute__((overloadable)) double8 __spirv_ConvertSToF_Rdouble8(char8); __attribute__((overloadable)) double8 __spirv_ConvertSToF_Rdouble8_rtz(char8); __attribute__((overloadable)) double8 __spirv_ConvertSToF_Rdouble8_rte(char8); __attribute__((overloadable)) double8 __spirv_ConvertSToF_Rdouble8_rtp(char8); __attribute__((overloadable)) double8 __spirv_ConvertSToF_Rdouble8_rtn(char8); __attribute__((overloadable)) double8 __spirv_ConvertSToF_Rdouble8(short8); __attribute__((overloadable)) double8 __spirv_ConvertSToF_Rdouble8_rtz(short8); __attribute__((overloadable)) double8 __spirv_ConvertSToF_Rdouble8_rte(short8); __attribute__((overloadable)) double8 __spirv_ConvertSToF_Rdouble8_rtp(short8); __attribute__((overloadable)) double8 __spirv_ConvertSToF_Rdouble8_rtn(short8); __attribute__((overloadable)) double8 __spirv_ConvertSToF_Rdouble8(int8); __attribute__((overloadable)) double8 __spirv_ConvertSToF_Rdouble8_rtz(int8); __attribute__((overloadable)) double8 __spirv_ConvertSToF_Rdouble8_rte(int8); __attribute__((overloadable)) double8 __spirv_ConvertSToF_Rdouble8_rtp(int8); __attribute__((overloadable)) double8 __spirv_ConvertSToF_Rdouble8_rtn(int8); __attribute__((overloadable)) double8 __spirv_ConvertSToF_Rdouble8(long8); __attribute__((overloadable)) double8 __spirv_ConvertSToF_Rdouble8_rtz(long8); __attribute__((overloadable)) double8 __spirv_ConvertSToF_Rdouble8_rte(long8); __attribute__((overloadable)) double8 __spirv_ConvertSToF_Rdouble8_rtp(long8); __attribute__((overloadable)) double8 __spirv_ConvertSToF_Rdouble8_rtn(long8); __attribute__((overloadable)) double16 __spirv_ConvertSToF_Rdouble16(char16); __attribute__((overloadable)) double16 __spirv_ConvertSToF_Rdouble16_rtz(char16); __attribute__((overloadable)) double16 __spirv_ConvertSToF_Rdouble16_rte(char16); __attribute__((overloadable)) double16 __spirv_ConvertSToF_Rdouble16_rtp(char16); __attribute__((overloadable)) double16 __spirv_ConvertSToF_Rdouble16_rtn(char16); __attribute__((overloadable)) double16 __spirv_ConvertSToF_Rdouble16(short16); __attribute__((overloadable)) double16 __spirv_ConvertSToF_Rdouble16_rtz(short16); __attribute__((overloadable)) double16 __spirv_ConvertSToF_Rdouble16_rte(short16); __attribute__((overloadable)) double16 __spirv_ConvertSToF_Rdouble16_rtp(short16); __attribute__((overloadable)) double16 __spirv_ConvertSToF_Rdouble16_rtn(short16); __attribute__((overloadable)) double16 __spirv_ConvertSToF_Rdouble16(int16); __attribute__((overloadable)) double16 __spirv_ConvertSToF_Rdouble16_rtz(int16); __attribute__((overloadable)) double16 __spirv_ConvertSToF_Rdouble16_rte(int16); __attribute__((overloadable)) double16 __spirv_ConvertSToF_Rdouble16_rtp(int16); __attribute__((overloadable)) double16 __spirv_ConvertSToF_Rdouble16_rtn(int16); __attribute__((overloadable)) double16 __spirv_ConvertSToF_Rdouble16(long16); __attribute__((overloadable)) double16 __spirv_ConvertSToF_Rdouble16_rtz(long16); __attribute__((overloadable)) double16 __spirv_ConvertSToF_Rdouble16_rte(long16); __attribute__((overloadable)) double16 __spirv_ConvertSToF_Rdouble16_rtp(long16); __attribute__((overloadable)) double16 __spirv_ConvertSToF_Rdouble16_rtn(long16); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar(uchar); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_rtz(uchar); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_rte(uchar); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_rtp(uchar); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_rtn(uchar); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_sat(uchar); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_sat_rtz(uchar); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_sat_rte(uchar); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_sat_rtp(uchar); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_sat_rtn(uchar); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar(ushort); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_rtz(ushort); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_rte(ushort); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_rtp(ushort); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_rtn(ushort); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_sat(ushort); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_sat_rtz(ushort); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_sat_rte(ushort); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_sat_rtp(ushort); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_sat_rtn(ushort); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar(uint); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_rtz(uint); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_rte(uint); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_rtp(uint); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_rtn(uint); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_sat(uint); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_sat_rtz(uint); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_sat_rte(uint); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_sat_rtp(uint); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_sat_rtn(uint); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar(ulong); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_rtz(ulong); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_rte(ulong); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_rtp(ulong); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_rtn(ulong); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_sat(ulong); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_sat_rtz(ulong); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_sat_rte(ulong); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_sat_rtp(ulong); __attribute__((overloadable)) uchar __spirv_UConvert_Ruchar_sat_rtn(ulong); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2(uchar2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_rtz(uchar2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_rte(uchar2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_rtp(uchar2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_rtn(uchar2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_sat(uchar2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_sat_rtz(uchar2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_sat_rte(uchar2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_sat_rtp(uchar2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_sat_rtn(uchar2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2(ushort2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_rtz(ushort2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_rte(ushort2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_rtp(ushort2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_rtn(ushort2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_sat(ushort2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_sat_rtz(ushort2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_sat_rte(ushort2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_sat_rtp(ushort2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_sat_rtn(ushort2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2(uint2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_rtz(uint2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_rte(uint2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_rtp(uint2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_rtn(uint2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_sat(uint2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_sat_rtz(uint2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_sat_rte(uint2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_sat_rtp(uint2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_sat_rtn(uint2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2(ulong2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_rtz(ulong2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_rte(ulong2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_rtp(ulong2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_rtn(ulong2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_sat(ulong2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_sat_rtz(ulong2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_sat_rte(ulong2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_sat_rtp(ulong2); __attribute__((overloadable)) uchar2 __spirv_UConvert_Ruchar2_sat_rtn(ulong2); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3(uchar3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_rtz(uchar3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_rte(uchar3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_rtp(uchar3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_rtn(uchar3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_sat(uchar3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_sat_rtz(uchar3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_sat_rte(uchar3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_sat_rtp(uchar3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_sat_rtn(uchar3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3(ushort3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_rtz(ushort3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_rte(ushort3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_rtp(ushort3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_rtn(ushort3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_sat(ushort3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_sat_rtz(ushort3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_sat_rte(ushort3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_sat_rtp(ushort3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_sat_rtn(ushort3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3(uint3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_rtz(uint3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_rte(uint3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_rtp(uint3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_rtn(uint3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_sat(uint3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_sat_rtz(uint3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_sat_rte(uint3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_sat_rtp(uint3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_sat_rtn(uint3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3(ulong3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_rtz(ulong3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_rte(ulong3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_rtp(ulong3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_rtn(ulong3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_sat(ulong3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_sat_rtz(ulong3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_sat_rte(ulong3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_sat_rtp(ulong3); __attribute__((overloadable)) uchar3 __spirv_UConvert_Ruchar3_sat_rtn(ulong3); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4(uchar4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_rtz(uchar4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_rte(uchar4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_rtp(uchar4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_rtn(uchar4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_sat(uchar4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_sat_rtz(uchar4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_sat_rte(uchar4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_sat_rtp(uchar4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_sat_rtn(uchar4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4(ushort4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_rtz(ushort4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_rte(ushort4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_rtp(ushort4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_rtn(ushort4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_sat(ushort4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_sat_rtz(ushort4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_sat_rte(ushort4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_sat_rtp(ushort4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_sat_rtn(ushort4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4(uint4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_rtz(uint4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_rte(uint4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_rtp(uint4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_rtn(uint4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_sat(uint4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_sat_rtz(uint4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_sat_rte(uint4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_sat_rtp(uint4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_sat_rtn(uint4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4(ulong4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_rtz(ulong4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_rte(ulong4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_rtp(ulong4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_rtn(ulong4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_sat(ulong4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_sat_rtz(ulong4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_sat_rte(ulong4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_sat_rtp(ulong4); __attribute__((overloadable)) uchar4 __spirv_UConvert_Ruchar4_sat_rtn(ulong4); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8(uchar8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_rtz(uchar8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_rte(uchar8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_rtp(uchar8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_rtn(uchar8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_sat(uchar8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_sat_rtz(uchar8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_sat_rte(uchar8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_sat_rtp(uchar8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_sat_rtn(uchar8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8(ushort8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_rtz(ushort8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_rte(ushort8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_rtp(ushort8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_rtn(ushort8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_sat(ushort8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_sat_rtz(ushort8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_sat_rte(ushort8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_sat_rtp(ushort8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_sat_rtn(ushort8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8(uint8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_rtz(uint8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_rte(uint8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_rtp(uint8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_rtn(uint8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_sat(uint8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_sat_rtz(uint8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_sat_rte(uint8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_sat_rtp(uint8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_sat_rtn(uint8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8(ulong8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_rtz(ulong8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_rte(ulong8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_rtp(ulong8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_rtn(ulong8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_sat(ulong8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_sat_rtz(ulong8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_sat_rte(ulong8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_sat_rtp(ulong8); __attribute__((overloadable)) uchar8 __spirv_UConvert_Ruchar8_sat_rtn(ulong8); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16(uchar16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_rtz(uchar16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_rte(uchar16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_rtp(uchar16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_rtn(uchar16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_sat(uchar16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_sat_rtz(uchar16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_sat_rte(uchar16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_sat_rtp(uchar16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_sat_rtn(uchar16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16(ushort16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_rtz(ushort16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_rte(ushort16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_rtp(ushort16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_rtn(ushort16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_sat(ushort16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_sat_rtz(ushort16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_sat_rte(ushort16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_sat_rtp(ushort16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_sat_rtn(ushort16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16(uint16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_rtz(uint16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_rte(uint16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_rtp(uint16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_rtn(uint16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_sat(uint16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_sat_rtz(uint16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_sat_rte(uint16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_sat_rtp(uint16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_sat_rtn(uint16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16(ulong16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_rtz(ulong16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_rte(ulong16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_rtp(ulong16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_rtn(ulong16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_sat(ulong16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_sat_rtz(ulong16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_sat_rte(ulong16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_sat_rtp(ulong16); __attribute__((overloadable)) uchar16 __spirv_UConvert_Ruchar16_sat_rtn(ulong16); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort(uchar); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_rtz(uchar); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_rte(uchar); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_rtp(uchar); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_rtn(uchar); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_sat(uchar); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_sat_rtz(uchar); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_sat_rte(uchar); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_sat_rtp(uchar); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_sat_rtn(uchar); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort(ushort); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_rtz(ushort); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_rte(ushort); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_rtp(ushort); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_rtn(ushort); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_sat(ushort); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_sat_rtz(ushort); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_sat_rte(ushort); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_sat_rtp(ushort); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_sat_rtn(ushort); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort(uint); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_rtz(uint); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_rte(uint); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_rtp(uint); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_rtn(uint); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_sat(uint); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_sat_rtz(uint); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_sat_rte(uint); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_sat_rtp(uint); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_sat_rtn(uint); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort(ulong); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_rtz(ulong); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_rte(ulong); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_rtp(ulong); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_rtn(ulong); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_sat(ulong); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_sat_rtz(ulong); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_sat_rte(ulong); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_sat_rtp(ulong); __attribute__((overloadable)) ushort __spirv_UConvert_Rushort_sat_rtn(ulong); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2(uchar2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_rtz(uchar2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_rte(uchar2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_rtp(uchar2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_rtn(uchar2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_sat(uchar2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_sat_rtz(uchar2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_sat_rte(uchar2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_sat_rtp(uchar2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_sat_rtn(uchar2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2(ushort2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_rtz(ushort2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_rte(ushort2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_rtp(ushort2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_rtn(ushort2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_sat(ushort2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_sat_rtz(ushort2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_sat_rte(ushort2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_sat_rtp(ushort2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_sat_rtn(ushort2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2(uint2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_rtz(uint2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_rte(uint2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_rtp(uint2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_rtn(uint2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_sat(uint2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_sat_rtz(uint2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_sat_rte(uint2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_sat_rtp(uint2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_sat_rtn(uint2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2(ulong2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_rtz(ulong2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_rte(ulong2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_rtp(ulong2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_rtn(ulong2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_sat(ulong2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_sat_rtz(ulong2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_sat_rte(ulong2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_sat_rtp(ulong2); __attribute__((overloadable)) ushort2 __spirv_UConvert_Rushort2_sat_rtn(ulong2); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3(uchar3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_rtz(uchar3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_rte(uchar3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_rtp(uchar3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_rtn(uchar3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_sat(uchar3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_sat_rtz(uchar3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_sat_rte(uchar3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_sat_rtp(uchar3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_sat_rtn(uchar3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3(ushort3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_rtz(ushort3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_rte(ushort3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_rtp(ushort3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_rtn(ushort3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_sat(ushort3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_sat_rtz(ushort3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_sat_rte(ushort3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_sat_rtp(ushort3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_sat_rtn(ushort3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3(uint3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_rtz(uint3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_rte(uint3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_rtp(uint3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_rtn(uint3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_sat(uint3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_sat_rtz(uint3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_sat_rte(uint3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_sat_rtp(uint3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_sat_rtn(uint3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3(ulong3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_rtz(ulong3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_rte(ulong3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_rtp(ulong3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_rtn(ulong3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_sat(ulong3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_sat_rtz(ulong3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_sat_rte(ulong3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_sat_rtp(ulong3); __attribute__((overloadable)) ushort3 __spirv_UConvert_Rushort3_sat_rtn(ulong3); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4(uchar4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_rtz(uchar4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_rte(uchar4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_rtp(uchar4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_rtn(uchar4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_sat(uchar4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_sat_rtz(uchar4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_sat_rte(uchar4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_sat_rtp(uchar4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_sat_rtn(uchar4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4(ushort4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_rtz(ushort4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_rte(ushort4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_rtp(ushort4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_rtn(ushort4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_sat(ushort4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_sat_rtz(ushort4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_sat_rte(ushort4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_sat_rtp(ushort4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_sat_rtn(ushort4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4(uint4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_rtz(uint4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_rte(uint4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_rtp(uint4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_rtn(uint4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_sat(uint4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_sat_rtz(uint4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_sat_rte(uint4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_sat_rtp(uint4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_sat_rtn(uint4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4(ulong4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_rtz(ulong4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_rte(ulong4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_rtp(ulong4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_rtn(ulong4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_sat(ulong4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_sat_rtz(ulong4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_sat_rte(ulong4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_sat_rtp(ulong4); __attribute__((overloadable)) ushort4 __spirv_UConvert_Rushort4_sat_rtn(ulong4); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8(uchar8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_rtz(uchar8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_rte(uchar8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_rtp(uchar8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_rtn(uchar8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_sat(uchar8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_sat_rtz(uchar8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_sat_rte(uchar8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_sat_rtp(uchar8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_sat_rtn(uchar8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8(ushort8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_rtz(ushort8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_rte(ushort8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_rtp(ushort8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_rtn(ushort8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_sat(ushort8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_sat_rtz(ushort8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_sat_rte(ushort8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_sat_rtp(ushort8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_sat_rtn(ushort8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8(uint8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_rtz(uint8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_rte(uint8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_rtp(uint8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_rtn(uint8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_sat(uint8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_sat_rtz(uint8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_sat_rte(uint8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_sat_rtp(uint8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_sat_rtn(uint8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8(ulong8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_rtz(ulong8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_rte(ulong8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_rtp(ulong8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_rtn(ulong8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_sat(ulong8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_sat_rtz(ulong8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_sat_rte(ulong8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_sat_rtp(ulong8); __attribute__((overloadable)) ushort8 __spirv_UConvert_Rushort8_sat_rtn(ulong8); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16(uchar16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_rtz(uchar16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_rte(uchar16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_rtp(uchar16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_rtn(uchar16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_sat(uchar16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_sat_rtz(uchar16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_sat_rte(uchar16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_sat_rtp(uchar16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_sat_rtn(uchar16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16(ushort16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_rtz(ushort16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_rte(ushort16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_rtp(ushort16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_rtn(ushort16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_sat(ushort16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_sat_rtz(ushort16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_sat_rte(ushort16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_sat_rtp(ushort16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_sat_rtn(ushort16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16(uint16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_rtz(uint16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_rte(uint16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_rtp(uint16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_rtn(uint16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_sat(uint16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_sat_rtz(uint16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_sat_rte(uint16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_sat_rtp(uint16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_sat_rtn(uint16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16(ulong16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_rtz(ulong16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_rte(ulong16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_rtp(ulong16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_rtn(ulong16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_sat(ulong16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_sat_rtz(ulong16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_sat_rte(ulong16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_sat_rtp(ulong16); __attribute__((overloadable)) ushort16 __spirv_UConvert_Rushort16_sat_rtn(ulong16); __attribute__((overloadable)) uint __spirv_UConvert_Ruint(uchar); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_rtz(uchar); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_rte(uchar); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_rtp(uchar); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_rtn(uchar); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_sat(uchar); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_sat_rtz(uchar); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_sat_rte(uchar); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_sat_rtp(uchar); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_sat_rtn(uchar); __attribute__((overloadable)) uint __spirv_UConvert_Ruint(ushort); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_rtz(ushort); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_rte(ushort); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_rtp(ushort); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_rtn(ushort); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_sat(ushort); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_sat_rtz(ushort); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_sat_rte(ushort); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_sat_rtp(ushort); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_sat_rtn(ushort); __attribute__((overloadable)) uint __spirv_UConvert_Ruint(uint); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_rtz(uint); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_rte(uint); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_rtp(uint); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_rtn(uint); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_sat(uint); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_sat_rtz(uint); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_sat_rte(uint); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_sat_rtp(uint); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_sat_rtn(uint); __attribute__((overloadable)) uint __spirv_UConvert_Ruint(ulong); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_rtz(ulong); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_rte(ulong); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_rtp(ulong); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_rtn(ulong); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_sat(ulong); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_sat_rtz(ulong); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_sat_rte(ulong); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_sat_rtp(ulong); __attribute__((overloadable)) uint __spirv_UConvert_Ruint_sat_rtn(ulong); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2(uchar2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_rtz(uchar2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_rte(uchar2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_rtp(uchar2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_rtn(uchar2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_sat(uchar2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_sat_rtz(uchar2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_sat_rte(uchar2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_sat_rtp(uchar2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_sat_rtn(uchar2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2(ushort2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_rtz(ushort2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_rte(ushort2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_rtp(ushort2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_rtn(ushort2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_sat(ushort2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_sat_rtz(ushort2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_sat_rte(ushort2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_sat_rtp(ushort2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_sat_rtn(ushort2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2(uint2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_rtz(uint2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_rte(uint2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_rtp(uint2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_rtn(uint2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_sat(uint2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_sat_rtz(uint2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_sat_rte(uint2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_sat_rtp(uint2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_sat_rtn(uint2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2(ulong2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_rtz(ulong2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_rte(ulong2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_rtp(ulong2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_rtn(ulong2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_sat(ulong2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_sat_rtz(ulong2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_sat_rte(ulong2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_sat_rtp(ulong2); __attribute__((overloadable)) uint2 __spirv_UConvert_Ruint2_sat_rtn(ulong2); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3(uchar3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_rtz(uchar3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_rte(uchar3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_rtp(uchar3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_rtn(uchar3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_sat(uchar3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_sat_rtz(uchar3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_sat_rte(uchar3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_sat_rtp(uchar3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_sat_rtn(uchar3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3(ushort3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_rtz(ushort3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_rte(ushort3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_rtp(ushort3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_rtn(ushort3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_sat(ushort3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_sat_rtz(ushort3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_sat_rte(ushort3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_sat_rtp(ushort3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_sat_rtn(ushort3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3(uint3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_rtz(uint3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_rte(uint3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_rtp(uint3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_rtn(uint3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_sat(uint3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_sat_rtz(uint3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_sat_rte(uint3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_sat_rtp(uint3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_sat_rtn(uint3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3(ulong3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_rtz(ulong3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_rte(ulong3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_rtp(ulong3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_rtn(ulong3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_sat(ulong3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_sat_rtz(ulong3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_sat_rte(ulong3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_sat_rtp(ulong3); __attribute__((overloadable)) uint3 __spirv_UConvert_Ruint3_sat_rtn(ulong3); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4(uchar4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_rtz(uchar4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_rte(uchar4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_rtp(uchar4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_rtn(uchar4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_sat(uchar4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_sat_rtz(uchar4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_sat_rte(uchar4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_sat_rtp(uchar4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_sat_rtn(uchar4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4(ushort4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_rtz(ushort4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_rte(ushort4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_rtp(ushort4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_rtn(ushort4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_sat(ushort4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_sat_rtz(ushort4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_sat_rte(ushort4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_sat_rtp(ushort4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_sat_rtn(ushort4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4(uint4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_rtz(uint4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_rte(uint4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_rtp(uint4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_rtn(uint4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_sat(uint4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_sat_rtz(uint4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_sat_rte(uint4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_sat_rtp(uint4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_sat_rtn(uint4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4(ulong4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_rtz(ulong4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_rte(ulong4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_rtp(ulong4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_rtn(ulong4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_sat(ulong4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_sat_rtz(ulong4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_sat_rte(ulong4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_sat_rtp(ulong4); __attribute__((overloadable)) uint4 __spirv_UConvert_Ruint4_sat_rtn(ulong4); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8(uchar8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_rtz(uchar8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_rte(uchar8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_rtp(uchar8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_rtn(uchar8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_sat(uchar8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_sat_rtz(uchar8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_sat_rte(uchar8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_sat_rtp(uchar8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_sat_rtn(uchar8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8(ushort8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_rtz(ushort8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_rte(ushort8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_rtp(ushort8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_rtn(ushort8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_sat(ushort8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_sat_rtz(ushort8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_sat_rte(ushort8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_sat_rtp(ushort8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_sat_rtn(ushort8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8(uint8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_rtz(uint8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_rte(uint8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_rtp(uint8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_rtn(uint8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_sat(uint8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_sat_rtz(uint8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_sat_rte(uint8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_sat_rtp(uint8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_sat_rtn(uint8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8(ulong8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_rtz(ulong8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_rte(ulong8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_rtp(ulong8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_rtn(ulong8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_sat(ulong8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_sat_rtz(ulong8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_sat_rte(ulong8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_sat_rtp(ulong8); __attribute__((overloadable)) uint8 __spirv_UConvert_Ruint8_sat_rtn(ulong8); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16(uchar16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_rtz(uchar16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_rte(uchar16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_rtp(uchar16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_rtn(uchar16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_sat(uchar16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_sat_rtz(uchar16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_sat_rte(uchar16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_sat_rtp(uchar16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_sat_rtn(uchar16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16(ushort16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_rtz(ushort16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_rte(ushort16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_rtp(ushort16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_rtn(ushort16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_sat(ushort16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_sat_rtz(ushort16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_sat_rte(ushort16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_sat_rtp(ushort16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_sat_rtn(ushort16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16(uint16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_rtz(uint16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_rte(uint16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_rtp(uint16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_rtn(uint16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_sat(uint16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_sat_rtz(uint16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_sat_rte(uint16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_sat_rtp(uint16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_sat_rtn(uint16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16(ulong16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_rtz(ulong16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_rte(ulong16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_rtp(ulong16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_rtn(ulong16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_sat(ulong16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_sat_rtz(ulong16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_sat_rte(ulong16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_sat_rtp(ulong16); __attribute__((overloadable)) uint16 __spirv_UConvert_Ruint16_sat_rtn(ulong16); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong(uchar); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_rtz(uchar); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_rte(uchar); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_rtp(uchar); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_rtn(uchar); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_sat(uchar); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_sat_rtz(uchar); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_sat_rte(uchar); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_sat_rtp(uchar); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_sat_rtn(uchar); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong(ushort); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_rtz(ushort); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_rte(ushort); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_rtp(ushort); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_rtn(ushort); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_sat(ushort); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_sat_rtz(ushort); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_sat_rte(ushort); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_sat_rtp(ushort); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_sat_rtn(ushort); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong(uint); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_rtz(uint); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_rte(uint); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_rtp(uint); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_rtn(uint); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_sat(uint); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_sat_rtz(uint); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_sat_rte(uint); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_sat_rtp(uint); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_sat_rtn(uint); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong(ulong); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_rtz(ulong); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_rte(ulong); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_rtp(ulong); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_rtn(ulong); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_sat(ulong); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_sat_rtz(ulong); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_sat_rte(ulong); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_sat_rtp(ulong); __attribute__((overloadable)) ulong __spirv_UConvert_Rulong_sat_rtn(ulong); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2(uchar2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_rtz(uchar2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_rte(uchar2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_rtp(uchar2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_rtn(uchar2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_sat(uchar2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_sat_rtz(uchar2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_sat_rte(uchar2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_sat_rtp(uchar2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_sat_rtn(uchar2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2(ushort2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_rtz(ushort2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_rte(ushort2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_rtp(ushort2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_rtn(ushort2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_sat(ushort2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_sat_rtz(ushort2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_sat_rte(ushort2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_sat_rtp(ushort2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_sat_rtn(ushort2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2(uint2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_rtz(uint2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_rte(uint2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_rtp(uint2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_rtn(uint2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_sat(uint2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_sat_rtz(uint2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_sat_rte(uint2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_sat_rtp(uint2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_sat_rtn(uint2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2(ulong2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_rtz(ulong2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_rte(ulong2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_rtp(ulong2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_rtn(ulong2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_sat(ulong2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_sat_rtz(ulong2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_sat_rte(ulong2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_sat_rtp(ulong2); __attribute__((overloadable)) ulong2 __spirv_UConvert_Rulong2_sat_rtn(ulong2); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3(uchar3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_rtz(uchar3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_rte(uchar3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_rtp(uchar3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_rtn(uchar3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_sat(uchar3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_sat_rtz(uchar3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_sat_rte(uchar3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_sat_rtp(uchar3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_sat_rtn(uchar3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3(ushort3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_rtz(ushort3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_rte(ushort3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_rtp(ushort3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_rtn(ushort3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_sat(ushort3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_sat_rtz(ushort3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_sat_rte(ushort3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_sat_rtp(ushort3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_sat_rtn(ushort3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3(uint3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_rtz(uint3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_rte(uint3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_rtp(uint3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_rtn(uint3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_sat(uint3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_sat_rtz(uint3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_sat_rte(uint3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_sat_rtp(uint3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_sat_rtn(uint3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3(ulong3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_rtz(ulong3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_rte(ulong3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_rtp(ulong3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_rtn(ulong3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_sat(ulong3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_sat_rtz(ulong3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_sat_rte(ulong3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_sat_rtp(ulong3); __attribute__((overloadable)) ulong3 __spirv_UConvert_Rulong3_sat_rtn(ulong3); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4(uchar4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_rtz(uchar4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_rte(uchar4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_rtp(uchar4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_rtn(uchar4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_sat(uchar4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_sat_rtz(uchar4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_sat_rte(uchar4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_sat_rtp(uchar4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_sat_rtn(uchar4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4(ushort4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_rtz(ushort4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_rte(ushort4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_rtp(ushort4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_rtn(ushort4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_sat(ushort4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_sat_rtz(ushort4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_sat_rte(ushort4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_sat_rtp(ushort4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_sat_rtn(ushort4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4(uint4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_rtz(uint4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_rte(uint4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_rtp(uint4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_rtn(uint4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_sat(uint4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_sat_rtz(uint4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_sat_rte(uint4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_sat_rtp(uint4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_sat_rtn(uint4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4(ulong4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_rtz(ulong4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_rte(ulong4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_rtp(ulong4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_rtn(ulong4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_sat(ulong4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_sat_rtz(ulong4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_sat_rte(ulong4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_sat_rtp(ulong4); __attribute__((overloadable)) ulong4 __spirv_UConvert_Rulong4_sat_rtn(ulong4); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8(uchar8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_rtz(uchar8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_rte(uchar8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_rtp(uchar8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_rtn(uchar8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_sat(uchar8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_sat_rtz(uchar8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_sat_rte(uchar8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_sat_rtp(uchar8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_sat_rtn(uchar8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8(ushort8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_rtz(ushort8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_rte(ushort8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_rtp(ushort8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_rtn(ushort8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_sat(ushort8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_sat_rtz(ushort8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_sat_rte(ushort8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_sat_rtp(ushort8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_sat_rtn(ushort8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8(uint8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_rtz(uint8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_rte(uint8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_rtp(uint8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_rtn(uint8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_sat(uint8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_sat_rtz(uint8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_sat_rte(uint8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_sat_rtp(uint8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_sat_rtn(uint8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8(ulong8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_rtz(ulong8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_rte(ulong8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_rtp(ulong8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_rtn(ulong8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_sat(ulong8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_sat_rtz(ulong8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_sat_rte(ulong8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_sat_rtp(ulong8); __attribute__((overloadable)) ulong8 __spirv_UConvert_Rulong8_sat_rtn(ulong8); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16(uchar16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_rtz(uchar16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_rte(uchar16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_rtp(uchar16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_rtn(uchar16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_sat(uchar16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_sat_rtz(uchar16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_sat_rte(uchar16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_sat_rtp(uchar16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_sat_rtn(uchar16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16(ushort16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_rtz(ushort16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_rte(ushort16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_rtp(ushort16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_rtn(ushort16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_sat(ushort16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_sat_rtz(ushort16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_sat_rte(ushort16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_sat_rtp(ushort16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_sat_rtn(ushort16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16(uint16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_rtz(uint16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_rte(uint16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_rtp(uint16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_rtn(uint16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_sat(uint16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_sat_rtz(uint16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_sat_rte(uint16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_sat_rtp(uint16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_sat_rtn(uint16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16(ulong16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_rtz(ulong16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_rte(ulong16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_rtp(ulong16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_rtn(ulong16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_sat(ulong16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_sat_rtz(ulong16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_sat_rte(ulong16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_sat_rtp(ulong16); __attribute__((overloadable)) ulong16 __spirv_UConvert_Rulong16_sat_rtn(ulong16); __attribute__((overloadable)) char __spirv_SConvert_Rchar(char); __attribute__((overloadable)) char __spirv_SConvert_Rchar_rtz(char); __attribute__((overloadable)) char __spirv_SConvert_Rchar_rte(char); __attribute__((overloadable)) char __spirv_SConvert_Rchar_rtp(char); __attribute__((overloadable)) char __spirv_SConvert_Rchar_rtn(char); __attribute__((overloadable)) char __spirv_SConvert_Rchar_sat(char); __attribute__((overloadable)) char __spirv_SConvert_Rchar_sat_rtz(char); __attribute__((overloadable)) char __spirv_SConvert_Rchar_sat_rte(char); __attribute__((overloadable)) char __spirv_SConvert_Rchar_sat_rtp(char); __attribute__((overloadable)) char __spirv_SConvert_Rchar_sat_rtn(char); __attribute__((overloadable)) char __spirv_SConvert_Rchar(short); __attribute__((overloadable)) char __spirv_SConvert_Rchar_rtz(short); __attribute__((overloadable)) char __spirv_SConvert_Rchar_rte(short); __attribute__((overloadable)) char __spirv_SConvert_Rchar_rtp(short); __attribute__((overloadable)) char __spirv_SConvert_Rchar_rtn(short); __attribute__((overloadable)) char __spirv_SConvert_Rchar_sat(short); __attribute__((overloadable)) char __spirv_SConvert_Rchar_sat_rtz(short); __attribute__((overloadable)) char __spirv_SConvert_Rchar_sat_rte(short); __attribute__((overloadable)) char __spirv_SConvert_Rchar_sat_rtp(short); __attribute__((overloadable)) char __spirv_SConvert_Rchar_sat_rtn(short); __attribute__((overloadable)) char __spirv_SConvert_Rchar(int); __attribute__((overloadable)) char __spirv_SConvert_Rchar_rtz(int); __attribute__((overloadable)) char __spirv_SConvert_Rchar_rte(int); __attribute__((overloadable)) char __spirv_SConvert_Rchar_rtp(int); __attribute__((overloadable)) char __spirv_SConvert_Rchar_rtn(int); __attribute__((overloadable)) char __spirv_SConvert_Rchar_sat(int); __attribute__((overloadable)) char __spirv_SConvert_Rchar_sat_rtz(int); __attribute__((overloadable)) char __spirv_SConvert_Rchar_sat_rte(int); __attribute__((overloadable)) char __spirv_SConvert_Rchar_sat_rtp(int); __attribute__((overloadable)) char __spirv_SConvert_Rchar_sat_rtn(int); __attribute__((overloadable)) char __spirv_SConvert_Rchar(long); __attribute__((overloadable)) char __spirv_SConvert_Rchar_rtz(long); __attribute__((overloadable)) char __spirv_SConvert_Rchar_rte(long); __attribute__((overloadable)) char __spirv_SConvert_Rchar_rtp(long); __attribute__((overloadable)) char __spirv_SConvert_Rchar_rtn(long); __attribute__((overloadable)) char __spirv_SConvert_Rchar_sat(long); __attribute__((overloadable)) char __spirv_SConvert_Rchar_sat_rtz(long); __attribute__((overloadable)) char __spirv_SConvert_Rchar_sat_rte(long); __attribute__((overloadable)) char __spirv_SConvert_Rchar_sat_rtp(long); __attribute__((overloadable)) char __spirv_SConvert_Rchar_sat_rtn(long); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2(char2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_rtz(char2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_rte(char2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_rtp(char2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_rtn(char2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_sat(char2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_sat_rtz(char2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_sat_rte(char2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_sat_rtp(char2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_sat_rtn(char2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2(short2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_rtz(short2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_rte(short2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_rtp(short2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_rtn(short2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_sat(short2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_sat_rtz(short2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_sat_rte(short2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_sat_rtp(short2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_sat_rtn(short2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2(int2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_rtz(int2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_rte(int2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_rtp(int2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_rtn(int2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_sat(int2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_sat_rtz(int2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_sat_rte(int2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_sat_rtp(int2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_sat_rtn(int2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2(long2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_rtz(long2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_rte(long2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_rtp(long2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_rtn(long2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_sat(long2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_sat_rtz(long2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_sat_rte(long2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_sat_rtp(long2); __attribute__((overloadable)) char2 __spirv_SConvert_Rchar2_sat_rtn(long2); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3(char3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_rtz(char3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_rte(char3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_rtp(char3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_rtn(char3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_sat(char3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_sat_rtz(char3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_sat_rte(char3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_sat_rtp(char3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_sat_rtn(char3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3(short3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_rtz(short3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_rte(short3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_rtp(short3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_rtn(short3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_sat(short3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_sat_rtz(short3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_sat_rte(short3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_sat_rtp(short3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_sat_rtn(short3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3(int3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_rtz(int3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_rte(int3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_rtp(int3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_rtn(int3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_sat(int3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_sat_rtz(int3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_sat_rte(int3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_sat_rtp(int3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_sat_rtn(int3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3(long3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_rtz(long3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_rte(long3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_rtp(long3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_rtn(long3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_sat(long3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_sat_rtz(long3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_sat_rte(long3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_sat_rtp(long3); __attribute__((overloadable)) char3 __spirv_SConvert_Rchar3_sat_rtn(long3); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4(char4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_rtz(char4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_rte(char4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_rtp(char4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_rtn(char4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_sat(char4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_sat_rtz(char4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_sat_rte(char4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_sat_rtp(char4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_sat_rtn(char4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4(short4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_rtz(short4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_rte(short4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_rtp(short4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_rtn(short4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_sat(short4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_sat_rtz(short4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_sat_rte(short4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_sat_rtp(short4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_sat_rtn(short4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4(int4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_rtz(int4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_rte(int4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_rtp(int4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_rtn(int4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_sat(int4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_sat_rtz(int4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_sat_rte(int4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_sat_rtp(int4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_sat_rtn(int4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4(long4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_rtz(long4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_rte(long4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_rtp(long4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_rtn(long4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_sat(long4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_sat_rtz(long4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_sat_rte(long4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_sat_rtp(long4); __attribute__((overloadable)) char4 __spirv_SConvert_Rchar4_sat_rtn(long4); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8(char8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_rtz(char8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_rte(char8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_rtp(char8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_rtn(char8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_sat(char8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_sat_rtz(char8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_sat_rte(char8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_sat_rtp(char8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_sat_rtn(char8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8(short8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_rtz(short8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_rte(short8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_rtp(short8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_rtn(short8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_sat(short8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_sat_rtz(short8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_sat_rte(short8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_sat_rtp(short8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_sat_rtn(short8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8(int8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_rtz(int8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_rte(int8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_rtp(int8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_rtn(int8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_sat(int8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_sat_rtz(int8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_sat_rte(int8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_sat_rtp(int8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_sat_rtn(int8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8(long8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_rtz(long8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_rte(long8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_rtp(long8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_rtn(long8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_sat(long8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_sat_rtz(long8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_sat_rte(long8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_sat_rtp(long8); __attribute__((overloadable)) char8 __spirv_SConvert_Rchar8_sat_rtn(long8); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16(char16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_rtz(char16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_rte(char16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_rtp(char16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_rtn(char16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_sat(char16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_sat_rtz(char16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_sat_rte(char16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_sat_rtp(char16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_sat_rtn(char16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16(short16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_rtz(short16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_rte(short16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_rtp(short16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_rtn(short16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_sat(short16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_sat_rtz(short16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_sat_rte(short16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_sat_rtp(short16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_sat_rtn(short16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16(int16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_rtz(int16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_rte(int16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_rtp(int16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_rtn(int16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_sat(int16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_sat_rtz(int16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_sat_rte(int16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_sat_rtp(int16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_sat_rtn(int16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16(long16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_rtz(long16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_rte(long16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_rtp(long16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_rtn(long16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_sat(long16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_sat_rtz(long16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_sat_rte(long16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_sat_rtp(long16); __attribute__((overloadable)) char16 __spirv_SConvert_Rchar16_sat_rtn(long16); __attribute__((overloadable)) short __spirv_SConvert_Rshort(char); __attribute__((overloadable)) short __spirv_SConvert_Rshort_rtz(char); __attribute__((overloadable)) short __spirv_SConvert_Rshort_rte(char); __attribute__((overloadable)) short __spirv_SConvert_Rshort_rtp(char); __attribute__((overloadable)) short __spirv_SConvert_Rshort_rtn(char); __attribute__((overloadable)) short __spirv_SConvert_Rshort_sat(char); __attribute__((overloadable)) short __spirv_SConvert_Rshort_sat_rtz(char); __attribute__((overloadable)) short __spirv_SConvert_Rshort_sat_rte(char); __attribute__((overloadable)) short __spirv_SConvert_Rshort_sat_rtp(char); __attribute__((overloadable)) short __spirv_SConvert_Rshort_sat_rtn(char); __attribute__((overloadable)) short __spirv_SConvert_Rshort(short); __attribute__((overloadable)) short __spirv_SConvert_Rshort_rtz(short); __attribute__((overloadable)) short __spirv_SConvert_Rshort_rte(short); __attribute__((overloadable)) short __spirv_SConvert_Rshort_rtp(short); __attribute__((overloadable)) short __spirv_SConvert_Rshort_rtn(short); __attribute__((overloadable)) short __spirv_SConvert_Rshort_sat(short); __attribute__((overloadable)) short __spirv_SConvert_Rshort_sat_rtz(short); __attribute__((overloadable)) short __spirv_SConvert_Rshort_sat_rte(short); __attribute__((overloadable)) short __spirv_SConvert_Rshort_sat_rtp(short); __attribute__((overloadable)) short __spirv_SConvert_Rshort_sat_rtn(short); __attribute__((overloadable)) short __spirv_SConvert_Rshort(int); __attribute__((overloadable)) short __spirv_SConvert_Rshort_rtz(int); __attribute__((overloadable)) short __spirv_SConvert_Rshort_rte(int); __attribute__((overloadable)) short __spirv_SConvert_Rshort_rtp(int); __attribute__((overloadable)) short __spirv_SConvert_Rshort_rtn(int); __attribute__((overloadable)) short __spirv_SConvert_Rshort_sat(int); __attribute__((overloadable)) short __spirv_SConvert_Rshort_sat_rtz(int); __attribute__((overloadable)) short __spirv_SConvert_Rshort_sat_rte(int); __attribute__((overloadable)) short __spirv_SConvert_Rshort_sat_rtp(int); __attribute__((overloadable)) short __spirv_SConvert_Rshort_sat_rtn(int); __attribute__((overloadable)) short __spirv_SConvert_Rshort(long); __attribute__((overloadable)) short __spirv_SConvert_Rshort_rtz(long); __attribute__((overloadable)) short __spirv_SConvert_Rshort_rte(long); __attribute__((overloadable)) short __spirv_SConvert_Rshort_rtp(long); __attribute__((overloadable)) short __spirv_SConvert_Rshort_rtn(long); __attribute__((overloadable)) short __spirv_SConvert_Rshort_sat(long); __attribute__((overloadable)) short __spirv_SConvert_Rshort_sat_rtz(long); __attribute__((overloadable)) short __spirv_SConvert_Rshort_sat_rte(long); __attribute__((overloadable)) short __spirv_SConvert_Rshort_sat_rtp(long); __attribute__((overloadable)) short __spirv_SConvert_Rshort_sat_rtn(long); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2(char2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_rtz(char2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_rte(char2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_rtp(char2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_rtn(char2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_sat(char2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_sat_rtz(char2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_sat_rte(char2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_sat_rtp(char2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_sat_rtn(char2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2(short2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_rtz(short2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_rte(short2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_rtp(short2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_rtn(short2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_sat(short2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_sat_rtz(short2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_sat_rte(short2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_sat_rtp(short2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_sat_rtn(short2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2(int2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_rtz(int2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_rte(int2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_rtp(int2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_rtn(int2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_sat(int2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_sat_rtz(int2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_sat_rte(int2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_sat_rtp(int2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_sat_rtn(int2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2(long2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_rtz(long2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_rte(long2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_rtp(long2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_rtn(long2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_sat(long2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_sat_rtz(long2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_sat_rte(long2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_sat_rtp(long2); __attribute__((overloadable)) short2 __spirv_SConvert_Rshort2_sat_rtn(long2); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3(char3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_rtz(char3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_rte(char3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_rtp(char3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_rtn(char3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_sat(char3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_sat_rtz(char3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_sat_rte(char3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_sat_rtp(char3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_sat_rtn(char3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3(short3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_rtz(short3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_rte(short3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_rtp(short3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_rtn(short3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_sat(short3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_sat_rtz(short3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_sat_rte(short3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_sat_rtp(short3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_sat_rtn(short3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3(int3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_rtz(int3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_rte(int3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_rtp(int3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_rtn(int3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_sat(int3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_sat_rtz(int3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_sat_rte(int3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_sat_rtp(int3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_sat_rtn(int3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3(long3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_rtz(long3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_rte(long3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_rtp(long3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_rtn(long3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_sat(long3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_sat_rtz(long3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_sat_rte(long3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_sat_rtp(long3); __attribute__((overloadable)) short3 __spirv_SConvert_Rshort3_sat_rtn(long3); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4(char4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_rtz(char4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_rte(char4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_rtp(char4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_rtn(char4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_sat(char4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_sat_rtz(char4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_sat_rte(char4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_sat_rtp(char4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_sat_rtn(char4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4(short4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_rtz(short4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_rte(short4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_rtp(short4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_rtn(short4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_sat(short4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_sat_rtz(short4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_sat_rte(short4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_sat_rtp(short4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_sat_rtn(short4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4(int4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_rtz(int4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_rte(int4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_rtp(int4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_rtn(int4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_sat(int4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_sat_rtz(int4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_sat_rte(int4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_sat_rtp(int4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_sat_rtn(int4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4(long4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_rtz(long4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_rte(long4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_rtp(long4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_rtn(long4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_sat(long4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_sat_rtz(long4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_sat_rte(long4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_sat_rtp(long4); __attribute__((overloadable)) short4 __spirv_SConvert_Rshort4_sat_rtn(long4); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8(char8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_rtz(char8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_rte(char8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_rtp(char8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_rtn(char8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_sat(char8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_sat_rtz(char8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_sat_rte(char8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_sat_rtp(char8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_sat_rtn(char8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8(short8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_rtz(short8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_rte(short8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_rtp(short8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_rtn(short8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_sat(short8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_sat_rtz(short8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_sat_rte(short8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_sat_rtp(short8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_sat_rtn(short8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8(int8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_rtz(int8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_rte(int8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_rtp(int8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_rtn(int8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_sat(int8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_sat_rtz(int8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_sat_rte(int8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_sat_rtp(int8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_sat_rtn(int8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8(long8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_rtz(long8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_rte(long8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_rtp(long8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_rtn(long8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_sat(long8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_sat_rtz(long8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_sat_rte(long8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_sat_rtp(long8); __attribute__((overloadable)) short8 __spirv_SConvert_Rshort8_sat_rtn(long8); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16(char16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_rtz(char16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_rte(char16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_rtp(char16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_rtn(char16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_sat(char16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_sat_rtz(char16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_sat_rte(char16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_sat_rtp(char16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_sat_rtn(char16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16(short16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_rtz(short16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_rte(short16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_rtp(short16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_rtn(short16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_sat(short16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_sat_rtz(short16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_sat_rte(short16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_sat_rtp(short16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_sat_rtn(short16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16(int16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_rtz(int16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_rte(int16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_rtp(int16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_rtn(int16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_sat(int16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_sat_rtz(int16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_sat_rte(int16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_sat_rtp(int16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_sat_rtn(int16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16(long16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_rtz(long16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_rte(long16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_rtp(long16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_rtn(long16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_sat(long16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_sat_rtz(long16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_sat_rte(long16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_sat_rtp(long16); __attribute__((overloadable)) short16 __spirv_SConvert_Rshort16_sat_rtn(long16); __attribute__((overloadable)) int __spirv_SConvert_Rint(char); __attribute__((overloadable)) int __spirv_SConvert_Rint_rtz(char); __attribute__((overloadable)) int __spirv_SConvert_Rint_rte(char); __attribute__((overloadable)) int __spirv_SConvert_Rint_rtp(char); __attribute__((overloadable)) int __spirv_SConvert_Rint_rtn(char); __attribute__((overloadable)) int __spirv_SConvert_Rint_sat(char); __attribute__((overloadable)) int __spirv_SConvert_Rint_sat_rtz(char); __attribute__((overloadable)) int __spirv_SConvert_Rint_sat_rte(char); __attribute__((overloadable)) int __spirv_SConvert_Rint_sat_rtp(char); __attribute__((overloadable)) int __spirv_SConvert_Rint_sat_rtn(char); __attribute__((overloadable)) int __spirv_SConvert_Rint(short); __attribute__((overloadable)) int __spirv_SConvert_Rint_rtz(short); __attribute__((overloadable)) int __spirv_SConvert_Rint_rte(short); __attribute__((overloadable)) int __spirv_SConvert_Rint_rtp(short); __attribute__((overloadable)) int __spirv_SConvert_Rint_rtn(short); __attribute__((overloadable)) int __spirv_SConvert_Rint_sat(short); __attribute__((overloadable)) int __spirv_SConvert_Rint_sat_rtz(short); __attribute__((overloadable)) int __spirv_SConvert_Rint_sat_rte(short); __attribute__((overloadable)) int __spirv_SConvert_Rint_sat_rtp(short); __attribute__((overloadable)) int __spirv_SConvert_Rint_sat_rtn(short); __attribute__((overloadable)) int __spirv_SConvert_Rint(int); __attribute__((overloadable)) int __spirv_SConvert_Rint_rtz(int); __attribute__((overloadable)) int __spirv_SConvert_Rint_rte(int); __attribute__((overloadable)) int __spirv_SConvert_Rint_rtp(int); __attribute__((overloadable)) int __spirv_SConvert_Rint_rtn(int); __attribute__((overloadable)) int __spirv_SConvert_Rint_sat(int); __attribute__((overloadable)) int __spirv_SConvert_Rint_sat_rtz(int); __attribute__((overloadable)) int __spirv_SConvert_Rint_sat_rte(int); __attribute__((overloadable)) int __spirv_SConvert_Rint_sat_rtp(int); __attribute__((overloadable)) int __spirv_SConvert_Rint_sat_rtn(int); __attribute__((overloadable)) int __spirv_SConvert_Rint(long); __attribute__((overloadable)) int __spirv_SConvert_Rint_rtz(long); __attribute__((overloadable)) int __spirv_SConvert_Rint_rte(long); __attribute__((overloadable)) int __spirv_SConvert_Rint_rtp(long); __attribute__((overloadable)) int __spirv_SConvert_Rint_rtn(long); __attribute__((overloadable)) int __spirv_SConvert_Rint_sat(long); __attribute__((overloadable)) int __spirv_SConvert_Rint_sat_rtz(long); __attribute__((overloadable)) int __spirv_SConvert_Rint_sat_rte(long); __attribute__((overloadable)) int __spirv_SConvert_Rint_sat_rtp(long); __attribute__((overloadable)) int __spirv_SConvert_Rint_sat_rtn(long); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2(char2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_rtz(char2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_rte(char2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_rtp(char2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_rtn(char2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_sat(char2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_sat_rtz(char2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_sat_rte(char2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_sat_rtp(char2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_sat_rtn(char2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2(short2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_rtz(short2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_rte(short2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_rtp(short2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_rtn(short2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_sat(short2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_sat_rtz(short2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_sat_rte(short2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_sat_rtp(short2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_sat_rtn(short2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2(int2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_rtz(int2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_rte(int2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_rtp(int2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_rtn(int2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_sat(int2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_sat_rtz(int2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_sat_rte(int2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_sat_rtp(int2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_sat_rtn(int2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2(long2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_rtz(long2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_rte(long2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_rtp(long2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_rtn(long2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_sat(long2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_sat_rtz(long2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_sat_rte(long2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_sat_rtp(long2); __attribute__((overloadable)) int2 __spirv_SConvert_Rint2_sat_rtn(long2); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3(char3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_rtz(char3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_rte(char3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_rtp(char3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_rtn(char3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_sat(char3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_sat_rtz(char3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_sat_rte(char3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_sat_rtp(char3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_sat_rtn(char3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3(short3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_rtz(short3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_rte(short3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_rtp(short3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_rtn(short3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_sat(short3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_sat_rtz(short3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_sat_rte(short3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_sat_rtp(short3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_sat_rtn(short3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3(int3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_rtz(int3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_rte(int3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_rtp(int3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_rtn(int3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_sat(int3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_sat_rtz(int3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_sat_rte(int3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_sat_rtp(int3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_sat_rtn(int3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3(long3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_rtz(long3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_rte(long3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_rtp(long3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_rtn(long3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_sat(long3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_sat_rtz(long3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_sat_rte(long3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_sat_rtp(long3); __attribute__((overloadable)) int3 __spirv_SConvert_Rint3_sat_rtn(long3); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4(char4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_rtz(char4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_rte(char4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_rtp(char4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_rtn(char4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_sat(char4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_sat_rtz(char4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_sat_rte(char4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_sat_rtp(char4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_sat_rtn(char4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4(short4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_rtz(short4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_rte(short4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_rtp(short4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_rtn(short4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_sat(short4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_sat_rtz(short4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_sat_rte(short4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_sat_rtp(short4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_sat_rtn(short4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4(int4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_rtz(int4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_rte(int4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_rtp(int4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_rtn(int4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_sat(int4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_sat_rtz(int4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_sat_rte(int4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_sat_rtp(int4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_sat_rtn(int4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4(long4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_rtz(long4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_rte(long4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_rtp(long4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_rtn(long4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_sat(long4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_sat_rtz(long4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_sat_rte(long4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_sat_rtp(long4); __attribute__((overloadable)) int4 __spirv_SConvert_Rint4_sat_rtn(long4); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8(char8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_rtz(char8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_rte(char8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_rtp(char8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_rtn(char8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_sat(char8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_sat_rtz(char8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_sat_rte(char8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_sat_rtp(char8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_sat_rtn(char8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8(short8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_rtz(short8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_rte(short8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_rtp(short8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_rtn(short8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_sat(short8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_sat_rtz(short8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_sat_rte(short8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_sat_rtp(short8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_sat_rtn(short8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8(int8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_rtz(int8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_rte(int8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_rtp(int8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_rtn(int8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_sat(int8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_sat_rtz(int8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_sat_rte(int8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_sat_rtp(int8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_sat_rtn(int8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8(long8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_rtz(long8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_rte(long8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_rtp(long8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_rtn(long8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_sat(long8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_sat_rtz(long8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_sat_rte(long8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_sat_rtp(long8); __attribute__((overloadable)) int8 __spirv_SConvert_Rint8_sat_rtn(long8); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16(char16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_rtz(char16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_rte(char16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_rtp(char16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_rtn(char16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_sat(char16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_sat_rtz(char16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_sat_rte(char16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_sat_rtp(char16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_sat_rtn(char16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16(short16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_rtz(short16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_rte(short16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_rtp(short16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_rtn(short16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_sat(short16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_sat_rtz(short16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_sat_rte(short16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_sat_rtp(short16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_sat_rtn(short16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16(int16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_rtz(int16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_rte(int16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_rtp(int16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_rtn(int16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_sat(int16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_sat_rtz(int16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_sat_rte(int16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_sat_rtp(int16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_sat_rtn(int16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16(long16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_rtz(long16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_rte(long16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_rtp(long16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_rtn(long16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_sat(long16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_sat_rtz(long16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_sat_rte(long16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_sat_rtp(long16); __attribute__((overloadable)) int16 __spirv_SConvert_Rint16_sat_rtn(long16); __attribute__((overloadable)) long __spirv_SConvert_Rlong(char); __attribute__((overloadable)) long __spirv_SConvert_Rlong_rtz(char); __attribute__((overloadable)) long __spirv_SConvert_Rlong_rte(char); __attribute__((overloadable)) long __spirv_SConvert_Rlong_rtp(char); __attribute__((overloadable)) long __spirv_SConvert_Rlong_rtn(char); __attribute__((overloadable)) long __spirv_SConvert_Rlong_sat(char); __attribute__((overloadable)) long __spirv_SConvert_Rlong_sat_rtz(char); __attribute__((overloadable)) long __spirv_SConvert_Rlong_sat_rte(char); __attribute__((overloadable)) long __spirv_SConvert_Rlong_sat_rtp(char); __attribute__((overloadable)) long __spirv_SConvert_Rlong_sat_rtn(char); __attribute__((overloadable)) long __spirv_SConvert_Rlong(short); __attribute__((overloadable)) long __spirv_SConvert_Rlong_rtz(short); __attribute__((overloadable)) long __spirv_SConvert_Rlong_rte(short); __attribute__((overloadable)) long __spirv_SConvert_Rlong_rtp(short); __attribute__((overloadable)) long __spirv_SConvert_Rlong_rtn(short); __attribute__((overloadable)) long __spirv_SConvert_Rlong_sat(short); __attribute__((overloadable)) long __spirv_SConvert_Rlong_sat_rtz(short); __attribute__((overloadable)) long __spirv_SConvert_Rlong_sat_rte(short); __attribute__((overloadable)) long __spirv_SConvert_Rlong_sat_rtp(short); __attribute__((overloadable)) long __spirv_SConvert_Rlong_sat_rtn(short); __attribute__((overloadable)) long __spirv_SConvert_Rlong(int); __attribute__((overloadable)) long __spirv_SConvert_Rlong_rtz(int); __attribute__((overloadable)) long __spirv_SConvert_Rlong_rte(int); __attribute__((overloadable)) long __spirv_SConvert_Rlong_rtp(int); __attribute__((overloadable)) long __spirv_SConvert_Rlong_rtn(int); __attribute__((overloadable)) long __spirv_SConvert_Rlong_sat(int); __attribute__((overloadable)) long __spirv_SConvert_Rlong_sat_rtz(int); __attribute__((overloadable)) long __spirv_SConvert_Rlong_sat_rte(int); __attribute__((overloadable)) long __spirv_SConvert_Rlong_sat_rtp(int); __attribute__((overloadable)) long __spirv_SConvert_Rlong_sat_rtn(int); __attribute__((overloadable)) long __spirv_SConvert_Rlong(long); __attribute__((overloadable)) long __spirv_SConvert_Rlong_rtz(long); __attribute__((overloadable)) long __spirv_SConvert_Rlong_rte(long); __attribute__((overloadable)) long __spirv_SConvert_Rlong_rtp(long); __attribute__((overloadable)) long __spirv_SConvert_Rlong_rtn(long); __attribute__((overloadable)) long __spirv_SConvert_Rlong_sat(long); __attribute__((overloadable)) long __spirv_SConvert_Rlong_sat_rtz(long); __attribute__((overloadable)) long __spirv_SConvert_Rlong_sat_rte(long); __attribute__((overloadable)) long __spirv_SConvert_Rlong_sat_rtp(long); __attribute__((overloadable)) long __spirv_SConvert_Rlong_sat_rtn(long); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2(char2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_rtz(char2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_rte(char2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_rtp(char2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_rtn(char2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_sat(char2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_sat_rtz(char2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_sat_rte(char2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_sat_rtp(char2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_sat_rtn(char2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2(short2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_rtz(short2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_rte(short2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_rtp(short2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_rtn(short2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_sat(short2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_sat_rtz(short2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_sat_rte(short2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_sat_rtp(short2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_sat_rtn(short2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2(int2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_rtz(int2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_rte(int2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_rtp(int2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_rtn(int2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_sat(int2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_sat_rtz(int2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_sat_rte(int2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_sat_rtp(int2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_sat_rtn(int2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2(long2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_rtz(long2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_rte(long2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_rtp(long2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_rtn(long2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_sat(long2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_sat_rtz(long2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_sat_rte(long2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_sat_rtp(long2); __attribute__((overloadable)) long2 __spirv_SConvert_Rlong2_sat_rtn(long2); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3(char3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_rtz(char3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_rte(char3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_rtp(char3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_rtn(char3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_sat(char3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_sat_rtz(char3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_sat_rte(char3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_sat_rtp(char3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_sat_rtn(char3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3(short3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_rtz(short3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_rte(short3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_rtp(short3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_rtn(short3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_sat(short3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_sat_rtz(short3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_sat_rte(short3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_sat_rtp(short3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_sat_rtn(short3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3(int3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_rtz(int3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_rte(int3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_rtp(int3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_rtn(int3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_sat(int3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_sat_rtz(int3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_sat_rte(int3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_sat_rtp(int3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_sat_rtn(int3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3(long3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_rtz(long3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_rte(long3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_rtp(long3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_rtn(long3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_sat(long3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_sat_rtz(long3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_sat_rte(long3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_sat_rtp(long3); __attribute__((overloadable)) long3 __spirv_SConvert_Rlong3_sat_rtn(long3); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4(char4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_rtz(char4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_rte(char4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_rtp(char4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_rtn(char4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_sat(char4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_sat_rtz(char4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_sat_rte(char4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_sat_rtp(char4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_sat_rtn(char4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4(short4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_rtz(short4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_rte(short4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_rtp(short4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_rtn(short4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_sat(short4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_sat_rtz(short4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_sat_rte(short4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_sat_rtp(short4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_sat_rtn(short4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4(int4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_rtz(int4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_rte(int4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_rtp(int4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_rtn(int4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_sat(int4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_sat_rtz(int4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_sat_rte(int4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_sat_rtp(int4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_sat_rtn(int4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4(long4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_rtz(long4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_rte(long4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_rtp(long4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_rtn(long4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_sat(long4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_sat_rtz(long4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_sat_rte(long4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_sat_rtp(long4); __attribute__((overloadable)) long4 __spirv_SConvert_Rlong4_sat_rtn(long4); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8(char8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_rtz(char8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_rte(char8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_rtp(char8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_rtn(char8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_sat(char8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_sat_rtz(char8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_sat_rte(char8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_sat_rtp(char8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_sat_rtn(char8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8(short8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_rtz(short8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_rte(short8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_rtp(short8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_rtn(short8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_sat(short8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_sat_rtz(short8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_sat_rte(short8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_sat_rtp(short8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_sat_rtn(short8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8(int8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_rtz(int8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_rte(int8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_rtp(int8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_rtn(int8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_sat(int8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_sat_rtz(int8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_sat_rte(int8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_sat_rtp(int8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_sat_rtn(int8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8(long8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_rtz(long8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_rte(long8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_rtp(long8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_rtn(long8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_sat(long8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_sat_rtz(long8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_sat_rte(long8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_sat_rtp(long8); __attribute__((overloadable)) long8 __spirv_SConvert_Rlong8_sat_rtn(long8); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16(char16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_rtz(char16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_rte(char16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_rtp(char16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_rtn(char16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_sat(char16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_sat_rtz(char16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_sat_rte(char16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_sat_rtp(char16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_sat_rtn(char16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16(short16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_rtz(short16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_rte(short16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_rtp(short16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_rtn(short16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_sat(short16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_sat_rtz(short16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_sat_rte(short16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_sat_rtp(short16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_sat_rtn(short16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16(int16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_rtz(int16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_rte(int16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_rtp(int16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_rtn(int16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_sat(int16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_sat_rtz(int16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_sat_rte(int16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_sat_rtp(int16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_sat_rtn(int16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16(long16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_rtz(long16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_rte(long16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_rtp(long16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_rtn(long16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_sat(long16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_sat_rtz(long16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_sat_rte(long16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_sat_rtp(long16); __attribute__((overloadable)) long16 __spirv_SConvert_Rlong16_sat_rtn(long16); __attribute__((overloadable)) half __spirv_FConvert_Rhalf(half); __attribute__((overloadable)) half __spirv_FConvert_Rhalf_rtz(half); __attribute__((overloadable)) half __spirv_FConvert_Rhalf_rte(half); __attribute__((overloadable)) half __spirv_FConvert_Rhalf_rtp(half); __attribute__((overloadable)) half __spirv_FConvert_Rhalf_rtn(half); __attribute__((overloadable)) half __spirv_FConvert_Rhalf(float); __attribute__((overloadable)) half __spirv_FConvert_Rhalf_rtz(float); __attribute__((overloadable)) half __spirv_FConvert_Rhalf_rte(float); __attribute__((overloadable)) half __spirv_FConvert_Rhalf_rtp(float); __attribute__((overloadable)) half __spirv_FConvert_Rhalf_rtn(float); __attribute__((overloadable)) half __spirv_FConvert_Rhalf(double); __attribute__((overloadable)) half __spirv_FConvert_Rhalf_rtz(double); __attribute__((overloadable)) half __spirv_FConvert_Rhalf_rte(double); __attribute__((overloadable)) half __spirv_FConvert_Rhalf_rtp(double); __attribute__((overloadable)) half __spirv_FConvert_Rhalf_rtn(double); __attribute__((overloadable)) half2 __spirv_FConvert_Rhalf2(half2); __attribute__((overloadable)) half2 __spirv_FConvert_Rhalf2_rtz(half2); __attribute__((overloadable)) half2 __spirv_FConvert_Rhalf2_rte(half2); __attribute__((overloadable)) half2 __spirv_FConvert_Rhalf2_rtp(half2); __attribute__((overloadable)) half2 __spirv_FConvert_Rhalf2_rtn(half2); __attribute__((overloadable)) half2 __spirv_FConvert_Rhalf2(float2); __attribute__((overloadable)) half2 __spirv_FConvert_Rhalf2_rtz(float2); __attribute__((overloadable)) half2 __spirv_FConvert_Rhalf2_rte(float2); __attribute__((overloadable)) half2 __spirv_FConvert_Rhalf2_rtp(float2); __attribute__((overloadable)) half2 __spirv_FConvert_Rhalf2_rtn(float2); __attribute__((overloadable)) half2 __spirv_FConvert_Rhalf2(double2); __attribute__((overloadable)) half2 __spirv_FConvert_Rhalf2_rtz(double2); __attribute__((overloadable)) half2 __spirv_FConvert_Rhalf2_rte(double2); __attribute__((overloadable)) half2 __spirv_FConvert_Rhalf2_rtp(double2); __attribute__((overloadable)) half2 __spirv_FConvert_Rhalf2_rtn(double2); __attribute__((overloadable)) half3 __spirv_FConvert_Rhalf3(half3); __attribute__((overloadable)) half3 __spirv_FConvert_Rhalf3_rtz(half3); __attribute__((overloadable)) half3 __spirv_FConvert_Rhalf3_rte(half3); __attribute__((overloadable)) half3 __spirv_FConvert_Rhalf3_rtp(half3); __attribute__((overloadable)) half3 __spirv_FConvert_Rhalf3_rtn(half3); __attribute__((overloadable)) half3 __spirv_FConvert_Rhalf3(float3); __attribute__((overloadable)) half3 __spirv_FConvert_Rhalf3_rtz(float3); __attribute__((overloadable)) half3 __spirv_FConvert_Rhalf3_rte(float3); __attribute__((overloadable)) half3 __spirv_FConvert_Rhalf3_rtp(float3); __attribute__((overloadable)) half3 __spirv_FConvert_Rhalf3_rtn(float3); __attribute__((overloadable)) half3 __spirv_FConvert_Rhalf3(double3); __attribute__((overloadable)) half3 __spirv_FConvert_Rhalf3_rtz(double3); __attribute__((overloadable)) half3 __spirv_FConvert_Rhalf3_rte(double3); __attribute__((overloadable)) half3 __spirv_FConvert_Rhalf3_rtp(double3); __attribute__((overloadable)) half3 __spirv_FConvert_Rhalf3_rtn(double3); __attribute__((overloadable)) half4 __spirv_FConvert_Rhalf4(half4); __attribute__((overloadable)) half4 __spirv_FConvert_Rhalf4_rtz(half4); __attribute__((overloadable)) half4 __spirv_FConvert_Rhalf4_rte(half4); __attribute__((overloadable)) half4 __spirv_FConvert_Rhalf4_rtp(half4); __attribute__((overloadable)) half4 __spirv_FConvert_Rhalf4_rtn(half4); __attribute__((overloadable)) half4 __spirv_FConvert_Rhalf4(float4); __attribute__((overloadable)) half4 __spirv_FConvert_Rhalf4_rtz(float4); __attribute__((overloadable)) half4 __spirv_FConvert_Rhalf4_rte(float4); __attribute__((overloadable)) half4 __spirv_FConvert_Rhalf4_rtp(float4); __attribute__((overloadable)) half4 __spirv_FConvert_Rhalf4_rtn(float4); __attribute__((overloadable)) half4 __spirv_FConvert_Rhalf4(double4); __attribute__((overloadable)) half4 __spirv_FConvert_Rhalf4_rtz(double4); __attribute__((overloadable)) half4 __spirv_FConvert_Rhalf4_rte(double4); __attribute__((overloadable)) half4 __spirv_FConvert_Rhalf4_rtp(double4); __attribute__((overloadable)) half4 __spirv_FConvert_Rhalf4_rtn(double4); __attribute__((overloadable)) half8 __spirv_FConvert_Rhalf8(half8); __attribute__((overloadable)) half8 __spirv_FConvert_Rhalf8_rtz(half8); __attribute__((overloadable)) half8 __spirv_FConvert_Rhalf8_rte(half8); __attribute__((overloadable)) half8 __spirv_FConvert_Rhalf8_rtp(half8); __attribute__((overloadable)) half8 __spirv_FConvert_Rhalf8_rtn(half8); __attribute__((overloadable)) half8 __spirv_FConvert_Rhalf8(float8); __attribute__((overloadable)) half8 __spirv_FConvert_Rhalf8_rtz(float8); __attribute__((overloadable)) half8 __spirv_FConvert_Rhalf8_rte(float8); __attribute__((overloadable)) half8 __spirv_FConvert_Rhalf8_rtp(float8); __attribute__((overloadable)) half8 __spirv_FConvert_Rhalf8_rtn(float8); __attribute__((overloadable)) half8 __spirv_FConvert_Rhalf8(double8); __attribute__((overloadable)) half8 __spirv_FConvert_Rhalf8_rtz(double8); __attribute__((overloadable)) half8 __spirv_FConvert_Rhalf8_rte(double8); __attribute__((overloadable)) half8 __spirv_FConvert_Rhalf8_rtp(double8); __attribute__((overloadable)) half8 __spirv_FConvert_Rhalf8_rtn(double8); __attribute__((overloadable)) half16 __spirv_FConvert_Rhalf16(half16); __attribute__((overloadable)) half16 __spirv_FConvert_Rhalf16_rtz(half16); __attribute__((overloadable)) half16 __spirv_FConvert_Rhalf16_rte(half16); __attribute__((overloadable)) half16 __spirv_FConvert_Rhalf16_rtp(half16); __attribute__((overloadable)) half16 __spirv_FConvert_Rhalf16_rtn(half16); __attribute__((overloadable)) half16 __spirv_FConvert_Rhalf16(float16); __attribute__((overloadable)) half16 __spirv_FConvert_Rhalf16_rtz(float16); __attribute__((overloadable)) half16 __spirv_FConvert_Rhalf16_rte(float16); __attribute__((overloadable)) half16 __spirv_FConvert_Rhalf16_rtp(float16); __attribute__((overloadable)) half16 __spirv_FConvert_Rhalf16_rtn(float16); __attribute__((overloadable)) half16 __spirv_FConvert_Rhalf16(double16); __attribute__((overloadable)) half16 __spirv_FConvert_Rhalf16_rtz(double16); __attribute__((overloadable)) half16 __spirv_FConvert_Rhalf16_rte(double16); __attribute__((overloadable)) half16 __spirv_FConvert_Rhalf16_rtp(double16); __attribute__((overloadable)) half16 __spirv_FConvert_Rhalf16_rtn(double16); __attribute__((overloadable)) float __spirv_FConvert_Rfloat(half); __attribute__((overloadable)) float __spirv_FConvert_Rfloat_rtz(half); __attribute__((overloadable)) float __spirv_FConvert_Rfloat_rte(half); __attribute__((overloadable)) float __spirv_FConvert_Rfloat_rtp(half); __attribute__((overloadable)) float __spirv_FConvert_Rfloat_rtn(half); __attribute__((overloadable)) float __spirv_FConvert_Rfloat(float); __attribute__((overloadable)) float __spirv_FConvert_Rfloat_rtz(float); __attribute__((overloadable)) float __spirv_FConvert_Rfloat_rte(float); __attribute__((overloadable)) float __spirv_FConvert_Rfloat_rtp(float); __attribute__((overloadable)) float __spirv_FConvert_Rfloat_rtn(float); __attribute__((overloadable)) float __spirv_FConvert_Rfloat(double); __attribute__((overloadable)) float __spirv_FConvert_Rfloat_rtz(double); __attribute__((overloadable)) float __spirv_FConvert_Rfloat_rte(double); __attribute__((overloadable)) float __spirv_FConvert_Rfloat_rtp(double); __attribute__((overloadable)) float __spirv_FConvert_Rfloat_rtn(double); __attribute__((overloadable)) float2 __spirv_FConvert_Rfloat2(half2); __attribute__((overloadable)) float2 __spirv_FConvert_Rfloat2_rtz(half2); __attribute__((overloadable)) float2 __spirv_FConvert_Rfloat2_rte(half2); __attribute__((overloadable)) float2 __spirv_FConvert_Rfloat2_rtp(half2); __attribute__((overloadable)) float2 __spirv_FConvert_Rfloat2_rtn(half2); __attribute__((overloadable)) float2 __spirv_FConvert_Rfloat2(float2); __attribute__((overloadable)) float2 __spirv_FConvert_Rfloat2_rtz(float2); __attribute__((overloadable)) float2 __spirv_FConvert_Rfloat2_rte(float2); __attribute__((overloadable)) float2 __spirv_FConvert_Rfloat2_rtp(float2); __attribute__((overloadable)) float2 __spirv_FConvert_Rfloat2_rtn(float2); __attribute__((overloadable)) float2 __spirv_FConvert_Rfloat2(double2); __attribute__((overloadable)) float2 __spirv_FConvert_Rfloat2_rtz(double2); __attribute__((overloadable)) float2 __spirv_FConvert_Rfloat2_rte(double2); __attribute__((overloadable)) float2 __spirv_FConvert_Rfloat2_rtp(double2); __attribute__((overloadable)) float2 __spirv_FConvert_Rfloat2_rtn(double2); __attribute__((overloadable)) float3 __spirv_FConvert_Rfloat3(half3); __attribute__((overloadable)) float3 __spirv_FConvert_Rfloat3_rtz(half3); __attribute__((overloadable)) float3 __spirv_FConvert_Rfloat3_rte(half3); __attribute__((overloadable)) float3 __spirv_FConvert_Rfloat3_rtp(half3); __attribute__((overloadable)) float3 __spirv_FConvert_Rfloat3_rtn(half3); __attribute__((overloadable)) float3 __spirv_FConvert_Rfloat3(float3); __attribute__((overloadable)) float3 __spirv_FConvert_Rfloat3_rtz(float3); __attribute__((overloadable)) float3 __spirv_FConvert_Rfloat3_rte(float3); __attribute__((overloadable)) float3 __spirv_FConvert_Rfloat3_rtp(float3); __attribute__((overloadable)) float3 __spirv_FConvert_Rfloat3_rtn(float3); __attribute__((overloadable)) float3 __spirv_FConvert_Rfloat3(double3); __attribute__((overloadable)) float3 __spirv_FConvert_Rfloat3_rtz(double3); __attribute__((overloadable)) float3 __spirv_FConvert_Rfloat3_rte(double3); __attribute__((overloadable)) float3 __spirv_FConvert_Rfloat3_rtp(double3); __attribute__((overloadable)) float3 __spirv_FConvert_Rfloat3_rtn(double3); __attribute__((overloadable)) float4 __spirv_FConvert_Rfloat4(half4); __attribute__((overloadable)) float4 __spirv_FConvert_Rfloat4_rtz(half4); __attribute__((overloadable)) float4 __spirv_FConvert_Rfloat4_rte(half4); __attribute__((overloadable)) float4 __spirv_FConvert_Rfloat4_rtp(half4); __attribute__((overloadable)) float4 __spirv_FConvert_Rfloat4_rtn(half4); __attribute__((overloadable)) float4 __spirv_FConvert_Rfloat4(float4); __attribute__((overloadable)) float4 __spirv_FConvert_Rfloat4_rtz(float4); __attribute__((overloadable)) float4 __spirv_FConvert_Rfloat4_rte(float4); __attribute__((overloadable)) float4 __spirv_FConvert_Rfloat4_rtp(float4); __attribute__((overloadable)) float4 __spirv_FConvert_Rfloat4_rtn(float4); __attribute__((overloadable)) float4 __spirv_FConvert_Rfloat4(double4); __attribute__((overloadable)) float4 __spirv_FConvert_Rfloat4_rtz(double4); __attribute__((overloadable)) float4 __spirv_FConvert_Rfloat4_rte(double4); __attribute__((overloadable)) float4 __spirv_FConvert_Rfloat4_rtp(double4); __attribute__((overloadable)) float4 __spirv_FConvert_Rfloat4_rtn(double4); __attribute__((overloadable)) float8 __spirv_FConvert_Rfloat8(half8); __attribute__((overloadable)) float8 __spirv_FConvert_Rfloat8_rtz(half8); __attribute__((overloadable)) float8 __spirv_FConvert_Rfloat8_rte(half8); __attribute__((overloadable)) float8 __spirv_FConvert_Rfloat8_rtp(half8); __attribute__((overloadable)) float8 __spirv_FConvert_Rfloat8_rtn(half8); __attribute__((overloadable)) float8 __spirv_FConvert_Rfloat8(float8); __attribute__((overloadable)) float8 __spirv_FConvert_Rfloat8_rtz(float8); __attribute__((overloadable)) float8 __spirv_FConvert_Rfloat8_rte(float8); __attribute__((overloadable)) float8 __spirv_FConvert_Rfloat8_rtp(float8); __attribute__((overloadable)) float8 __spirv_FConvert_Rfloat8_rtn(float8); __attribute__((overloadable)) float8 __spirv_FConvert_Rfloat8(double8); __attribute__((overloadable)) float8 __spirv_FConvert_Rfloat8_rtz(double8); __attribute__((overloadable)) float8 __spirv_FConvert_Rfloat8_rte(double8); __attribute__((overloadable)) float8 __spirv_FConvert_Rfloat8_rtp(double8); __attribute__((overloadable)) float8 __spirv_FConvert_Rfloat8_rtn(double8); __attribute__((overloadable)) float16 __spirv_FConvert_Rfloat16(half16); __attribute__((overloadable)) float16 __spirv_FConvert_Rfloat16_rtz(half16); __attribute__((overloadable)) float16 __spirv_FConvert_Rfloat16_rte(half16); __attribute__((overloadable)) float16 __spirv_FConvert_Rfloat16_rtp(half16); __attribute__((overloadable)) float16 __spirv_FConvert_Rfloat16_rtn(half16); __attribute__((overloadable)) float16 __spirv_FConvert_Rfloat16(float16); __attribute__((overloadable)) float16 __spirv_FConvert_Rfloat16_rtz(float16); __attribute__((overloadable)) float16 __spirv_FConvert_Rfloat16_rte(float16); __attribute__((overloadable)) float16 __spirv_FConvert_Rfloat16_rtp(float16); __attribute__((overloadable)) float16 __spirv_FConvert_Rfloat16_rtn(float16); __attribute__((overloadable)) float16 __spirv_FConvert_Rfloat16(double16); __attribute__((overloadable)) float16 __spirv_FConvert_Rfloat16_rtz(double16); __attribute__((overloadable)) float16 __spirv_FConvert_Rfloat16_rte(double16); __attribute__((overloadable)) float16 __spirv_FConvert_Rfloat16_rtp(double16); __attribute__((overloadable)) float16 __spirv_FConvert_Rfloat16_rtn(double16); __attribute__((overloadable)) double __spirv_FConvert_Rdouble(half); __attribute__((overloadable)) double __spirv_FConvert_Rdouble_rtz(half); __attribute__((overloadable)) double __spirv_FConvert_Rdouble_rte(half); __attribute__((overloadable)) double __spirv_FConvert_Rdouble_rtp(half); __attribute__((overloadable)) double __spirv_FConvert_Rdouble_rtn(half); __attribute__((overloadable)) double __spirv_FConvert_Rdouble(float); __attribute__((overloadable)) double __spirv_FConvert_Rdouble_rtz(float); __attribute__((overloadable)) double __spirv_FConvert_Rdouble_rte(float); __attribute__((overloadable)) double __spirv_FConvert_Rdouble_rtp(float); __attribute__((overloadable)) double __spirv_FConvert_Rdouble_rtn(float); __attribute__((overloadable)) double __spirv_FConvert_Rdouble(double); __attribute__((overloadable)) double __spirv_FConvert_Rdouble_rtz(double); __attribute__((overloadable)) double __spirv_FConvert_Rdouble_rte(double); __attribute__((overloadable)) double __spirv_FConvert_Rdouble_rtp(double); __attribute__((overloadable)) double __spirv_FConvert_Rdouble_rtn(double); __attribute__((overloadable)) double2 __spirv_FConvert_Rdouble2(half2); __attribute__((overloadable)) double2 __spirv_FConvert_Rdouble2_rtz(half2); __attribute__((overloadable)) double2 __spirv_FConvert_Rdouble2_rte(half2); __attribute__((overloadable)) double2 __spirv_FConvert_Rdouble2_rtp(half2); __attribute__((overloadable)) double2 __spirv_FConvert_Rdouble2_rtn(half2); __attribute__((overloadable)) double2 __spirv_FConvert_Rdouble2(float2); __attribute__((overloadable)) double2 __spirv_FConvert_Rdouble2_rtz(float2); __attribute__((overloadable)) double2 __spirv_FConvert_Rdouble2_rte(float2); __attribute__((overloadable)) double2 __spirv_FConvert_Rdouble2_rtp(float2); __attribute__((overloadable)) double2 __spirv_FConvert_Rdouble2_rtn(float2); __attribute__((overloadable)) double2 __spirv_FConvert_Rdouble2(double2); __attribute__((overloadable)) double2 __spirv_FConvert_Rdouble2_rtz(double2); __attribute__((overloadable)) double2 __spirv_FConvert_Rdouble2_rte(double2); __attribute__((overloadable)) double2 __spirv_FConvert_Rdouble2_rtp(double2); __attribute__((overloadable)) double2 __spirv_FConvert_Rdouble2_rtn(double2); __attribute__((overloadable)) double3 __spirv_FConvert_Rdouble3(half3); __attribute__((overloadable)) double3 __spirv_FConvert_Rdouble3_rtz(half3); __attribute__((overloadable)) double3 __spirv_FConvert_Rdouble3_rte(half3); __attribute__((overloadable)) double3 __spirv_FConvert_Rdouble3_rtp(half3); __attribute__((overloadable)) double3 __spirv_FConvert_Rdouble3_rtn(half3); __attribute__((overloadable)) double3 __spirv_FConvert_Rdouble3(float3); __attribute__((overloadable)) double3 __spirv_FConvert_Rdouble3_rtz(float3); __attribute__((overloadable)) double3 __spirv_FConvert_Rdouble3_rte(float3); __attribute__((overloadable)) double3 __spirv_FConvert_Rdouble3_rtp(float3); __attribute__((overloadable)) double3 __spirv_FConvert_Rdouble3_rtn(float3); __attribute__((overloadable)) double3 __spirv_FConvert_Rdouble3(double3); __attribute__((overloadable)) double3 __spirv_FConvert_Rdouble3_rtz(double3); __attribute__((overloadable)) double3 __spirv_FConvert_Rdouble3_rte(double3); __attribute__((overloadable)) double3 __spirv_FConvert_Rdouble3_rtp(double3); __attribute__((overloadable)) double3 __spirv_FConvert_Rdouble3_rtn(double3); __attribute__((overloadable)) double4 __spirv_FConvert_Rdouble4(half4); __attribute__((overloadable)) double4 __spirv_FConvert_Rdouble4_rtz(half4); __attribute__((overloadable)) double4 __spirv_FConvert_Rdouble4_rte(half4); __attribute__((overloadable)) double4 __spirv_FConvert_Rdouble4_rtp(half4); __attribute__((overloadable)) double4 __spirv_FConvert_Rdouble4_rtn(half4); __attribute__((overloadable)) double4 __spirv_FConvert_Rdouble4(float4); __attribute__((overloadable)) double4 __spirv_FConvert_Rdouble4_rtz(float4); __attribute__((overloadable)) double4 __spirv_FConvert_Rdouble4_rte(float4); __attribute__((overloadable)) double4 __spirv_FConvert_Rdouble4_rtp(float4); __attribute__((overloadable)) double4 __spirv_FConvert_Rdouble4_rtn(float4); __attribute__((overloadable)) double4 __spirv_FConvert_Rdouble4(double4); __attribute__((overloadable)) double4 __spirv_FConvert_Rdouble4_rtz(double4); __attribute__((overloadable)) double4 __spirv_FConvert_Rdouble4_rte(double4); __attribute__((overloadable)) double4 __spirv_FConvert_Rdouble4_rtp(double4); __attribute__((overloadable)) double4 __spirv_FConvert_Rdouble4_rtn(double4); __attribute__((overloadable)) double8 __spirv_FConvert_Rdouble8(half8); __attribute__((overloadable)) double8 __spirv_FConvert_Rdouble8_rtz(half8); __attribute__((overloadable)) double8 __spirv_FConvert_Rdouble8_rte(half8); __attribute__((overloadable)) double8 __spirv_FConvert_Rdouble8_rtp(half8); __attribute__((overloadable)) double8 __spirv_FConvert_Rdouble8_rtn(half8); __attribute__((overloadable)) double8 __spirv_FConvert_Rdouble8(float8); __attribute__((overloadable)) double8 __spirv_FConvert_Rdouble8_rtz(float8); __attribute__((overloadable)) double8 __spirv_FConvert_Rdouble8_rte(float8); __attribute__((overloadable)) double8 __spirv_FConvert_Rdouble8_rtp(float8); __attribute__((overloadable)) double8 __spirv_FConvert_Rdouble8_rtn(float8); __attribute__((overloadable)) double8 __spirv_FConvert_Rdouble8(double8); __attribute__((overloadable)) double8 __spirv_FConvert_Rdouble8_rtz(double8); __attribute__((overloadable)) double8 __spirv_FConvert_Rdouble8_rte(double8); __attribute__((overloadable)) double8 __spirv_FConvert_Rdouble8_rtp(double8); __attribute__((overloadable)) double8 __spirv_FConvert_Rdouble8_rtn(double8); __attribute__((overloadable)) double16 __spirv_FConvert_Rdouble16(half16); __attribute__((overloadable)) double16 __spirv_FConvert_Rdouble16_rtz(half16); __attribute__((overloadable)) double16 __spirv_FConvert_Rdouble16_rte(half16); __attribute__((overloadable)) double16 __spirv_FConvert_Rdouble16_rtp(half16); __attribute__((overloadable)) double16 __spirv_FConvert_Rdouble16_rtn(half16); __attribute__((overloadable)) double16 __spirv_FConvert_Rdouble16(float16); __attribute__((overloadable)) double16 __spirv_FConvert_Rdouble16_rtz(float16); __attribute__((overloadable)) double16 __spirv_FConvert_Rdouble16_rte(float16); __attribute__((overloadable)) double16 __spirv_FConvert_Rdouble16_rtp(float16); __attribute__((overloadable)) double16 __spirv_FConvert_Rdouble16_rtn(float16); __attribute__((overloadable)) double16 __spirv_FConvert_Rdouble16(double16); __attribute__((overloadable)) double16 __spirv_FConvert_Rdouble16_rtz(double16); __attribute__((overloadable)) double16 __spirv_FConvert_Rdouble16_rte(double16); __attribute__((overloadable)) double16 __spirv_FConvert_Rdouble16_rtp(double16); __attribute__((overloadable)) double16 __spirv_FConvert_Rdouble16_rtn(double16); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar(char); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_rtz(char); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_rte(char); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_rtp(char); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_rtn(char); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_sat(char); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_sat_rtz(char); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_sat_rte(char); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_sat_rtp(char); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_sat_rtn(char); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar(short); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_rtz(short); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_rte(short); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_rtp(short); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_rtn(short); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_sat(short); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_sat_rtz(short); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_sat_rte(short); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_sat_rtp(short); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_sat_rtn(short); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar(int); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_rtz(int); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_rte(int); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_rtp(int); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_rtn(int); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_sat(int); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_sat_rtz(int); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_sat_rte(int); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_sat_rtp(int); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_sat_rtn(int); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar(long); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_rtz(long); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_rte(long); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_rtp(long); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_rtn(long); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_sat(long); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_sat_rtz(long); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_sat_rte(long); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_sat_rtp(long); __attribute__((overloadable)) uchar __spirv_SatConvertSToU_Ruchar_sat_rtn(long); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2(char2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_rtz(char2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_rte(char2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_rtp(char2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_rtn(char2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_sat(char2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_sat_rtz(char2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_sat_rte(char2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_sat_rtp(char2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_sat_rtn(char2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2(short2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_rtz(short2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_rte(short2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_rtp(short2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_rtn(short2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_sat(short2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_sat_rtz(short2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_sat_rte(short2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_sat_rtp(short2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_sat_rtn(short2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2(int2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_rtz(int2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_rte(int2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_rtp(int2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_rtn(int2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_sat(int2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_sat_rtz(int2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_sat_rte(int2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_sat_rtp(int2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_sat_rtn(int2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2(long2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_rtz(long2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_rte(long2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_rtp(long2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_rtn(long2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_sat(long2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_sat_rtz(long2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_sat_rte(long2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_sat_rtp(long2); __attribute__((overloadable)) uchar2 __spirv_SatConvertSToU_Ruchar2_sat_rtn(long2); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3(char3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_rtz(char3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_rte(char3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_rtp(char3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_rtn(char3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_sat(char3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_sat_rtz(char3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_sat_rte(char3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_sat_rtp(char3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_sat_rtn(char3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3(short3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_rtz(short3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_rte(short3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_rtp(short3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_rtn(short3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_sat(short3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_sat_rtz(short3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_sat_rte(short3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_sat_rtp(short3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_sat_rtn(short3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3(int3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_rtz(int3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_rte(int3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_rtp(int3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_rtn(int3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_sat(int3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_sat_rtz(int3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_sat_rte(int3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_sat_rtp(int3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_sat_rtn(int3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3(long3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_rtz(long3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_rte(long3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_rtp(long3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_rtn(long3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_sat(long3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_sat_rtz(long3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_sat_rte(long3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_sat_rtp(long3); __attribute__((overloadable)) uchar3 __spirv_SatConvertSToU_Ruchar3_sat_rtn(long3); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4(char4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_rtz(char4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_rte(char4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_rtp(char4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_rtn(char4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_sat(char4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_sat_rtz(char4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_sat_rte(char4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_sat_rtp(char4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_sat_rtn(char4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4(short4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_rtz(short4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_rte(short4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_rtp(short4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_rtn(short4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_sat(short4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_sat_rtz(short4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_sat_rte(short4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_sat_rtp(short4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_sat_rtn(short4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4(int4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_rtz(int4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_rte(int4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_rtp(int4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_rtn(int4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_sat(int4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_sat_rtz(int4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_sat_rte(int4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_sat_rtp(int4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_sat_rtn(int4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4(long4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_rtz(long4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_rte(long4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_rtp(long4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_rtn(long4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_sat(long4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_sat_rtz(long4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_sat_rte(long4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_sat_rtp(long4); __attribute__((overloadable)) uchar4 __spirv_SatConvertSToU_Ruchar4_sat_rtn(long4); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8(char8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_rtz(char8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_rte(char8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_rtp(char8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_rtn(char8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_sat(char8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_sat_rtz(char8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_sat_rte(char8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_sat_rtp(char8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_sat_rtn(char8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8(short8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_rtz(short8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_rte(short8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_rtp(short8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_rtn(short8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_sat(short8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_sat_rtz(short8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_sat_rte(short8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_sat_rtp(short8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_sat_rtn(short8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8(int8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_rtz(int8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_rte(int8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_rtp(int8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_rtn(int8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_sat(int8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_sat_rtz(int8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_sat_rte(int8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_sat_rtp(int8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_sat_rtn(int8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8(long8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_rtz(long8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_rte(long8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_rtp(long8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_rtn(long8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_sat(long8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_sat_rtz(long8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_sat_rte(long8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_sat_rtp(long8); __attribute__((overloadable)) uchar8 __spirv_SatConvertSToU_Ruchar8_sat_rtn(long8); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16(char16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_rtz(char16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_rte(char16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_rtp(char16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_rtn(char16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_sat(char16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_sat_rtz(char16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_sat_rte(char16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_sat_rtp(char16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_sat_rtn(char16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16(short16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_rtz(short16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_rte(short16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_rtp(short16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_rtn(short16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_sat(short16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_sat_rtz(short16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_sat_rte(short16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_sat_rtp(short16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_sat_rtn(short16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16(int16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_rtz(int16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_rte(int16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_rtp(int16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_rtn(int16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_sat(int16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_sat_rtz(int16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_sat_rte(int16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_sat_rtp(int16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_sat_rtn(int16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16(long16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_rtz(long16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_rte(long16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_rtp(long16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_rtn(long16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_sat(long16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_sat_rtz(long16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_sat_rte(long16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_sat_rtp(long16); __attribute__((overloadable)) uchar16 __spirv_SatConvertSToU_Ruchar16_sat_rtn(long16); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort(char); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_rtz(char); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_rte(char); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_rtp(char); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_rtn(char); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_sat(char); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_sat_rtz(char); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_sat_rte(char); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_sat_rtp(char); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_sat_rtn(char); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort(short); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_rtz(short); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_rte(short); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_rtp(short); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_rtn(short); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_sat(short); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_sat_rtz(short); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_sat_rte(short); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_sat_rtp(short); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_sat_rtn(short); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort(int); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_rtz(int); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_rte(int); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_rtp(int); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_rtn(int); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_sat(int); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_sat_rtz(int); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_sat_rte(int); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_sat_rtp(int); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_sat_rtn(int); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort(long); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_rtz(long); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_rte(long); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_rtp(long); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_rtn(long); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_sat(long); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_sat_rtz(long); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_sat_rte(long); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_sat_rtp(long); __attribute__((overloadable)) ushort __spirv_SatConvertSToU_Rushort_sat_rtn(long); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2(char2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_rtz(char2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_rte(char2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_rtp(char2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_rtn(char2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_sat(char2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_sat_rtz(char2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_sat_rte(char2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_sat_rtp(char2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_sat_rtn(char2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2(short2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_rtz(short2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_rte(short2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_rtp(short2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_rtn(short2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_sat(short2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_sat_rtz(short2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_sat_rte(short2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_sat_rtp(short2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_sat_rtn(short2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2(int2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_rtz(int2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_rte(int2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_rtp(int2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_rtn(int2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_sat(int2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_sat_rtz(int2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_sat_rte(int2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_sat_rtp(int2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_sat_rtn(int2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2(long2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_rtz(long2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_rte(long2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_rtp(long2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_rtn(long2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_sat(long2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_sat_rtz(long2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_sat_rte(long2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_sat_rtp(long2); __attribute__((overloadable)) ushort2 __spirv_SatConvertSToU_Rushort2_sat_rtn(long2); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3(char3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_rtz(char3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_rte(char3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_rtp(char3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_rtn(char3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_sat(char3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_sat_rtz(char3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_sat_rte(char3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_sat_rtp(char3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_sat_rtn(char3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3(short3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_rtz(short3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_rte(short3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_rtp(short3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_rtn(short3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_sat(short3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_sat_rtz(short3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_sat_rte(short3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_sat_rtp(short3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_sat_rtn(short3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3(int3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_rtz(int3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_rte(int3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_rtp(int3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_rtn(int3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_sat(int3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_sat_rtz(int3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_sat_rte(int3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_sat_rtp(int3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_sat_rtn(int3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3(long3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_rtz(long3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_rte(long3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_rtp(long3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_rtn(long3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_sat(long3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_sat_rtz(long3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_sat_rte(long3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_sat_rtp(long3); __attribute__((overloadable)) ushort3 __spirv_SatConvertSToU_Rushort3_sat_rtn(long3); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4(char4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_rtz(char4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_rte(char4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_rtp(char4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_rtn(char4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_sat(char4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_sat_rtz(char4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_sat_rte(char4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_sat_rtp(char4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_sat_rtn(char4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4(short4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_rtz(short4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_rte(short4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_rtp(short4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_rtn(short4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_sat(short4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_sat_rtz(short4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_sat_rte(short4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_sat_rtp(short4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_sat_rtn(short4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4(int4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_rtz(int4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_rte(int4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_rtp(int4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_rtn(int4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_sat(int4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_sat_rtz(int4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_sat_rte(int4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_sat_rtp(int4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_sat_rtn(int4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4(long4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_rtz(long4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_rte(long4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_rtp(long4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_rtn(long4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_sat(long4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_sat_rtz(long4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_sat_rte(long4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_sat_rtp(long4); __attribute__((overloadable)) ushort4 __spirv_SatConvertSToU_Rushort4_sat_rtn(long4); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8(char8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_rtz(char8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_rte(char8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_rtp(char8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_rtn(char8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_sat(char8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_sat_rtz(char8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_sat_rte(char8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_sat_rtp(char8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_sat_rtn(char8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8(short8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_rtz(short8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_rte(short8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_rtp(short8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_rtn(short8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_sat(short8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_sat_rtz(short8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_sat_rte(short8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_sat_rtp(short8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_sat_rtn(short8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8(int8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_rtz(int8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_rte(int8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_rtp(int8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_rtn(int8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_sat(int8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_sat_rtz(int8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_sat_rte(int8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_sat_rtp(int8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_sat_rtn(int8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8(long8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_rtz(long8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_rte(long8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_rtp(long8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_rtn(long8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_sat(long8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_sat_rtz(long8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_sat_rte(long8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_sat_rtp(long8); __attribute__((overloadable)) ushort8 __spirv_SatConvertSToU_Rushort8_sat_rtn(long8); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16(char16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_rtz(char16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_rte(char16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_rtp(char16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_rtn(char16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_sat(char16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_sat_rtz(char16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_sat_rte(char16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_sat_rtp(char16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_sat_rtn(char16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16(short16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_rtz(short16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_rte(short16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_rtp(short16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_rtn(short16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_sat(short16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_sat_rtz(short16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_sat_rte(short16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_sat_rtp(short16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_sat_rtn(short16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16(int16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_rtz(int16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_rte(int16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_rtp(int16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_rtn(int16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_sat(int16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_sat_rtz(int16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_sat_rte(int16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_sat_rtp(int16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_sat_rtn(int16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16(long16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_rtz(long16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_rte(long16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_rtp(long16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_rtn(long16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_sat(long16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_sat_rtz(long16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_sat_rte(long16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_sat_rtp(long16); __attribute__((overloadable)) ushort16 __spirv_SatConvertSToU_Rushort16_sat_rtn(long16); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint(char); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_rtz(char); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_rte(char); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_rtp(char); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_rtn(char); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_sat(char); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_sat_rtz(char); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_sat_rte(char); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_sat_rtp(char); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_sat_rtn(char); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint(short); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_rtz(short); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_rte(short); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_rtp(short); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_rtn(short); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_sat(short); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_sat_rtz(short); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_sat_rte(short); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_sat_rtp(short); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_sat_rtn(short); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint(int); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_rtz(int); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_rte(int); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_rtp(int); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_rtn(int); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_sat(int); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_sat_rtz(int); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_sat_rte(int); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_sat_rtp(int); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_sat_rtn(int); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint(long); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_rtz(long); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_rte(long); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_rtp(long); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_rtn(long); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_sat(long); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_sat_rtz(long); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_sat_rte(long); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_sat_rtp(long); __attribute__((overloadable)) uint __spirv_SatConvertSToU_Ruint_sat_rtn(long); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2(char2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_rtz(char2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_rte(char2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_rtp(char2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_rtn(char2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_sat(char2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_sat_rtz(char2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_sat_rte(char2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_sat_rtp(char2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_sat_rtn(char2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2(short2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_rtz(short2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_rte(short2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_rtp(short2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_rtn(short2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_sat(short2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_sat_rtz(short2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_sat_rte(short2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_sat_rtp(short2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_sat_rtn(short2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2(int2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_rtz(int2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_rte(int2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_rtp(int2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_rtn(int2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_sat(int2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_sat_rtz(int2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_sat_rte(int2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_sat_rtp(int2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_sat_rtn(int2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2(long2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_rtz(long2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_rte(long2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_rtp(long2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_rtn(long2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_sat(long2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_sat_rtz(long2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_sat_rte(long2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_sat_rtp(long2); __attribute__((overloadable)) uint2 __spirv_SatConvertSToU_Ruint2_sat_rtn(long2); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3(char3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_rtz(char3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_rte(char3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_rtp(char3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_rtn(char3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_sat(char3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_sat_rtz(char3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_sat_rte(char3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_sat_rtp(char3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_sat_rtn(char3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3(short3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_rtz(short3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_rte(short3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_rtp(short3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_rtn(short3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_sat(short3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_sat_rtz(short3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_sat_rte(short3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_sat_rtp(short3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_sat_rtn(short3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3(int3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_rtz(int3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_rte(int3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_rtp(int3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_rtn(int3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_sat(int3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_sat_rtz(int3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_sat_rte(int3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_sat_rtp(int3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_sat_rtn(int3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3(long3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_rtz(long3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_rte(long3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_rtp(long3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_rtn(long3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_sat(long3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_sat_rtz(long3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_sat_rte(long3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_sat_rtp(long3); __attribute__((overloadable)) uint3 __spirv_SatConvertSToU_Ruint3_sat_rtn(long3); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4(char4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_rtz(char4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_rte(char4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_rtp(char4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_rtn(char4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_sat(char4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_sat_rtz(char4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_sat_rte(char4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_sat_rtp(char4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_sat_rtn(char4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4(short4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_rtz(short4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_rte(short4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_rtp(short4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_rtn(short4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_sat(short4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_sat_rtz(short4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_sat_rte(short4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_sat_rtp(short4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_sat_rtn(short4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4(int4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_rtz(int4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_rte(int4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_rtp(int4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_rtn(int4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_sat(int4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_sat_rtz(int4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_sat_rte(int4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_sat_rtp(int4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_sat_rtn(int4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4(long4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_rtz(long4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_rte(long4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_rtp(long4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_rtn(long4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_sat(long4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_sat_rtz(long4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_sat_rte(long4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_sat_rtp(long4); __attribute__((overloadable)) uint4 __spirv_SatConvertSToU_Ruint4_sat_rtn(long4); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8(char8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_rtz(char8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_rte(char8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_rtp(char8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_rtn(char8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_sat(char8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_sat_rtz(char8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_sat_rte(char8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_sat_rtp(char8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_sat_rtn(char8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8(short8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_rtz(short8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_rte(short8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_rtp(short8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_rtn(short8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_sat(short8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_sat_rtz(short8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_sat_rte(short8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_sat_rtp(short8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_sat_rtn(short8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8(int8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_rtz(int8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_rte(int8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_rtp(int8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_rtn(int8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_sat(int8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_sat_rtz(int8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_sat_rte(int8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_sat_rtp(int8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_sat_rtn(int8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8(long8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_rtz(long8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_rte(long8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_rtp(long8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_rtn(long8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_sat(long8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_sat_rtz(long8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_sat_rte(long8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_sat_rtp(long8); __attribute__((overloadable)) uint8 __spirv_SatConvertSToU_Ruint8_sat_rtn(long8); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16(char16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_rtz(char16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_rte(char16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_rtp(char16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_rtn(char16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_sat(char16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_sat_rtz(char16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_sat_rte(char16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_sat_rtp(char16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_sat_rtn(char16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16(short16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_rtz(short16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_rte(short16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_rtp(short16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_rtn(short16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_sat(short16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_sat_rtz(short16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_sat_rte(short16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_sat_rtp(short16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_sat_rtn(short16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16(int16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_rtz(int16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_rte(int16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_rtp(int16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_rtn(int16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_sat(int16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_sat_rtz(int16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_sat_rte(int16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_sat_rtp(int16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_sat_rtn(int16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16(long16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_rtz(long16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_rte(long16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_rtp(long16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_rtn(long16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_sat(long16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_sat_rtz(long16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_sat_rte(long16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_sat_rtp(long16); __attribute__((overloadable)) uint16 __spirv_SatConvertSToU_Ruint16_sat_rtn(long16); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong(char); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_rtz(char); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_rte(char); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_rtp(char); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_rtn(char); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_sat(char); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_sat_rtz(char); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_sat_rte(char); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_sat_rtp(char); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_sat_rtn(char); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong(short); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_rtz(short); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_rte(short); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_rtp(short); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_rtn(short); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_sat(short); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_sat_rtz(short); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_sat_rte(short); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_sat_rtp(short); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_sat_rtn(short); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong(int); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_rtz(int); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_rte(int); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_rtp(int); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_rtn(int); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_sat(int); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_sat_rtz(int); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_sat_rte(int); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_sat_rtp(int); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_sat_rtn(int); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong(long); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_rtz(long); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_rte(long); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_rtp(long); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_rtn(long); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_sat(long); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_sat_rtz(long); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_sat_rte(long); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_sat_rtp(long); __attribute__((overloadable)) ulong __spirv_SatConvertSToU_Rulong_sat_rtn(long); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2(char2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_rtz(char2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_rte(char2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_rtp(char2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_rtn(char2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_sat(char2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_sat_rtz(char2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_sat_rte(char2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_sat_rtp(char2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_sat_rtn(char2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2(short2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_rtz(short2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_rte(short2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_rtp(short2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_rtn(short2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_sat(short2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_sat_rtz(short2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_sat_rte(short2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_sat_rtp(short2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_sat_rtn(short2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2(int2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_rtz(int2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_rte(int2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_rtp(int2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_rtn(int2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_sat(int2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_sat_rtz(int2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_sat_rte(int2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_sat_rtp(int2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_sat_rtn(int2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2(long2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_rtz(long2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_rte(long2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_rtp(long2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_rtn(long2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_sat(long2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_sat_rtz(long2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_sat_rte(long2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_sat_rtp(long2); __attribute__((overloadable)) ulong2 __spirv_SatConvertSToU_Rulong2_sat_rtn(long2); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3(char3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_rtz(char3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_rte(char3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_rtp(char3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_rtn(char3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_sat(char3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_sat_rtz(char3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_sat_rte(char3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_sat_rtp(char3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_sat_rtn(char3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3(short3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_rtz(short3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_rte(short3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_rtp(short3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_rtn(short3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_sat(short3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_sat_rtz(short3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_sat_rte(short3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_sat_rtp(short3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_sat_rtn(short3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3(int3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_rtz(int3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_rte(int3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_rtp(int3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_rtn(int3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_sat(int3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_sat_rtz(int3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_sat_rte(int3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_sat_rtp(int3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_sat_rtn(int3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3(long3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_rtz(long3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_rte(long3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_rtp(long3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_rtn(long3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_sat(long3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_sat_rtz(long3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_sat_rte(long3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_sat_rtp(long3); __attribute__((overloadable)) ulong3 __spirv_SatConvertSToU_Rulong3_sat_rtn(long3); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4(char4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_rtz(char4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_rte(char4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_rtp(char4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_rtn(char4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_sat(char4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_sat_rtz(char4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_sat_rte(char4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_sat_rtp(char4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_sat_rtn(char4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4(short4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_rtz(short4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_rte(short4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_rtp(short4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_rtn(short4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_sat(short4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_sat_rtz(short4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_sat_rte(short4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_sat_rtp(short4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_sat_rtn(short4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4(int4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_rtz(int4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_rte(int4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_rtp(int4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_rtn(int4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_sat(int4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_sat_rtz(int4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_sat_rte(int4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_sat_rtp(int4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_sat_rtn(int4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4(long4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_rtz(long4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_rte(long4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_rtp(long4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_rtn(long4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_sat(long4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_sat_rtz(long4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_sat_rte(long4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_sat_rtp(long4); __attribute__((overloadable)) ulong4 __spirv_SatConvertSToU_Rulong4_sat_rtn(long4); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8(char8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_rtz(char8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_rte(char8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_rtp(char8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_rtn(char8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_sat(char8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_sat_rtz(char8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_sat_rte(char8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_sat_rtp(char8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_sat_rtn(char8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8(short8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_rtz(short8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_rte(short8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_rtp(short8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_rtn(short8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_sat(short8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_sat_rtz(short8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_sat_rte(short8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_sat_rtp(short8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_sat_rtn(short8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8(int8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_rtz(int8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_rte(int8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_rtp(int8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_rtn(int8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_sat(int8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_sat_rtz(int8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_sat_rte(int8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_sat_rtp(int8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_sat_rtn(int8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8(long8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_rtz(long8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_rte(long8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_rtp(long8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_rtn(long8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_sat(long8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_sat_rtz(long8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_sat_rte(long8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_sat_rtp(long8); __attribute__((overloadable)) ulong8 __spirv_SatConvertSToU_Rulong8_sat_rtn(long8); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16(char16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_rtz(char16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_rte(char16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_rtp(char16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_rtn(char16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_sat(char16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_sat_rtz(char16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_sat_rte(char16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_sat_rtp(char16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_sat_rtn(char16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16(short16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_rtz(short16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_rte(short16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_rtp(short16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_rtn(short16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_sat(short16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_sat_rtz(short16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_sat_rte(short16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_sat_rtp(short16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_sat_rtn(short16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16(int16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_rtz(int16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_rte(int16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_rtp(int16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_rtn(int16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_sat(int16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_sat_rtz(int16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_sat_rte(int16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_sat_rtp(int16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_sat_rtn(int16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16(long16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_rtz(long16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_rte(long16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_rtp(long16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_rtn(long16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_sat(long16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_sat_rtz(long16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_sat_rte(long16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_sat_rtp(long16); __attribute__((overloadable)) ulong16 __spirv_SatConvertSToU_Rulong16_sat_rtn(long16); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar(uchar); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_rtz(uchar); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_rte(uchar); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_rtp(uchar); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_rtn(uchar); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_sat(uchar); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_sat_rtz(uchar); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_sat_rte(uchar); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_sat_rtp(uchar); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_sat_rtn(uchar); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar(ushort); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_rtz(ushort); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_rte(ushort); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_rtp(ushort); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_rtn(ushort); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_sat(ushort); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_sat_rtz(ushort); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_sat_rte(ushort); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_sat_rtp(ushort); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_sat_rtn(ushort); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar(uint); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_rtz(uint); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_rte(uint); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_rtp(uint); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_rtn(uint); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_sat(uint); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_sat_rtz(uint); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_sat_rte(uint); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_sat_rtp(uint); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_sat_rtn(uint); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar(ulong); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_rtz(ulong); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_rte(ulong); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_rtp(ulong); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_rtn(ulong); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_sat(ulong); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_sat_rtz(ulong); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_sat_rte(ulong); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_sat_rtp(ulong); __attribute__((overloadable)) char __spirv_SatConvertUToS_Rchar_sat_rtn(ulong); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2(uchar2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_rtz(uchar2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_rte(uchar2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_rtp(uchar2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_rtn(uchar2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_sat(uchar2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_sat_rtz(uchar2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_sat_rte(uchar2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_sat_rtp(uchar2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_sat_rtn(uchar2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2(ushort2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_rtz(ushort2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_rte(ushort2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_rtp(ushort2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_rtn(ushort2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_sat(ushort2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_sat_rtz(ushort2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_sat_rte(ushort2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_sat_rtp(ushort2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_sat_rtn(ushort2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2(uint2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_rtz(uint2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_rte(uint2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_rtp(uint2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_rtn(uint2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_sat(uint2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_sat_rtz(uint2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_sat_rte(uint2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_sat_rtp(uint2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_sat_rtn(uint2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2(ulong2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_rtz(ulong2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_rte(ulong2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_rtp(ulong2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_rtn(ulong2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_sat(ulong2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_sat_rtz(ulong2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_sat_rte(ulong2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_sat_rtp(ulong2); __attribute__((overloadable)) char2 __spirv_SatConvertUToS_Rchar2_sat_rtn(ulong2); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3(uchar3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_rtz(uchar3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_rte(uchar3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_rtp(uchar3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_rtn(uchar3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_sat(uchar3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_sat_rtz(uchar3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_sat_rte(uchar3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_sat_rtp(uchar3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_sat_rtn(uchar3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3(ushort3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_rtz(ushort3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_rte(ushort3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_rtp(ushort3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_rtn(ushort3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_sat(ushort3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_sat_rtz(ushort3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_sat_rte(ushort3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_sat_rtp(ushort3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_sat_rtn(ushort3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3(uint3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_rtz(uint3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_rte(uint3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_rtp(uint3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_rtn(uint3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_sat(uint3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_sat_rtz(uint3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_sat_rte(uint3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_sat_rtp(uint3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_sat_rtn(uint3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3(ulong3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_rtz(ulong3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_rte(ulong3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_rtp(ulong3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_rtn(ulong3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_sat(ulong3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_sat_rtz(ulong3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_sat_rte(ulong3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_sat_rtp(ulong3); __attribute__((overloadable)) char3 __spirv_SatConvertUToS_Rchar3_sat_rtn(ulong3); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4(uchar4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_rtz(uchar4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_rte(uchar4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_rtp(uchar4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_rtn(uchar4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_sat(uchar4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_sat_rtz(uchar4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_sat_rte(uchar4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_sat_rtp(uchar4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_sat_rtn(uchar4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4(ushort4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_rtz(ushort4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_rte(ushort4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_rtp(ushort4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_rtn(ushort4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_sat(ushort4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_sat_rtz(ushort4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_sat_rte(ushort4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_sat_rtp(ushort4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_sat_rtn(ushort4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4(uint4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_rtz(uint4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_rte(uint4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_rtp(uint4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_rtn(uint4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_sat(uint4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_sat_rtz(uint4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_sat_rte(uint4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_sat_rtp(uint4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_sat_rtn(uint4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4(ulong4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_rtz(ulong4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_rte(ulong4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_rtp(ulong4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_rtn(ulong4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_sat(ulong4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_sat_rtz(ulong4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_sat_rte(ulong4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_sat_rtp(ulong4); __attribute__((overloadable)) char4 __spirv_SatConvertUToS_Rchar4_sat_rtn(ulong4); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8(uchar8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_rtz(uchar8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_rte(uchar8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_rtp(uchar8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_rtn(uchar8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_sat(uchar8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_sat_rtz(uchar8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_sat_rte(uchar8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_sat_rtp(uchar8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_sat_rtn(uchar8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8(ushort8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_rtz(ushort8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_rte(ushort8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_rtp(ushort8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_rtn(ushort8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_sat(ushort8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_sat_rtz(ushort8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_sat_rte(ushort8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_sat_rtp(ushort8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_sat_rtn(ushort8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8(uint8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_rtz(uint8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_rte(uint8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_rtp(uint8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_rtn(uint8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_sat(uint8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_sat_rtz(uint8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_sat_rte(uint8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_sat_rtp(uint8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_sat_rtn(uint8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8(ulong8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_rtz(ulong8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_rte(ulong8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_rtp(ulong8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_rtn(ulong8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_sat(ulong8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_sat_rtz(ulong8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_sat_rte(ulong8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_sat_rtp(ulong8); __attribute__((overloadable)) char8 __spirv_SatConvertUToS_Rchar8_sat_rtn(ulong8); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16(uchar16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_rtz(uchar16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_rte(uchar16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_rtp(uchar16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_rtn(uchar16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_sat(uchar16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_sat_rtz(uchar16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_sat_rte(uchar16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_sat_rtp(uchar16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_sat_rtn(uchar16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16(ushort16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_rtz(ushort16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_rte(ushort16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_rtp(ushort16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_rtn(ushort16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_sat(ushort16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_sat_rtz(ushort16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_sat_rte(ushort16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_sat_rtp(ushort16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_sat_rtn(ushort16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16(uint16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_rtz(uint16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_rte(uint16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_rtp(uint16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_rtn(uint16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_sat(uint16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_sat_rtz(uint16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_sat_rte(uint16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_sat_rtp(uint16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_sat_rtn(uint16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16(ulong16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_rtz(ulong16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_rte(ulong16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_rtp(ulong16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_rtn(ulong16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_sat(ulong16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_sat_rtz(ulong16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_sat_rte(ulong16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_sat_rtp(ulong16); __attribute__((overloadable)) char16 __spirv_SatConvertUToS_Rchar16_sat_rtn(ulong16); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort(uchar); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_rtz(uchar); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_rte(uchar); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_rtp(uchar); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_rtn(uchar); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_sat(uchar); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_sat_rtz(uchar); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_sat_rte(uchar); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_sat_rtp(uchar); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_sat_rtn(uchar); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort(ushort); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_rtz(ushort); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_rte(ushort); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_rtp(ushort); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_rtn(ushort); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_sat(ushort); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_sat_rtz(ushort); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_sat_rte(ushort); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_sat_rtp(ushort); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_sat_rtn(ushort); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort(uint); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_rtz(uint); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_rte(uint); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_rtp(uint); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_rtn(uint); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_sat(uint); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_sat_rtz(uint); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_sat_rte(uint); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_sat_rtp(uint); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_sat_rtn(uint); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort(ulong); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_rtz(ulong); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_rte(ulong); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_rtp(ulong); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_rtn(ulong); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_sat(ulong); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_sat_rtz(ulong); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_sat_rte(ulong); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_sat_rtp(ulong); __attribute__((overloadable)) short __spirv_SatConvertUToS_Rshort_sat_rtn(ulong); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2(uchar2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_rtz(uchar2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_rte(uchar2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_rtp(uchar2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_rtn(uchar2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_sat(uchar2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_sat_rtz(uchar2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_sat_rte(uchar2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_sat_rtp(uchar2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_sat_rtn(uchar2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2(ushort2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_rtz(ushort2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_rte(ushort2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_rtp(ushort2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_rtn(ushort2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_sat(ushort2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_sat_rtz(ushort2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_sat_rte(ushort2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_sat_rtp(ushort2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_sat_rtn(ushort2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2(uint2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_rtz(uint2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_rte(uint2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_rtp(uint2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_rtn(uint2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_sat(uint2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_sat_rtz(uint2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_sat_rte(uint2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_sat_rtp(uint2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_sat_rtn(uint2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2(ulong2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_rtz(ulong2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_rte(ulong2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_rtp(ulong2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_rtn(ulong2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_sat(ulong2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_sat_rtz(ulong2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_sat_rte(ulong2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_sat_rtp(ulong2); __attribute__((overloadable)) short2 __spirv_SatConvertUToS_Rshort2_sat_rtn(ulong2); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3(uchar3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_rtz(uchar3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_rte(uchar3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_rtp(uchar3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_rtn(uchar3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_sat(uchar3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_sat_rtz(uchar3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_sat_rte(uchar3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_sat_rtp(uchar3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_sat_rtn(uchar3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3(ushort3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_rtz(ushort3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_rte(ushort3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_rtp(ushort3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_rtn(ushort3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_sat(ushort3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_sat_rtz(ushort3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_sat_rte(ushort3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_sat_rtp(ushort3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_sat_rtn(ushort3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3(uint3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_rtz(uint3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_rte(uint3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_rtp(uint3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_rtn(uint3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_sat(uint3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_sat_rtz(uint3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_sat_rte(uint3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_sat_rtp(uint3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_sat_rtn(uint3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3(ulong3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_rtz(ulong3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_rte(ulong3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_rtp(ulong3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_rtn(ulong3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_sat(ulong3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_sat_rtz(ulong3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_sat_rte(ulong3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_sat_rtp(ulong3); __attribute__((overloadable)) short3 __spirv_SatConvertUToS_Rshort3_sat_rtn(ulong3); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4(uchar4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_rtz(uchar4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_rte(uchar4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_rtp(uchar4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_rtn(uchar4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_sat(uchar4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_sat_rtz(uchar4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_sat_rte(uchar4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_sat_rtp(uchar4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_sat_rtn(uchar4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4(ushort4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_rtz(ushort4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_rte(ushort4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_rtp(ushort4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_rtn(ushort4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_sat(ushort4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_sat_rtz(ushort4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_sat_rte(ushort4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_sat_rtp(ushort4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_sat_rtn(ushort4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4(uint4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_rtz(uint4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_rte(uint4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_rtp(uint4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_rtn(uint4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_sat(uint4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_sat_rtz(uint4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_sat_rte(uint4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_sat_rtp(uint4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_sat_rtn(uint4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4(ulong4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_rtz(ulong4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_rte(ulong4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_rtp(ulong4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_rtn(ulong4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_sat(ulong4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_sat_rtz(ulong4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_sat_rte(ulong4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_sat_rtp(ulong4); __attribute__((overloadable)) short4 __spirv_SatConvertUToS_Rshort4_sat_rtn(ulong4); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8(uchar8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_rtz(uchar8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_rte(uchar8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_rtp(uchar8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_rtn(uchar8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_sat(uchar8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_sat_rtz(uchar8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_sat_rte(uchar8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_sat_rtp(uchar8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_sat_rtn(uchar8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8(ushort8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_rtz(ushort8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_rte(ushort8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_rtp(ushort8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_rtn(ushort8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_sat(ushort8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_sat_rtz(ushort8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_sat_rte(ushort8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_sat_rtp(ushort8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_sat_rtn(ushort8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8(uint8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_rtz(uint8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_rte(uint8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_rtp(uint8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_rtn(uint8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_sat(uint8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_sat_rtz(uint8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_sat_rte(uint8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_sat_rtp(uint8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_sat_rtn(uint8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8(ulong8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_rtz(ulong8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_rte(ulong8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_rtp(ulong8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_rtn(ulong8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_sat(ulong8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_sat_rtz(ulong8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_sat_rte(ulong8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_sat_rtp(ulong8); __attribute__((overloadable)) short8 __spirv_SatConvertUToS_Rshort8_sat_rtn(ulong8); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16(uchar16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_rtz(uchar16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_rte(uchar16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_rtp(uchar16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_rtn(uchar16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_sat(uchar16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_sat_rtz(uchar16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_sat_rte(uchar16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_sat_rtp(uchar16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_sat_rtn(uchar16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16(ushort16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_rtz(ushort16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_rte(ushort16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_rtp(ushort16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_rtn(ushort16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_sat(ushort16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_sat_rtz(ushort16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_sat_rte(ushort16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_sat_rtp(ushort16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_sat_rtn(ushort16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16(uint16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_rtz(uint16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_rte(uint16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_rtp(uint16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_rtn(uint16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_sat(uint16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_sat_rtz(uint16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_sat_rte(uint16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_sat_rtp(uint16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_sat_rtn(uint16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16(ulong16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_rtz(ulong16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_rte(ulong16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_rtp(ulong16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_rtn(ulong16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_sat(ulong16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_sat_rtz(ulong16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_sat_rte(ulong16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_sat_rtp(ulong16); __attribute__((overloadable)) short16 __spirv_SatConvertUToS_Rshort16_sat_rtn(ulong16); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint(uchar); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_rtz(uchar); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_rte(uchar); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_rtp(uchar); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_rtn(uchar); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_sat(uchar); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_sat_rtz(uchar); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_sat_rte(uchar); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_sat_rtp(uchar); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_sat_rtn(uchar); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint(ushort); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_rtz(ushort); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_rte(ushort); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_rtp(ushort); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_rtn(ushort); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_sat(ushort); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_sat_rtz(ushort); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_sat_rte(ushort); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_sat_rtp(ushort); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_sat_rtn(ushort); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint(uint); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_rtz(uint); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_rte(uint); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_rtp(uint); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_rtn(uint); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_sat(uint); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_sat_rtz(uint); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_sat_rte(uint); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_sat_rtp(uint); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_sat_rtn(uint); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint(ulong); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_rtz(ulong); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_rte(ulong); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_rtp(ulong); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_rtn(ulong); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_sat(ulong); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_sat_rtz(ulong); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_sat_rte(ulong); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_sat_rtp(ulong); __attribute__((overloadable)) int __spirv_SatConvertUToS_Rint_sat_rtn(ulong); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2(uchar2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_rtz(uchar2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_rte(uchar2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_rtp(uchar2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_rtn(uchar2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_sat(uchar2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_sat_rtz(uchar2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_sat_rte(uchar2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_sat_rtp(uchar2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_sat_rtn(uchar2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2(ushort2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_rtz(ushort2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_rte(ushort2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_rtp(ushort2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_rtn(ushort2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_sat(ushort2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_sat_rtz(ushort2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_sat_rte(ushort2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_sat_rtp(ushort2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_sat_rtn(ushort2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2(uint2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_rtz(uint2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_rte(uint2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_rtp(uint2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_rtn(uint2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_sat(uint2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_sat_rtz(uint2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_sat_rte(uint2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_sat_rtp(uint2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_sat_rtn(uint2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2(ulong2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_rtz(ulong2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_rte(ulong2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_rtp(ulong2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_rtn(ulong2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_sat(ulong2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_sat_rtz(ulong2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_sat_rte(ulong2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_sat_rtp(ulong2); __attribute__((overloadable)) int2 __spirv_SatConvertUToS_Rint2_sat_rtn(ulong2); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3(uchar3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_rtz(uchar3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_rte(uchar3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_rtp(uchar3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_rtn(uchar3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_sat(uchar3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_sat_rtz(uchar3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_sat_rte(uchar3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_sat_rtp(uchar3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_sat_rtn(uchar3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3(ushort3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_rtz(ushort3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_rte(ushort3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_rtp(ushort3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_rtn(ushort3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_sat(ushort3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_sat_rtz(ushort3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_sat_rte(ushort3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_sat_rtp(ushort3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_sat_rtn(ushort3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3(uint3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_rtz(uint3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_rte(uint3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_rtp(uint3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_rtn(uint3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_sat(uint3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_sat_rtz(uint3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_sat_rte(uint3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_sat_rtp(uint3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_sat_rtn(uint3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3(ulong3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_rtz(ulong3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_rte(ulong3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_rtp(ulong3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_rtn(ulong3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_sat(ulong3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_sat_rtz(ulong3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_sat_rte(ulong3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_sat_rtp(ulong3); __attribute__((overloadable)) int3 __spirv_SatConvertUToS_Rint3_sat_rtn(ulong3); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4(uchar4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_rtz(uchar4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_rte(uchar4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_rtp(uchar4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_rtn(uchar4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_sat(uchar4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_sat_rtz(uchar4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_sat_rte(uchar4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_sat_rtp(uchar4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_sat_rtn(uchar4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4(ushort4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_rtz(ushort4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_rte(ushort4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_rtp(ushort4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_rtn(ushort4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_sat(ushort4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_sat_rtz(ushort4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_sat_rte(ushort4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_sat_rtp(ushort4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_sat_rtn(ushort4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4(uint4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_rtz(uint4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_rte(uint4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_rtp(uint4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_rtn(uint4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_sat(uint4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_sat_rtz(uint4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_sat_rte(uint4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_sat_rtp(uint4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_sat_rtn(uint4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4(ulong4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_rtz(ulong4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_rte(ulong4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_rtp(ulong4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_rtn(ulong4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_sat(ulong4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_sat_rtz(ulong4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_sat_rte(ulong4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_sat_rtp(ulong4); __attribute__((overloadable)) int4 __spirv_SatConvertUToS_Rint4_sat_rtn(ulong4); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8(uchar8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_rtz(uchar8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_rte(uchar8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_rtp(uchar8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_rtn(uchar8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_sat(uchar8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_sat_rtz(uchar8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_sat_rte(uchar8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_sat_rtp(uchar8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_sat_rtn(uchar8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8(ushort8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_rtz(ushort8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_rte(ushort8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_rtp(ushort8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_rtn(ushort8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_sat(ushort8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_sat_rtz(ushort8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_sat_rte(ushort8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_sat_rtp(ushort8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_sat_rtn(ushort8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8(uint8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_rtz(uint8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_rte(uint8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_rtp(uint8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_rtn(uint8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_sat(uint8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_sat_rtz(uint8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_sat_rte(uint8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_sat_rtp(uint8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_sat_rtn(uint8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8(ulong8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_rtz(ulong8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_rte(ulong8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_rtp(ulong8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_rtn(ulong8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_sat(ulong8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_sat_rtz(ulong8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_sat_rte(ulong8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_sat_rtp(ulong8); __attribute__((overloadable)) int8 __spirv_SatConvertUToS_Rint8_sat_rtn(ulong8); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16(uchar16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_rtz(uchar16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_rte(uchar16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_rtp(uchar16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_rtn(uchar16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_sat(uchar16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_sat_rtz(uchar16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_sat_rte(uchar16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_sat_rtp(uchar16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_sat_rtn(uchar16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16(ushort16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_rtz(ushort16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_rte(ushort16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_rtp(ushort16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_rtn(ushort16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_sat(ushort16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_sat_rtz(ushort16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_sat_rte(ushort16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_sat_rtp(ushort16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_sat_rtn(ushort16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16(uint16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_rtz(uint16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_rte(uint16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_rtp(uint16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_rtn(uint16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_sat(uint16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_sat_rtz(uint16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_sat_rte(uint16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_sat_rtp(uint16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_sat_rtn(uint16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16(ulong16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_rtz(ulong16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_rte(ulong16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_rtp(ulong16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_rtn(ulong16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_sat(ulong16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_sat_rtz(ulong16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_sat_rte(ulong16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_sat_rtp(ulong16); __attribute__((overloadable)) int16 __spirv_SatConvertUToS_Rint16_sat_rtn(ulong16); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong(uchar); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_rtz(uchar); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_rte(uchar); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_rtp(uchar); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_rtn(uchar); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_sat(uchar); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_sat_rtz(uchar); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_sat_rte(uchar); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_sat_rtp(uchar); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_sat_rtn(uchar); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong(ushort); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_rtz(ushort); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_rte(ushort); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_rtp(ushort); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_rtn(ushort); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_sat(ushort); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_sat_rtz(ushort); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_sat_rte(ushort); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_sat_rtp(ushort); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_sat_rtn(ushort); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong(uint); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_rtz(uint); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_rte(uint); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_rtp(uint); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_rtn(uint); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_sat(uint); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_sat_rtz(uint); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_sat_rte(uint); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_sat_rtp(uint); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_sat_rtn(uint); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong(ulong); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_rtz(ulong); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_rte(ulong); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_rtp(ulong); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_rtn(ulong); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_sat(ulong); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_sat_rtz(ulong); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_sat_rte(ulong); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_sat_rtp(ulong); __attribute__((overloadable)) long __spirv_SatConvertUToS_Rlong_sat_rtn(ulong); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2(uchar2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_rtz(uchar2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_rte(uchar2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_rtp(uchar2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_rtn(uchar2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_sat(uchar2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_sat_rtz(uchar2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_sat_rte(uchar2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_sat_rtp(uchar2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_sat_rtn(uchar2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2(ushort2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_rtz(ushort2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_rte(ushort2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_rtp(ushort2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_rtn(ushort2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_sat(ushort2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_sat_rtz(ushort2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_sat_rte(ushort2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_sat_rtp(ushort2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_sat_rtn(ushort2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2(uint2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_rtz(uint2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_rte(uint2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_rtp(uint2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_rtn(uint2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_sat(uint2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_sat_rtz(uint2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_sat_rte(uint2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_sat_rtp(uint2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_sat_rtn(uint2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2(ulong2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_rtz(ulong2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_rte(ulong2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_rtp(ulong2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_rtn(ulong2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_sat(ulong2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_sat_rtz(ulong2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_sat_rte(ulong2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_sat_rtp(ulong2); __attribute__((overloadable)) long2 __spirv_SatConvertUToS_Rlong2_sat_rtn(ulong2); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3(uchar3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_rtz(uchar3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_rte(uchar3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_rtp(uchar3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_rtn(uchar3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_sat(uchar3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_sat_rtz(uchar3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_sat_rte(uchar3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_sat_rtp(uchar3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_sat_rtn(uchar3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3(ushort3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_rtz(ushort3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_rte(ushort3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_rtp(ushort3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_rtn(ushort3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_sat(ushort3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_sat_rtz(ushort3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_sat_rte(ushort3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_sat_rtp(ushort3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_sat_rtn(ushort3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3(uint3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_rtz(uint3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_rte(uint3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_rtp(uint3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_rtn(uint3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_sat(uint3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_sat_rtz(uint3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_sat_rte(uint3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_sat_rtp(uint3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_sat_rtn(uint3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3(ulong3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_rtz(ulong3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_rte(ulong3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_rtp(ulong3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_rtn(ulong3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_sat(ulong3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_sat_rtz(ulong3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_sat_rte(ulong3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_sat_rtp(ulong3); __attribute__((overloadable)) long3 __spirv_SatConvertUToS_Rlong3_sat_rtn(ulong3); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4(uchar4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_rtz(uchar4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_rte(uchar4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_rtp(uchar4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_rtn(uchar4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_sat(uchar4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_sat_rtz(uchar4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_sat_rte(uchar4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_sat_rtp(uchar4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_sat_rtn(uchar4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4(ushort4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_rtz(ushort4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_rte(ushort4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_rtp(ushort4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_rtn(ushort4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_sat(ushort4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_sat_rtz(ushort4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_sat_rte(ushort4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_sat_rtp(ushort4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_sat_rtn(ushort4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4(uint4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_rtz(uint4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_rte(uint4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_rtp(uint4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_rtn(uint4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_sat(uint4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_sat_rtz(uint4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_sat_rte(uint4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_sat_rtp(uint4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_sat_rtn(uint4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4(ulong4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_rtz(ulong4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_rte(ulong4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_rtp(ulong4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_rtn(ulong4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_sat(ulong4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_sat_rtz(ulong4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_sat_rte(ulong4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_sat_rtp(ulong4); __attribute__((overloadable)) long4 __spirv_SatConvertUToS_Rlong4_sat_rtn(ulong4); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8(uchar8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_rtz(uchar8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_rte(uchar8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_rtp(uchar8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_rtn(uchar8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_sat(uchar8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_sat_rtz(uchar8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_sat_rte(uchar8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_sat_rtp(uchar8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_sat_rtn(uchar8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8(ushort8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_rtz(ushort8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_rte(ushort8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_rtp(ushort8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_rtn(ushort8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_sat(ushort8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_sat_rtz(ushort8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_sat_rte(ushort8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_sat_rtp(ushort8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_sat_rtn(ushort8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8(uint8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_rtz(uint8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_rte(uint8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_rtp(uint8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_rtn(uint8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_sat(uint8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_sat_rtz(uint8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_sat_rte(uint8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_sat_rtp(uint8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_sat_rtn(uint8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8(ulong8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_rtz(ulong8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_rte(ulong8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_rtp(ulong8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_rtn(ulong8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_sat(ulong8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_sat_rtz(ulong8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_sat_rte(ulong8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_sat_rtp(ulong8); __attribute__((overloadable)) long8 __spirv_SatConvertUToS_Rlong8_sat_rtn(ulong8); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16(uchar16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_rtz(uchar16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_rte(uchar16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_rtp(uchar16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_rtn(uchar16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_sat(uchar16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_sat_rtz(uchar16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_sat_rte(uchar16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_sat_rtp(uchar16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_sat_rtn(uchar16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16(ushort16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_rtz(ushort16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_rte(ushort16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_rtp(ushort16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_rtn(ushort16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_sat(ushort16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_sat_rtz(ushort16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_sat_rte(ushort16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_sat_rtp(ushort16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_sat_rtn(ushort16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16(uint16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_rtz(uint16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_rte(uint16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_rtp(uint16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_rtn(uint16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_sat(uint16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_sat_rtz(uint16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_sat_rte(uint16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_sat_rtp(uint16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_sat_rtn(uint16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16(ulong16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_rtz(ulong16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_rte(ulong16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_rtp(ulong16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_rtn(ulong16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_sat(ulong16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_sat_rtz(ulong16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_sat_rte(ulong16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_sat_rtp(ulong16); __attribute__((overloadable)) long16 __spirv_SatConvertUToS_Rlong16_sat_rtn(ulong16); SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/runtime/OpenCL/src/000077500000000000000000000000001363521741200224415ustar00rootroot00000000000000SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/runtime/OpenCL/src/ImageQuerySize.cl000066400000000000000000000037551363521741200256760ustar00rootroot00000000000000#include "../inc/spirv.h" __attribute__((overloadable, always_inline)) int __spirv_ImageQuerySize(image1d_buffer_t img) { return get_image_width(img); } __attribute__((overloadable, always_inline)) int __spirv_ImageQuerySizeLod(image1d_t img, int lod) { return get_image_width(img) >> lod; } __attribute__((overloadable, always_inline)) int2 __spirv_ImageQuerySize(image1d_array_t img) { return (int2)(get_image_width(img), get_image_array_size(img)); } __attribute__((overloadable, always_inline)) int2 __spirv_ImageQuerySizeLod(image1d_array_t img, int lod) { return (int2)(get_image_width(img) >> lod, get_image_array_size(img) >> lod); } #define DEFINE_SPIRV_ImageQuerySizeLod_2d(ImgTy) \ __attribute__((overloadable, always_inline)) int2 __spirv_ImageQuerySizeLod(ImgTy img, int lod) { \ return get_image_dim(img) >> lod; \ } #define DEFINE_SPIRV_ImageQuerySizeLod_2darray(ImgTy) \ __attribute__((overloadable, always_inline)) int3 __spirv_ImageQuerySizeLod(ImgTy img, int lod) { \ return (int3)(get_image_dim(img) >> lod, get_image_array_size(img) >> lod); \ } #define DEFINE_SPIRV_ImageQuerySize_2d(ImgTy) \ __attribute__((overloadable, always_inline)) int2 __spirv_ImageQuerySize(ImgTy img) { \ return get_image_dim(img); \ } #define DEFINE_SPIRV_ImageQuerySize_2darray(ImgTy) \ __attribute__((overloadable, always_inline)) int3 __spirv_ImageQuerySize(ImgTy img) { \ return (int3)(get_image_dim(img), get_image_array_size(img)); \ } __attribute__((overloadable, always_inline)) int3 __spirv_ImageQuerySizeLod(image3d_t img, int lod) { return get_image_dim(img).xyz >> lod; } DEFINE_SPIRV_ImageQuerySize_2d(image2d_t) DEFINE_SPIRV_ImageQuerySize_2d(image2d_depth_t) DEFINE_SPIRV_ImageQuerySizeLod_2d(image2d_t) DEFINE_SPIRV_ImageQuerySizeLod_2d(image2d_depth_t) DEFINE_SPIRV_ImageQuerySize_2darray(image2d_array_t) DEFINE_SPIRV_ImageQuerySize_2darray(image2d_array_depth_t) DEFINE_SPIRV_ImageQuerySizeLod_2darray(image2d_array_t) DEFINE_SPIRV_ImageQuerySizeLod_2darray(image2d_array_depth_t) SPIRV-LLVM-Translator-10.0.0/lib/SPIRV/runtime/README.txt000066400000000000000000000006521363521741200222330ustar00rootroot00000000000000This directory contains SPIR-V builtin functions used by the LLVM module converted from SPIR-V by the SPIR-V/LLVM converter. The SPIR-V consumers need to add these builtin functions to their runtime library. For OpenCL, most of the SPIR-V instructions are translated to either LLVM instructions or OpenCL builtin function calls by the converter. Therefore only a few SPIR-V instructions need to be implemented in the runtime.SPIRV-LLVM-Translator-10.0.0/test/000077500000000000000000000000001363521741200163555ustar00rootroot00000000000000SPIRV-LLVM-Translator-10.0.0/test/AtomicCompareExchange_cl12.ll000066400000000000000000000051051363521741200237160ustar00rootroot00000000000000; RUN: llvm-as %s -o %t.bc ; RUN: llvm-spirv %t.bc -spirv-text -o %t ; RUN: FileCheck < %t %s ; RUN: llvm-spirv %t.bc -o %t.spv ; RUN: spirv-val %t.spv target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" target triple = "spir-unknown-unknown" ; CHECK: 3 Source 3 102000 ; CHECK: Name [[Pointer:[0-9]+]] "object" ; CHECK: Name [[Comparator:[0-9]+]] "expected" ; CHECK: Name [[Value:[0-9]+]] "desired" ; CHECK: 4 TypeInt [[int:[0-9]+]] 32 0 ; CHECK: Constant [[int]] [[DeviceScope:[0-9]+]] 1 ; CHECK: Constant [[int]] [[SequentiallyConsistent_MS:[0-9]+]] 16 ; CHECK: 4 TypePointer [[int_ptr:[0-9]+]] 5 [[int]] ; Function Attrs: nounwind define spir_func i32 @test(i32 addrspace(1)* %object, i32 %expected, i32 %desired) #0 { ; CHECK: FunctionParameter [[int_ptr]] [[Pointer]] ; CHECK: FunctionParameter [[int]] [[Comparator]] ; CHECK: FunctionParameter [[int]] [[Value]] entry: %object.addr = alloca i32 addrspace(1)*, align 4 %expected.addr = alloca i32, align 4 %desired.addr = alloca i32, align 4 %res = alloca i32, align 4 store i32 addrspace(1)* %object, i32 addrspace(1)** %object.addr, align 4 store i32 %expected, i32* %expected.addr, align 4 store i32 %desired, i32* %desired.addr, align 4 %0 = load i32 addrspace(1)*, i32 addrspace(1)** %object.addr, align 4 %1 = load i32, i32* %expected.addr, align 4 %2 = load i32, i32* %desired.addr, align 4 %call = call spir_func i32 @_Z14atomic_cmpxchgPVU3AS1iii(i32 addrspace(1)* %0, i32 %1, i32 %2) ; CHECK 9 AtomicCompareExchange [[int]] [[result:[0-9]+]] [[Pointer]] [[DeviceScope]] [[SequentiallyConsistent_MS]] [[SequentiallyConsistent_MS]] [[Value]] [[Comparator]] store i32 %call, i32* %res, align 4 %3 = load i32, i32* %res, align 4 ret i32 %3 ; CHECK 2 ReturnValue [[result]] } declare spir_func i32 @_Z14atomic_cmpxchgPVU3AS1iii(i32 addrspace(1)*, i32, i32) #1 attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } !opencl.enable.FP_CONTRACT = !{} !opencl.spir.version = !{!0} !opencl.ocl.version = !{!0} !opencl.used.extensions = !{!1} !opencl.used.optional.core.features = !{!1} !opencl.compiler.options = !{!1} !0 = !{i32 1, i32 2} !1 = !{} SPIRV-LLVM-Translator-10.0.0/test/AtomicCompareExchange_cl20.ll000066400000000000000000000115061363521741200237170ustar00rootroot00000000000000; RUN: llvm-as %s -o %t.bc ; RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s ; RUN: llvm-spirv %t.bc -o %t.spv ; RUN: spirv-val %t.spv target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" target triple = "spir-unknown-unknown" ; CHECK: 3 Source 3 200000 ; Int64Atomics capability must be declared only if atomic builtins have 64-bit integers arguments. ; CHECK-NOT: Capability Int64Atomics ; CHECK: 4 TypeInt [[int:[0-9]+]] 32 0 ; CHECK: Constant [[int]] [[DeviceScope:[0-9]+]] 1 ; CHECK: Constant [[int]] [[SequentiallyConsistent_MS:[0-9]+]] 16 ; CHECK: 4 TypePointer [[int_ptr:[0-9]+]] 8 [[int]] ; CHECK: 2 TypeBool [[bool:[0-9]+]] ; Function Attrs: nounwind define spir_func void @test(i32 addrspace(4)* %object, i32 addrspace(4)* %expected, i32 %desired) #0 { ; CHECK: FunctionParameter [[int_ptr]] [[object:[0-9]+]] ; CHECK: FunctionParameter [[int_ptr]] [[expected:[0-9]+]] ; CHECK: FunctionParameter [[int]] [[desired:[0-9]+]] entry: %object.addr = alloca i32 addrspace(4)*, align 4 %expected.addr = alloca i32 addrspace(4)*, align 4 %desired.addr = alloca i32, align 4 %strong_res = alloca i8, align 1 %res = alloca i8, align 1 %weak_res = alloca i8, align 1 store i32 addrspace(4)* %object, i32 addrspace(4)** %object.addr, align 4 store i32 addrspace(4)* %expected, i32 addrspace(4)** %expected.addr, align 4 store i32 %desired, i32* %desired.addr, align 4 %0 = load i32 addrspace(4)*, i32 addrspace(4)** %object.addr, align 4 %1 = load i32 addrspace(4)*, i32 addrspace(4)** %expected.addr, align 4 %2 = load i32, i32* %desired.addr, align 4 ; CHECK: Store [[object_addr:[0-9]+]] [[object]] ; CHECK: Store [[expected_addr:[0-9]+]] [[expected]] ; CHECK: Store [[desired_addr:[0-9]+]] [[desired]] ; CHECK: Load [[int_ptr]] [[Pointer:[0-9]+]] [[object_addr]] ; CHECK: Load [[int_ptr]] [[exp:[0-9]+]] [[expected_addr]] ; CHECK: Load [[int]] [[Value:[0-9]+]] [[desired_addr]] ; CHECK: Load [[int]] [[Comparator:[0-9]+]] [[exp]] ; CHECK-NEXT: 9 AtomicCompareExchange [[int]] [[Result:[0-9]+]] [[Pointer]] [[DeviceScope]] [[SequentiallyConsistent_MS]] [[SequentiallyConsistent_MS]] [[Value]] [[Comparator]] %call = call spir_func zeroext i1 @_Z30atomic_compare_exchange_strongPVU3AS4U7_AtomiciPU3AS4ii(i32 addrspace(4)* %0, i32 addrspace(4)* %1, i32 %2) ; CHECK-NEXT: Store [[exp]] [[Result]] ; CHECK-NEXT: IEqual [[bool]] [[CallRes:[0-9]+]] [[Result]] [[Comparator]] ; CHECK-NOT: [[Result]] %frombool = zext i1 %call to i8 store i8 %frombool, i8* %strong_res, align 1 %3 = load i8, i8* %strong_res, align 1 %tobool = trunc i8 %3 to i1 %lnot = xor i1 %tobool, true %frombool1 = zext i1 %lnot to i8 store i8 %frombool1, i8* %res, align 1 %4 = load i32 addrspace(4)*, i32 addrspace(4)** %object.addr, align 4 %5 = load i32 addrspace(4)*, i32 addrspace(4)** %expected.addr, align 4 %6 = load i32, i32* %desired.addr, align 4 ; CHECK: Load [[int_ptr]] [[Pointer:[0-9]+]] [[object_addr]] ; CHECK: Load [[int_ptr]] [[exp:[0-9]+]] [[expected_addr]] ; CHECK: Load [[int]] [[Value:[0-9]+]] [[desired_addr]] ; CHECK: Load [[int]] [[ComparatorWeak:[0-9]+]] [[exp]] %call2 = call spir_func zeroext i1 @_Z28atomic_compare_exchange_weakPVU3AS4U7_AtomiciPU3AS4ii(i32 addrspace(4)* %4, i32 addrspace(4)* %5, i32 %6) ; CHECK-NEXT: 9 AtomicCompareExchangeWeak [[int]] [[Result:[0-9]+]] [[Pointer]] [[DeviceScope]] [[SequentiallyConsistent_MS]] [[SequentiallyConsistent_MS]] [[Value]] [[ComparatorWeak]] ; CHECK-NEXT: Store [[exp]] [[Result]] ; CHECK-NEXT: IEqual [[bool]] [[CallRes:[0-9]+]] [[Result]] [[ComparatorWeak]] ; CHECK-NOT: [[Result]] %frombool3 = zext i1 %call2 to i8 store i8 %frombool3, i8* %weak_res, align 1 %7 = load i8, i8* %weak_res, align 1 %tobool4 = trunc i8 %7 to i1 %lnot5 = xor i1 %tobool4, true %frombool6 = zext i1 %lnot5 to i8 store i8 %frombool6, i8* %res, align 1 ret void } declare spir_func zeroext i1 @_Z30atomic_compare_exchange_strongPVU3AS4U7_AtomiciPU3AS4ii(i32 addrspace(4)*, i32 addrspace(4)*, i32) #1 declare spir_func zeroext i1 @_Z28atomic_compare_exchange_weakPVU3AS4U7_AtomiciPU3AS4ii(i32 addrspace(4)*, i32 addrspace(4)*, i32) #1 attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } !opencl.enable.FP_CONTRACT = !{} !opencl.spir.version = !{!0} !opencl.ocl.version = !{!1} !opencl.used.extensions = !{!2} !opencl.used.optional.core.features = !{!2} !opencl.compiler.options = !{!2} !0 = !{i32 1, i32 2} !1 = !{i32 2, i32 0} !2 = !{} SPIRV-LLVM-Translator-10.0.0/test/CMakeLists.txt000066400000000000000000000046011363521741200211160ustar00rootroot00000000000000include(FindPkgConfig) llvm_canonicalize_cmake_booleans(SPIRV_SKIP_CLANG_BUILD) llvm_canonicalize_cmake_booleans(SPIRV_SKIP_DEBUG_INFO_TESTS) # required by lit.site.cfg.py.in get_target_property(LLVM_SPIRV_DIR llvm-spirv BINARY_DIR) set(LLVM_SPIRV_TEST_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) # find spirv-val pkg_search_module(SPIRV_TOOLS SPIRV-Tools) if(SPIRV_TOOLS_FOUND) find_program(SPIRV_TOOLS_SPIRV_AS NAMES spirv-as PATHS ${SPIRV_TOOLS_PREFIX}/bin) if(SPIRV_TOOLS_SPIRV_AS) set(SPIRV_TOOLS_SPIRV_AS_FOUND True) endif() find_program(SPIRV_TOOLS_SPIRV_VAL NAMES spirv-val PATHS ${SPIRV_TOOLS_PREFIX}/bin) if(SPIRV_TOOLS_SPIRV_VAL) set(SPIRV_TOOLS_SPIRV_VAL_FOUND True) endif() set(SPIRV_TOOLS_BINDIR "${SPIRV_TOOLS_PREFIX}/bin") endif() if(NOT SPIRV_TOOLS_SPIRV_AS) message(WARNING "spirv-as not found! SPIR-V assembly tests will not be run.") set(SPIRV_TOOLS_SPIRV_AS_FOUND False) endif() if(NOT SPIRV_TOOLS_SPIRV_VAL) message(WARNING "spirv-val not found! SPIR-V generated for test suite will not be validated.") set(SPIRV_TOOLS_SPIRV_VAL_FOUND False) endif() configure_lit_site_cfg( ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py MAIN_CONFIG ${CMAKE_CURRENT_SOURCE_DIR}/lit.cfg.py ) if(NOT LLVM_SPIRV_BUILD_EXTERNAL) set(LLVM_SPIRV_TEST_DEPS FileCheck count llvm-as llvm-config llvm-dis not ) if(NOT SPIRV_SKIP_CLANG_BUILD) list(APPEND LLVM_SPIRV_TEST_DEPS clang ) endif(NOT SPIRV_SKIP_CLANG_BUILD) if(NOT SPIRV_SKIP_DEBUG_INFO_TESTS) list(APPEND LLVM_SPIRV_TEST_DEPS llc llvm-dwarfdump llvm-objdump llvm-readelf llvm-readobj ) endif(NOT SPIRV_SKIP_DEBUG_INFO_TESTS) endif(NOT LLVM_SPIRV_BUILD_EXTERNAL) add_lit_testsuite(check-llvm-spirv "Running the LLVM-SPIRV regression tests" ${CMAKE_CURRENT_BINARY_DIR} ARGS --verbose DEPENDS ${LLVM_SPIRV_TEST_DEPS} llvm-spirv ) # to enable a custom test target on cmake below 3.11 # starting with 3.11 "test" is only reserved if ENABLE_TESTING(ON) if(LLVM_SPIRV_BUILD_EXTERNAL) cmake_policy(PUSH) if(POLICY CMP0037 AND ${CMAKE_VERSION} VERSION_LESS "3.11.0") cmake_policy(SET CMP0037 OLD) endif(POLICY CMP0037 AND ${CMAKE_VERSION} VERSION_LESS "3.11.0") add_custom_target(test DEPENDS check-llvm-spirv ) cmake_policy(POP) endif(LLVM_SPIRV_BUILD_EXTERNAL) SPIRV-LLVM-Translator-10.0.0/test/CheckCapKernelWithoutKernel.ll000066400000000000000000000013621363521741200242370ustar00rootroot00000000000000; RUN: llvm-as %s -o %t.bc ; RUN: llvm-spirv %t.bc -spirv-text -o %t ; RUN: FileCheck < %t %s ; RUN: llvm-spirv %t.bc -o %t.spv ; RUN: spirv-val %t.spv ; ModuleID = '../rel/CheckCapKernelWithoutKernel.bc' target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" target triple = "spir64-unknown-unknown" @a = addrspace(2) constant i32 1, align 4 ; CHECK-DAG: {{[0-9]*}} Capability Kernel !opencl.enable.FP_CONTRACT = !{} !opencl.spir.version = !{!0} !opencl.ocl.version = !{!1} !opencl.used.extensions = !{!2} !opencl.used.optional.core.features = !{!2} !opencl.compiler.options = !{!2} !llvm.ident = !{!3} !0 = !{i32 1, i32 2} !1 = !{i32 1, i32 0} !2 = !{} !3 = !{!"clang version 3.6.1 "} SPIRV-LLVM-Translator-10.0.0/test/ComparePointers.cl000066400000000000000000000013531363521741200220110ustar00rootroot00000000000000kernel void test(int global *in, int global *in2) { if (!in) return; if (in == 1) return; if (in > in2) return; if (in < in2) return; } // RUN: %clang_cc1 -triple spir64 -x cl -cl-std=CL2.0 -O0 -emit-llvm-bc %s -o %t.bc // RUN: llvm-spirv %t.bc -spirv-text -o %t.spt // RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV // RUN: llvm-spirv %t.bc -o %t.spv // RUN: spirv-val %t.spv // CHECK-SPIRV:ConvertPtrToU // CHECK-SPIRV:ConvertPtrToU // CHECK-SPIRV:INotEqual // CHECK-SPIRV:ConvertPtrToU // CHECK-SPIRV:ConvertPtrToU // CHECK-SPIRV:IEqual // CHECK-SPIRV:ConvertPtrToU // CHECK-SPIRV:ConvertPtrToU // CHECK-SPIRV:UGreaterThan // CHECK-SPIRV:ConvertPtrToU // CHECK-SPIRV:ConvertPtrToU // CHECK-SPIRV:ULessThan SPIRV-LLVM-Translator-10.0.0/test/ContractionOff.ll000066400000000000000000000057631363521741200216370ustar00rootroot00000000000000; Source: ; void kernel k1 (float a, float b, float c) { ; #pragma OPENCL FP_CONTRACT OFF ; float d = a * b + c; ; } ; ; void kernel k2 (float a, float b, float c) { ; float d = a * b + c; ; } ; ; void kernel k3 (float a, float b, float c) { ; float d = a * b; // a * b together with -d in the next statement look ; float e = a * c - d; // exactly like an unfused fmuladd in LLVM IR ; } ; ; IR generated using the following commands: ; clang -cc1 -x cl -emit-llvm -O2 -disable-llvm-passes -triple spir64 1.cl -o 1.ll ; opt -mem2reg 1.ll -S -o 1.o.ll ; RUN: llvm-as %s -o %t.bc ; RUN: llvm-spirv %t.bc -spirv-text -o %t ; RUN: FileCheck < %t %s ; RUN: llvm-spirv %t.bc -o %t.spv ; RUN: spirv-val %t.spv ; CHECK: EntryPoint 6 [[K1:[0-9]+]] "k1" ; CHECK: EntryPoint 6 [[K2:[0-9]+]] "k2" ; CHECK: EntryPoint 6 [[K3:[0-9]+]] "k3" ; CHECK: ExecutionMode [[K1]] 31 ; CHECK-NOT: ExecutionMode [[K2]] 31 ; CHECK-NOT: ExecutionMode [[K3]] 31 target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" target triple = "spir64" ; Function Attrs: convergent nounwind define spir_kernel void @k1(float %a, float %b, float %c) #0 !kernel_arg_addr_space !4 !kernel_arg_access_qual !5 !kernel_arg_type !6 !kernel_arg_base_type !6 !kernel_arg_type_qual !7 { entry: %mul = fmul float %a, %b %add = fadd float %mul, %c ret void } ; Function Attrs: convergent nounwind define spir_kernel void @k2(float %a, float %b, float %c) #0 !kernel_arg_addr_space !4 !kernel_arg_access_qual !5 !kernel_arg_type !6 !kernel_arg_base_type !6 !kernel_arg_type_qual !7 { entry: %0 = call float @llvm.fmuladd.f32(float %a, float %b, float %c) ret void } ; Function Attrs: nounwind readnone speculatable declare float @llvm.fmuladd.f32(float, float, float) #2 ; Function Attrs: convergent nounwind define spir_kernel void @k3(float %a, float %b, float %c) #0 !kernel_arg_addr_space !4 !kernel_arg_access_qual !5 !kernel_arg_type !6 !kernel_arg_base_type !6 !kernel_arg_type_qual !7 { entry: %mul = fmul float %a, %b %neg = fsub float -0.000000e+00, %mul %0 = call float @llvm.fmuladd.f32(float %a, float %c, float %neg) ret void } attributes #0 = { convergent nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "denorms-are-zero"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "uniform-work-group-size"="true" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { argmemonly nounwind } attributes #2 = { nounwind readnone speculatable } !llvm.module.flags = !{!0} !opencl.ocl.version = !{!1} !opencl.spir.version = !{!2} !llvm.ident = !{!3} !0 = !{i32 1, !"wchar_size", i32 4} !1 = !{i32 1, i32 0} !2 = !{i32 1, i32 2} !3 = !{!"clang version 7.0.1"} !4 = !{i32 0, i32 0, i32 0} !5 = !{!"none", !"none", !"none"} !6 = !{!"float", !"float", !"float"} !7 = !{!"", !"", !""} SPIRV-LLVM-Translator-10.0.0/test/CreatePipeFromPipeStorage.ll000066400000000000000000000273501363521741200237250ustar00rootroot00000000000000; RUN: llvm-as %s -o %t.bc ; RUN: llvm-spirv %t.bc -spirv-text -o %t.txt ; RUN: FileCheck < %t.txt %s --check-prefix=CHECK-SPIRV ; RUN: llvm-spirv %t.bc -o %t.spv ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM ; CHECK-LLVM: %"[[CL_PIPE_STORAGE_NAME:[^"]+]]" = type { %spirv.PipeStorage addrspace(1)* } ; CHECK-LLVM: %"[[CL_READ_PIPE_NAME:[^"]+read>]]" = type { %spirv.Pipe._0 addrspace(1)* } ; CHECK-LLVM: %spirv.Pipe._0 = type opaque ; CHECK-LLVM: %"[[CL_WRITE_PIPE_NAME:[^"]+write>]]" = type { %spirv.Pipe._1 addrspace(1)* } ; CHECK-LLVM: %spirv.Pipe._1 = type opaque ; CHECK-SPIRV: Capability Pipes ; CHECK-SPIRV: Capability PipeStorage ; CHECK-SPIRV: Name [[PIPE_STORAGE_ID:[0-9]+]] "mygpipe" ; CHECK-SPIRV: Name [[READ_PIPE_WRAPPER_ID:[0-9]+]] "myrpipe" ; CHECK-SPIRV: Name [[WRITE_PIPE_WRAPPER_ID:[0-9]+]] "mywpipe" ; CHECK-SPIRV: Name [[WRITE_PIPE_WRAPPER_CTOR:[0-9]+]] "_ZNU3AS42cl4pipeIDv4_iLNS_11pipe_accessE1EEC1EPU3AS1NS_7__spirv10OpTypePipeILNS3_15AccessQualifierE1EEE" ; CHECK-SPIRV: Name [[READ_PIPE_WRAPPER_CTOR:[0-9]+]] "_ZNU3AS42cl4pipeIDv4_iLNS_11pipe_accessE0EEC1EPU3AS1NS_7__spirv10OpTypePipeILNS3_15AccessQualifierE0EEE" ; CHECK-SPIRV: TypeInt [[INT_T:[0-9]+]] 32 0 ; CHECK-SPIRV: Constant [[INT_T]] [[CONSTANT_ZERO_ID:[0-9]+]] 0 ; CHECK-SPIRV: TypePipe [[READ_PIPE:[0-9]+]] 0 ; CHECK-SPIRV: TypeStruct [[READ_PIPE_WRAPPER:[0-9]+]] [[READ_PIPE]] ; CHECK-SPIRV: TypePointer [[READ_PIPE_WRAPPER_PTR:[0-9]+]] 7 [[READ_PIPE_WRAPPER]] ; CHECK-SPIRV: TypePipe [[WRITE_PIPE:[0-9]+]] 1 ; CHECK-SPIRV: TypeStruct [[WRITE_PIPE_WRAPPER:[0-9]+]] [[WRITE_PIPE]] ; CHECK-SPIRV: TypePointer [[WRITE_PIPE_WRAPPER_PTR:[0-9]+]] 7 [[WRITE_PIPE_WRAPPER]] target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" target triple = "spir-unknown-unknown" %spirv.ConstantPipeStorage = type { i32, i32, i32 } %"class.cl::pipe_storage" = type { %spirv.PipeStorage addrspace(1)* } %spirv.PipeStorage = type opaque %"class.cl::pipe" = type { %spirv.Pipe._0 addrspace(1)* } %spirv.Pipe._0 = type opaque %"class.cl::pipe" = type { %spirv.Pipe._1 addrspace(1)* } %spirv.Pipe._1 = type opaque @_ZN2cl9__details29OpConstantPipeStorage_CreatorILi16ELi16ELi1EE5valueE = linkonce_odr addrspace(1) global %spirv.ConstantPipeStorage { i32 16, i32 16, i32 1 }, align 4 @mygpipe = addrspace(1) global %"class.cl::pipe_storage" { %spirv.PipeStorage addrspace(1)* bitcast (%spirv.ConstantPipeStorage addrspace(1)* @_ZN2cl9__details29OpConstantPipeStorage_CreatorILi16ELi16ELi1EE5valueE to %spirv.PipeStorage addrspace(1)*) }, align 4 ; Function Attrs: nounwind define spir_kernel void @worker() { entry: ; CHECK-LLVM: %myrpipe = alloca %"[[CL_READ_PIPE_NAME]]", align 4 ; CHECK-LLVM: %mywpipe = alloca %"[[CL_WRITE_PIPE_NAME]]", align 4 ; CHECK-SPIRV: Variable [[READ_PIPE_WRAPPER_PTR]] [[READ_PIPE_WRAPPER_ID]] 7 ; CHECK-SPIRV: Variable [[WRITE_PIPE_WRAPPER_PTR]] [[WRITE_PIPE_WRAPPER_ID]] 7 %myrpipe = alloca %"class.cl::pipe", align 4 %mywpipe = alloca %"class.cl::pipe", align 4 ; CHECK-LLVM: %[[ID0:[0-9]+]] = addrspacecast %"[[CL_PIPE_STORAGE_NAME]]" addrspace(1)* @mygpipe to %"[[CL_PIPE_STORAGE_NAME]]" addrspace(4)* ; CHECK-LLVM: %[[ID1:[0-9]+]] = getelementptr %"[[CL_PIPE_STORAGE_NAME]]", %"[[CL_PIPE_STORAGE_NAME]]" addrspace(4)* %[[ID0]], i32 0, i32 0 ; CHECK-SPIRV: PtrCastToGeneric {{[0-9]+}} [[SPIRV0:[0-9]+]] [[PIPE_STORAGE_ID]] ; CHECK-SPIRV: PtrAccessChain {{[0-9]+}} [[SPIRV1:[0-9]+]] [[SPIRV0]] [[CONSTANT_ZERO_ID]] [[CONSTANT_ZERO_ID]] %0 = addrspacecast %"class.cl::pipe_storage" addrspace(1)* @mygpipe to %"class.cl::pipe_storage" addrspace(4)* %1 = getelementptr %"class.cl::pipe_storage", %"class.cl::pipe_storage" addrspace(4)* %0, i32 0, i32 0 ; CHECK-LLVM: %[[PIPE_STORAGE_1:[0-9]+]] = load %spirv.PipeStorage addrspace(1)*, %spirv.PipeStorage addrspace(1)* addrspace(4)* %[[ID1]], align 4 ; CHECK-LLVM: %[[WRITE_PIPE:[0-9]+]] = call spir_func %spirv.Pipe._1 addrspace(1)* @_Z39__spirv_CreatePipeFromPipeStorage_writePU3AS119__spirv_PipeStorage(%spirv.PipeStorage addrspace(1)* %[[PIPE_STORAGE_1]]) ; CHECK-LLVM: %[[WRITE_PIPE_WRAPPER:[0-9]+]] = addrspacecast %"[[CL_WRITE_PIPE_NAME]]"* %mywpipe to %"[[CL_WRITE_PIPE_NAME]]" addrspace(4)* ; CHECK-LLVM: call spir_func void @_ZNU3AS42cl4pipeIDv4_iLNS_11pipe_accessE1EEC1EPU3AS1NS_7__spirv10OpTypePipeILNS3_15AccessQualifierE1EEE(%"[[CL_WRITE_PIPE_NAME]]" addrspace(4)* nocapture %[[WRITE_PIPE_WRAPPER]], %spirv.Pipe._1 addrspace(1)* %[[WRITE_PIPE]]) ; CHECK-SPIRV: Load {{[0-9]+}} [[PIPE_STORAGE_ID0:[0-9]+]] [[SPIRV1]] 2 4 ; CHECK-SPIRV: CreatePipeFromPipeStorage [[WRITE_PIPE]] [[WRITE_PIPE_ID:[0-9]+]] [[PIPE_STORAGE_ID0]] ; CHECK-SPIRV: PtrCastToGeneric {{[0-9]+}} [[GENERIC_WRITE_PIPE_WRAPPER_ID:[0-9]+]] [[WRITE_PIPE_WRAPPER_ID]] ; CHECK-SPIRV: FunctionCall {{[0-9]+}} {{[0-9]+}} [[WRITE_PIPE_WRAPPER_CTOR]] [[GENERIC_WRITE_PIPE_WRAPPER_ID]] [[WRITE_PIPE_ID]] %2 = load %spirv.PipeStorage addrspace(1)*, %spirv.PipeStorage addrspace(1)* addrspace(4)* %1, align 4 %3 = tail call spir_func %spirv.Pipe._1 addrspace(1)* @_Z39__spirv_CreatePipeFromPipeStorage_writePU3AS1K19__spirv_PipeStorage(%spirv.PipeStorage addrspace(1)* %2) %4 = addrspacecast %"class.cl::pipe"* %mywpipe to %"class.cl::pipe" addrspace(4)* call spir_func void @_ZNU3AS42cl4pipeIDv4_iLNS_11pipe_accessE1EEC1EPU3AS1NS_7__spirv10OpTypePipeILNS3_15AccessQualifierE1EEE(%"class.cl::pipe" addrspace(4)* %4, %spirv.Pipe._1 addrspace(1)* %3) ; CHECK-LLVM: %[[PIPE_STORAGE_2:[0-9]+]] = load %spirv.PipeStorage addrspace(1)*, %spirv.PipeStorage addrspace(1)* addrspace(4)* %[[ID1]], align 4 ; CHECK-LLVM: %[[READ_PIPE:[0-9]+]] = call spir_func %spirv.Pipe._0 addrspace(1)* @_Z38__spirv_CreatePipeFromPipeStorage_readPU3AS119__spirv_PipeStorage(%spirv.PipeStorage addrspace(1)* %[[PIPE_STORAGE_2]]) ; CHECK-LLVM: %[[READ_PIPE_WRAPPER:[0-9]+]] = addrspacecast %"[[CL_READ_PIPE_NAME]]"* %myrpipe to %"[[CL_READ_PIPE_NAME]]" addrspace(4)* ; CHECK-LLVM: call spir_func void @_ZNU3AS42cl4pipeIDv4_iLNS_11pipe_accessE0EEC1EPU3AS1NS_7__spirv10OpTypePipeILNS3_15AccessQualifierE0EEE(%"[[CL_READ_PIPE_NAME]]" addrspace(4)* nocapture %[[READ_PIPE_WRAPPER]], %spirv.Pipe._0 addrspace(1)* %[[READ_PIPE]]) ; CHECK-SPIRV: Load {{[0-9]+}} [[PIPE_STORAGE_ID1:[0-9]+]] [[SPIRV1]] 2 4 ; CHECK-SPIRV: CreatePipeFromPipeStorage [[READ_PIPE]] [[READ_PIPE_ID:[0-9]+]] [[PIPE_STORAGE_ID1]] ; CHECK-SPIRV: PtrCastToGeneric {{[0-9]+}} [[GENERIC_READ_PIPE_WRAPPER_ID:[0-9]+]] [[READ_PIPE_WRAPPER_ID]] ; CHECK-SPIRV: FunctionCall {{[0-9]+}} {{[0-9]+}} [[READ_PIPE_WRAPPER_CTOR]] [[GENERIC_READ_PIPE_WRAPPER_ID]] [[READ_PIPE_ID]] %5 = load %spirv.PipeStorage addrspace(1)*, %spirv.PipeStorage addrspace(1)* addrspace(4)* %1, align 4 %6 = tail call spir_func %spirv.Pipe._0 addrspace(1)* @_Z38__spirv_CreatePipeFromPipeStorage_readPU3AS1K19__spirv_PipeStorage(%spirv.PipeStorage addrspace(1)* %5) %7 = addrspacecast %"class.cl::pipe"* %myrpipe to %"class.cl::pipe" addrspace(4)* call spir_func void @_ZNU3AS42cl4pipeIDv4_iLNS_11pipe_accessE0EEC1EPU3AS1NS_7__spirv10OpTypePipeILNS3_15AccessQualifierE0EEE(%"class.cl::pipe" addrspace(4)* %7, %spirv.Pipe._0 addrspace(1)* %6) ret void } ; Function Attrs: nounwind define linkonce_odr spir_func void @_ZNU3AS42cl4pipeIDv4_iLNS_11pipe_accessE0EEC1EPU3AS1NS_7__spirv10OpTypePipeILNS3_15AccessQualifierE0EEE(%"class.cl::pipe" addrspace(4)* nocapture %this, %spirv.Pipe._0 addrspace(1)* %handle) unnamed_addr align 2 { entry: tail call spir_func void @_ZNU3AS42cl4pipeIDv4_iLNS_11pipe_accessE0EEC2EPU3AS1NS_7__spirv10OpTypePipeILNS3_15AccessQualifierE0EEE(%"class.cl::pipe" addrspace(4)* %this, %spirv.Pipe._0 addrspace(1)* %handle) ret void } ; Function Attrs: nounwind define linkonce_odr spir_func void @_ZNU3AS42cl4pipeIDv4_iLNS_11pipe_accessE0EEC2EPU3AS1NS_7__spirv10OpTypePipeILNS3_15AccessQualifierE0EEE(%"class.cl::pipe" addrspace(4)* nocapture %this, %spirv.Pipe._0 addrspace(1)* %handle) unnamed_addr align 2 { entry: %_handle = getelementptr inbounds %"class.cl::pipe", %"class.cl::pipe" addrspace(4)* %this, i32 0, i32 0 store %spirv.Pipe._0 addrspace(1)* %handle, %spirv.Pipe._0 addrspace(1)* addrspace(4)* %_handle, align 4, !tbaa !11 ret void } ; Function Attrs: nounwind declare spir_func %spirv.Pipe._0 addrspace(1)* @_Z38__spirv_CreatePipeFromPipeStorage_readPU3AS1K19__spirv_PipeStorage(%spirv.PipeStorage addrspace(1)*) ; Function Attrs: nounwind define linkonce_odr spir_func void @_ZNU3AS42cl4pipeIDv4_iLNS_11pipe_accessE1EEC1EPU3AS1NS_7__spirv10OpTypePipeILNS3_15AccessQualifierE1EEE(%"class.cl::pipe" addrspace(4)* nocapture %this, %spirv.Pipe._1 addrspace(1)* %handle) unnamed_addr align 2 { entry: tail call spir_func void @_ZNU3AS42cl4pipeIDv4_iLNS_11pipe_accessE1EEC2EPU3AS1NS_7__spirv10OpTypePipeILNS3_15AccessQualifierE1EEE(%"class.cl::pipe" addrspace(4)* %this, %spirv.Pipe._1 addrspace(1)* %handle) ret void } ; Function Attrs: nounwind define linkonce_odr spir_func void @_ZNU3AS42cl4pipeIDv4_iLNS_11pipe_accessE1EEC2EPU3AS1NS_7__spirv10OpTypePipeILNS3_15AccessQualifierE1EEE(%"class.cl::pipe" addrspace(4)* nocapture %this, %spirv.Pipe._1 addrspace(1)* %handle) unnamed_addr align 2 { entry: %_handle = getelementptr inbounds %"class.cl::pipe", %"class.cl::pipe" addrspace(4)* %this, i32 0, i32 0 store %spirv.Pipe._1 addrspace(1)* %handle, %spirv.Pipe._1 addrspace(1)* addrspace(4)* %_handle, align 4, !tbaa !13 ret void } ; Function Attrs: nounwind declare spir_func %spirv.Pipe._1 addrspace(1)* @_Z39__spirv_CreatePipeFromPipeStorage_writePU3AS1K19__spirv_PipeStorage(%spirv.PipeStorage addrspace(1)*) !opencl.enable.FP_CONTRACT = !{} !opencl.spir.version = !{!0} !opencl.ocl.version = !{!1} !opencl.used.extensions = !{!2} !opencl.used.optional.core.features = !{!2} !opencl.compiler.options = !{!2} !llvm.ident = !{!3} !spirv.Source = !{!4} !spirv.String = !{} !0 = !{i32 1, i32 2} !1 = !{i32 2, i32 2} !2 = !{} !3 = !{!"clang version 3.6.1 "} !4 = !{i32 4, i32 202000} !6 = !{!7, !8, i64 0} !7 = !{!"_ZTSN2cl12pipe_storageIDv4_iLj1EEE", !8, i64 0} !8 = !{!"any pointer", !9, i64 0} !9 = !{!"omnipotent char", !10, i64 0} !10 = !{!"Simple C/C++ TBAA"} !11 = !{!12, !8, i64 0} !12 = !{!"_ZTSN2cl4pipeIDv4_iLNS_11pipe_accessE0EEE", !8, i64 0} !13 = !{!14, !8, i64 0} !14 = !{!"_ZTSN2cl4pipeIDv4_iLNS_11pipe_accessE1EEE", !8, i64 0} SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/000077500000000000000000000000001363521741200202175ustar00rootroot00000000000000SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/BuiltinCallLocation.cl000066400000000000000000000014121363521741200244300ustar00rootroot00000000000000// Check that DebugLoc attached to a builtin call is preserved after translation. // RUN: %clang_cc1 -triple spir -fdeclare-opencl-builtins -finclude-default-header %s -disable-llvm-passes -emit-llvm-bc -debug-info-kind=line-tables-only -dwarf-column-info -o %t.bc // RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV // RUN: llvm-spirv %t.bc -o %t.spv // RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK-LLVM // CHECK-SPIRV: Label // CHECK-SPIRV: ExtInst {{.*}} DebugScope // CHECK-SPIRV: ExtInst {{.*}} sin // CHECK-LLVM: call spir_func float @_Z3sinf(float %{{.*}}) {{.*}} !dbg ![[loc:[0-9]+]] // CHECK-LLVM: ![[loc]] = !DILocation(line: 14, column: 10, scope: !{{.*}}) float f(float x) { return sin(x); } SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/COFF/000077500000000000000000000000001363521741200207345ustar00rootroot00000000000000SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/COFF/global-dllimport.ll000066400000000000000000000036141363521741200245350ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple < %t.ll | FileCheck %s ; CHECK-NOT: S_GDATA32 source_filename = "test/DebugInfo/COFF/global-dllimport.ll" target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" target triple = "spir64-unknown-unknown" @"\01?id@?$numpunct@D@@0HA" = available_externally dllimport global i32 0, align 4, !dbg !0 !llvm.dbg.cu = !{!2} !llvm.module.flags = !{!14, !15} !llvm.ident = !{!16} !0 = distinct !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = !DIGlobalVariable(name: "id", linkageName: "\01?id@?$numpunct@D@@0HA", scope: !2, file: !6, line: 4, type: !7, isLocal: false, isDefinition: true, declaration: !8) !2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 3.9.0 (trunk 272628) (llvm/trunk 272566)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5) !3 = !DIFile(filename: "/usr/local/google/home/majnemer/Downloads/", directory: "/usr/local/google/home/majnemer/llvm/src") !4 = !{} !5 = !{!0} !6 = !DIFile(filename: "/usr/local/google/home/majnemer/Downloads/t.ii", directory: "/usr/local/google/home/majnemer/llvm/src") !7 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !8 = !DIDerivedType(tag: DW_TAG_member, name: "id", scope: !9, file: !6, line: 2, baseType: !7, flags: DIFlagStaticMember) !9 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "numpunct", file: !6, line: 2, size: 8, align: 8, elements: !10, templateParams: !11) !10 = !{!8} !11 = !{!12} !12 = !DITemplateTypeParameter(type: !13) !13 = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char) !14 = !{i32 2, !"CodeView", i32 1} !15 = !{i32 2, !"Debug Info Version", i32 3} !16 = !{!"clang version 3.9.0 (trunk 272628) (llvm/trunk 272566)"} SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/COFF/no-cus.ll000066400000000000000000000012661363521741200224760ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple < %t.ll -filetype=obj -o %t.o ; RUN: llvm-objdump -section-headers %t.o | FileCheck %s ; Don't emit debug info in this scenario and don't crash. ; CHECK-NOT: .debug$S ; CHECK: .text ; CHECK-NOT: .debug$S ; ModuleID = 't.cpp' source_filename = "t.cpp" target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" target triple = "spir64-unknown-unknown" define void @f() { entry: ret void } !llvm.module.flags = !{!0, !1} !llvm.ident = !{!2} !0 = !{i32 2, !"CodeView", i32 1} !1 = !{i32 1, !"PIC Level", i32 2} !2 = !{!"clang version 5.0.0 "} SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/DebugControlFlow.cl000066400000000000000000000027311363521741200237610ustar00rootroot00000000000000// RUN: %clang_cc1 -triple spir64-unknown-unknown -cl-std=CL2.0 -O0 -debug-info-kind=standalone -emit-llvm %s -o %t.ll // RUN: llvm-as %t.ll -o %t.bc // RUN: llvm-spirv %t.bc -spirv-text -o %t.spt // RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV // RUN: llvm-spirv %t.bc -o %t.spv // RUN: llvm-spirv -r %t.spv -o %t.bc // RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-LLVM // Test that no debug info instruction is inserted // between LoopMerge and Branch/BranchConditional instructions. // Otherwise, debug info interferes with SPIRVToLLVM translation // of structured flow control kernel void sample() { int arr[10]; #pragma clang loop unroll(full) for (int i = 0; i < 10; i++) arr[i] = 0; int j = 0; #pragma clang loop unroll(full) do { arr[j] = 0; } while (j++ < 10); } // Check that all Line items are retained // CHECK-SPIRV: Line [[File:[0-9]+]] 18 0 // Control flow // CHECK-SPIRV: {{[0-9]+}} LoopMerge [[MergeBlock:[0-9]+]] [[ContinueTarget:[0-9]+]] 1 // CHECK-SPIRV-NEXT: BranchConditional // Check that all Line items are retained // CHECK-SPIRV: Line [[File]] 23 0 // CHECK-SPIRV: Line [[File]] 24 0 // Control flow // CHECK-SPIRV: {{[0-9]+}} LoopMerge [[MergeBlock:[0-9]+]] [[ContinueTarget:[0-9]+]] 1 // CHECK-SPIRV-NEXT: Branch // CHECK-LLVM: br label %{{.*}}, !dbg !{{[0-9]+}}, !llvm.loop ![[MD:[0-9]+]] // CHECK-LLVM: ![[MD]] = distinct !{![[MD]], ![[MD_unroll:[0-9]+]]} // CHECK-LLVM: ![[MD_unroll]] = !{!"llvm.loop.unroll.enable"} SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/DebugDeclareUnused.cl000066400000000000000000000014571363521741200242400ustar00rootroot00000000000000// Check that we can translate llvm.dbg.declare for a local variable which was // deleted by mem2reg pass(disabled by default in llvm-spirv) // RUN: %clang_cc1 %s -triple spir -disable-llvm-passes -debug-info-kind=standalone -emit-llvm-bc -o - | llvm-spirv -spirv-mem2reg -o %t.spv // RUN: llvm-spirv %t.spv -to-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV // RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK-LLVM void foo() { int a; } // CHECK-SPIRV: ExtInst {{[0-9]+}} [[None:[0-9]+]] {{[0-9]+}} DebugInfoNone // CHECK-SPIRV: ExtInst {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} DebugDeclare {{[0-9]+}} [[None]] {{[0-9]+}} // CHECK-LLVM: call void @llvm.dbg.declare(metadata ![[VarAddr:[0-9]+]], metadata !{{[0-9]+}}, metadata !DIExpression()) // CHECK-LLVM: ![[VarAddr]] = !{} SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/DebugFunction.cl000066400000000000000000000023761363521741200233030ustar00rootroot00000000000000// Check for 2 things: // - After round trip translation function definition has !dbg metadata attached // specifically if -gline-tables-only was used for Clang // - Parent operand of DebugFunction is DebugCompileUnit, not an OpString, even // if in LLVM IR it points to a DIFile instead of DICompileUnit. // RUN: %clang_cc1 %s -cl-std=clc++ -emit-llvm-bc -triple spir -debug-info-kind=line-tables-only -O0 -o - | llvm-spirv -o %t.spv // RUN: llvm-spirv %t.spv -to-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV // RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK-LLVM float foo(int i) { return i * 3.14; } void kernel k() { float a = foo(2); } // CHECK-SPIRV: String [[foo:[0-9]+]] "foo" // CHECK-SPIRV: String [[k:[0-9]+]] "k" // CHECK-SPIRV: [[CU:[0-9]+]] {{[0-9]+}} DebugCompileUnit // CHECK-SPIRV: DebugFunction [[foo]] {{.*}} [[CU]] {{.*}} [[foo_id:[0-9]+]] {{[0-9]+}} {{$}} // CHECK-SPIRV: DebugFunction [[k]] {{.*}} [[CU]] {{.*}} [[k_id:[0-9]+]] {{[0-9]+}} {{$}} // CHECK-SPIRV: Function {{[0-9]+}} [[foo_id]] // CHECK-LLVM: define spir_func float @_Z3fooi(i32 %i) #{{[0-9]+}} !dbg !{{[0-9]+}} { // CHECK-SPIRV: Function {{[0-9]+}} [[k_id]] // CHECK-LLVM: define spir_kernel void @k() #{{[0-9]+}} !dbg !{{[0-9]+}} SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/DebugUnstructuredControlFlow.cl000066400000000000000000000020401363521741200264020ustar00rootroot00000000000000// RUN: %clang_cc1 -triple spir64-unknown-unknown -cl-std=CL2.0 -O0 -debug-info-kind=standalone -emit-llvm-bc %s -o %t.bc // RUN: llvm-spirv %t.bc --spirv-ext=+SPV_INTEL_unstructured_loop_controls -o %t.spv // RUN: llvm-spirv %t.spv --to-text -o %t.spt // RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV // RUN: llvm-spirv -r %t.spv -o %t.bc // RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-LLVM // Test that no debug info instruction is inserted between LoopControlINTEL and // Branch instructions. Otherwise, debug info interferes with SPIRVToLLVM // translation of structured flow control kernel void sample() { #pragma clang loop unroll(full) for(;;); } // Check that all Line items are retained // CHECK-SPIRV: Line [[File:[0-9]+]] 15 0 // Loop control // CHECK-SPIRV: 2 LoopControlINTEL 1 // CHECK-SPIRV-NEXT: Branch // CHECK-LLVM: br label %{{.*}}, !dbg !{{[0-9]+}}, !llvm.loop ![[MD:[0-9]+]] // CHECK-LLVM: ![[MD]] = distinct !{![[MD]], ![[MD_unroll:[0-9]+]]} // CHECK-LLVM: ![[MD_unroll]] = !{!"llvm.loop.unroll.enable"} SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/000077500000000000000000000000001363521741200215735ustar00rootroot00000000000000SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/2009-11-05-DeadGlobalVariable.ll000066400000000000000000000031611363521741200266020ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple %t.ll -o /dev/null ; Here variable bar is optimized away. Do not trip over while trying to generate debug info. source_filename = "test/DebugInfo/Generic/2009-11-05-DeadGlobalVariable.ll" ; Function Attrs: nounwind readnone ssp uwtable define i32 @foo() #0 !dbg !6 { entry: ret i32 42, !dbg !11 } attributes #0 = { nounwind readnone ssp uwtable } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!10} !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.0 (trunk 139632)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !3) !1 = !DIFile(filename: "fb.c", directory: "/private/tmp") !2 = !{} !3 = !{!4} !4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression()) !5 = !DIGlobalVariable(name: "bar", scope: !6, file: !1, line: 2, type: !9, isLocal: true, isDefinition: true) !6 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: true, unit: !0) !7 = !DISubroutineType(types: !8) !8 = !{!9} !9 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !10 = !{i32 1, !"Debug Info Version", i32 3} !11 = !DILocation(line: 3, column: 3, scope: !12) !12 = distinct !DILexicalBlock(scope: !6, file: !1, line: 1, column: 11) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/2009-11-06-NamelessGlobalVariable.ll000066400000000000000000000021151363521741200275130ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple %t.ll -o /dev/null source_filename = "test/DebugInfo/Generic/2009-11-06-NamelessGlobalVariable.ll" @0 = internal constant i32 1, !dbg !0 !llvm.dbg.cu = !{!4} !llvm.module.flags = !{!7} !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = !DIGlobalVariable(name: "a", scope: null, file: !2, line: 2, type: !3, isLocal: false, isDefinition: true) !2 = !DIFile(filename: "g.c", directory: "/private/tmp") !3 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !4 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang version 3.0 (trunk 139632)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6) !5 = !{} !6 = !{!0} !7 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/2009-11-10-CurrentFn.ll000066400000000000000000000032151363521741200250600ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple < %t.ll -o /dev/null define void @bar(i32 %i) nounwind uwtable ssp !dbg !5 { entry: tail call void (...) @foo() nounwind, !dbg !14 ret void, !dbg !16 } declare void @foo(...) declare void @llvm.dbg.value(metadata, metadata, metadata) nounwind readnone !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!18} !0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.0 (trunk 139632)", isOptimized: true, emissionKind: FullDebug, file: !17, enums: !1, retainedTypes: !1, globals: !1) !1 = !{} !5 = distinct !DISubprogram(name: "bar", line: 3, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, file: !17, scope: !6, type: !7, retainedNodes: !9) !6 = !DIFile(filename: "cf.c", directory: "/private/tmp") !7 = !DISubroutineType(types: !8) !8 = !{null} !9 = !{!11} !11 = !DILocalVariable(name: "i", line: 3, arg: 1, scope: !5, file: !17, type: !12) !12 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !13 = !DILocation(line: 3, column: 14, scope: !5) !14 = !DILocation(line: 4, column: 3, scope: !15) !15 = distinct !DILexicalBlock(line: 3, column: 17, file: !17, scope: !5) !16 = !DILocation(line: 5, column: 1, scope: !15) !17 = !DIFile(filename: "cf.c", directory: "/private/tmp") !18 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/2010-01-05-DbgScope.ll000066400000000000000000000026611363521741200246370ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple < %t.ll -o /dev/null ; PR 5942 define i8* @foo() nounwind { entry: %0 = load i32, i32* undef, align 4, !dbg !0 ; [#uses=1] %1 = inttoptr i32 %0 to i8*, !dbg !0 ; [#uses=1] ret i8* %1, !dbg !10 } !llvm.dbg.cu = !{!3} !llvm.module.flags = !{!14} !0 = !DILocation(line: 571, column: 3, scope: !1) !1 = distinct !DILexicalBlock(line: 1, column: 1, file: !11, scope: !2) !2 = distinct !DISubprogram(name: "foo", linkageName: "foo", file: !11, line: 561, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !3, scope: !3, type: !4) !3 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang 1.1", isOptimized: true, emissionKind: FullDebug, file: !11, enums: !12, retainedTypes: !12) !4 = !DISubroutineType(types: !5) !5 = !{!6} !6 = !DIBasicType(tag: DW_TAG_base_type, name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char) !10 = !DILocation(line: 588, column: 1, scope: !2) !11 = !DIFile(filename: "hashtab.c", directory: "/usr/src/gnu/usr.bin/cc/cc_tools/../../../../contrib/gcclibs/libiberty") !12 = !{} !14 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/2010-03-12-llc-crash.ll000066400000000000000000000027521363521741200250220ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 < %t.ll -o /dev/null ; llc should not crash on this optimized out debug info. ; PR6588 declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone define void @foo() { entry: call void @llvm.dbg.declare(metadata i32* undef, metadata !0, metadata !DIExpression()), !dbg !DILocation(scope: !1) ret void } !llvm.dbg.cu = !{!3} !0 = !DILocalVariable(name: "sy", line: 890, arg: 1, scope: !1, file: !2, type: !7) !1 = distinct !DISubprogram(name: "foo", linkageName: "foo", line: 892, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !3, file: !8, scope: !3, type: !4) !2 = !DIFile(filename: "qpainter.h", directory: "QtGui") !3 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang 1.1", isOptimized: true, emissionKind: FullDebug, file: !9, enums: !10, retainedTypes: !10) !4 = !DISubroutineType(types: !6) !5 = !DIFile(filename: "splineeditor.cpp", directory: "src") !6 = !{null} !7 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !8 = !DIFile(filename: "qpainter.h", directory: "QtGui") !9 = !DIFile(filename: "splineeditor.cpp", directory: "src") !10 = !{i32 0} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/2010-03-24-MemberFn.ll000066400000000000000000000104751363521741200246510ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 < %t.ll | grep AT_decl_file | grep 2 ; Here _ZN1S3fooEv is defined in header file identified as AT_decl_file no. 2 in debug info. %struct.S = type <{ i8 }> define i32 @_Z3barv() nounwind ssp !dbg !3 { entry: %retval = alloca i32 ; [#uses=2] %0 = alloca i32 ; [#uses=2] %s1 = alloca %struct.S ; <%struct.S*> [#uses=1] %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] call void @llvm.dbg.declare(metadata %struct.S* %s1, metadata !0, metadata !DIExpression()), !dbg !16 %1 = call i32 @_ZN1S3fooEv(%struct.S* %s1) nounwind, !dbg !17 ; [#uses=1] store i32 %1, i32* %0, align 4, !dbg !17 %2 = load i32, i32* %0, align 4, !dbg !17 ; [#uses=1] store i32 %2, i32* %retval, align 4, !dbg !17 br label %return, !dbg !17 return: ; preds = %entry %retval1 = load i32, i32* %retval, !dbg !17 ; [#uses=1] ret i32 %retval1, !dbg !16 } define linkonce_odr i32 @_ZN1S3fooEv(%struct.S* %this) nounwind ssp align 2 !dbg !12 { entry: %this_addr = alloca %struct.S* ; <%struct.S**> [#uses=1] %retval = alloca i32 ; [#uses=1] %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] call void @llvm.dbg.declare(metadata %struct.S** %this_addr, metadata !18, metadata !DIExpression(DW_OP_deref)), !dbg !21 store %struct.S* %this, %struct.S** %this_addr br label %return, !dbg !21 return: ; preds = %entry %retval1 = load i32, i32* %retval, !dbg !21 ; [#uses=1] ret i32 %retval1, !dbg !22 } declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone !llvm.dbg.cu = !{!5} !llvm.module.flags = !{!28} !0 = !DILocalVariable(name: "s1", line: 3, scope: !1, file: !4, type: !9) !1 = distinct !DILexicalBlock(line: 3, column: 0, file: !25, scope: !2) !2 = distinct !DILexicalBlock(line: 3, column: 0, file: !25, scope: !3) !3 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", line: 3, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !5, scopeLine: 3, file: !25, scope: !4, type: !6) !4 = !DIFile(filename: "one.cc", directory: "/tmp/") !5 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "4.2.1 (Based on Apple Inc. build 5658) (LLVM build)", isOptimized: false, emissionKind: FullDebug, file: !25, enums: !27, retainedTypes: !27, imports: null) !6 = !DISubroutineType(types: !7) !7 = !{!8} !8 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !9 = !DICompositeType(tag: DW_TAG_structure_type, name: "S", line: 2, size: 8, align: 8, file: !26, scope: !4, elements: !11) !10 = !DIFile(filename: "one.h", directory: "/tmp/") !11 = !{!12} !12 = distinct !DISubprogram(name: "foo", linkageName: "_ZN1S3fooEv", line: 3, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !5, scopeLine: 3, file: !26, scope: !9, type: !13) !13 = !DISubroutineType(types: !14) !14 = !{!8, !15} !15 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, flags: DIFlagArtificial, file: !25, scope: !4, baseType: !9) !16 = !DILocation(line: 3, scope: !1) !17 = !DILocation(line: 3, scope: !3) ; Modified from being a pointer, to make this testcase independent of target pointer size !18 = !DILocalVariable(name: "this", line: 3, arg: 1, scope: !12, file: !10, type: !9) !19 = !DIDerivedType(tag: DW_TAG_const_type, size: 64, align: 64, flags: DIFlagArtificial, file: !25, scope: !4, baseType: !20) !20 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, file: !25, scope: !4, baseType: !9) !21 = !DILocation(line: 3, scope: !12) !22 = !DILocation(line: 3, scope: !23) !23 = distinct !DILexicalBlock(line: 3, column: 0, file: !26, scope: !12) !25 = !DIFile(filename: "one.cc", directory: "/tmp/") !26 = !DIFile(filename: "one.h", directory: "/tmp/") !27 = !{} !28 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/2010-04-19-FramePtr.ll000066400000000000000000000043301363521741200246740ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -debugger-tune=lldb -asm-verbose -O1 -o - < %t.ll | FileCheck %s ; RUN: llc -mtriple=%triple -debugger-tune=gdb -asm-verbose -O1 -o - < %t.ll | FileCheck %s --check-prefix=DISABLE ; RUN: llc -mtriple=%triple -frame-pointer=all -debugger-tune=lldb -asm-verbose -O1 -o - < %t.ll | FileCheck %s --check-prefix=DISABLE ; CHECK: DW_AT_APPLE_omit_frame_ptr ; DISABLE-NOT: DW_AT_APPLE_omit_frame_ptr define i32 @foo() nounwind ssp !dbg !1 { entry: %retval = alloca i32 ; [#uses=2] %0 = alloca i32 ; [#uses=2] %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] store i32 42, i32* %0, align 4, !dbg !0 %1 = load i32, i32* %0, align 4, !dbg !0 ; [#uses=1] store i32 %1, i32* %retval, align 4, !dbg !0 br label %return, !dbg !0 return: ; preds = %entry %retval1 = load i32, i32* %retval, !dbg !0 ; [#uses=1] ret i32 %retval1, !dbg !7 } !llvm.dbg.cu = !{!3} !llvm.module.flags = !{!12} !9 = !{!1} !0 = !DILocation(line: 2, scope: !1) !1 = distinct !DISubprogram(name: "foo", linkageName: "foo", line: 2, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !3, scopeLine: 2, file: !10, scope: null, type: !4) !2 = !DIFile(filename: "a.c", directory: "/tmp") !3 = distinct !DICompileUnit(language: DW_LANG_C89, producer: "4.2.1 (Based on Apple Inc. build 5658) (LLVM build)", isOptimized: false, emissionKind: FullDebug, file: !10, enums: !11, retainedTypes: !11, imports: null) !4 = !DISubroutineType(types: !5) !5 = !{!6} !6 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !7 = !DILocation(line: 2, scope: !8) !8 = distinct !DILexicalBlock(line: 2, column: 0, file: !10, scope: !1) !10 = !DIFile(filename: "a.c", directory: "/tmp") !11 = !{} !12 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/2010-06-29-InlinedFnLocalVar.ll000066400000000000000000000064751363521741200264650ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O2 %t.ll -o - | FileCheck %s ; Check struct X for dead variable xyz from inlined function foo. ; CHECK: debug_info, ; CHECK: DW_TAG_structure_type ; CHECK-NEXT: DW_AT_name source_filename = "test/DebugInfo/Generic/2010-06-29-InlinedFnLocalVar.ll" @i = common global i32 0, !dbg !0 ; Function Attrs: nounwind readnone declare void @llvm.dbg.declare(metadata, metadata, metadata) #0 ; Function Attrs: nounwind readnone declare void @llvm.dbg.value(metadata, metadata, metadata) #0 ; Function Attrs: nounwind ssp define i32 @bar() #1 !dbg !8 { entry: %0 = load i32, i32* @i, align 4, !dbg !11 tail call void @llvm.dbg.value(metadata i32 %0, metadata !13, metadata !24), !dbg !25 tail call void @llvm.dbg.declare(metadata !5, metadata !18, metadata !24), !dbg !26 %1 = mul nsw i32 %0, %0, !dbg !27 store i32 %1, i32* @i, align 4, !dbg !11 ret i32 %1, !dbg !28 } attributes #0 = { nounwind readnone } attributes #1 = { nounwind ssp } !llvm.dbg.cu = !{!4} !llvm.module.flags = !{!7} !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = !DIGlobalVariable(name: "i", scope: !2, file: !2, line: 5, type: !3, isLocal: false, isDefinition: true) !2 = !DIFile(filename: "bar.c", directory: "/tmp/") !3 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !4 = distinct !DICompileUnit(language: DW_LANG_C89, file: !2, producer: "4.2.1 (Based on Apple Inc. build 5658) (LLVM build)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !5) !5 = !{} !6 = !{!0} !7 = !{i32 1, !"Debug Info Version", i32 3} !8 = distinct !DISubprogram(name: "bar", linkageName: "bar", scope: !2, file: !2, line: 14, type: !9, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: true, unit: !4) !9 = !DISubroutineType(types: !10) !10 = !{!3} !11 = !DILocation(line: 15, scope: !12) !12 = distinct !DILexicalBlock(scope: !8, file: !2, line: 14) !13 = !DILocalVariable(name: "j", arg: 1, scope: !14, file: !2, line: 9, type: !3) !14 = distinct !DISubprogram(name: "foo", scope: !2, file: !2, line: 9, type: !15, isLocal: true, isDefinition: true, scopeLine: 9, virtualIndex: 6, isOptimized: true, unit: !4, retainedNodes: !17) !15 = !DISubroutineType(types: !16) !16 = !{!3, !3} !17 = !{!13, !18} !18 = !DILocalVariable(name: "xyz", scope: !19, file: !2, line: 10, type: !20) !19 = distinct !DILexicalBlock(scope: !14, file: !2, line: 9) !20 = !DICompositeType(tag: DW_TAG_structure_type, name: "X", scope: !14, file: !2, line: 10, size: 64, align: 32, elements: !21) !21 = !{!22, !23} !22 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !20, file: !2, line: 10, baseType: !3, size: 32, align: 32) !23 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !20, file: !2, line: 10, baseType: !3, size: 32, align: 32, offset: 32) !24 = !DIExpression() !25 = !DILocation(line: 9, scope: !14, inlinedAt: !11) !26 = !DILocation(line: 9, scope: !19, inlinedAt: !11) !27 = !DILocation(line: 11, scope: !19, inlinedAt: !11) !28 = !DILocation(line: 16, scope: !12) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/2010-10-01-crash.ll000066400000000000000000000032771363521741200242510ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 %t.ll -o /dev/null define void @CGRectStandardize(i32* sret %agg.result, i32* byval %rect) nounwind ssp !dbg !0 { entry: call void @llvm.dbg.declare(metadata i32* %rect, metadata !23, metadata !DIExpression()), !dbg !24 ret void } declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind !llvm.dbg.cu = !{!2} !llvm.module.flags = !{!27} !0 = distinct !DISubprogram(name: "CGRectStandardize", linkageName: "CGRectStandardize", line: 54, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !2, file: !1, scope: null, type: !28) !1 = !DIFile(filename: "GSFusedSilica.m", directory: "/Volumes/Data/Users/sabre/Desktop") !2 = distinct !DICompileUnit(language: DW_LANG_ObjC, producer: "clang version 2.9 (trunk 115292)", isOptimized: true, runtimeVersion: 1, emissionKind: FullDebug, file: !25, enums: !26, retainedTypes: !26) !5 = !DIDerivedType(tag: DW_TAG_typedef, name: "CGRect", line: 49, file: !25, baseType: null) !23 = !DILocalVariable(name: "rect", line: 53, arg: 2, scope: !0, file: !1, type: !5) !24 = !DILocation(line: 53, column: 33, scope: !0) !25 = !DIFile(filename: "GSFusedSilica.m", directory: "/Volumes/Data/Users/sabre/Desktop") !26 = !{} !27 = !{i32 1, !"Debug Info Version", i32 3} !28 = !DISubroutineType(types: !29) !29 = !{null} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/PR20038.ll000066400000000000000000000210361363521741200230440ustar00rootroot00000000000000; REQUIRES: object-emission ; For some reason, the output when targetting sparc is not quite as expected. ; XFAIL: sparc ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 -filetype=obj -dwarf-linkage-names=All < %t.ll | llvm-dwarfdump -v -debug-info - | FileCheck %s ; IR generated from clang -O0 with: ; struct C { ; ~C(); ; }; ; extern bool b; ; void fun4() { b && (C(), 1); } ; __attribute__((always_inline)) C::~C() { } ; CHECK: DW_TAG_structure_type ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "C" ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_subprogram ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "~C" ; CHECK: DW_TAG_subprogram ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_linkage_name {{.*}} "_ZN1CD1Ev" ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_formal_parameter ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "this" ; CHECK: DW_TAG_subprogram ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "fun4" ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_inlined_subroutine ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_abstract_origin {{.*}} "_ZN1CD1Ev" ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_formal_parameter ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_abstract_origin {{.*}} "this" ; FIXME: D2 is actually inlined into D1 but doesn't show up here, possibly due ; to there being no work in D2 (calling another member function from the dtor ; causes D2 to show up, calling a free function doesn't). ; CHECK-NOT: DW_TAG ; CHECK: NULL ; CHECK-NOT: DW_TAG ; CHECK: NULL %struct.C = type { i8 } @b = external global i8 ; Function Attrs: nounwind define void @_Z4fun4v() #0 !dbg !12 { entry: %this.addr.i.i = alloca %struct.C*, align 8, !dbg !21 %this.addr.i = alloca %struct.C*, align 8, !dbg !22 %agg.tmp.ensured = alloca %struct.C, align 1 %cleanup.cond = alloca i1 %0 = load i8, i8* @b, align 1, !dbg !24 %tobool = trunc i8 %0 to i1, !dbg !24 store i1 false, i1* %cleanup.cond br i1 %tobool, label %land.rhs, label %land.end, !dbg !24 land.rhs: ; preds = %entry store i1 true, i1* %cleanup.cond, !dbg !25 br label %land.end land.end: ; preds = %land.rhs, %entry %1 = phi i1 [ false, %entry ], [ true, %land.rhs ] %cleanup.is_active = load i1, i1* %cleanup.cond, !dbg !27 br i1 %cleanup.is_active, label %cleanup.action, label %cleanup.done, !dbg !27 cleanup.action: ; preds = %land.end store %struct.C* %agg.tmp.ensured, %struct.C** %this.addr.i, align 8, !dbg !22 call void @llvm.dbg.declare(metadata %struct.C** %this.addr.i, metadata !129, metadata !DIExpression()), !dbg !31 %this1.i = load %struct.C*, %struct.C** %this.addr.i, !dbg !22 store %struct.C* %this1.i, %struct.C** %this.addr.i.i, align 8, !dbg !21 call void @llvm.dbg.declare(metadata %struct.C** %this.addr.i.i, metadata !132, metadata !DIExpression()), !dbg !33 %this1.i.i = load %struct.C*, %struct.C** %this.addr.i.i, !dbg !21 br label %cleanup.done, !dbg !22 cleanup.done: ; preds = %cleanup.action, %land.end ret void, !dbg !34 } ; Function Attrs: alwaysinline nounwind define void @_ZN1CD1Ev(%struct.C* %this) unnamed_addr #1 align 2 !dbg !17 { entry: %this.addr.i = alloca %struct.C*, align 8, !dbg !37 %this.addr = alloca %struct.C*, align 8 store %struct.C* %this, %struct.C** %this.addr, align 8 call void @llvm.dbg.declare(metadata %struct.C** %this.addr, metadata !29, metadata !DIExpression()), !dbg !38 %this1 = load %struct.C*, %struct.C** %this.addr store %struct.C* %this1, %struct.C** %this.addr.i, align 8, !dbg !37 call void @llvm.dbg.declare(metadata %struct.C** %this.addr.i, metadata !232, metadata !DIExpression()), !dbg !39 %this1.i = load %struct.C*, %struct.C** %this.addr.i, !dbg !37 ret void, !dbg !37 } ; Function Attrs: alwaysinline nounwind define void @_ZN1CD2Ev(%struct.C* %this) unnamed_addr #1 align 2 !dbg !16 { entry: %this.addr = alloca %struct.C*, align 8 store %struct.C* %this, %struct.C** %this.addr, align 8 call void @llvm.dbg.declare(metadata %struct.C** %this.addr, metadata !32, metadata !DIExpression()), !dbg !40 %this1 = load %struct.C*, %struct.C** %this.addr ret void, !dbg !41 } ; Function Attrs: nounwind readnone declare void @llvm.dbg.declare(metadata, metadata, metadata) #2 attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { alwaysinline nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #2 = { nounwind readnone } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!18, !19} !llvm.ident = !{!20} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.5.0 ", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !3, globals: !2, imports: !2) !1 = !DIFile(filename: "", directory: "/tmp/dbginfo") !2 = !{} !3 = !{!4} !4 = !DICompositeType(tag: DW_TAG_structure_type, name: "C", line: 1, size: 8, align: 8, file: !5, elements: !6, identifier: "_ZTS1C") !5 = !DIFile(filename: "PR20038.cpp", directory: "/tmp/dbginfo") !6 = !{!7} !7 = !DISubprogram(name: "~C", line: 2, isLocal: false, isDefinition: false, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, scopeLine: 2, file: !5, scope: !4, type: !8) !8 = !DISubroutineType(types: !9) !9 = !{null, !10} !10 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer, baseType: !4) !12 = distinct !DISubprogram(name: "fun4", linkageName: "_Z4fun4v", line: 5, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 5, file: !5, scope: !13, type: !14, retainedNodes: !2) !13 = !DIFile(filename: "PR20038.cpp", directory: "/tmp/dbginfo") !14 = !DISubroutineType(types: !15) !15 = !{null} !16 = distinct !DISubprogram(name: "~C", linkageName: "_ZN1CD2Ev", line: 6, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 6, file: !5, scope: !4, type: !8, declaration: !7, retainedNodes: !2) !17 = distinct !DISubprogram(name: "~C", linkageName: "_ZN1CD1Ev", line: 6, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 6, file: !5, scope: !4, type: !8, declaration: !7, retainedNodes: !2) !18 = !{i32 2, !"Dwarf Version", i32 4} !19 = !{i32 2, !"Debug Info Version", i32 3} !20 = !{!"clang version 3.5.0 "} !21 = !DILocation(line: 6, scope: !17, inlinedAt: !22) !22 = !DILocation(line: 5, scope: !23) !23 = distinct !DILexicalBlock(line: 5, column: 0, file: !5, scope: !12) !24 = !DILocation(line: 5, scope: !12) !25 = !DILocation(line: 5, scope: !26) !26 = distinct !DILexicalBlock(line: 5, column: 0, file: !5, scope: !12) !27 = !DILocation(line: 5, scope: !28) !28 = distinct !DILexicalBlock(line: 5, column: 0, file: !5, scope: !12) !29 = !DILocalVariable(name: "this", arg: 1, flags: DIFlagArtificial | DIFlagObjectPointer, scope: !17, type: !30) !30 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, baseType: !4) !31 = !DILocation(line: 0, scope: !17, inlinedAt: !22) !32 = !DILocalVariable(name: "this", arg: 1, flags: DIFlagArtificial | DIFlagObjectPointer, scope: !16, type: !30) !33 = !DILocation(line: 0, scope: !16, inlinedAt: !21) !129 = !DILocalVariable(name: "this", arg: 1, flags: DIFlagArtificial | DIFlagObjectPointer, scope: !17, type: !30) !132 = !DILocalVariable(name: "this", arg: 1, flags: DIFlagArtificial | DIFlagObjectPointer, scope: !16, type: !30) !232 = !DILocalVariable(name: "this", arg: 1, flags: DIFlagArtificial | DIFlagObjectPointer, scope: !16, type: !30) !34 = !DILocation(line: 5, scope: !35) !35 = distinct !DILexicalBlock(line: 5, column: 0, file: !5, scope: !36) !36 = distinct !DILexicalBlock(line: 5, column: 0, file: !5, scope: !12) !37 = !DILocation(line: 6, scope: !17) !38 = !DILocation(line: 0, scope: !17) !39 = !DILocation(line: 0, scope: !16, inlinedAt: !37) !40 = !DILocation(line: 0, scope: !16) !41 = !DILocation(line: 6, scope: !16) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/bug_null_debuginfo.ll000066400000000000000000000011201363521741200257470ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple < %t.ll !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!2} !0 = distinct !DICompileUnit(language: DW_LANG_C99, isOptimized: false, emissionKind: FullDebug, file: !1, globals: null) !1 = !DIFile(filename: "t", directory: "") !2 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/constant-pointers.ll000066400000000000000000000055541363521741200256270ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 -filetype=obj %t.ll -o - | llvm-dwarfdump -v -debug-info - | FileCheck %s ; Ensure that pointer constants are emitted as unsigned data. Alternatively, ; these could be signless data (dataN). ; Built with Clang from: ; template ; void func() {} ; template void func(); ; CHECK: DW_TAG_subprogram ; CHECK: DW_TAG_template_value_parameter ; CHECK: DW_AT_name {{.*}} "V" ; CHECK: DW_AT_const_value [DW_FORM_udata] (0) ; CHECK: DW_TAG_template_value_parameter ; CHECK: DW_AT_name {{.*}} "F" ; CHECK: DW_AT_const_value [DW_FORM_udata] (0) ; Function Attrs: nounwind uwtable define weak_odr void @_Z4funcILPv0ELPFvvE0ELi42EEvv() #0 !dbg !4 { entry: ret void, !dbg !18 } attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!15, !16} !llvm.ident = !{!17} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.5.0 ", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) !1 = !DIFile(filename: "constant-pointers.cpp", directory: "/tmp/dbginfo") !2 = !{} !4 = distinct !DISubprogram(name: "func", linkageName: "_Z4funcILPv0ELPFvvE0ELi42EEvv", line: 2, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 2, file: !1, scope: !5, type: !6, templateParams: !8, retainedNodes: !2) !5 = !DIFile(filename: "constant-pointers.cpp", directory: "/tmp/dbginfo") !6 = !DISubroutineType(types: !7) !7 = !{null} !8 = !{!9, !11, !13} !9 = !DITemplateValueParameter(tag: DW_TAG_template_value_parameter, name: "V", type: !10, value: i8 0) !10 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, baseType: null) !11 = !DITemplateValueParameter(tag: DW_TAG_template_value_parameter, name: "F", type: !12, value: i8 0) !12 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, baseType: !6) !13 = !DITemplateValueParameter(tag: DW_TAG_template_value_parameter, name: "i", type: !14, value: i32 42) !14 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !15 = !{i32 2, !"Dwarf Version", i32 4} !16 = !{i32 2, !"Debug Info Version", i32 3} !17 = !{!"clang version 3.5.0 "} !18 = !DILocation(line: 3, scope: !4) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/dead-argument-order.ll000066400000000000000000000075311363521741200257600ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 -filetype=obj < %t.ll | llvm-dwarfdump -v -debug-info - | FileCheck %s ; Built from the following source with clang -O1 ; struct S { int i; }; ; int function(struct S s, int i) { return s.i + i; } ; Due to the X86_64 ABI, 's' is passed in registers and once optimized, the ; entirety of 's' is never reconstituted, since only the int is required, and ; thus the variable's location is unknown/dead to debug info. ; Future/current work should enable us to describe partial variables, which, in ; this case, happens to be the entire variable. ; CHECK: DW_TAG_subprogram ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "function" ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_formal_parameter ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "s" ; CHECK-NOT: DW_TAG ; FIXME: Even though 's' is never reconstituted into a struct, the one member ; variable is still live and used, and so we should be able to describe 's's ; location as the location of that int. ; CHECK-NOT: DW_AT_location ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_formal_parameter ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_location ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "i" %struct.S = type { i32 } ; Function Attrs: nounwind readnone uwtable define i32 @_Z8function1Si(i32 %s.coerce, i32 %i) #0 !dbg !9 { entry: tail call void @llvm.dbg.declare(metadata %struct.S* undef, metadata !14, metadata !DIExpression()), !dbg !20 tail call void @llvm.dbg.value(metadata i32 %i, metadata !15, metadata !DIExpression()), !dbg !20 %add = add nsw i32 %i, %s.coerce, !dbg !20 ret i32 %add, !dbg !20 } ; Function Attrs: nounwind readnone declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 ; Function Attrs: nounwind readnone declare void @llvm.dbg.value(metadata, metadata, metadata) #1 attributes #0 = { nounwind readnone uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { nounwind readnone } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!16, !17} !llvm.ident = !{!18} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.5.0 ", isOptimized: true, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !3, globals: !2, imports: !2) !1 = !DIFile(filename: "dead-argument-order.cpp", directory: "/tmp/dbginfo") !2 = !{} !3 = !{!4} !4 = !DICompositeType(tag: DW_TAG_structure_type, name: "S", line: 1, size: 32, align: 32, file: !1, elements: !5, identifier: "_ZTS1S") !5 = !{!6} !6 = !DIDerivedType(tag: DW_TAG_member, name: "i", line: 1, size: 32, align: 32, file: !1, scope: !4, baseType: !7) !7 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !9 = distinct !DISubprogram(name: "function", linkageName: "_Z8function1Si", line: 2, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 2, file: !1, scope: !10, type: !11, retainedNodes: !13) !10 = !DIFile(filename: "dead-argument-order.cpp", directory: "/tmp/dbginfo") !11 = !DISubroutineType(types: !12) !12 = !{!7, !4, !7} !13 = !{!14, !15} !14 = !DILocalVariable(name: "s", line: 2, arg: 1, scope: !9, file: !10, type: !4) !15 = !DILocalVariable(name: "i", line: 2, arg: 2, scope: !9, file: !10, type: !7) !16 = !{i32 2, !"Dwarf Version", i32 4} !17 = !{i32 2, !"Debug Info Version", i32 3} !18 = !{!"clang version 3.5.0 "} !19 = !{%struct.S* undef} !20 = !DILocation(line: 2, scope: !9) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/def-line.ll000066400000000000000000000113131363521741200236060ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple < %t.ll -filetype=obj | llvm-dwarfdump -debug-info - | FileCheck %s ; Given the following source, ensure that the decl_line/file is correctly ; emitted and omitted on definitions if it mismatches/matches the declaration ; struct foo { ; static void f1() { ; } ; static void f2(); ; static void f3(); ; }; ; void foo::f2() { ; f1(); // just to ensure f1 is emitted ; } ; #line 1 "bar.cpp" ; void foo::f3() { ; } ; Skip the declarations ; CHECK: DW_TAG_subprogram ; CHECK: DW_TAG_subprogram ; CHECK: DW_TAG_subprogram ; CHECK: DW_TAG_subprogram ; CHECK-NOT: {{DW_TAG|NULL|DW_AT_decl_file}} ; CHECK: DW_AT_decl_line {{.*}}7 ; CHECK-NOT: {{DW_TAG|NULL|DW_AT_decl_file}} ; CHECK: DW_AT_specification {{.*}}f2 ; CHECK-NOT: {{DW_TAG|NULL|DW_AT_decl_file}} ; CHECK: DW_TAG_subprogram ; CHECK-NOT: {{DW_TAG|NULL|DW_AT_decl_line|DW_AT_decl_file}} ; CHECK: DW_AT_specification {{.*}}f1 ; CHECK: DW_TAG_subprogram ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_AT_decl_file {{.*}}bar.cpp ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_AT_decl_line {{.*}}1 ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_AT_specification {{.*}}f3 ; Function Attrs: uwtable define void @_ZN3foo2f2Ev() #0 align 2 !dbg !12 { entry: call void @_ZN3foo2f1Ev(), !dbg !19 ret void, !dbg !20 } ; Function Attrs: nounwind uwtable define linkonce_odr void @_ZN3foo2f1Ev() #1 align 2 !dbg !15 { entry: ret void, !dbg !21 } ; Function Attrs: nounwind uwtable define void @_ZN3foo2f3Ev() #1 align 2 !dbg !13 { entry: ret void, !dbg !22 } attributes #0 = { uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!16, !17} !llvm.ident = !{!18} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.8.0 (trunk 249440) (llvm/trunk 249465)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3) !1 = !DIFile(filename: "def-line.cpp", directory: "/tmp/dbginfo") !2 = !{} !3 = !{!4} !4 = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", file: !1, line: 1, size: 8, align: 8, elements: !5, identifier: "_ZTS3foo") !5 = !{!6, !9, !10} !6 = !DISubprogram(name: "f1", linkageName: "_ZN3foo2f1Ev", scope: !4, file: !1, line: 2, type: !7, isLocal: false, isDefinition: false, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false) !7 = !DISubroutineType(types: !8) !8 = !{null} !9 = !DISubprogram(name: "f2", linkageName: "_ZN3foo2f2Ev", scope: !4, file: !1, line: 4, type: !7, isLocal: false, isDefinition: false, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false) !10 = !DISubprogram(name: "f3", linkageName: "_ZN3foo2f3Ev", scope: !4, file: !1, line: 5, type: !7, isLocal: false, isDefinition: false, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: false) !12 = distinct !DISubprogram(name: "f2", linkageName: "_ZN3foo2f2Ev", scope: !4, file: !1, line: 7, type: !7, isLocal: false, isDefinition: true, scopeLine: 7, flags: DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !9, retainedNodes: !2) !13 = distinct !DISubprogram(name: "f3", linkageName: "_ZN3foo2f3Ev", scope: !4, file: !14, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !10, retainedNodes: !2) !14 = !DIFile(filename: "bar.cpp", directory: "/tmp/dbginfo") !15 = distinct !DISubprogram(name: "f1", linkageName: "_ZN3foo2f1Ev", scope: !4, file: !1, line: 2, type: !7, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !6, retainedNodes: !2) !16 = !{i32 2, !"Dwarf Version", i32 4} !17 = !{i32 2, !"Debug Info Version", i32 3} !18 = !{!"clang version 3.8.0 (trunk 249440) (llvm/trunk 249465)"} !19 = !DILocation(line: 8, column: 3, scope: !12) !20 = !DILocation(line: 9, column: 1, scope: !12) !21 = !DILocation(line: 3, column: 3, scope: !15) !22 = !DILocation(line: 2, column: 1, scope: !13) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/discriminator.ll000066400000000000000000000054031363521741200247750ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple < %t.ll -filetype=obj | llvm-dwarfdump -debug-info - | FileCheck %s ; Given the following source, ensure that the discriminator is emitted for ; the inlined callsite. ;void xyz(); ;static void __attribute__((always_inline)) bar() { xyz(); } ;void foo() { ; bar(); bar(); ;} ;CHECK: DW_TAG_inlined_subroutine ;CHECK-NOT: DW_AT_GNU_discriminator ;CHECK: DW_TAG_inlined_subroutine ;CHECK-NOT: {{DW_TAG|NULL}} ;CHECK: DW_AT_GNU_discriminator{{.*}}0x01 ; Function Attrs: uwtable define void @_Z3foov() #0 !dbg !4 { tail call void @_Z3xyzv(), !dbg !11 tail call void @_Z3xyzv(), !dbg !13 ret void, !dbg !16 } declare void @_Z3xyzv() #1 attributes #0 = { uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!8, !9} !llvm.ident = !{!10} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.8.0 (trunk 252497)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) !1 = !DIFile(filename: "a.cc", directory: "/tmp") !2 = !{} !4 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !1, file: !1, line: 3, type: !5, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2) !5 = !DISubroutineType(types: !6) !6 = !{null} !7 = distinct !DISubprogram(name: "bar", linkageName: "_ZL3barv", scope: !1, file: !1, line: 2, type: !5, isLocal: true, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2) !8 = !{i32 2, !"Dwarf Version", i32 4} !9 = !{i32 2, !"Debug Info Version", i32 3} !10 = !{!"clang version 3.8.0 (trunk 252497)"} !11 = !DILocation(line: 2, column: 52, scope: !7, inlinedAt: !12) !12 = distinct !DILocation(line: 4, column: 3, scope: !4) !13 = !DILocation(line: 2, column: 52, scope: !7, inlinedAt: !14) !14 = distinct !DILocation(line: 4, column: 10, scope: !15) !15 = !DILexicalBlockFile(scope: !4, file: !1, discriminator: 1) !16 = !DILocation(line: 5, column: 1, scope: !4) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/dwarf-public-names.ll000066400000000000000000000161201363521741200256040ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -debugger-tune=gdb -filetype=obj -o %t.o < %t.ll ; RUN: llvm-dwarfdump -debug-pubnames %t.o | FileCheck %s ; ModuleID = 'dwarf-public-names.cpp' ; ; Generated from: ; ; struct C { ; void member_function(); ; static int static_member_function(); ; static int static_member_variable; ; }; ; ; int C::static_member_variable = 0; ; ; void C::member_function() { ; static_member_variable = 0; ; } ; ; int C::static_member_function() { ; return static_member_variable; ; } ; ; C global_variable; ; ; int global_function() { ; return -1; ; } ; ; namespace ns { ; void global_namespace_function() { ; global_variable.member_function(); ; } ; int global_namespace_variable = 1; ; } ; Skip the output to the header of the pubnames section. ; CHECK: debug_pubnames ; CHECK: version = 0x0002 ; Check for each name in the output. ; CHECK-DAG: "ns" ; CHECK-DAG: "C::static_member_function" ; CHECK-DAG: "global_variable" ; CHECK-DAG: "ns::global_namespace_variable" ; CHECK-DAG: "ns::global_namespace_function" ; CHECK-DAG: "global_function" ; CHECK-DAG: "C::static_member_variable" ; CHECK-DAG: "C::member_function" source_filename = "test/DebugInfo/Generic/dwarf-public-names.ll" %struct.C = type { i8 } @_ZN1C22static_member_variableE = global i32 0, align 4, !dbg !0 @global_variable = global %struct.C zeroinitializer, align 1, !dbg !15 @_ZN2ns25global_namespace_variableE = global i32 1, align 4, !dbg !17 ; Function Attrs: nounwind uwtable define void @_ZN1C15member_functionEv(%struct.C* %this) #0 align 2 !dbg !23 { entry: %this.addr = alloca %struct.C*, align 8 store %struct.C* %this, %struct.C** %this.addr, align 8 call void @llvm.dbg.declare(metadata %struct.C** %this.addr, metadata !24, metadata !26), !dbg !27 %this1 = load %struct.C*, %struct.C** %this.addr store i32 0, i32* @_ZN1C22static_member_variableE, align 4, !dbg !28 ret void, !dbg !29 } ; Function Attrs: nounwind readnone declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 ; Function Attrs: nounwind uwtable define i32 @_ZN1C22static_member_functionEv() #0 align 2 !dbg !30 { entry: %0 = load i32, i32* @_ZN1C22static_member_variableE, align 4, !dbg !31 ret i32 %0, !dbg !31 } ; Function Attrs: nounwind uwtable define i32 @_Z15global_functionv() #0 !dbg !32 { entry: ret i32 -1, !dbg !33 } ; Function Attrs: nounwind uwtable define void @_ZN2ns25global_namespace_functionEv() #0 !dbg !34 { entry: call void @_ZN1C15member_functionEv(%struct.C* @global_variable), !dbg !37 ret void, !dbg !38 } attributes #0 = { nounwind uwtable } attributes #1 = { nounwind readnone } !llvm.dbg.cu = !{!20} !llvm.module.flags = !{!22} !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = !DIGlobalVariable(name: "static_member_variable", linkageName: "_ZN1C22static_member_variableE", scope: !2, file: !3, line: 7, type: !6, isLocal: false, isDefinition: true, declaration: !5) !2 = !DICompositeType(tag: DW_TAG_structure_type, name: "C", file: !3, line: 1, size: 8, align: 8, elements: !4) !3 = !DIFile(filename: "dwarf-public-names.cpp", directory: "/usr2/kparzysz/s.hex/t") !4 = !{!5, !7, !12} !5 = !DIDerivedType(tag: DW_TAG_member, name: "static_member_variable", scope: !2, file: !3, line: 4, baseType: !6, flags: DIFlagStaticMember) !6 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !7 = !DISubprogram(name: "member_function", linkageName: "_ZN1C15member_functionEv", scope: !2, file: !3, line: 2, type: !8, isLocal: false, isDefinition: false, scopeLine: 2, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, retainedNodes: !11) !8 = !DISubroutineType(types: !9) !9 = !{null, !10} !10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !2, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer) !11 = !{} !12 = !DISubprogram(name: "static_member_function", linkageName: "_ZN1C22static_member_functionEv", scope: !2, file: !3, line: 3, type: !13, isLocal: false, isDefinition: false, scopeLine: 3, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, retainedNodes: !11) !13 = !DISubroutineType(types: !14) !14 = !{!6} !15 = !DIGlobalVariableExpression(var: !16, expr: !DIExpression()) !16 = !DIGlobalVariable(name: "global_variable", scope: null, file: !3, line: 17, type: !2, isLocal: false, isDefinition: true) ; previously: invalid DW_TAG_base_type !17 = !DIGlobalVariableExpression(var: !18, expr: !DIExpression()) !18 = !DIGlobalVariable(name: "global_namespace_variable", linkageName: "_ZN2ns25global_namespace_variableE", scope: !19, file: !3, line: 27, type: !6, isLocal: false, isDefinition: true) !19 = !DINamespace(name: "ns", scope: null) !20 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 3.3 (http://llvm.org/git/clang.git a09cd8103a6a719cb2628cdf0c91682250a17bd2) (http://llvm.org/git/llvm.git 47d03cec0afca0c01ae42b82916d1d731716cd20)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !11, retainedTypes: !11, globals: !21, imports: !11) ; previously: invalid DW_TAG_base_type !21 = !{!0, !15, !17} !22 = !{i32 1, !"Debug Info Version", i32 3} !23 = distinct !DISubprogram(name: "member_function", linkageName: "_ZN1C15member_functionEv", scope: null, file: !3, line: 9, type: !8, isLocal: false, isDefinition: true, scopeLine: 9, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !20, declaration: !7, retainedNodes: !11) !24 = !DILocalVariable(name: "this", arg: 1, scope: !23, file: !3, line: 9, type: !25, flags: DIFlagArtificial | DIFlagObjectPointer) !25 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !2, size: 64, align: 64) !26 = !DIExpression() !27 = !DILocation(line: 9, scope: !23) !28 = !DILocation(line: 10, scope: !23) !29 = !DILocation(line: 11, scope: !23) !30 = distinct !DISubprogram(name: "static_member_function", linkageName: "_ZN1C22static_member_functionEv", scope: null, file: !3, line: 13, type: !13, isLocal: false, isDefinition: true, scopeLine: 13, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !20, declaration: !12, retainedNodes: !11) !31 = !DILocation(line: 14, scope: !30) !32 = distinct !DISubprogram(name: "global_function", linkageName: "_Z15global_functionv", scope: !3, file: !3, line: 19, type: !13, isLocal: false, isDefinition: true, scopeLine: 19, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !20, retainedNodes: !11) !33 = !DILocation(line: 20, scope: !32) !34 = distinct !DISubprogram(name: "global_namespace_function", linkageName: "_ZN2ns25global_namespace_functionEv", scope: !19, file: !3, line: 24, type: !35, isLocal: false, isDefinition: true, scopeLine: 24, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !20, retainedNodes: !11) !35 = !DISubroutineType(types: !36) !36 = !{null} !37 = !DILocation(line: 25, scope: !34) !38 = !DILocation(line: 26, scope: !34) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/enum.ll000066400000000000000000000074601363521741200230770ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 -filetype=obj < %t.ll > %t ; RUN: llvm-dwarfdump -v %t | FileCheck %s ; IR generated from the following code compiled with clang -g: ; enum e1 { I, J = 0xffffffffU, K = 0xf000000000000000ULL } a; ; enum e2 { X }; ; void func() { ; int b = X; ; } ; These values were previously being truncated to -1 and 0 respectively. ; CHECK: debug_info contents ; CHECK: DW_TAG_enumeration_type ; CHECK-NEXT: DW_AT_name{{.*}} = "e1" ; CHECK-NOT: NULL ; CHECK: DW_TAG_enumerator ; CHECK-NOT: NULL ; CHECK: DW_TAG_enumerator ; CHECK-NEXT: DW_AT_name{{.*}} = "J" ; CHECK-NEXT: DW_AT_const_value [DW_FORM_sdata] (4294967295) ; CHECK-NOT: NULL ; CHECK: DW_TAG_enumerator ; CHECK-NEXT: DW_AT_name{{.*}} = "K" ; CHECK-NEXT: DW_AT_const_value [DW_FORM_sdata] (-1152921504606846976) ; Check that we retain enums that aren't referenced by any variables, etc ; CHECK: DW_TAG_enumeration_type ; CHECK-NEXT: DW_AT_name{{.*}} = "e2" ; CHECK-NOT: NULL ; CHECK: DW_TAG_enumerator ; CHECK-NEXT: DW_AT_name{{.*}} = "X" source_filename = "test/DebugInfo/Generic/enum.ll" @a = global i64 0, align 8, !dbg !0 ; Function Attrs: nounwind uwtable define void @_Z4funcv() #0 !dbg !17 { entry: %b = alloca i32, align 4 call void @llvm.dbg.declare(metadata i32* %b, metadata !20, metadata !22), !dbg !23 store i32 0, i32* %b, align 4, !dbg !23 ret void, !dbg !24 } ; Function Attrs: nounwind readnone declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { nounwind readnone } !llvm.dbg.cu = !{!8} !llvm.module.flags = !{!15, !16} !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = !DIGlobalVariable(name: "a", scope: null, file: !2, line: 1, type: !3, isLocal: false, isDefinition: true) !2 = !DIFile(filename: "enum.cpp", directory: "/tmp") !3 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "e1", file: !2, line: 1, size: 64, align: 64, elements: !4) !4 = !{!5, !6, !7} !5 = !DIEnumerator(name: "I", value: 0) !6 = !DIEnumerator(name: "J", value: 4294967295) ; [ DW_TAG_enumerator ] [I :: 0] !7 = !DIEnumerator(name: "K", value: -1152921504606846976) ; [ DW_TAG_enumerator ] [J :: 4294967295] !8 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, producer: "clang version 3.4 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !9, retainedTypes: !13, globals: !14, imports: !13) ; [ DW_TAG_enumerator ] [K :: 17293822569102704640] !9 = !{!3, !10} !10 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "e2", file: !2, line: 2, size: 32, align: 32, elements: !11) !11 = !{!12} !12 = !DIEnumerator(name: "X", value: 0) ; [ DW_TAG_enumerator ] [X :: 0] !13 = !{} !14 = !{!0} !15 = !{i32 2, !"Dwarf Version", i32 3} !16 = !{i32 1, !"Debug Info Version", i32 3} !17 = distinct !DISubprogram(name: "func", linkageName: "_Z4funcv", scope: !2, file: !2, line: 3, type: !18, isLocal: false, isDefinition: true, scopeLine: 3, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !8, retainedNodes: !13) !18 = !DISubroutineType(types: !19) !19 = !{null} !20 = !DILocalVariable(name: "b", scope: !17, file: !2, line: 4, type: !21) !21 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !22 = !DIExpression() !23 = !DILocation(line: 4, scope: !17) !24 = !DILocation(line: 5, scope: !17) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/func-using-decl.ll000066400000000000000000000057421363521741200251170ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 -filetype=obj < %t.ll > %t ; RUN: llvm-dwarfdump %t | FileCheck %s ; Generated from the following source: ; extern void func_test1(int, int); ; namespace my_ns ; { ; using ::func_test1; ; } ; int main () ; { ; return 0; ; } ; Ensure forward routine declarations with an associated using declaration ; are resolved properly (temporary node would trigger an assert). ; CHECK: DW_TAG_namespace ; CHECK: DW_AT_name {{.*}}"my_ns" ; CHECK: DW_TAG_imported_declaration ; CHECK: NULL ; CHECK: DW_TAG_subprogram ; CHECK: DW_AT_name {{.*}}"func_test1" ; CHECK: NULL source_filename = "test/DebugInfo/Generic/func-using-decl.ll" ; Function Attrs: noinline norecurse nounwind optnone uwtable define dso_local i32 @main() #0 !dbg !14 { entry: %retval = alloca i32, align 4 store i32 0, i32* %retval, align 4 ret i32 0, !dbg !17 } attributes #0 = { noinline norecurse nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!10, !11, !12} !llvm.ident = !{!13} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 8.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, imports: !3, nameTableKind: None) !1 = !DIFile(filename: "func-using-decl.cpp", directory: "/tmp") !2 = !{} !3 = !{!4} !4 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !5, entity: !6, file: !1, line: 4) !5 = !DINamespace(name: "my_ns", scope: null) !6 = !DISubprogram(name: "func_test1", linkageName: "_Z10func_test1ii", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: false, flags: DIFlagPrototyped, isOptimized: false) !7 = !DISubroutineType(types: !8) !8 = !{null, !9, !9} !9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) !10 = !{i32 2, !"Dwarf Version", i32 4} !11 = !{i32 2, !"Debug Info Version", i32 3} !12 = !{i32 1, !"wchar_size", i32 4} !13 = !{!"clang version 8.0.0"} !14 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 6, type: !15, isLocal: false, isDefinition: true, scopeLine: 7, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) !15 = !DISubroutineType(types: !16) !16 = !{!9} !17 = !DILocation(line: 8, column: 3, scope: !14) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/global.ll000066400000000000000000000041061363521741200233650ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 -filetype=obj < %t.ll > %t ; RUN: llvm-dwarfdump %t | FileCheck %s ; Also test that the null streamer doesn't crash with debug info. ; RUN: llc -mtriple=%triple -O0 -filetype=null < %t.ll ; generated from the following source compiled to bitcode with clang -g -O1 ; static int i; ; int main() { ; (void)&i; ; } ; CHECK: debug_info contents ; CHECK: DW_TAG_variable source_filename = "test/DebugInfo/Generic/global.ll" ; Function Attrs: nounwind readnone uwtable define i32 @main() #0 !dbg !9 { entry: ret i32 0, !dbg !12 } attributes #0 = { nounwind readnone uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!7, !8} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.4 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !3, imports: !2) !1 = !DIFile(filename: "global.cpp", directory: "/tmp") !2 = !{} !3 = !{!4} !4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression()) !5 = !DIGlobalVariable(name: "i", linkageName: "_ZL1i", scope: null, file: !1, line: 1, type: !6, isLocal: true, isDefinition: true) !6 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !7 = !{i32 2, !"Dwarf Version", i32 3} !8 = !{i32 1, !"Debug Info Version", i32 3} !9 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 2, type: !10, isLocal: false, isDefinition: true, scopeLine: 2, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2) !10 = !DISubroutineType(types: !11) !11 = !{!6} !12 = !DILocation(line: 4, scope: !9) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/gmlt_profiling.ll000066400000000000000000000032231363521741200251400ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 -filetype=obj < %S/gmlt_profiling.ll | llvm-dwarfdump -v - | FileCheck %S/gmlt_profiling.ll ; CHECK: .debug_info ; CHECK: DW_TAG_subprogram ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "f1" ; With debug-info-for-profiling attribute, we need to emit decl_file and ; decl_line of the subprogram. ; CHECK-NEXT: DW_AT_decl_file ; CHECK-NEXT: DW_AT_decl_line ; Function Attrs: nounwind uwtable define void @_Z2f1v() !dbg !4 { entry: ret void, !dbg !13 } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!10, !11} !llvm.ident = !{!12} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.6.0 ", isOptimized: false, emissionKind: LineTablesOnly, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2, debugInfoForProfiling: true) !1 = !DIFile(filename: "gmlt.cpp", directory: "/tmp/dbginfo") !2 = !{} !4 = distinct !DISubprogram(name: "f1", line: 1, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 1, file: !1, scope: !5, type: !6, retainedNodes: !2) !5 = !DIFile(filename: "gmlt.cpp", directory: "/tmp/dbginfo") !6 = !DISubroutineType(types: !2) !10 = !{i32 2, !"Dwarf Version", i32 4} !11 = !{i32 2, !"Debug Info Version", i32 3} !12 = !{!"clang version 3.6.0 "} !13 = !DILocation(line: 1, column: 12, scope: !4) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/imported-name-inlined.ll000066400000000000000000000060001363521741200263010ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 -filetype=obj < %t.ll | llvm-dwarfdump -v -debug-info - | FileCheck --implicit-check-not "{{DW_TAG|NULL}}" %s ; Generated from the following source: ; namespace ns { ; void f(); ; } ; inline __attribute__((always_inline)) void f1() { ; using ns::f; ; f(); ; } ; void f2() { f1(); } ; Ensure that top level imported declarations don't produce an extra degenerate ; concrete subprogram definition. ; FIXME: imported entities should only be emitted to the abstract origin if one is present ; CHECK: DW_TAG_compile_unit ; CHECK: DW_TAG_subprogram ; CHECK: DW_AT_name {{.*}} "f1" ; CHECK: DW_TAG_imported_declaration ; CHECK: NULL ; CHECK: DW_TAG_namespace ; CHECK: DW_TAG_subprogram ; CHECK: NULL ; CHECK: DW_TAG_subprogram ; CHECK: DW_AT_name {{.*}} "f2" ; CHECK: DW_TAG_inlined_subroutine ; CHECK: DW_TAG_imported_declaration ; CHECK: NULL ; CHECK: NULL ; CHECK: NULL ; Function Attrs: noinline define void @_Z2f2v() noinline !dbg !14 { entry: call void @_ZN2ns1fEv(), !dbg !15 ret void, !dbg !17 } declare void @_ZN2ns1fEv() !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!10, !11, !12} !llvm.ident = !{!13} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 6.0.0 (trunk 309061) (llvm/trunk 309076)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, imports: !3) !1 = !DIFile(filename: "imported-name-inlined.cpp", directory: "/usr/local/google/home/blaikie/dev/scratch") !2 = !{} !3 = !{!4} !4 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !5, entity: !8, file: !1, line: 5) !5 = distinct !DISubprogram(name: "f1", linkageName: "_Z2f1v", scope: !1, file: !1, line: 4, type: !6, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) !6 = !DISubroutineType(types: !7) !7 = !{null} !8 = !DISubprogram(name: "f", linkageName: "_ZN2ns1fEv", scope: !9, file: !1, line: 2, type: !6, isLocal: false, isDefinition: false, flags: DIFlagPrototyped, isOptimized: false) !9 = !DINamespace(name: "ns", scope: null) !10 = !{i32 2, !"Dwarf Version", i32 4} !11 = !{i32 2, !"Debug Info Version", i32 3} !12 = !{i32 1, !"wchar_size", i32 4} !13 = !{!"clang version 6.0.0 (trunk 309061) (llvm/trunk 309076)"} !14 = distinct !DISubprogram(name: "f2", linkageName: "_Z2f2v", scope: !1, file: !1, line: 8, type: !6, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) !15 = !DILocation(line: 6, column: 3, scope: !5, inlinedAt: !16) !16 = distinct !DILocation(line: 8, column: 13, scope: !14) !17 = !DILocation(line: 8, column: 19, scope: !14) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/incorrect-variable-debugloc1.ll000066400000000000000000000100141363521741200275360ustar00rootroot00000000000000; REQUIRES: object-emission ; This test is failing for powerpc64, because a location list for the ; variable 'c' is not generated at all. Temporary marking this test as XFAIL ; for powerpc, until PR21881 is fixed. ; XFAIL: powerpc64 ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O2 -dwarf-version 2 -filetype=obj < %t.ll | llvm-dwarfdump - | FileCheck %s --check-prefix=DWARF23 ; RUN: llc -mtriple=%triple -O2 -dwarf-version 3 -filetype=obj < %t.ll | llvm-dwarfdump - | FileCheck %s --check-prefix=DWARF23 ; RUN: llc -mtriple=%triple -O2 -dwarf-version 4 -filetype=obj < %t.ll | llvm-dwarfdump - | FileCheck %s --check-prefix=DWARF4 ; This is a test for PR21176. ; DW_OP_const doesn't describe a constant value, but a value at a constant address. ; The proper way to describe a constant value is DW_OP_constu , DW_OP_stack_value. ; For values < 32 we emit the canonical DW_OP_lit. ; Generated with clang -S -emit-llvm -g -O2 test.cpp ; extern int func(); ; ; int main() ; { ; volatile int c = 13; ; c = func(); ; return c; ; } ; CHECK: DW_TAG_variable ; CHECK: DW_AT_location ; CHECK-NOT: DW_AT ; DWARF23: DW_OP_lit13{{$}} ; DWARF4: DW_OP_lit13, DW_OP_stack_value{{$}} ; Function Attrs: uwtable define i32 @main() #0 !dbg !4 { entry: %c = alloca i32, align 4 tail call void @llvm.dbg.value(metadata i32 13, metadata !10, metadata !16), !dbg !17 store volatile i32 13, i32* %c, align 4, !dbg !18 %call = tail call i32 @_Z4funcv(), !dbg !19 tail call void @llvm.dbg.value(metadata i32 %call, metadata !10, metadata !16), !dbg !17 store volatile i32 %call, i32* %c, align 4, !dbg !19 tail call void @llvm.dbg.value(metadata i32* %c, metadata !10, metadata !21), !dbg !17 %c.0.c.0. = load volatile i32, i32* %c, align 4, !dbg !20 ret i32 %c.0.c.0., !dbg !20 } declare i32 @_Z4funcv() #1 ; Function Attrs: nounwind readnone declare void @llvm.dbg.value(metadata, metadata, metadata) #2 attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #2 = { nounwind readnone } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!12, !13} !llvm.ident = !{!14} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.6.0 (trunk 223522)", isOptimized: true, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) !1 = !DIFile(filename: "test.cpp", directory: "/home/kromanova/ngh/ToT_latest/llvm/test/DebugInfo") !2 = !{} !4 = distinct !DISubprogram(name: "main", line: 3, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 4, file: !1, scope: !5, type: !6, retainedNodes: !9) !5 = !DIFile(filename: "test.cpp", directory: "/home/kromanova/ngh/ToT_latest/llvm/test/DebugInfo") !6 = !DISubroutineType(types: !7) !7 = !{!8} !8 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !9 = !{!10} !10 = !DILocalVariable(name: "c", line: 5, scope: !4, file: !5, type: !11) !11 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !8) !12 = !{i32 2, !"Dwarf Version", i32 2} !13 = !{i32 2, !"Debug Info Version", i32 3} !14 = !{!"clang version 3.6.0 (trunk 223522)"} !15 = !{i32 13} !16 = !DIExpression() !17 = !DILocation(line: 5, column: 16, scope: !4) !18 = !DILocation(line: 5, column: 3, scope: !4) !19 = !DILocation(line: 6, column: 7, scope: !4) !20 = !DILocation(line: 7, column: 3, scope: !4) !21 = !DIExpression(DW_OP_deref) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/inline-scopes.ll000066400000000000000000000142101363521741200246720ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 -filetype=obj < %t.ll | llvm-dwarfdump -debug-info - | FileCheck %s ; bool f(); ; inline __attribute__((always_inline)) int f1() { ; if (bool b = f()) ; return 1; ; return 2; ; } ; ; inline __attribute__((always_inline)) int f2() { ; # 2 "y.cc" ; if (bool b = f()) ; return 3; ; return 4; ; } ; ; int main() { ; f1(); ; f2(); ; } ; Ensure that lexical_blocks within inlined_subroutines are preserved/emitted. ; CHECK: DW_TAG_inlined_subroutine ; CHECK-NOT: DW_TAG ; CHECK-NOT: NULL ; CHECK: DW_TAG_lexical_block ; CHECK-NOT: DW_TAG ; CHECK-NOT: NULL ; CHECK: DW_TAG_variable ; Ensure that file changes don't interfere with creating inlined subroutines. ; (see the line directive inside 'f2' in thesource) ; CHECK: DW_TAG_inlined_subroutine ; CHECK: DW_TAG_variable ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_abstract_origin ; Function Attrs: uwtable define i32 @main() #0 !dbg !4 { entry: %retval.i2 = alloca i32, align 4 %b.i3 = alloca i8, align 1 %retval.i = alloca i32, align 4 %b.i = alloca i8, align 1 call void @llvm.dbg.declare(metadata i8* %b.i, metadata !16, metadata !DIExpression()), !dbg !19 %call.i = call zeroext i1 @_Z1fv(), !dbg !19 %frombool.i = zext i1 %call.i to i8, !dbg !19 store i8 %frombool.i, i8* %b.i, align 1, !dbg !19 %0 = load i8, i8* %b.i, align 1, !dbg !19 %tobool.i = trunc i8 %0 to i1, !dbg !19 br i1 %tobool.i, label %if.then.i, label %if.end.i, !dbg !19 if.then.i: ; preds = %entry store i32 1, i32* %retval.i, !dbg !21 br label %_Z2f1v.exit, !dbg !21 if.end.i: ; preds = %entry store i32 2, i32* %retval.i, !dbg !22 br label %_Z2f1v.exit, !dbg !22 _Z2f1v.exit: ; preds = %if.then.i, %if.end.i %1 = load i32, i32* %retval.i, !dbg !23 call void @llvm.dbg.declare(metadata i8* %b.i3, metadata !24, metadata !DIExpression()), !dbg !27 %call.i4 = call zeroext i1 @_Z1fv(), !dbg !27 %frombool.i5 = zext i1 %call.i4 to i8, !dbg !27 store i8 %frombool.i5, i8* %b.i3, align 1, !dbg !27 %2 = load i8, i8* %b.i3, align 1, !dbg !27 %tobool.i6 = trunc i8 %2 to i1, !dbg !27 br i1 %tobool.i6, label %if.then.i7, label %if.end.i8, !dbg !27 if.then.i7: ; preds = %_Z2f1v.exit store i32 3, i32* %retval.i2, !dbg !29 br label %_Z2f2v.exit, !dbg !29 if.end.i8: ; preds = %_Z2f1v.exit store i32 4, i32* %retval.i2, !dbg !30 br label %_Z2f2v.exit, !dbg !30 _Z2f2v.exit: ; preds = %if.then.i7, %if.end.i8 %3 = load i32, i32* %retval.i2, !dbg !31 ret i32 0, !dbg !32 } ; Function Attrs: nounwind readnone declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 declare zeroext i1 @_Z1fv() #2 attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { nounwind readnone } attributes #2 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!13, !14} !llvm.ident = !{!15} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.5.0 ", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) !1 = !DIFile(filename: "inline-scopes.cpp", directory: "/tmp/dbginfo") !2 = !{} !4 = distinct !DISubprogram(name: "main", line: 7, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 7, file: !5, scope: !6, type: !7, retainedNodes: !2) !5 = !DIFile(filename: "y.cc", directory: "/tmp/dbginfo") !6 = !DIFile(filename: "y.cc", directory: "/tmp/dbginfo") !7 = !DISubroutineType(types: !8) !8 = !{!9} !9 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !10 = distinct !DISubprogram(name: "f2", linkageName: "_Z2f2v", line: 8, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 8, file: !1, scope: !11, type: !7, retainedNodes: !2) !11 = !DIFile(filename: "inline-scopes.cpp", directory: "/tmp/dbginfo") !12 = distinct !DISubprogram(name: "f1", linkageName: "_Z2f1v", line: 2, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 2, file: !1, scope: !11, type: !7, retainedNodes: !2) !13 = !{i32 2, !"Dwarf Version", i32 4} !14 = !{i32 1, !"Debug Info Version", i32 3} !15 = !{!"clang version 3.5.0 "} !16 = !DILocalVariable(name: "b", line: 3, scope: !17, file: !11, type: !18) !17 = distinct !DILexicalBlock(line: 3, column: 0, file: !1, scope: !12) !18 = !DIBasicType(tag: DW_TAG_base_type, name: "bool", size: 8, align: 8, encoding: DW_ATE_boolean) !19 = !DILocation(line: 3, scope: !17, inlinedAt: !20) !20 = !DILocation(line: 8, scope: !4) !21 = !DILocation(line: 4, scope: !17, inlinedAt: !20) !22 = !DILocation(line: 5, scope: !12, inlinedAt: !20) !23 = !DILocation(line: 6, scope: !12, inlinedAt: !20) !24 = !DILocalVariable(name: "b", line: 2, scope: !25, file: !6, type: !18) !25 = distinct !DILexicalBlock(line: 2, column: 0, file: !5, scope: !26) !26 = !DILexicalBlockFile(discriminator: 0, file: !5, scope: !10) !27 = !DILocation(line: 2, scope: !25, inlinedAt: !28) !28 = !DILocation(line: 9, scope: !4) !29 = !DILocation(line: 3, scope: !25, inlinedAt: !28) !30 = !DILocation(line: 4, scope: !26, inlinedAt: !28) !31 = !DILocation(line: 5, scope: !26, inlinedAt: !28) !32 = !DILocation(line: 10, scope: !4) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/inlined-arguments.ll000066400000000000000000000074431363521741200255610ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -filetype=obj < %t.ll > %t ; RUN: llvm-dwarfdump %t | FileCheck %s ; IR generated from clang -O -g with the following source ; ; void f1(int x, int y); ; void f3(int line); ; void f2() { ; f1(1, 2); ; } ; void f1(int x, int y) { ; f3(y); ; } ; CHECK: DW_AT_name{{.*}}"f1" ; CHECK: DW_TAG_formal_parameter ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name{{.*}}"x" ; CHECK: DW_TAG_formal_parameter ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name{{.*}}"y" ; Function Attrs: uwtable define void @_Z2f2v() #0 !dbg !4 { tail call void @llvm.dbg.value(metadata i32 undef, metadata !16, metadata !DIExpression()), !dbg !18 tail call void @llvm.dbg.value(metadata i32 2, metadata !20, metadata !DIExpression()), !dbg !18 tail call void @_Z2f3i(i32 2), !dbg !21 ret void, !dbg !22 } ; Function Attrs: uwtable define void @_Z2f1ii(i32 %x, i32 %y) #0 !dbg !8 { tail call void @llvm.dbg.value(metadata i32 %x, metadata !13, metadata !DIExpression()), !dbg !23 tail call void @llvm.dbg.value(metadata i32 %y, metadata !14, metadata !DIExpression()), !dbg !23 tail call void @_Z2f3i(i32 %y), !dbg !24 ret void, !dbg !25 } declare void @_Z2f3i(i32) #1 ; Function Attrs: nounwind readnone declare void @llvm.dbg.value(metadata, metadata, metadata) #2 attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #2 = { nounwind readnone } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!26} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.4 ", isOptimized: true, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) !1 = !DIFile(filename: "exp.cpp", directory: "/usr/local/google/home/blaikie/dev/scratch") !2 = !{} !4 = distinct !DISubprogram(name: "f2", linkageName: "_Z2f2v", line: 3, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 3, file: !1, scope: !5, type: !6, retainedNodes: !2) !5 = !DIFile(filename: "exp.cpp", directory: "/usr/local/google/home/blaikie/dev/scratch") !6 = !DISubroutineType(types: !7) !7 = !{null} !8 = distinct !DISubprogram(name: "f1", linkageName: "_Z2f1ii", line: 6, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 6, file: !1, scope: !5, type: !9, retainedNodes: !12) !9 = !DISubroutineType(types: !10) !10 = !{null, !11, !11} !11 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !12 = !{!13, !14} !13 = !DILocalVariable(name: "x", line: 6, arg: 1, scope: !8, file: !5, type: !11) !14 = !DILocalVariable(name: "y", line: 6, arg: 2, scope: !8, file: !5, type: !11) !15 = !{i32 undef} !16 = !DILocalVariable(name: "x", line: 6, arg: 1, scope: !8, file: !5, type: !11) !17 = !DILocation(line: 4, scope: !4) !18 = !DILocation(line: 6, scope: !8, inlinedAt: !17) !19 = !{i32 2} !20 = !DILocalVariable(name: "y", line: 6, arg: 2, scope: !8, file: !5, type: !11) !21 = !DILocation(line: 7, scope: !8, inlinedAt: !17) !22 = !DILocation(line: 5, scope: !4) !23 = !DILocation(line: 6, scope: !8) !24 = !DILocation(line: 7, scope: !8) !25 = !DILocation(line: 8, scope: !8) !26 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/inlined-locations.ll000066400000000000000000000110571363521741200255430ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o - | FileCheck %s ; Check that the "inlinedAt" attribute of a DILocation references another ; DILocation that is marked as distinct. Note that the checks for distinct ; DILocations do not include the column number as SPIR-V does not allow for ; representing this info. ; Built with clang -O -g from the source: ; bool f(); ; inline __attribute__((always_inline)) int f1() { ; if (bool b = f()) ; return 1; ; return 0; ; } ; ; inline __attribute__((always_inline)) int f2() { ; if (int i = f1()) ; return 3; ; return 4; ; } ; ; int main() { ; f2(); ; } source_filename = "test/DebugInfo/Generic/inlined-locations.ll" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" target triple = "spir64-unknown-unknown" ; Function Attrs: norecurse define dso_local i32 @main() local_unnamed_addr #0 !dbg !7 { %1 = tail call spir_func zeroext i1 @_Z1fv(), !dbg !11 call void @llvm.dbg.value(metadata i8 undef, metadata !16, metadata !DIExpression()), !dbg !24 ret i32 0, !dbg !25 } declare dso_local spir_func zeroext i1 @_Z1fv() local_unnamed_addr #1 ; Function Attrs: nounwind readnone speculatable declare void @llvm.dbg.value(metadata, metadata, metadata) #2 attributes #0 = { norecurse "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #2 = { nounwind readnone speculatable } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!3, !4, !5} !llvm.ident = !{!6} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 9.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) !1 = !DIFile(filename: "inlined-locations.cpp", directory: "/tmp/dbginfo") !2 = !{} !3 = !{i32 2, !"Dwarf Version", i32 4} !4 = !{i32 2, !"Debug Info Version", i32 3} !5 = !{i32 1, !"wchar_size", i32 4} !6 = !{!"clang version 9.0.0 "} !7 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 14, type: !8, scopeLine: 14, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) !8 = !DISubroutineType(types: !9) !9 = !{!10} !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) !11 = !DILocation(line: 3, column: 16, scope: !12, inlinedAt: !18) ; CHECK: !{{.*}} = !DILocation(line: 3, column: 16, scope: !{{.*}}, inlinedAt: ![[loc1:[0-9]+]]) !12 = distinct !DILexicalBlock(scope: !13, file: !1, line: 3, column: 12) !13 = distinct !DISubprogram(name: "f1", linkageName: "_Z2f1v", scope: !1, file: !1, line: 2, type: !14, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !15) !14 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !9) !15 = !{!16} !16 = !DILocalVariable(name: "b", scope: !12, file: !1, line: 3, type: !17) !17 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean) !18 = distinct !DILocation(line: 9, column: 15, scope: !19, inlinedAt: !23) ; CHECK: ![[loc1]] = distinct !DILocation(line: 9, scope: !{{.*}}, inlinedAt: ![[loc2:[0-9]+]]) !19 = distinct !DILexicalBlock(scope: !20, file: !1, line: 9, column: 11) !20 = distinct !DISubprogram(name: "f2", linkageName: "_Z2f2v", scope: !1, file: !1, line: 8, type: !14, scopeLine: 8, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !21) !21 = !{!22} !22 = !DILocalVariable(name: "i", scope: !19, file: !1, line: 9, type: !10) !23 = distinct !DILocation(line: 15, column: 3, scope: !7) ; CHECK: ![[loc2]] = distinct !DILocation(line: 15, scope: !{{.*}}) !24 = !DILocation(line: 3, column: 12, scope: !12, inlinedAt: !18) ; CHECK: !{{.*}} = !DILocation(line: 3, column: 12, scope: !{{.*}}, inlinedAt: ![[loc1]]) !25 = !DILocation(line: 16, column: 1, scope: !7) SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/inlined-vars.ll000066400000000000000000000061071363521741200245230ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 < %t.ll | FileCheck %s -check-prefix ARGUMENT ; RUN: llc -mtriple=%triple -O0 < %t.ll | FileCheck %s -check-prefix VARIABLE ; PR 13202 define i32 @main() uwtable !dbg !5 { entry: tail call void @llvm.dbg.value(metadata i32 0, metadata !18, metadata !DIExpression()), !dbg !21 tail call void @llvm.dbg.value(metadata i32 0, metadata !22, metadata !DIExpression()), !dbg !23 tail call void @smth(i32 0), !dbg !24 tail call void @smth(i32 0), !dbg !25 ret i32 0, !dbg !19 } declare void @smth(i32) declare void @llvm.dbg.value(metadata, metadata, metadata) nounwind readnone !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!27} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.2 (trunk 159419)", isOptimized: true, emissionKind: FullDebug, file: !26, enums: !2, retainedTypes: !2, globals: !2, imports: !2) !1 = !{i32 0} !2 = !{} !5 = distinct !DISubprogram(name: "main", line: 10, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 10, file: !26, scope: !6, type: !7, retainedNodes: !2) !6 = !DIFile(filename: "inline-bug.cc", directory: "/tmp/dbginfo/pr13202") !7 = !DISubroutineType(types: !8) !8 = !{!9} !9 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !10 = distinct !DISubprogram(name: "f", linkageName: "_ZL1fi", line: 3, isLocal: true, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 3, file: !26, scope: !6, type: !11, retainedNodes: !13) !11 = !DISubroutineType(types: !12) !12 = !{!9, !9} !13 = !{!15, !16} !15 = !DILocalVariable(name: "argument", line: 3, arg: 1, scope: !10, file: !6, type: !9) ; Two DW_TAG_formal_parameter: one abstract and one inlined. ; ARGUMENT: {{.*Abbrev.*DW_TAG_formal_parameter}} ; ARGUMENT: {{.*Abbrev.*DW_TAG_formal_parameter}} ; ARGUMENT-NOT: {{.*Abbrev.*DW_TAG_formal_parameter}} !16 = !DILocalVariable(name: "local", line: 4, scope: !10, file: !6, type: !9) ; Two DW_TAG_variable: one abstract and one inlined. ; VARIABLE: {{.*Abbrev.*DW_TAG_variable}} ; VARIABLE: {{.*Abbrev.*DW_TAG_variable}} ; VARIABLE-NOT: {{.*Abbrev.*DW_TAG_variable}} !18 = !DILocalVariable(name: "argument", line: 3, arg: 1, scope: !10, file: !6, type: !9) !19 = !DILocation(line: 11, column: 10, scope: !5) !21 = !DILocation(line: 3, column: 25, scope: !10, inlinedAt: !19) !22 = !DILocalVariable(name: "local", line: 4, scope: !10, file: !6, type: !9) !23 = !DILocation(line: 4, column: 16, scope: !10, inlinedAt: !19) !24 = !DILocation(line: 5, column: 3, scope: !10, inlinedAt: !19) !25 = !DILocation(line: 6, column: 3, scope: !10, inlinedAt: !19) !26 = !DIFile(filename: "inline-bug.cc", directory: "/tmp/dbginfo/pr13202") !27 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/linear-dbg-value.ll000066400000000000000000000077231363521741200252530ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -stop-before=finalize-isel -pre-RA-sched=linearize < %t.ll | FileCheck %s ; RUN: llvm-spirv %t.spv -to-text -o - | FileCheck --check-prefix CHECK-SPIRV %s ; CHECK-SPIRV: ExtInstImport [[Set:[0-9]+]] "SPIRV.debug" ; CHECK-SPIRV: TypeVoid [[Void:[0-9]+]] ; CHECK-SPIRV: ExtInst [[Void]] {{[0-9]+}} [[Set]] DebugValue source_filename = "linear-dbg-value.ll" ; Function Attrs: nounwind readonly uwtable define i32 @foo(i32* nocapture readonly %a, i32 %N) local_unnamed_addr #0 !dbg !6 { entry: %cmp6 = icmp sgt i32 %N, 0, !dbg !11 br i1 %cmp6, label %for.body.preheader, label %for.cond.cleanup, !dbg !15 for.body.preheader: ; preds = %entry %wide.trip.count = zext i32 %N to i64 br label %for.body, !dbg !17 for.cond.cleanup.loopexit: ; preds = %for.body br label %for.cond.cleanup, !dbg !19 for.cond.cleanup: ; preds = %for.cond.cleanup.loopexit, %entry %x.0.lcssa = phi i32 [ 0, %entry ], [ %add, %for.cond.cleanup.loopexit ] ret i32 %x.0.lcssa, !dbg !19 for.body: ; preds = %for.body, %for.body.preheader ; CHECK: ![[X:[0-9]+]] = !DILocalVariable(name: "x", ; CHECK-LABEL: bb.3.for.body: ; CHECK: DBG_VALUE {{.*}} ![[X]], !DIExpression() ; CHECK: DBG_VALUE {{.*}} ![[X]], !DIExpression() %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %for.body.preheader ] %x.07 = phi i32 [ %add, %for.body ], [ 0, %for.body.preheader ] %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv, !dbg !17 %0 = load i32, i32* %arrayidx, align 4, !dbg !17 %add = add nsw i32 %0, %x.07, !dbg !17 call void @llvm.dbg.value(metadata i32 %add, metadata !9, metadata !DIExpression()), !dbg !20 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !21 call void @llvm.dbg.value(metadata i32 %add, metadata !9, metadata !DIExpression()), !dbg !20 %exitcond = icmp eq i64 %indvars.iv.next, %wide.trip.count, !dbg !11 br i1 %exitcond, label %for.cond.cleanup.loopexit, label %for.body, !dbg !15 } ; Function Attrs: nounwind readnone speculatable declare void @llvm.dbg.value(metadata, metadata, metadata) #1 attributes #0 = { nounwind readonly uwtable } attributes #1 = { nounwind readnone speculatable } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!3, !4} !llvm.ident = !{!5} !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.1 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) !1 = !DIFile(filename: "foo.c", directory: "/tmp") !2 = !{} !3 = !{i32 2, !"Dwarf Version", i32 4} !4 = !{i32 2, !"Debug Info Version", i32 3} !5 = !{!"clang version 4.0.1 "} !6 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 2, type: !7, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !8) !7 = !DISubroutineType(types: !2) !8 = !{!9} !9 = !DILocalVariable(name: "x", scope: !6, file: !1, line: 3, type: !10) !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) !11 = !DILocation(line: 4, scope: !12) !12 = !DILexicalBlockFile(scope: !13, file: !1, discriminator: 1) !13 = distinct !DILexicalBlock(scope: !14, file: !1, line: 4, column: 3) !14 = distinct !DILexicalBlock(scope: !6, file: !1, line: 4, column: 3) !15 = !DILocation(line: 4, scope: !16) !16 = !DILexicalBlockFile(scope: !14, file: !1, discriminator: 1) !17 = !DILocation(line: 5, scope: !18) !18 = distinct !DILexicalBlock(scope: !13, file: !1, line: 4, column: 31) !19 = !DILocation(line: 7, scope: !6) !20 = !DILocation(line: 3, scope: !6) !21 = !DILocation(line: 4, scope: !22) !22 = !DILexicalBlockFile(scope: !13, file: !1, discriminator: 3) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/linkage-name-abstract.ll000066400000000000000000000133141363521741200262570ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 -filetype=obj -dwarf-linkage-names=Abstract < %t.ll | llvm-dwarfdump -v -debug-info - > %t ; RUN: FileCheck %s -check-prefix=ONENAME < %t ; RUN: FileCheck %s -check-prefix=REF < %t ; Verify tuning for SCE gets us Abstract only. ; RUN: llc -mtriple=%triple -O0 -filetype=obj -debugger-tune=sce < %t.ll | llvm-dwarfdump -v -debug-info - > %t ; RUN: FileCheck %s -check-prefix=ONENAME < %t ; RUN: FileCheck %s -check-prefix=REF < %t ; REQUIRES: object-emission ; Verify that the only linkage-name present is the abstract origin of the ; inlined subprogram. ; IR generated from clang -O0 with: ; void f1(); ; __attribute__((always_inline)) void f2() { ; f1(); ; } ; void f3() { ; f2(); ; } ; ; struct F4 { ; __attribute__((always_inline)) void f5(); ; }; ; void F4::f5() { ; f1(); ; } ; void f6() { ; F4::f5(); ; } ; Show that the only linkage names are for the inlined functions, ; because those are the ones with an abstract origin. ; ONENAME-NOT: {{DW_AT(_MIPS)?_linkage_name}} ; ONENAME: {{DW_AT(_MIPS)?_linkage_name}} {{.*}} "_Z2f2v" ; ONENAME-NOT: {{DW_AT(_MIPS)?_linkage_name}} ; ONENAME: {{DW_AT(_MIPS)?_linkage_name}} {{.*}} "_ZN2F42f5Ev" ; ONENAME-NOT: {{DW_AT(_MIPS)?_linkage_name}} ; For f2() we see the definition pointing to an abstract origin DIE, ; which in turn is where the linkage_name is; and then there's ; an inlined_subroutine pointing back to the abstract origin. ; The order of these DIEs is not important of course, just the links. ; REF: DW_TAG_subprogram ; REF-NOT: {{DW_TAG|NULL}} ; REF: DW_AT_abstract_origin {{.*}} {[[F2:0x.*]]} "_Z2f2v" ; REF: [[F2]]: DW_TAG_subprogram ; REF-NEXT: linkage_name {{.*}} "_Z2f2v" ; REF: DW_TAG_inlined_subroutine ; REF-NOT: {{DW_TAG|NULL}} ; REF: DW_AT_abstract_origin {{.*}} {[[F2]]} ; For F4::f5(), first we see the in-class declaration, ; then the definition, abstract origin, and the inlined_subroutine. ; REF: DW_TAG_structure_type ; REF-NEXT: DW_AT_name {{.*}} "F4" ; REF-NOT: {{DW_TAG|NULL}} ; REF: [[F5_DECL:0x.*]]: DW_TAG_subprogram ; REF-NEXT: DW_AT_name {{.*}} "f5" ; REF: DW_TAG_subprogram ; REF-NOT: {{DW_TAG|NULL}} ; REF: DW_AT_abstract_origin {{.*}} {[[F5_ABS:0x.*]]} "_ZN2F42f5Ev" ; REF: [[F5_ABS]]: DW_TAG_subprogram ; REF-NOT: {{DW_TAG|NULL}} ; REF: linkage_name {{.*}} "_ZN2F42f5Ev" ; REF-NEXT: DW_AT_specification {{.*}} {[[F5_DECL]]} ; REF: DW_TAG_inlined_subroutine ; REF-NOT: {{DW_TAG|NULL}} ; REF: DW_AT_abstract_origin {{.*}} {[[F5_ABS]]} ; Function Attrs: alwaysinline uwtable define void @_Z2f2v() #0 !dbg !6 { entry: call void @_Z2f1v(), !dbg !9 ret void, !dbg !10 } declare void @_Z2f1v() ; Function Attrs: uwtable define void @_Z2f3v() !dbg !11 { entry: call void @_Z2f1v(), !dbg !12 ret void, !dbg !14 } ; Function Attrs: alwaysinline uwtable define void @_ZN2F42f5Ev() #0 align 2 !dbg !15 { entry: call void @_Z2f1v(), !dbg !19 ret void, !dbg !20 } ; Function Attrs: uwtable define void @_Z2f6v() !dbg !21 { entry: call void @_Z2f1v(), !dbg !22 ret void, !dbg !24 } attributes #0 = { alwaysinline } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!3, !4} !llvm.ident = !{!5} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 4.0.0 (trunk 288231)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) !1 = !DIFile(filename: "linkage-name-abstract-static.cpp", directory: "/home/probinson/projects/scratch") !2 = !{} !3 = !{i32 2, !"Dwarf Version", i32 4} !4 = !{i32 2, !"Debug Info Version", i32 3} !5 = !{!"clang version 4.0.0 (trunk 288231)"} !6 = distinct !DISubprogram(name: "f2", linkageName: "_Z2f2v", scope: !1, file: !1, line: 2, type: !7, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) !7 = !DISubroutineType(types: !8) !8 = !{null} !9 = !DILocation(line: 3, column: 3, scope: !6) !10 = !DILocation(line: 4, column: 1, scope: !6) !11 = distinct !DISubprogram(name: "f3", linkageName: "_Z2f3v", scope: !1, file: !1, line: 5, type: !7, isLocal: false, isDefinition: true, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) !12 = !DILocation(line: 3, column: 3, scope: !6, inlinedAt: !13) !13 = distinct !DILocation(line: 6, column: 3, scope: !11) !14 = !DILocation(line: 7, column: 1, scope: !11) !15 = distinct !DISubprogram(name: "f5", linkageName: "_ZN2F42f5Ev", scope: !16, file: !1, line: 12, type: !7, isLocal: false, isDefinition: true, scopeLine: 12, flags: DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !18, retainedNodes: !2) !16 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "F4", file: !1, line: 9, size: 8, elements: !17, identifier: "_ZTS2F4") !17 = !{!18} !18 = !DISubprogram(name: "f5", linkageName: "_ZN2F42f5Ev", scope: !16, file: !1, line: 10, type: !7, isLocal: false, isDefinition: false, scopeLine: 10, flags: DIFlagPrototyped, isOptimized: false) !19 = !DILocation(line: 13, column: 3, scope: !15) !20 = !DILocation(line: 14, column: 1, scope: !15) !21 = distinct !DISubprogram(name: "f6", linkageName: "_Z2f6v", scope: !1, file: !1, line: 15, type: !7, isLocal: false, isDefinition: true, scopeLine: 15, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) !22 = !DILocation(line: 13, column: 3, scope: !15, inlinedAt: !23) !23 = distinct !DILocation(line: 16, column: 3, scope: !21) !24 = !DILocation(line: 17, column: 1, scope: !21) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/member-order.ll000066400000000000000000000065051363521741200245120ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -filetype=obj -O0 < %t.ll | llvm-dwarfdump -v -debug-info - | FileCheck %s ; generated by clang from: ; struct foo { ; void f1(); ; void f2(); ; }; ; ; void foo::f1() { ; } ; CHECK: DW_TAG_structure_type ; CHECK-NEXT: DW_AT_name {{.*}} "foo" ; CHECK-NOT: NULL ; CHECK: DW_TAG_subprogram ; CHECK-NOT: NULL ; CHECK: DW_AT_name {{.*}} "f1" ; CHECK: DW_TAG_subprogram ; CHECK-NOT: NULL ; CHECK: DW_AT_name {{.*}} "f2" %struct.foo = type { i8 } ; Function Attrs: nounwind uwtable define void @_ZN3foo2f1Ev(%struct.foo* %this) #0 align 2 !dbg !14 { entry: %this.addr = alloca %struct.foo*, align 8 store %struct.foo* %this, %struct.foo** %this.addr, align 8 call void @llvm.dbg.declare(metadata %struct.foo** %this.addr, metadata !16, metadata !DIExpression()), !dbg !18 %this1 = load %struct.foo*, %struct.foo** %this.addr ret void, !dbg !19 } ; Function Attrs: nounwind readnone declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { nounwind readnone } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!15, !20} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.4 ", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !3, globals: !2, imports: !2) !1 = !DIFile(filename: "member-order.cpp", directory: "/tmp/dbginfo") !2 = !{} !3 = !{!4} !4 = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", line: 1, size: 8, align: 8, file: !1, elements: !5, identifier: "_ZTS3foo") !5 = !{!6, !11} !6 = !DISubprogram(name: "f1", linkageName: "_ZN3foo2f1Ev", line: 2, isLocal: false, isDefinition: false, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, scopeLine: 2, file: !1, scope: !4, type: !7) !7 = !DISubroutineType(types: !8) !8 = !{null, !9} !9 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer, baseType: !4) !10 = !{i32 786468} !11 = !DISubprogram(name: "f2", linkageName: "_ZN3foo2f2Ev", line: 3, isLocal: false, isDefinition: false, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, scopeLine: 3, file: !1, scope: !4, type: !7) !12 = !{i32 786468} !14 = distinct !DISubprogram(name: "f1", linkageName: "_ZN3foo2f1Ev", line: 6, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 6, file: !1, scope: null, type: !7, declaration: !6, retainedNodes: !2) !15 = !{i32 2, !"Dwarf Version", i32 4} !16 = !DILocalVariable(name: "this", arg: 1, flags: DIFlagArtificial | DIFlagObjectPointer, scope: !14, type: !17) !17 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, baseType: !4) !18 = !DILocation(line: 0, scope: !14) !19 = !DILocation(line: 7, scope: !14) !20 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/missing-abstract-variable.ll000066400000000000000000000167651363521741200272000ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 -filetype=obj < %t.ll | llvm-dwarfdump -v -debug-info - | FileCheck %s ; Build from the following source with clang -O2. ; The important details are that 'x's abstract definition is first built during ; the definition of 'b', where the parameter to 'x' is constant and so 'x's 's' ; variable is optimized away. No abstract definition DIE for 's' is constructed. ; Then, during 'a' emission, the abstract DbgVariable for 's' is created, but ; the abstract DIE isn't (since the abstract definition for 'b' is already ; built). This results in 's' inlined in 'a' being emitted with its name, line, ; file there, rather than referencing an abstract definition. ; extern int t; ; ; void f(int); ; ; inline void x(bool b) { ; if (b) { ; int s = t; ; f(s); ; } ; f(0); ; } ; ; void b() { ; x(false); ; } ; ; void a(bool u) { ; x(u); ; } ; CHECK: [[X_DECL:.*]]: DW_TAG_subprogram ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "x" ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_formal_parameter ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "b" ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_lexical_block ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_variable ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "s" ; CHECK: DW_TAG_subprogram ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "b" ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_inlined_subroutine ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_abstract_origin {{.*}} {[[X_DECL]]} ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_formal_parameter ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_abstract_origin {{.*}} "b" ; Notice 'x's local variable 's' is missing. Not necessarily a bug here, ; since it's been optimized entirely away and it should be described in ; abstract subprogram. ; CHECK-NOT: DW_TAG ; CHECK: NULL ; CHECK-NOT: DW_TAG ; CHECK: NULL ; CHECK: DW_TAG_subprogram ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "a" ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_formal_parameter ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_inlined_subroutine ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_abstract_origin {{.*}} {[[X_DECL]]} ; CHECK-NOT: {{DW_TAG|NULL}} ; FIXME: This formal parameter goes missing at least at -O2 (& on ; mips/powerpc), maybe before that. Perhaps SelectionDAG is to blame (and ; fastisel succeeds). ; CHECK: DW_TAG_formal_parameter ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_abstract_origin {{.*}} "b" ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_lexical_block ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_variable ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_abstract_origin {{.*}} "s" @t = external global i32 ; Function Attrs: uwtable define void @_Z1bv() #0 !dbg !4 { entry: tail call void @llvm.dbg.value(metadata i1 false, metadata !25, metadata !DIExpression()), !dbg !27 tail call void @_Z1fi(i32 0), !dbg !28 ret void, !dbg !29 } ; Function Attrs: uwtable define void @_Z1ab(i1 zeroext %u) #0 !dbg !8 { entry: tail call void @llvm.dbg.value(metadata i1 %u, metadata !13, metadata !DIExpression()), !dbg !30 tail call void @llvm.dbg.value(metadata i1 %u, metadata !31, metadata !DIExpression()), !dbg !33 br i1 %u, label %if.then.i, label %_Z1xb.exit, !dbg !34 if.then.i: ; preds = %entry %0 = load i32, i32* @t, align 4, !dbg !35, !tbaa !36 tail call void @llvm.dbg.value(metadata i32 %0, metadata !40, metadata !DIExpression()), !dbg !35 tail call void @_Z1fi(i32 %0), !dbg !41 br label %_Z1xb.exit, !dbg !42 _Z1xb.exit: ; preds = %entry, %if.then.i tail call void @_Z1fi(i32 0), !dbg !43 ret void, !dbg !44 } declare void @_Z1fi(i32) #1 ; Function Attrs: nounwind readnone declare void @llvm.dbg.value(metadata, metadata, metadata) #2 attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #2 = { nounwind readnone } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!21, !22} !llvm.ident = !{!23} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.5.0 ", isOptimized: true, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) !1 = !DIFile(filename: "missing-abstract-variables.cc", directory: "/tmp/dbginfo") !2 = !{} !4 = distinct !DISubprogram(name: "b", linkageName: "_Z1bv", line: 13, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 13, file: !1, scope: !5, type: !6, retainedNodes: !2) !5 = !DIFile(filename: "missing-abstract-variables.cc", directory: "/tmp/dbginfo") !6 = !DISubroutineType(types: !7) !7 = !{null} !8 = distinct !DISubprogram(name: "a", linkageName: "_Z1ab", line: 17, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 17, file: !1, scope: !5, type: !9, retainedNodes: !12) !9 = !DISubroutineType(types: !10) !10 = !{null, !11} !11 = !DIBasicType(tag: DW_TAG_base_type, name: "bool", size: 8, align: 8, encoding: DW_ATE_boolean) !12 = !{!13} !13 = !DILocalVariable(name: "u", line: 17, arg: 1, scope: !8, file: !5, type: !11) !14 = distinct !DISubprogram(name: "x", linkageName: "_Z1xb", line: 5, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 5, file: !1, scope: !5, type: !9, retainedNodes: !15) !15 = !{!16, !17} !16 = !DILocalVariable(name: "b", line: 5, arg: 1, scope: !14, file: !5, type: !11) !17 = !DILocalVariable(name: "s", line: 7, scope: !18, file: !5, type: !20) !18 = distinct !DILexicalBlock(line: 6, column: 0, file: !1, scope: !19) !19 = distinct !DILexicalBlock(line: 6, column: 0, file: !1, scope: !14) !20 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !21 = !{i32 2, !"Dwarf Version", i32 4} !22 = !{i32 2, !"Debug Info Version", i32 3} !23 = !{!"clang version 3.5.0 "} !24 = !{i1 false} !25 = !DILocalVariable(name: "b", line: 5, arg: 1, scope: !14, file: !5, type: !11) !26 = !DILocation(line: 14, scope: !4) !27 = !DILocation(line: 5, scope: !14, inlinedAt: !26) !28 = !DILocation(line: 10, scope: !14, inlinedAt: !26) !29 = !DILocation(line: 15, scope: !4) !30 = !DILocation(line: 17, scope: !8) !31 = !DILocalVariable(name: "b", line: 5, arg: 1, scope: !14, file: !5, type: !11) !32 = !DILocation(line: 18, scope: !8) !33 = !DILocation(line: 5, scope: !14, inlinedAt: !32) !34 = !DILocation(line: 6, scope: !19, inlinedAt: !32) !35 = !DILocation(line: 7, scope: !18, inlinedAt: !32) !36 = !{!37, !37, i64 0} !37 = !{!"int", !38, i64 0} !38 = !{!"omnipotent char", !39, i64 0} !39 = !{!"Simple C/C++ TBAA"} !40 = !DILocalVariable(name: "s", line: 7, scope: !18, file: !5, type: !20) !41 = !DILocation(line: 8, scope: !18, inlinedAt: !32) !42 = !DILocation(line: 9, scope: !18, inlinedAt: !32) !43 = !DILocation(line: 10, scope: !14, inlinedAt: !32) !44 = !DILocation(line: 19, scope: !8) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/multiline.ll000066400000000000000000000065751363521741200241430ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -filetype=asm -asm-verbose=0 -O0 < %t.ll | FileCheck %s ; RUN: llc -mtriple=%triple -filetype=obj -O0 < %t.ll | llvm-dwarfdump -debug-line - | FileCheck %s --check-prefix=INT ; Check that the assembly output properly handles is_stmt changes. And since ; we're testing anyway, check the integrated assembler too. ; Generated with clang from multiline.c: ; void f1(); ; void f2() { ; f1(); f1(); f1(); ; f1(); f1(); f1(); ; } ; CHECK: .loc 1 2 0{{$}} ; CHECK-NOT: .loc{{ }} ; CHECK: .loc 1 3 3 prologue_end{{$}} ; CHECK-NOT: .loc ; CHECK: .loc 1 3 9 is_stmt 0{{$}} ; CHECK-NOT: .loc ; CHECK: .loc 1 3 15{{$}} ; CHECK-NOT: .loc ; CHECK: .loc 1 4 3 is_stmt 1{{$}} ; CHECK-NOT: .loc ; CHECK: .loc 1 4 9 is_stmt 0{{$}} ; CHECK-NOT: .loc ; CHECK: .loc 1 4 15{{$}} ; CHECK-NOT: .loc ; CHECK: .loc 1 5 1 is_stmt 1{{$}} ; INT: {{^}}Address ; INT: ----- ; INT-NEXT: 2 0 1 0 0 is_stmt{{$}} ; INT-NEXT: 3 3 1 0 0 is_stmt prologue_end{{$}} ; INT-NEXT: 3 9 1 0 0 {{$}} ; INT-NEXT: 3 15 1 0 0 {{$}} ; INT-NEXT: 4 3 1 0 0 is_stmt{{$}} ; INT-NEXT: 4 9 1 0 0 {{$}} ; INT-NEXT: 4 15 1 0 0 {{$}} ; INT-NEXT: 5 1 1 0 0 is_stmt{{$}} ; Function Attrs: nounwind uwtable define void @f2() #0 !dbg !4 { entry: call void (...) @f1(), !dbg !11 call void (...) @f1(), !dbg !12 call void (...) @f1(), !dbg !13 call void (...) @f1(), !dbg !14 call void (...) @f1(), !dbg !15 call void (...) @f1(), !dbg !16 ret void, !dbg !17 } declare void @f1(...) #1 attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!8, !9} !llvm.ident = !{!10} !0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.6.0 (trunk 225000) (llvm/trunk 224999)", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) !1 = !DIFile(filename: "multiline.c", directory: "/tmp/dbginfo") !2 = !{} !4 = distinct !DISubprogram(name: "f2", line: 2, isLocal: false, isDefinition: true, isOptimized: false, unit: !0, scopeLine: 2, file: !1, scope: !5, type: !6, retainedNodes: !2) !5 = !DIFile(filename: "multiline.c", directory: "/tmp/dbginfo") !6 = !DISubroutineType(types: !7) !7 = !{null} !8 = !{i32 2, !"Dwarf Version", i32 4} !9 = !{i32 2, !"Debug Info Version", i32 3} !10 = !{!"clang version 3.6.0 (trunk 225000) (llvm/trunk 224999)"} !11 = !DILocation(line: 3, column: 3, scope: !4) !12 = !DILocation(line: 3, column: 9, scope: !4) !13 = !DILocation(line: 3, column: 15, scope: !4) !14 = !DILocation(line: 4, column: 3, scope: !4) !15 = !DILocation(line: 4, column: 9, scope: !4) !16 = !DILocation(line: 4, column: 15, scope: !4) !17 = !DILocation(line: 5, column: 1, scope: !4) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/namespace_function_definition.ll000066400000000000000000000037551363521741200302070ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 -filetype=obj -dwarf-linkage-names=All < %t.ll | llvm-dwarfdump -v -debug-info - | FileCheck %s ; Generated from clang with the following source: ; namespace ns { ; void func() { ; } ; } ; CHECK: DW_TAG_namespace ; CHECK-NEXT: DW_AT_name {{.*}} "ns" ; CHECK: DW_TAG_subprogram ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_low_pc ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_linkage_name {{.*}} "_ZN2ns4funcEv" ; CHECK: NULL ; CHECK: NULL ; Function Attrs: nounwind uwtable define void @_ZN2ns4funcEv() #0 !dbg !4 { entry: ret void, !dbg !11 } attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!8, !9} !llvm.ident = !{!10} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.5.0 ", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) !1 = !DIFile(filename: "namespace_function_definition.cpp", directory: "/tmp/dbginfo") !2 = !{} !4 = distinct !DISubprogram(name: "func", linkageName: "_ZN2ns4funcEv", line: 2, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 2, file: !1, scope: !5, type: !6, retainedNodes: !2) !5 = !DINamespace(name: "ns", scope: null) !6 = !DISubroutineType(types: !7) !7 = !{null} !8 = !{i32 2, !"Dwarf Version", i32 4} !9 = !{i32 1, !"Debug Info Version", i32 3} !10 = !{!"clang version 3.5.0 "} !11 = !DILocation(line: 3, scope: !4) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/namespace_inline_function_definition.ll000066400000000000000000000106201363521741200315320ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 -filetype=obj -dwarf-linkage-names=All < %t.ll | llvm-dwarfdump -v -debug-info - | FileCheck %s ; Generate from clang with the following source. Note that the definition of ; the inline function follows its use to workaround another bug that should be ; fixed soon. ; namespace ns { ; int func(int i); ; } ; extern int x; ; int main() { return ns::func(x); } ; int __attribute__((always_inline)) ns::func(int i) { return i * 2; } ; CHECK: DW_TAG_namespace ; CHECK-NEXT: DW_AT_name {{.*}} "ns" ; CHECK-NOT: DW_TAG ; CHECK: DW_TAG_subprogram ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_linkage_name {{.*}} "_ZN2ns4funcEi" ; CHECK-NOT: DW_TAG ; CHECK: DW_TAG_formal_parameter ; CHECK: NULL ; CHECK-NOT: NULL ; CHECK: DW_TAG_subprogram ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_abstract_origin {{.*}} "_ZN2ns4funcEi" ; CHECK-NOT: DW_TAG ; CHECK: DW_TAG_formal_parameter ; CHECK: DW_AT_abstract_origin {{.*}} "i" ; CHECK: NULL ; CHECK: NULL ; CHECK: NULL @x = external global i32 ; Function Attrs: uwtable define i32 @main() #0 !dbg !4 { entry: %i.addr.i = alloca i32, align 4 %retval = alloca i32, align 4 store i32 0, i32* %retval %0 = load i32, i32* @x, align 4, !dbg !16 store i32 %0, i32* %i.addr.i, align 4 call void @llvm.dbg.declare(metadata i32* %i.addr.i, metadata !117, metadata !DIExpression()), !dbg !18 %1 = load i32, i32* %i.addr.i, align 4, !dbg !18 %mul.i = mul nsw i32 %1, 2, !dbg !18 ret i32 %mul.i, !dbg !16 } ; Function Attrs: alwaysinline nounwind uwtable define i32 @_ZN2ns4funcEi(i32 %i) #1 !dbg !9 { entry: %i.addr = alloca i32, align 4 store i32 %i, i32* %i.addr, align 4 call void @llvm.dbg.declare(metadata i32* %i.addr, metadata !17, metadata !DIExpression()), !dbg !19 %0 = load i32, i32* %i.addr, align 4, !dbg !19 %mul = mul nsw i32 %0, 2, !dbg !19 ret i32 %mul, !dbg !19 } ; Function Attrs: nounwind readnone declare void @llvm.dbg.declare(metadata, metadata, metadata) #2 attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { alwaysinline nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #2 = { nounwind readnone } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!13, !14} !llvm.ident = !{!15} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.5.0 ", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) !1 = !DIFile(filename: "namespace_inline_function_definition.cpp", directory: "/tmp/dbginfo") !2 = !{} !4 = distinct !DISubprogram(name: "main", line: 5, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 5, file: !1, scope: !5, type: !6, retainedNodes: !2) !5 = !DIFile(filename: "namespace_inline_function_definition.cpp", directory: "/tmp/dbginfo") !6 = !DISubroutineType(types: !7) !7 = !{!8} !8 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !9 = distinct !DISubprogram(name: "func", linkageName: "_ZN2ns4funcEi", line: 6, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 6, file: !1, scope: !10, type: !11, retainedNodes: !2) !10 = !DINamespace(name: "ns", scope: null) !11 = !DISubroutineType(types: !12) !12 = !{!8, !8} !13 = !{i32 2, !"Dwarf Version", i32 4} !14 = !{i32 2, !"Debug Info Version", i32 3} !15 = !{!"clang version 3.5.0 "} !16 = !DILocation(line: 5, scope: !4) !17 = !DILocalVariable(name: "i", line: 6, arg: 1, scope: !9, file: !5, type: !8) !117 = !DILocalVariable(name: "i", line: 6, arg: 1, scope: !9, file: !5, type: !8) !18 = !DILocation(line: 6, scope: !9, inlinedAt: !16) !19 = !DILocation(line: 6, scope: !9) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/noscopes.ll000066400000000000000000000027551363521741200237660ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 -filetype=obj < %t.ll | llvm-dwarfdump - | FileCheck %s ; Just because there are no scopes/locations on any instructions in the ; function doesn't mean we can't describe the address range of the function. ; Check that we do that ; CHECK: DW_TAG_subprogram ; CHECK-NOT: TAG ; CHECK: DW_AT_low_pc ; Function Attrs: nounwind uwtable define void @f() #0 !dbg !6 { entry: ret void } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!3, !4} !llvm.ident = !{!5} !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 289692) (llvm/trunk 289697)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) !1 = !DIFile(filename: "noscopes.c", directory: "/tmp/dbginfo") !2 = !{} !3 = !{i32 2, !"Dwarf Version", i32 4} !4 = !{i32 2, !"Debug Info Version", i32 3} !5 = !{!"clang version 4.0.0 (trunk 289692) (llvm/trunk 289697)"} !6 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !0, retainedNodes: !2) !7 = !DISubroutineType(types: !8) !8 = !{null} !9 = !DILocation(line: 2, column: 1, scope: !6) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/pass-by-value.ll000066400000000000000000000060141363521741200246150ustar00rootroot00000000000000; REQUIRES: object-emission ; ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; ; RUN: llc -mtriple=%triple -O0 -filetype=obj %t.ll -o - | llvm-dwarfdump -v -debug-info - | FileCheck %s ; ; // S is not trivially copyable. ; struct S { ; ~S() {} ; }; ; ; // T is a POD. ; struct T { ; ~T() = default; ; }; ; ; S s; ; T t; ; ; CHECK: DW_TAG_structure_type ; CHECK-NEXT: DW_AT_calling_convention {{.*}} (DW_CC_pass_by_reference) ; CHECK-NEXT: DW_AT_name {{.*}} "S" ; ; CHECK: DW_TAG_structure_type ; CHECK-NEXT: DW_AT_calling_convention {{.*}} (DW_CC_pass_by_value) ; CHECK-NEXT: DW_AT_name {{.*}} "T" %struct.S = type { i8 } %struct.T = type { i8 } @s = global %struct.S zeroinitializer, align 1, !dbg !0 @__dso_handle = external hidden global i8 @t = global %struct.T zeroinitializer, align 1, !dbg !6 !llvm.dbg.cu = !{!2} !llvm.module.flags = !{!20, !21, !22, !23} !llvm.ident = !{!24} !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = distinct !DIGlobalVariable(name: "s", scope: !2, file: !3, line: 9, type: !14, isLocal: false, isDefinition: true) !2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 7.0.0 (trunk 321763) (llvm/trunk 321758)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5) !3 = !DIFile(filename: "pass.cpp", directory: "/") !4 = !{} !5 = !{!0, !6} !6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression()) !7 = distinct !DIGlobalVariable(name: "t", scope: !2, file: !3, line: 10, type: !8, isLocal: false, isDefinition: true) !8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "T", file: !3, line: 5, size: 8, elements: !9, identifier: "_ZTS1T", flags: DIFlagTypePassByValue) !9 = !{!10} !10 = !DISubprogram(name: "~T", scope: !8, file: !3, line: 6, type: !11, isLocal: false, isDefinition: false, scopeLine: 6, flags: DIFlagPrototyped, isOptimized: false) !11 = !DISubroutineType(types: !12) !12 = !{null, !13} !13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) !14 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !3, line: 1, size: 8, elements: !15, identifier: "_ZTS1S", flags: DIFlagTypePassByReference) !15 = !{!16} !16 = !DISubprogram(name: "~S", scope: !14, file: !3, line: 2, type: !17, isLocal: false, isDefinition: false, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false) !17 = !DISubroutineType(types: !18) !18 = !{null, !19} !19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !14, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) !20 = !{i32 2, !"Dwarf Version", i32 4} !21 = !{i32 2, !"Debug Info Version", i32 3} !22 = !{i32 1, !"wchar_size", i32 4} !23 = !{i32 7, !"PIC Level", i32 2} !24 = !{!"clang version 7.0.0 (trunk 321763) (llvm/trunk 321758)"} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/ptrsize.ll000077500000000000000000000043051363521741200236310ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 -filetype=obj < %t.ll > %t ; RUN: llvm-dwarfdump -v %t | FileCheck %s ; Check that pointers and references get emitted without size information in ; DWARF, even if they are so specified in the IR ; CHECK: 0x[[O1:[0-9a-f]+]]: DW_TAG_pointer_type ; CHECK-NEXT: DW_AT_type [DW_FORM_ref4] ; CHECK-NOT: DW_AT_byte_size ; CHECK: 0x[[O2:[0-9a-f]+]]: DW_TAG_ ; CHECK: 0x[[O3:[0-9a-f]+]]: DW_TAG_reference_type ; CHECK-NEXT: DW_AT_type [DW_FORM_ref4] ; CHECK-NOT: DW_AT_byte_size define i32 @foo() !dbg !4 { entry: ret i32 0, !dbg !13 } define i32 @bar() !dbg !5 { entry: ret i32 0, !dbg !16 } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!11, !12} !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2, imports: !2) !1 = !DIFile(filename: "dwarf-test.c", directory: "test") !2 = !{} !4 = distinct !DISubprogram(name: "foo", scope: !0, file: !1, line: 6, type: !6, isLocal: false, isDefinition: true, scopeLine: 6, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) !5 = distinct !DISubprogram(name: "bar", scope: !0, file: !1, line: 6, type: !15, isLocal: false, isDefinition: true, scopeLine: 6, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) !6 = !DISubroutineType(types: !7) !7 = !{!9} !8 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !9 = !DIDerivedType(tag: DW_TAG_pointer_type, scope: !0, baseType: !8, size: 64, align: 64) !10 = !DIDerivedType(tag: DW_TAG_reference_type, scope: !0, baseType: !8, size: 64, align: 64) !11 = !{i32 2, !"Dwarf Version", i32 3} !12 = !{i32 1, !"Debug Info Version", i32 3} !13 = !DILocation(line: 7, scope: !4) !14 = !{!10} !15 = !DISubroutineType(types: !14) !16 = !DILocation(line: 7, scope: !5) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/restrict.ll000066400000000000000000000053771363521741200237770ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -dwarf-version=2 -O0 -filetype=obj < %t.ll | llvm-dwarfdump -v -debug-info - | FileCheck --check-prefix=CHECK --check-prefix=V2 %s ; RUN: llc -mtriple=%triple -dwarf-version=3 -O0 -filetype=obj < %t.ll | llvm-dwarfdump -v -debug-info - | FileCheck --check-prefix=CHECK --check-prefix=V3 %s ; CHECK: DW_AT_name {{.*}} "dst" ; V2: DW_AT_type {{.*}} {[[PTR:0x.*]]} ; V3: DW_AT_type {{.*}} {[[RESTRICT:0x.*]]} ; V3: [[RESTRICT]]: {{.*}}DW_TAG_restrict_type ; V3-NEXT: DW_AT_type {{.*}} {[[PTR:0x.*]]} ; CHECK: [[PTR]]: {{.*}}DW_TAG_pointer_type ; CHECK-NOT: DW_AT_type ; Generated with clang from: ; void foo(void* __restrict__ dst) { ; } ; Function Attrs: nounwind uwtable define void @_Z3fooPv(i8* noalias %dst) #0 !dbg !4 { entry: %dst.addr = alloca i8*, align 8 store i8* %dst, i8** %dst.addr, align 8 call void @llvm.dbg.declare(metadata i8** %dst.addr, metadata !13, metadata !DIExpression()), !dbg !14 ret void, !dbg !15 } ; Function Attrs: nounwind readnone declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { nounwind readnone } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!10, !11} !llvm.ident = !{!12} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.5.0 ", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) !1 = !DIFile(filename: "restrict.c", directory: "/tmp/dbginfo") !2 = !{} !4 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooPv", line: 1, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 1, file: !1, scope: !5, type: !6, retainedNodes: !2) !5 = !DIFile(filename: "restrict.c", directory: "/tmp/dbginfo") !6 = !DISubroutineType(types: !7) !7 = !{null, !8} !8 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !9) !9 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null) !10 = !{i32 2, !"Dwarf Version", i32 4} !11 = !{i32 1, !"Debug Info Version", i32 3} !12 = !{!"clang version 3.5.0 "} !13 = !DILocalVariable(name: "dst", line: 1, arg: 1, scope: !4, file: !5, type: !8) !14 = !DILocation(line: 1, scope: !4) !15 = !DILocation(line: 2, scope: !4) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/templ-func-decl.ll000066400000000000000000000077641363521741200251210ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=x86_64-linux -O0 -filetype=obj < %t.ll | llvm-dwarfdump -v -debug-info - | FileCheck %s ; IR generated with `clang -Xclang -debug-info-kind=limited -emit-llvm -S` from the following code: ; class A { ; public: ; template static int foo() { return T; } ; }; ; ; int main() { ; A::template foo<42>(); ; } ; CHECK: DW_TAG_subprogram ; CHECK: DW_AT_name{{.*}}"foo<42>" ; CHECK: DW_TAG_template_value_parameter ; CHECK: DW_AT_type {{.*}} "int" ; CHECK: DW_AT_name {{.*}} "T" ; CHECK: DW_AT_const_value {{.*}} (42) ; ModuleID = 'templ-func-decl.cpp' source_filename = "templ-func-decl.cpp" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "spir64-unknown-unknown" $_ZN1A3fooILi42EEEiv = comdat any ; Function Attrs: noinline norecurse optnone uwtable define dso_local i32 @main() #0 !dbg !6 { entry: %call = call i32 @_ZN1A3fooILi42EEEiv(), !dbg !10 ret i32 0, !dbg !11 } ; Function Attrs: noinline nounwind optnone uwtable define linkonce_odr dso_local i32 @_ZN1A3fooILi42EEEiv() #1 comdat align 2 !dbg !12 { entry: ret i32 42, !dbg !17 } attributes #0 = { noinline norecurse optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!3, !4} !llvm.ident = !{!5} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 8.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) !1 = !DIFile(filename: "templ-func-decl.cpp", directory: "/tmp") !2 = !{} !3 = !{i32 2, !"Debug Info Version", i32 3} !4 = !{i32 1, !"wchar_size", i32 4} !5 = !{!"clang version 8.0.0 "} !6 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 6, type: !7, isLocal: false, isDefinition: true, scopeLine: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) !7 = !DISubroutineType(types: !8) !8 = !{!9} !9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) !10 = !DILocation(line: 7, column: 3, scope: !6) !11 = !DILocation(line: 8, column: 1, scope: !6) !12 = distinct !DISubprogram(name: "foo<42>", linkageName: "_ZN1A3fooILi42EEEiv", scope: !13, file: !1, line: 3, type: !7, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, unit: !0, templateParams: !15, declaration: !14, retainedNodes: !2) !13 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "A", file: !1, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !2, identifier: "_ZTS1A") !14 = !DISubprogram(name: "foo<42>", linkageName: "_ZN1A3fooILi42EEEiv", scope: !13, file: !1, line: 3, type: !7, isLocal: false, isDefinition: false, scopeLine: 3, flags: DIFlagPublic | DIFlagPrototyped | DIFlagStaticMember, isOptimized: false, templateParams: !15) !15 = !{!16} !16 = !DITemplateValueParameter(name: "T", type: !9, value: i32 42) !17 = !DILocation(line: 3, column: 39, scope: !12) SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/template-recursive-void.ll000066400000000000000000000073451363521741200267140ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 -filetype=obj < %t.ll > %t ; RUN: llvm-dwarfdump -v %t | FileCheck %s ; This was pulled from clang's debug-info-template-recursive.cpp test. ; class base { }; ; template class foo : public base { ; void operator=(const foo r) { } ; }; ; class bar : public foo { }; ; bar filters; ; CHECK: DW_TAG_template_type_parameter [{{.*}}] ; CHECK-NEXT: DW_AT_name{{.*}}"T" ; CHECK-NOT: DW_AT_type ; CHECK: NULL source_filename = "test/DebugInfo/Generic/template-recursive-void.ll" %class.bar = type { i8 } @filters = global %class.bar zeroinitializer, align 1, !dbg !0 !llvm.dbg.cu = !{!29} !llvm.module.flags = !{!32, !33} !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = !DIGlobalVariable(name: "filters", scope: null, file: !2, line: 10, type: !3, isLocal: false, isDefinition: true) !2 = !DIFile(filename: "debug-info-template-recursive.cpp", directory: "/usr/local/google/home/echristo/tmp") !3 = !DICompositeType(tag: DW_TAG_class_type, name: "bar", file: !2, line: 9, size: 8, align: 8, elements: !4) !4 = !{!5, !25} !5 = !DIDerivedType(tag: DW_TAG_inheritance, scope: !3, baseType: !6) !6 = !DICompositeType(tag: DW_TAG_class_type, name: "foo", file: !2, line: 5, size: 8, align: 8, elements: !7, templateParams: !23) !7 = !{!8, !15, !20} !8 = !DIDerivedType(tag: DW_TAG_inheritance, scope: !6, baseType: !9) !9 = !DICompositeType(tag: DW_TAG_class_type, name: "base", file: !2, line: 3, size: 8, align: 8, elements: !10) !10 = !{!11} !11 = !DISubprogram(name: "base", scope: !9, file: !2, line: 3, type: !12, isLocal: false, isDefinition: false, scopeLine: 3, virtualIndex: 6, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false) !12 = !DISubroutineType(types: !13) !13 = !{null, !14} !14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer) !15 = !DISubprogram(name: "operator=", linkageName: "_ZN3fooIvEaSES0_", scope: !6, file: !2, line: 6, type: !16, isLocal: false, isDefinition: false, scopeLine: 6, virtualIndex: 6, flags: DIFlagPrivate | DIFlagPrototyped, isOptimized: false) !16 = !DISubroutineType(types: !17) !17 = !{null, !18, !19} !18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer) !19 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !6) !20 = !DISubprogram(name: "foo", scope: !6, file: !2, line: 5, type: !21, isLocal: false, isDefinition: false, scopeLine: 5, virtualIndex: 6, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false) !21 = !DISubroutineType(types: !22) !22 = !{null, !18} !23 = !{!24} !24 = !DITemplateTypeParameter(name: "T", type: null) !25 = !DISubprogram(name: "bar", scope: !3, file: !2, line: 9, type: !26, isLocal: false, isDefinition: false, scopeLine: 9, virtualIndex: 6, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false) !26 = !DISubroutineType(types: !27) !27 = !{null, !28} !28 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !3, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer) !29 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, producer: "clang version 3.4 (trunk 187958) (llvm/trunk 187964)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !30, retainedTypes: !30, globals: !31, imports: !30) !30 = !{} !31 = !{!0} !32 = !{i32 2, !"Dwarf Version", i32 3} !33 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/tu-member-pointer.ll000066400000000000000000000032601363521741200255000ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -filetype=obj -O0 < %t.ll > %t ; RUN: llvm-dwarfdump -v -debug-info %t | FileCheck %s ; CHECK: DW_TAG_ptr_to_member_type ; CHECK-NEXT: DW_AT_type [DW_FORM_ref4] (cu + {{.*}} => {[[TYPE:0x[0-9a-f]+]]} ; CHECK: [[TYPE]]: DW_TAG_base_type ; IR generated from clang -g with the following source: ; struct Foo { ; int e; ; }; ; int Foo:*x = 0; source_filename = "test/DebugInfo/Generic/tu-member-pointer.ll" @x = global i64 -1, align 8, !dbg !0 !llvm.dbg.cu = !{!6} !llvm.module.flags = !{!10, !11} !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = !DIGlobalVariable(name: "x", scope: null, file: !2, line: 4, type: !3, isLocal: false, isDefinition: true) !2 = !DIFile(filename: "foo.cpp", directory: ".") !3 = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !4, extraData: !5) !4 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !5 = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: !2, line: 1, flags: DIFlagFwdDecl, identifier: "_ZTS3Foo") !6 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, producer: "clang version 3.4", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !7, retainedTypes: !8, globals: !9, imports: !7) !7 = !{} !8 = !{!5} !9 = !{!0} !10 = !{i32 2, !"Dwarf Version", i32 2} !11 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/two-cus-from-same-file.ll000066400000000000000000000074771363521741200263450ustar00rootroot00000000000000; For http://llvm.org/bugs/show_bug.cgi?id=12942 ; There are two CUs coming from /tmp/foo.c in this module. Make sure it doesn't ; blow llc up and produces something reasonable. ; ; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple %t.ll -o %t -filetype=obj -O0 ; RUN: llvm-dwarfdump -debug-info %t | FileCheck %s ; ModuleID = 'test.bc' @str = private unnamed_addr constant [4 x i8] c"FOO\00" @str1 = private unnamed_addr constant [6 x i8] c"Main!\00" define void @foo() nounwind !dbg !5 { entry: %puts = tail call i32 @puts(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @str, i32 0, i32 0)), !dbg !23 ret void, !dbg !25 } declare i32 @puts(i8* nocapture) nounwind define i32 @main(i32 %argc, i8** nocapture %argv) nounwind !dbg !12 { entry: tail call void @llvm.dbg.value(metadata i32 %argc, metadata !21, metadata !DIExpression()), !dbg !26 ; Avoid talking about the pointer size in debug info because that's target dependent tail call void @llvm.dbg.value(metadata i8** %argv, metadata !22, metadata !DIExpression(DW_OP_deref, DW_OP_deref)), !dbg !27 %puts = tail call i32 @puts(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @str1, i32 0, i32 0)), !dbg !28 tail call void @foo() nounwind, !dbg !30 ret i32 0, !dbg !31 } declare void @llvm.dbg.value(metadata, metadata, metadata) nounwind readnone !llvm.dbg.cu = !{!0, !9} !llvm.module.flags = !{!33} !0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.2 (trunk 156513)", isOptimized: true, emissionKind: FullDebug, file: !32, enums: !1, retainedTypes: !1, globals: !1, imports: !1) !1 = !{} !5 = distinct !DISubprogram(name: "foo", line: 5, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 5, file: !32, scope: !6, type: !7, retainedNodes: !1) !6 = !DIFile(filename: "foo.c", directory: "/tmp") !7 = !DISubroutineType(types: !8) !8 = !{null} !9 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.2 (trunk 156513)", isOptimized: true, emissionKind: FullDebug, file: !32, enums: !1, retainedTypes: !1, globals: !1, imports: !1) !12 = distinct !DISubprogram(name: "main", line: 11, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !9, scopeLine: 11, file: !32, scope: !6, type: !13, retainedNodes: !19) !13 = !DISubroutineType(types: !14) !14 = !{!15, !15, !18} !15 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !18 = !DIBasicType(tag: DW_TAG_base_type, name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char) !19 = !{!21, !22} !21 = !DILocalVariable(name: "argc", line: 11, arg: 1, scope: !12, file: !6, type: !15) !22 = !DILocalVariable(name: "argv", line: 11, arg: 2, scope: !12, file: !6, type: !18) !23 = !DILocation(line: 6, column: 3, scope: !24) !24 = distinct !DILexicalBlock(line: 5, column: 16, file: !32, scope: !5) !25 = !DILocation(line: 7, column: 1, scope: !24) !26 = !DILocation(line: 11, column: 14, scope: !12) !27 = !DILocation(line: 11, column: 26, scope: !12) !28 = !DILocation(line: 12, column: 3, scope: !29) !29 = distinct !DILexicalBlock(line: 11, column: 34, file: !32, scope: !12) !30 = !DILocation(line: 13, column: 3, scope: !29) !31 = !DILocation(line: 14, column: 3, scope: !29) !32 = !DIFile(filename: "foo.c", directory: "/tmp") ; This test is simple to be cross platform (many targets don't yet have ; sufficiently good DWARF emission and/or dumping) ; CHECK: {{DW_TAG_compile_unit}} ; CHECK: {{foo\.c}} !33 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/typedef.ll000066400000000000000000000030721363521741200235660ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 -filetype=obj < %t.ll | llvm-dwarfdump -debug-info - | FileCheck %s ; From source: ; typedef void x; ; x *y; ; Check that a typedef with no DW_AT_type is produced. The absence of a type is used to imply the 'void' type. ; CHECK: DW_TAG_typedef ; CHECK-NOT: DW_AT_type ; CHECK: {{DW_TAG|NULL}} source_filename = "test/DebugInfo/Generic/typedef.ll" @y = global i8* null, align 8, !dbg !0 !llvm.dbg.cu = !{!5} !llvm.module.flags = !{!8, !9} !llvm.ident = !{!10} !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = !DIGlobalVariable(name: "y", scope: null, file: !2, line: 2, type: !3, isLocal: false, isDefinition: true) !2 = !DIFile(filename: "typedef.cpp", directory: "/tmp/dbginfo") !3 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !4, size: 64, align: 64) !4 = !DIDerivedType(tag: DW_TAG_typedef, name: "x", file: !2, line: 1, baseType: null) !5 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, producer: "clang version 3.5.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !6, retainedTypes: !6, globals: !7, imports: !6) !6 = !{} !7 = !{!0} !8 = !{i32 2, !"Dwarf Version", i32 4} !9 = !{i32 1, !"Debug Info Version", i32 3} !10 = !{!"clang version 3.5.0 "} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/varargs.ll000066400000000000000000000102451363521741200235730ustar00rootroot00000000000000; REQUIRES: object-emission ; ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 -filetype=obj %t.ll -o - | llvm-dwarfdump -v -debug-info - | FileCheck %s ; Test debug info for variadic function arguments. ; Created from tools/clang/tests/CodeGenCXX/debug-info-varargs.cpp with the ; function pointer removed. ; ; The ... parameter of variadic should be emitted as ; DW_TAG_unspecified_parameters. ; ; Normal variadic function. ; void b(int c, ...); ; ; CHECK: DW_TAG_subprogram ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "b" ; CHECK-NOT: DW_TAG ; CHECK: DW_TAG_formal_parameter ; CHECK-NOT: DW_TAG ; CHECK: DW_TAG_variable ; CHECK-NOT: DW_TAG ; CHECK: DW_TAG_unspecified_parameters ; ; CHECK: DW_TAG_subprogram ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "a" ; CHECK-NOT: DW_TAG ; CHECK: DW_TAG_formal_parameter ; CHECK-NOT: DW_TAG ; CHECK: DW_TAG_formal_parameter ; CHECK-NOT: DW_TAG ; CHECK: DW_TAG_unspecified_parameters ; ; Variadic C++ member function. ; struct A { void a(int c, ...); } ; ; ModuleID = 'debug-info-varargs.cpp' source_filename = "debug-info-varargs.cpp" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" target triple = "spir64-unknown-unknown" %struct.A = type { i8 } ; Function Attrs: noinline nounwind optnone define spir_func void @_Z1biz(i32 %c, ...) #0 !dbg !6 { entry: %c.addr = alloca i32, align 4 %a = alloca %struct.A, align 1 store i32 %c, i32* %c.addr, align 4 call void @llvm.dbg.declare(metadata i32* %c.addr, metadata !11, metadata !DIExpression()), !dbg !12 call void @llvm.dbg.declare(metadata %struct.A* %a, metadata !13, metadata !DIExpression()), !dbg !20 ret void, !dbg !21 } ; Function Attrs: nounwind readnone speculatable declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 attributes #0 = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { nounwind readnone speculatable } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!3, !4} !opencl.used.extensions = !{!2} !opencl.used.optional.core.features = !{!2} !opencl.compiler.options = !{!2} !llvm.ident = !{!5} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 8.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) !1 = !DIFile(filename: "", directory: "/tmp") !2 = !{} !3 = !{i32 2, !"Debug Info Version", i32 3} !4 = !{i32 1, !"wchar_size", i32 4} !5 = !{!"clang version 8.0.0 "} !6 = distinct !DISubprogram(name: "b", linkageName: "_Z1biz", scope: !7, file: !7, line: 11, type: !8, isLocal: false, isDefinition: true, scopeLine: 11, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) !7 = !DIFile(filename: "debug-info-varargs.cpp", directory: "/tmp") !8 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !9) !9 = !{null, !10, null} !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) !11 = !DILocalVariable(name: "c", arg: 1, scope: !6, file: !7, line: 11, type: !10) !12 = !DILocation(line: 11, scope: !6) !13 = !DILocalVariable(name: "a", scope: !6, file: !7, line: 23, type: !14) !14 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !7, line: 3, size: 8, flags: DIFlagTypePassByValue, elements: !15, identifier: "_ZTS1A") !15 = !{!16} !16 = !DISubprogram(name: "a", linkageName: "_ZN1A1aEiz", scope: !14, file: !7, line: 5, type: !17, isLocal: false, isDefinition: false, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: false) !17 = !DISubroutineType(types: !18) !18 = !{null, !19, !10, null} !19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !14, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) !20 = !DILocation(line: 23, scope: !6) !21 = !DILocation(line: 29, scope: !6) SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/Generic/version.ll000066400000000000000000000034231363521741200236130ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 -filetype=obj < %t.ll > %t ; RUN: llvm-dwarfdump %t | FileCheck %s ; Make sure we are generating DWARF version 3 when module flag says so. ; CHECK: Compile Unit: length = {{.*}} version = 0x0003 define i32 @main() #0 !dbg !4 { entry: %retval = alloca i32, align 4 store i32 0, i32* %retval ret i32 0, !dbg !10 } attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!9, !11} !0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.4 (trunk 185475)", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) !1 = !DIFile(filename: "CodeGen/dwarf-version.c", directory: "test") !2 = !{} !4 = distinct !DISubprogram(name: "main", line: 6, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 6, file: !1, scope: !5, type: !6, retainedNodes: !2) !5 = !DIFile(filename: "CodeGen/dwarf-version.c", directory: "test") !6 = !DISubroutineType(types: !7) !7 = !{!8} !8 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !9 = !{i32 2, !"Dwarf Version", i32 3} !10 = !DILocation(line: 7, scope: !4) !11 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/LocalAddressSpace.ll000066400000000000000000000074341363521741200240740ustar00rootroot00000000000000; Source: ;__kernel void foo(void) { ; __local int a; ;} ; clang -cc1 -triple spir -disable-llvm-passes -triple spir /work/tmp/tmp.cl -O0 -debug-info-kind=standalone -emit-llvm -o /work/llvm/projects/llvm-spirv/test/DebugInfo/LocalAddressSpace.ll ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv %t.bc -o - -spirv-text -spirv-mem2reg=false | FileCheck %s --check-prefix=CHECK-SPIRV ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: cat %t.ll | FileCheck %s --check-prefix=CHECK-LLVM ; RUN: llc -mtriple=%triple -filetype=obj -O0 < %t.ll | llvm-dwarfdump -v -debug-info - | FileCheck %s ; CHECK-SPIRV: Variable {{[0-9]+}} [[foo_a:[0-9]+]] ; CHECK-SPIRV: DebugGlobalVariable {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} [[foo_a]] ; CHECK-LLVM: @foo.a = internal addrspace(3) global i32 undef, align 4, !dbg ![[a_dbg_expr:[0-9]+]] ; CHECK-LLVM: ![[a_dbg_expr]] = !DIGlobalVariableExpression(var: ![[a_dbg_var:[0-9]+]], ; CHECK-LLVM: ![[a_dbg_var]] = distinct !DIGlobalVariable(name: "a" ; CHECK: DW_TAG_variable ; CHECK-NEXT: DW_AT_name {{.*}} = "a") ; CHECK-NEXT: DW_AT_type {{.*}} "int") ; CHECK-NEXT: DW_AT_decl_file {{.*}} ("/work/tmp{{[/\\]}}tmp.cl") ; CHECK-NEXT: DW_AT_decl_line {{.*}} (2) ; CHECK-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addr 0x0) ; ModuleID = '/work/tmp/tmp.cl' source_filename = "/work/tmp/tmp.cl" target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" target triple = "spir" @foo.a = internal addrspace(3) global i32 undef, align 4, !dbg !0 ; Function Attrs: convergent noinline nounwind optnone define spir_kernel void @foo() #0 !dbg !2 !kernel_arg_addr_space !8 !kernel_arg_access_qual !8 !kernel_arg_type !8 !kernel_arg_base_type !8 !kernel_arg_type_qual !8 { entry: ret void, !dbg !16 } attributes #0 = { convergent noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "denorms-are-zero"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "uniform-work-group-size"="true" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.dbg.cu = !{!6} !llvm.module.flags = !{!11, !12} !opencl.ocl.version = !{!13} !opencl.spir.version = !{!14} !llvm.ident = !{!15} !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 2, type: !10, isLocal: true, isDefinition: true) !2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 1, type: !4, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !8) !3 = !DIFile(filename: "tmp/tmp.cl", directory: "/work") !4 = !DISubroutineType(cc: DW_CC_LLVM_OpenCLKernel, types: !5) !5 = !{null} !6 = distinct !DICompileUnit(language: DW_LANG_C99, file: !7, producer: "clang version 9.0.0 (https://llvm.org/git/clang 92470c6aadff9e614bfac44f48e6e1d430e5a32d) (https://llvm.org/git/llvm 461a7ee6493f997d6dc03ca0e80b6a7bd7943a83)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !8, globals: !9, nameTableKind: None) !7 = !DIFile(filename: "/work/tmp/", directory: "/work/llvm/build") !8 = !{} !9 = !{!0} !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) !11 = !{i32 2, !"Debug Info Version", i32 3} !12 = !{i32 1, !"wchar_size", i32 4} !13 = !{i32 1, i32 0} !14 = !{i32 1, i32 2} !15 = !{!"clang version 9.0.0 (https://llvm.org/git/clang 92470c6aadff9e614bfac44f48e6e1d430e5a32d) (https://llvm.org/git/llvm 461a7ee6493f997d6dc03ca0e80b6a7bd7943a83)"} !16 = !DILocation(line: 3, scope: !2) SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/RecursiveDebugInfo.ll000066400000000000000000000326541363521741200243140ustar00rootroot00000000000000; Test checks that the translator converts debug info correctly and ; doesn't crash if the module has recursive template parameters definition. ; This LLVM IR was generated using Intel SYCL Clang compiler (https://github.com/intel/llvm) ; recursive_debug_info.cpp: ; ; namespace s = cl::sycl; ; ; template ; struct iterator { ; int *Itr; ; iterator() : Itr(nullptr) {} ; iterator(int* itr) : Itr(itr) {} ; }; ; ; struct vector { ; int *Start; ; typedef iterator vec_it; ; vec_it begin() { ; return vec_it(Start); ; } ; }; ; ; class foo; ; ; int main() { ; s::queue q; ; auto e = q.submit([=](s::handler &cgh) { ; cgh.single_task([=]() { ; iterator IV; ; vector V; ; }); ; }); ; e.wait(); ; return 0; ; } ; RUN: llvm-as %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ; RUN: llvm-dis < %t.rev.bc | FileCheck %s ; CHECK: [[IT_VEC:![0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "iterator", {{.+}}, templateParams: [[TMPL_P:![0-9]+]] ; CHECK: [[TMPL_P]] = !{[[TMPL_P1:![0-9]+]]} ; CHECK: [[TMPL_P1]] = !DITemplateTypeParameter(name: "Container", type: [[CTNR_TY:![0-9]+]]) ; CHECK: [[CTNR_TY]] = !DICompositeType(tag: DW_TAG_structure_type, name: "vector", {{.+}}, elements: [[ELMS:![0-9]+]] ; CHECK: [[ELMS]] = !{!{{[0-9]+}}, [[EL2:![0-9]+]]} ; CHECK: [[EL2]] = !DISubprogram(name: "begin", {{.+}}, type: [[SPRG_TY:![0-9]+]] ; CHECK: [[SPRG_TY]] = !DISubroutineType(types: [[FNC_TYS:![0-9]+]]) ; CHECK: [[FNC_TYS]] = !{[[FNC_TY1:![0-9]+]], !{{[0-9]+}}} ; CHECK: [[FNC_TY1]] = !DIDerivedType(tag: DW_TAG_typedef, name: "vec_it", {{.+}}, baseType: [[IT_VEC]]) target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" target triple = "spir64-unknown-unknown-sycldevice" %"class._ZTSZZ4mainENK3$_0clERN2cl4sycl7handlerEEUlvE_.anon" = type { i8 } %struct._ZTS8iteratorI6vectorE.iterator = type { i32 addrspace(4)* } %struct._ZTS6vector.vector = type { i32 addrspace(4)* } $_ZTS3foo = comdat any $_ZN8iteratorI6vectorEC2Ev = comdat any define weak_odr dso_local spir_kernel void @_ZTS3foo() #0 comdat !dbg !12 !kernel_arg_addr_space !10 !kernel_arg_access_qual !10 !kernel_arg_type !10 !kernel_arg_base_type !10 !kernel_arg_type_qual !10 !kernel_arg_host_accessible !10 !kernel_arg_pipe_depth !10 !kernel_arg_pipe_io !10 !kernel_arg_buffer_location !10 { entry: %0 = alloca %"class._ZTSZZ4mainENK3$_0clERN2cl4sycl7handlerEEUlvE_.anon", align 1 %1 = bitcast %"class._ZTSZZ4mainENK3$_0clERN2cl4sycl7handlerEEUlvE_.anon"* %0 to i8* call void @llvm.lifetime.start.p0i8(i64 1, i8* %1) #5 call void @llvm.dbg.declare(metadata %"class._ZTSZZ4mainENK3$_0clERN2cl4sycl7handlerEEUlvE_.anon"* %0, metadata !15, metadata !DIExpression()), !dbg !23 %2 = addrspacecast %"class._ZTSZZ4mainENK3$_0clERN2cl4sycl7handlerEEUlvE_.anon"* %0 to %"class._ZTSZZ4mainENK3$_0clERN2cl4sycl7handlerEEUlvE_.anon" addrspace(4)*, !dbg !24 call spir_func void @"_ZZZ4mainENK3$_0clERN2cl4sycl7handlerEENKUlvE_clEv"(%"class._ZTSZZ4mainENK3$_0clERN2cl4sycl7handlerEEUlvE_.anon" addrspace(4)* %2), !dbg !24 %3 = bitcast %"class._ZTSZZ4mainENK3$_0clERN2cl4sycl7handlerEEUlvE_.anon"* %0 to i8*, !dbg !23 call void @llvm.lifetime.end.p0i8(i64 1, i8* %3) #5, !dbg !23 ret void } ; Function Attrs: argmemonly nounwind willreturn declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1 ; Function Attrs: nounwind readnone speculatable willreturn declare void @llvm.dbg.declare(metadata, metadata, metadata) #2 ; Function Attrs: inlinehint define internal spir_func void @"_ZZZ4mainENK3$_0clERN2cl4sycl7handlerEENKUlvE_clEv"(%"class._ZTSZZ4mainENK3$_0clERN2cl4sycl7handlerEEUlvE_.anon" addrspace(4)* %this) #3 align 2 !dbg !26 { entry: %this.addr = alloca %"class._ZTSZZ4mainENK3$_0clERN2cl4sycl7handlerEEUlvE_.anon" addrspace(4)*, align 8 %IV = alloca %struct._ZTS8iteratorI6vectorE.iterator, align 8 %V = alloca %struct._ZTS6vector.vector, align 8 store %"class._ZTSZZ4mainENK3$_0clERN2cl4sycl7handlerEEUlvE_.anon" addrspace(4)* %this, %"class._ZTSZZ4mainENK3$_0clERN2cl4sycl7handlerEEUlvE_.anon" addrspace(4)** %this.addr, align 8, !tbaa !52 call void @llvm.dbg.declare(metadata %"class._ZTSZZ4mainENK3$_0clERN2cl4sycl7handlerEEUlvE_.anon" addrspace(4)** %this.addr, metadata !28, metadata !DIExpression()), !dbg !56 %0 = bitcast %struct._ZTS8iteratorI6vectorE.iterator* %IV to i8*, !dbg !57 call void @llvm.lifetime.start.p0i8(i64 8, i8* %0) #5, !dbg !57 call void @llvm.dbg.declare(metadata %struct._ZTS8iteratorI6vectorE.iterator* %IV, metadata !30, metadata !DIExpression()), !dbg !58 %1 = addrspacecast %struct._ZTS8iteratorI6vectorE.iterator* %IV to %struct._ZTS8iteratorI6vectorE.iterator addrspace(4)*, !dbg !58 call spir_func void @_ZN8iteratorI6vectorEC2Ev(%struct._ZTS8iteratorI6vectorE.iterator addrspace(4)* %1), !dbg !58 %2 = bitcast %struct._ZTS6vector.vector* %V to i8*, !dbg !59 call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) #5, !dbg !59 call void @llvm.dbg.declare(metadata %struct._ZTS6vector.vector* %V, metadata !51, metadata !DIExpression()), !dbg !60 %3 = bitcast %struct._ZTS6vector.vector* %V to i8*, !dbg !61 call void @llvm.lifetime.end.p0i8(i64 8, i8* %3) #5, !dbg !61 %4 = bitcast %struct._ZTS8iteratorI6vectorE.iterator* %IV to i8*, !dbg !61 call void @llvm.lifetime.end.p0i8(i64 8, i8* %4) #5, !dbg !61 ret void, !dbg !61 } ; Function Attrs: argmemonly nounwind willreturn declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1 ; Function Attrs: nounwind define linkonce_odr dso_local spir_func void @_ZN8iteratorI6vectorEC2Ev(%struct._ZTS8iteratorI6vectorE.iterator addrspace(4)* %this) unnamed_addr #4 comdat align 2 !dbg !62 { entry: %this.addr = alloca %struct._ZTS8iteratorI6vectorE.iterator addrspace(4)*, align 8 store %struct._ZTS8iteratorI6vectorE.iterator addrspace(4)* %this, %struct._ZTS8iteratorI6vectorE.iterator addrspace(4)** %this.addr, align 8, !tbaa !52 call void @llvm.dbg.declare(metadata %struct._ZTS8iteratorI6vectorE.iterator addrspace(4)** %this.addr, metadata !64, metadata !DIExpression()), !dbg !66 %this1 = load %struct._ZTS8iteratorI6vectorE.iterator addrspace(4)*, %struct._ZTS8iteratorI6vectorE.iterator addrspace(4)** %this.addr, align 8 %Itr = getelementptr inbounds %struct._ZTS8iteratorI6vectorE.iterator, %struct._ZTS8iteratorI6vectorE.iterator addrspace(4)* %this1, i32 0, i32 0, !dbg !67 store i32 addrspace(4)* null, i32 addrspace(4)* addrspace(4)* %Itr, align 8, !dbg !67, !tbaa !68 ret void, !dbg !70 } attributes #0 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "sycl-module-id"="recursive_debug_info.cpp" "uniform-work-group-size"="true" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { argmemonly nounwind willreturn } attributes #2 = { nounwind readnone speculatable willreturn } attributes #3 = { inlinehint "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #4 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #5 = { nounwind } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!5, !6, !7} !opencl.spir.version = !{!8} !spirv.Source = !{!9} !opencl.used.extensions = !{!10} !opencl.used.optional.core.features = !{!10} !opencl.compiler.options = !{!10} !llvm.ident = !{!11} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_11, file: !1, producer: "clang version 10.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, nameTableKind: None) !1 = !DIFile(filename: "recursive_debug_info.cpp", directory: "/localdisk/test") !2 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) !3 = !{null} !4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !2, size: 64) !5 = !{i32 7, !"Dwarf Version", i32 4} !6 = !{i32 2, !"Debug Info Version", i32 3} !7 = !{i32 1, !"wchar_size", i32 4} !8 = !{i32 1, i32 2} !9 = !{i32 4, i32 100000} !10 = !{} !11 = !{!"clang version 10.0.0"} !12 = distinct !DISubprogram(name: "_ZTS3foo", scope: !1, file: !1, line: 28, type: !13, flags: DIFlagArtificial | DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !14) !13 = !DISubroutineType(cc: DW_CC_LLVM_OpenCLKernel, types: !3) !14 = !{!15} !15 = !DILocalVariable(scope: !12, file: !1, type: !16) !16 = distinct !DICompositeType(tag: DW_TAG_class_type, file: !1, line: 28, size: 8, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !17) !17 = !{!18} !18 = !DISubprogram(name: "operator()", scope: !16, file: !1, line: 28, type: !19, scopeLine: 28, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagOptimized) !19 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !20) !20 = !{null, !21} !21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !22, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) !22 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !16) !23 = !DILocation(line: 0, scope: !12) !24 = !DILocation(line: 0, scope: !25) !25 = distinct !DILexicalBlock(scope: !12, file: !1) !26 = distinct !DISubprogram(name: "operator()", linkageName: "_ZZZ4mainENK3$_0clERN2cl4sycl7handlerEENKUlvE_clEv", scope: !16, file: !1, line: 28, type: !19, scopeLine: 28, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0, declaration: !18, retainedNodes: !27) !27 = !{!28, !30, !51} !28 = !DILocalVariable(name: "this", arg: 1, scope: !26, type: !29, flags: DIFlagArtificial | DIFlagObjectPointer) !29 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !22, size: 64) !30 = !DILocalVariable(name: "IV", scope: !26, file: !1, line: 29, type: !31) !31 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "iterator", file: !1, line: 6, size: 64, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !32, templateParams: !41, identifier: "_ZTS8iteratorI6vectorE") !32 = !{!33, !34, !38} !33 = !DIDerivedType(tag: DW_TAG_member, name: "Itr", scope: !31, file: !1, line: 7, baseType: !4, size: 64) !34 = !DISubprogram(name: "iterator", scope: !31, file: !1, line: 9, type: !35, scopeLine: 9, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized) !35 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !36) !36 = !{null, !37} !37 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !31, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) !38 = !DISubprogram(name: "iterator", scope: !31, file: !1, line: 10, type: !39, scopeLine: 10, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized) !39 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !40) !40 = !{null, !37, !4} !41 = !{!42} !42 = !DITemplateTypeParameter(name: "Container", type: !43) !43 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "vector", file: !1, line: 13, size: 64, flags: DIFlagTypePassByValue, elements: !44, identifier: "_ZTS6vector") !44 = !{!45, !46} !45 = !DIDerivedType(tag: DW_TAG_member, name: "Start", scope: !43, file: !1, line: 14, baseType: !4, size: 64) !46 = !DISubprogram(name: "begin", linkageName: "_ZN6vector5beginEv", scope: !43, file: !1, line: 18, type: !47, scopeLine: 18, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized) !47 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !48) !48 = !{!49, !50} !49 = !DIDerivedType(tag: DW_TAG_typedef, name: "vec_it", scope: !43, file: !1, line: 16, baseType: !31) !50 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !43, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) !51 = !DILocalVariable(name: "V", scope: !26, file: !1, line: 30, type: !43) !52 = !{!53, !53, i64 0} !53 = !{!"any pointer", !54, i64 0} !54 = !{!"omnipotent char", !55, i64 0} !55 = !{!"Simple C++ TBAA"} !56 = !DILocation(line: 0, scope: !26) !57 = !DILocation(line: 29, column: 7, scope: !26) !58 = !DILocation(line: 29, column: 24, scope: !26) !59 = !DILocation(line: 30, column: 7, scope: !26) !60 = !DILocation(line: 30, column: 14, scope: !26) !61 = !DILocation(line: 31, column: 5, scope: !26) !62 = distinct !DISubprogram(name: "iterator", linkageName: "_ZN8iteratorI6vectorEC2Ev", scope: !31, file: !1, line: 9, type: !35, scopeLine: 9, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, declaration: !34, retainedNodes: !63) !63 = !{!64} !64 = !DILocalVariable(name: "this", arg: 1, scope: !62, type: !65, flags: DIFlagArtificial | DIFlagObjectPointer) !65 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !31, size: 64) !66 = !DILocation(line: 0, scope: !62) !67 = !DILocation(line: 9, column: 16, scope: !62) !68 = !{!69, !53, i64 0} !69 = !{!"_ZTS8iteratorI6vectorE", !53, i64 0} !70 = !DILocation(line: 9, column: 30, scope: !62) SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/UnknownBaseType.ll000066400000000000000000000052171363521741200236510ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple < %t.ll -filetype=obj | llvm-dwarfdump -debug-info - | FileCheck %s ; Check that translator doesn't crash when it encounter basic type encoding ; (e.g. DW_ATE_complex_float) which is missing in the spec. ; CHECK: DW_TAG_unspecified_type ; CHECK-NEXT: DW_AT_name ("complex") target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" target triple = "spir-unknown-unknown" ; Function Attrs: convergent nounwind define spir_func void @foo({ float, float }* byval align 4 %f) #0 !dbg !7 { entry: call void @llvm.dbg.declare(metadata { float, float }* %f, metadata !13, metadata !DIExpression()), !dbg !14 ret void, !dbg !14 } ; Function Attrs: nounwind readnone speculatable declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 attributes #0 = { convergent nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "denorms-are-zero"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { nounwind readnone speculatable } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!3, !4} !opencl.ocl.version = !{!5} !opencl.spir.version = !{!5} !llvm.ident = !{!6} !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 9.0.0 (https://llvm.org/git/clang 1b09e8845172eccc47c896f546fa30805da53d51) (https://llvm.org/git/llvm 384f64397f6ad95a361b72d62c07d7bac9f24163)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) !1 = !DIFile(filename: "", directory: "/tmp") !2 = !{} !3 = !{i32 2, !"Debug Info Version", i32 3} !4 = !{i32 1, !"wchar_size", i32 4} !5 = !{i32 2, i32 0} !6 = !{!"clang version 9.0.0"} !7 = distinct !DISubprogram(name: "foo", scope: !8, file: !8, line: 1, type: !9, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12) !8 = !DIFile(filename: "tmp.cl", directory: "/tmp") !9 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !10) !10 = !{null, !11} !11 = !DIBasicType(name: "complex", size: 64, encoding: DW_ATE_complex_float) !12 = !{!13} !13 = !DILocalVariable(name: "f", arg: 1, scope: !7, file: !8, line: 1, type: !11) !14 = !DILocation(line: 1, scope: !7) SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/000077500000000000000000000000001363521741200206045ustar00rootroot00000000000000SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/2010-04-13-PubType.ll000066400000000000000000000065661363521741200235640ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -O0 -asm-verbose -mtriple=x86_64-macosx -debugger-tune=gdb < %t.ll | FileCheck %s ; CHECK-NOT: .asciz "X" ## External Name ; CHECK: .asciz "Y" ## External Name ; Test to check type with no definition is listed in pubtypes section. %struct.X = type opaque %struct.Y = type { i32 } define i32 @foo(%struct.X* %x, %struct.Y* %y) nounwind ssp !dbg !1 { entry: %x_addr = alloca %struct.X* ; <%struct.X**> [#uses=1] %y_addr = alloca %struct.Y* ; <%struct.Y**> [#uses=1] %retval = alloca i32 ; [#uses=2] %0 = alloca i32 ; [#uses=2] %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] call void @llvm.dbg.declare(metadata %struct.X** %x_addr, metadata !0, metadata !DIExpression()), !dbg !13 store %struct.X* %x, %struct.X** %x_addr call void @llvm.dbg.declare(metadata %struct.Y** %y_addr, metadata !14, metadata !DIExpression()), !dbg !13 store %struct.Y* %y, %struct.Y** %y_addr store i32 0, i32* %0, align 4, !dbg !13 %1 = load i32, i32* %0, align 4, !dbg !13 ; [#uses=1] store i32 %1, i32* %retval, align 4, !dbg !13 br label %return, !dbg !13 return: ; preds = %entry %retval1 = load i32, i32* %retval, !dbg !13 ; [#uses=1] ret i32 %retval1, !dbg !15 } declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone !llvm.dbg.cu = !{!3} !llvm.module.flags = !{!20} !0 = !DILocalVariable(name: "x", line: 7, arg: 1, scope: !1, file: !2, type: !7) !1 = distinct !DISubprogram(name: "foo", linkageName: "foo", line: 7, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !3, scopeLine: 7, file: !18, scope: !2, type: !4) !2 = !DIFile(filename: "a.c", directory: "/tmp/") !3 = distinct !DICompileUnit(language: DW_LANG_C89, producer: "4.2.1 (Based on Apple Inc. build 5658) (LLVM build)", isOptimized: false, emissionKind: FullDebug, file: !18, enums: !19, retainedTypes: !19, imports: null) !4 = !DISubroutineType(types: !5) !5 = !{!6, !7, !9} !6 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !7 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, file: !18, scope: !2, baseType: !8) !8 = !DICompositeType(tag: DW_TAG_structure_type, name: "X", line: 3, flags: DIFlagFwdDecl, file: !18, scope: !2) !9 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, file: !18, scope: !2, baseType: !10) !10 = !DICompositeType(tag: DW_TAG_structure_type, name: "Y", line: 4, size: 32, align: 32, file: !18, scope: !2, elements: !11) !11 = !{!12} !12 = !DIDerivedType(tag: DW_TAG_member, name: "x", line: 5, size: 32, align: 32, file: !18, scope: !10, baseType: !6) !13 = !DILocation(line: 7, scope: !1) !14 = !DILocalVariable(name: "y", line: 7, arg: 2, scope: !1, file: !2, type: !9) !15 = !DILocation(line: 7, scope: !16) !16 = distinct !DILexicalBlock(line: 7, column: 0, file: !18, scope: !1) !18 = !DIFile(filename: "a.c", directory: "/tmp/") !19 = !{} !20 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/2011-09-26-GlobalVarContext.ll000066400000000000000000000055001363521741200254070ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=x86_64-pc-linux-gnu %t.ll -o %t -filetype=obj ; RUN: llvm-dwarfdump -v -debug-info %t | FileCheck %s ; ModuleID = 'test.c' source_filename = "test/DebugInfo/X86/2011-09-26-GlobalVarContext.ll" @GLB = common global i32 0, align 4, !dbg !0 ; Function Attrs: nounwind define i32 @f() #0 !dbg !8 { %LOC = alloca i32, align 4 call void @llvm.dbg.declare(metadata i32* %LOC, metadata !11, metadata !13), !dbg !14 %1 = load i32, i32* @GLB, align 4, !dbg !15 store i32 %1, i32* %LOC, align 4, !dbg !15 %2 = load i32, i32* @GLB, align 4, !dbg !16 ret i32 %2, !dbg !16 } ; Function Attrs: nounwind readnone declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 attributes #0 = { nounwind } attributes #1 = { nounwind readnone } !llvm.dbg.cu = !{!4} !llvm.module.flags = !{!7} !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = !DIGlobalVariable(name: "GLB", scope: null, file: !2, line: 1, type: !3, isLocal: false, isDefinition: true) !2 = !DIFile(filename: "test.c", directory: "/work/llvm/vanilla/test/DebugInfo") !3 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !4 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang version 3.0 (trunk)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !5) !5 = !{} !6 = !{!0} !7 = !{i32 1, !"Debug Info Version", i32 3} !8 = distinct !DISubprogram(name: "f", scope: !2, file: !2, line: 3, type: !9, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !4) !9 = !DISubroutineType(types: !10) !10 = !{!3} !11 = !DILocalVariable(name: "LOC", scope: !12, file: !2, line: 4, type: !3) !12 = distinct !DILexicalBlock(scope: !8, file: !2, line: 3, column: 9) !13 = !DIExpression() !14 = !DILocation(line: 4, column: 9, scope: !12) !15 = !DILocation(line: 4, column: 23, scope: !12) !16 = !DILocation(line: 5, column: 5, scope: !12) ; CHECK: DW_TAG_variable ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x{{[0-9a-f]*}}] = "GLB") ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_decl_file [DW_FORM_data1] ("/work/llvm/vanilla/test/DebugInfo{{[/\\]}}test.c") ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_decl_line [DW_FORM_data1] (1) ; CHECK: DW_TAG_variable ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x{{[0-9a-f]*}}] = "LOC") ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_decl_file [DW_FORM_data1] ("/work/llvm/vanilla/test/DebugInfo{{[/\\]}}test.c") ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_decl_line [DW_FORM_data1] (4) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/2011-12-16-BadStructRef.ll000066400000000000000000000244541363521741200245230ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=x86_64-apple-macosx10.7 %t.ll -o %t -filetype=obj ; RUN: llvm-dwarfdump -debug-info %t | FileCheck %s ; CHECK: b_ref ; CHECK-NOT: AT_bit_size %struct.bar = type { %struct.baz, %struct.baz* } %struct.baz = type { i32 } define i32 @main(i32 %argc, i8** %argv) uwtable ssp !dbg !29 { entry: %retval = alloca i32, align 4 %argc.addr = alloca i32, align 4 %argv.addr = alloca i8**, align 8 %myBar = alloca %struct.bar, align 8 store i32 0, i32* %retval store i32 %argc, i32* %argc.addr, align 4 call void @llvm.dbg.declare(metadata i32* %argc.addr, metadata !49, metadata !DIExpression()), !dbg !50 store i8** %argv, i8*** %argv.addr, align 8 call void @llvm.dbg.declare(metadata i8*** %argv.addr, metadata !51, metadata !DIExpression()), !dbg !52 call void @llvm.dbg.declare(metadata %struct.bar* %myBar, metadata !53, metadata !DIExpression()), !dbg !55 call void @_ZN3barC1Ei(%struct.bar* %myBar, i32 1), !dbg !56 ret i32 0, !dbg !57 } declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone define linkonce_odr void @_ZN3barC1Ei(%struct.bar* %this, i32 %x) unnamed_addr uwtable ssp align 2 !dbg !37 { entry: %this.addr = alloca %struct.bar*, align 8 %x.addr = alloca i32, align 4 store %struct.bar* %this, %struct.bar** %this.addr, align 8 call void @llvm.dbg.declare(metadata %struct.bar** %this.addr, metadata !58, metadata !DIExpression()), !dbg !59 store i32 %x, i32* %x.addr, align 4 call void @llvm.dbg.declare(metadata i32* %x.addr, metadata !60, metadata !DIExpression()), !dbg !61 %this1 = load %struct.bar*, %struct.bar** %this.addr %0 = load i32, i32* %x.addr, align 4, !dbg !62 call void @_ZN3barC2Ei(%struct.bar* %this1, i32 %0), !dbg !62 ret void, !dbg !62 } define linkonce_odr void @_ZN3barC2Ei(%struct.bar* %this, i32 %x) unnamed_addr uwtable ssp align 2 !dbg !40 { entry: %this.addr = alloca %struct.bar*, align 8 %x.addr = alloca i32, align 4 store %struct.bar* %this, %struct.bar** %this.addr, align 8 call void @llvm.dbg.declare(metadata %struct.bar** %this.addr, metadata !63, metadata !DIExpression()), !dbg !64 store i32 %x, i32* %x.addr, align 4 call void @llvm.dbg.declare(metadata i32* %x.addr, metadata !65, metadata !DIExpression()), !dbg !66 %this1 = load %struct.bar*, %struct.bar** %this.addr %b = getelementptr inbounds %struct.bar, %struct.bar* %this1, i32 0, i32 0, !dbg !67 %0 = load i32, i32* %x.addr, align 4, !dbg !67 call void @_ZN3bazC1Ei(%struct.baz* %b, i32 %0), !dbg !67 %1 = getelementptr inbounds %struct.bar, %struct.bar* %this1, i32 0, i32 1, !dbg !67 %b2 = getelementptr inbounds %struct.bar, %struct.bar* %this1, i32 0, i32 0, !dbg !67 store %struct.baz* %b2, %struct.baz** %1, align 8, !dbg !67 ret void, !dbg !68 } define linkonce_odr void @_ZN3bazC1Ei(%struct.baz* %this, i32 %a) unnamed_addr uwtable ssp align 2 !dbg !43 { entry: %this.addr = alloca %struct.baz*, align 8 %a.addr = alloca i32, align 4 store %struct.baz* %this, %struct.baz** %this.addr, align 8 call void @llvm.dbg.declare(metadata %struct.baz** %this.addr, metadata !70, metadata !DIExpression()), !dbg !71 store i32 %a, i32* %a.addr, align 4 call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !72, metadata !DIExpression()), !dbg !73 %this1 = load %struct.baz*, %struct.baz** %this.addr %0 = load i32, i32* %a.addr, align 4, !dbg !74 call void @_ZN3bazC2Ei(%struct.baz* %this1, i32 %0), !dbg !74 ret void, !dbg !74 } define linkonce_odr void @_ZN3bazC2Ei(%struct.baz* %this, i32 %a) unnamed_addr nounwind uwtable ssp align 2 !dbg !46 { entry: %this.addr = alloca %struct.baz*, align 8 %a.addr = alloca i32, align 4 store %struct.baz* %this, %struct.baz** %this.addr, align 8 call void @llvm.dbg.declare(metadata %struct.baz** %this.addr, metadata !75, metadata !DIExpression()), !dbg !76 store i32 %a, i32* %a.addr, align 4 call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !77, metadata !DIExpression()), !dbg !78 %this1 = load %struct.baz*, %struct.baz** %this.addr %h = getelementptr inbounds %struct.baz, %struct.baz* %this1, i32 0, i32 0, !dbg !79 %0 = load i32, i32* %a.addr, align 4, !dbg !79 store i32 %0, i32* %h, align 4, !dbg !79 ret void, !dbg !80 } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!83} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.1 (trunk 146596)", isOptimized: false, emissionKind: FullDebug, file: !82, enums: !1, retainedTypes: !3, globals: !1, imports: !1) !1 = !{} !3 = !{!5, !9} !5 = !DICompositeType(tag: DW_TAG_class_type, name: "bar", line: 9, size: 128, align: 64, file: !82, elements: !7) !6 = !DIFile(filename: "main.cpp", directory: "/Users/echristo/tmp/bad-struct-ref") !7 = !{!8, !19, !21} !8 = !DIDerivedType(tag: DW_TAG_member, name: "b", line: 11, size: 32, align: 32, file: !82, scope: !5, baseType: !9) !9 = !DICompositeType(tag: DW_TAG_class_type, name: "baz", line: 3, size: 32, align: 32, file: !82, elements: !10) !10 = !{!11, !13} !11 = !DIDerivedType(tag: DW_TAG_member, name: "h", line: 5, size: 32, align: 32, file: !82, scope: !9, baseType: !12) !12 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !13 = !DISubprogram(name: "baz", line: 6, isLocal: false, isDefinition: false, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, file: !82, scope: !9, type: !14) !14 = !DISubroutineType(types: !15) !15 = !{null, !16, !12} !16 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, flags: DIFlagArtificial, baseType: !9) !19 = !DIDerivedType(tag: DW_TAG_member, name: "b_ref", line: 12, size: 64, align: 64, offset: 64, file: !82, scope: !5, baseType: !20) !20 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !9) !21 = !DISubprogram(name: "bar", line: 13, isLocal: false, isDefinition: false, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, file: !82, scope: !5, type: !22) !22 = !DISubroutineType(types: !23) !23 = !{null, !24, !12} !24 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, flags: DIFlagArtificial, baseType: !5) !29 = distinct !DISubprogram(name: "main", line: 17, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, file: !82, scope: !6, type: !30) !30 = !DISubroutineType(types: !31) !31 = !{!12, !12, !32} !32 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, baseType: !33) !33 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, baseType: !34) !34 = !DIBasicType(tag: DW_TAG_base_type, name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char) !35 = !{!36} !36 = !{} ; previously: invalid DW_TAG_base_type !37 = distinct !DISubprogram(name: "bar", linkageName: "_ZN3barC1Ei", line: 13, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, file: !82, scope: null, type: !22, declaration: !21) !38 = !{!39} !39 = !{} ; previously: invalid DW_TAG_base_type !40 = distinct !DISubprogram(name: "bar", linkageName: "_ZN3barC2Ei", line: 13, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, file: !82, scope: null, type: !22, declaration: !21) !41 = !{!42} !42 = !{} ; previously: invalid DW_TAG_base_type !43 = distinct !DISubprogram(name: "baz", linkageName: "_ZN3bazC1Ei", line: 6, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, file: !82, scope: null, type: !14, declaration: !13) !44 = !{!45} !45 = !{} ; previously: invalid DW_TAG_base_type !46 = distinct !DISubprogram(name: "baz", linkageName: "_ZN3bazC2Ei", line: 6, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, file: !82, scope: null, type: !14, declaration: !13) !49 = !DILocalVariable(name: "argc", line: 16, arg: 1, scope: !29, file: !6, type: !12) !50 = !DILocation(line: 16, column: 14, scope: !29) !51 = !DILocalVariable(name: "argv", line: 16, arg: 2, scope: !29, file: !6, type: !32) !52 = !DILocation(line: 16, column: 27, scope: !29) !53 = !DILocalVariable(name: "myBar", line: 18, scope: !54, file: !6, type: !5) !54 = distinct !DILexicalBlock(line: 17, column: 1, file: !82, scope: !29) !55 = !DILocation(line: 18, column: 9, scope: !54) !56 = !DILocation(line: 18, column: 17, scope: !54) !57 = !DILocation(line: 19, column: 5, scope: !54) !58 = !DILocalVariable(name: "this", line: 13, arg: 1, flags: DIFlagArtificial, scope: !37, file: !6, type: !24) !59 = !DILocation(line: 13, column: 5, scope: !37) !60 = !DILocalVariable(name: "x", line: 13, arg: 2, scope: !37, file: !6, type: !12) !61 = !DILocation(line: 13, column: 13, scope: !37) !62 = !DILocation(line: 13, column: 34, scope: !37) !63 = !DILocalVariable(name: "this", line: 13, arg: 1, flags: DIFlagArtificial, scope: !40, file: !6, type: !24) !64 = !DILocation(line: 13, column: 5, scope: !40) !65 = !DILocalVariable(name: "x", line: 13, arg: 2, scope: !40, file: !6, type: !12) !66 = !DILocation(line: 13, column: 13, scope: !40) !67 = !DILocation(line: 13, column: 33, scope: !40) !68 = !DILocation(line: 13, column: 34, scope: !69) !69 = distinct !DILexicalBlock(line: 13, column: 33, file: !82, scope: !40) !70 = !DILocalVariable(name: "this", line: 6, arg: 1, flags: DIFlagArtificial, scope: !43, file: !6, type: !16) !71 = !DILocation(line: 6, column: 5, scope: !43) !72 = !DILocalVariable(name: "a", line: 6, arg: 2, scope: !43, file: !6, type: !12) !73 = !DILocation(line: 6, column: 13, scope: !43) !74 = !DILocation(line: 6, column: 24, scope: !43) !75 = !DILocalVariable(name: "this", line: 6, arg: 1, flags: DIFlagArtificial, scope: !46, file: !6, type: !16) !76 = !DILocation(line: 6, column: 5, scope: !46) !77 = !DILocalVariable(name: "a", line: 6, arg: 2, scope: !46, file: !6, type: !12) !78 = !DILocation(line: 6, column: 13, scope: !46) !79 = !DILocation(line: 6, column: 23, scope: !46) !80 = !DILocation(line: 6, column: 24, scope: !81) !81 = distinct !DILexicalBlock(line: 6, column: 23, file: !82, scope: !46) !82 = !DIFile(filename: "main.cpp", directory: "/Users/echristo/tmp/bad-struct-ref") !83 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/DW_AT_byte_size.ll000066400000000000000000000050551363521741200241150ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=x86_64-apple-darwin %t.ll -o %t -filetype=obj ; RUN: llvm-dwarfdump -all %t | FileCheck %s ; Checks that we don't emit a size for a pointer type. ; CHECK: DW_TAG_pointer_type ; CHECK-NEXT: DW_AT_type ; CHECK-NOT: DW_AT_byte_size ; CHECK: DW_TAG ; CHECK: .debug_info contents %struct.A = type { i32 } define i32 @_Z3fooP1A(%struct.A* %a) nounwind uwtable ssp !dbg !5 { entry: %a.addr = alloca %struct.A*, align 8 store %struct.A* %a, %struct.A** %a.addr, align 8 call void @llvm.dbg.declare(metadata %struct.A** %a.addr, metadata !16, metadata !DIExpression()), !dbg !17 %0 = load %struct.A*, %struct.A** %a.addr, align 8, !dbg !18 %b = getelementptr inbounds %struct.A, %struct.A* %0, i32 0, i32 0, !dbg !18 %1 = load i32, i32* %b, align 4, !dbg !18 ret i32 %1, !dbg !18 } declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!21} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.1 (trunk 150996)", isOptimized: false, emissionKind: FullDebug, file: !20, enums: !1, retainedTypes: !1, globals: !1, imports: !1) !1 = !{} !5 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooP1A", line: 3, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 3, file: !20, scope: !6, type: !7) !6 = !DIFile(filename: "foo.cpp", directory: "/Users/echristo") !7 = !DISubroutineType(types: !8) !8 = !{!9, !10} !9 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !10 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, baseType: !11) !11 = !DICompositeType(tag: DW_TAG_class_type, name: "A", line: 1, size: 32, align: 32, file: !20, elements: !12) !12 = !{!13} !13 = !DIDerivedType(tag: DW_TAG_member, name: "b", line: 1, size: 32, align: 32, file: !20, scope: !11, baseType: !9) !16 = !DILocalVariable(name: "a", line: 3, arg: 1, scope: !5, file: !6, type: !10) !17 = !DILocation(line: 3, column: 13, scope: !5) !18 = !DILocation(line: 4, column: 3, scope: !19) !19 = distinct !DILexicalBlock(line: 3, column: 16, file: !20, scope: !5) !20 = !DIFile(filename: "foo.cpp", directory: "/Users/echristo") !21 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/DW_AT_linkage_name.ll000066400000000000000000000122651363521741200245330ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=x86_64-apple-macosx %t.ll -o %t -filetype=obj ; RUN: llvm-dwarfdump -v -debug-info %t | FileCheck %s ; ; struct A { ; A(int i); ; ~A(); ; }; ; ; A::~A() {} ; ; void foo() { ; A a(1); ; } ; ; rdar://problem/16362674 ; ; Test that we do not emit a linkage name for the declaration of a destructor. ; Test that we do emit a linkage name for a specific instance of it. ; CHECK: DW_TAG_subprogram ; CHECK: DW_TAG_subprogram ; CHECK: DW_AT_name {{.*}} "~A" ; CHECK-NOT: DW_AT_MIPS_linkage_name ; CHECK: DW_TAG_subprogram ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_MIPS_linkage_name {{.*}} "_ZN1AD2Ev" ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_specification {{.*}} "~A" target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "spir64-unknown-unknown" %struct.A = type { i8 } ; Function Attrs: nounwind ssp uwtable define void @_ZN1AD2Ev(%struct.A* %this) unnamed_addr #0 align 2 !dbg !17 { entry: %this.addr = alloca %struct.A*, align 8 store %struct.A* %this, %struct.A** %this.addr, align 8 call void @llvm.dbg.declare(metadata %struct.A** %this.addr, metadata !26, metadata !DIExpression()), !dbg !28 %this1 = load %struct.A*, %struct.A** %this.addr ret void, !dbg !29 } ; Function Attrs: nounwind readnone declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 ; Function Attrs: nounwind ssp uwtable define void @_ZN1AD1Ev(%struct.A* %this) unnamed_addr #0 align 2 !dbg !18 { entry: %this.addr = alloca %struct.A*, align 8 store %struct.A* %this, %struct.A** %this.addr, align 8 call void @llvm.dbg.declare(metadata %struct.A** %this.addr, metadata !30, metadata !DIExpression()), !dbg !31 %this1 = load %struct.A*, %struct.A** %this.addr call void @_ZN1AD2Ev(%struct.A* %this1), !dbg !32 ret void, !dbg !33 } ; Function Attrs: ssp uwtable define void @_Z3foov() #2 !dbg !19 { entry: %a = alloca %struct.A, align 1 call void @llvm.dbg.declare(metadata %struct.A* %a, metadata !34, metadata !DIExpression()), !dbg !35 call void @_ZN1AC1Ei(%struct.A* %a, i32 1), !dbg !35 call void @_ZN1AD1Ev(%struct.A* %a), !dbg !36 ret void, !dbg !36 } declare void @_ZN1AC1Ei(%struct.A*, i32) attributes #0 = { nounwind ssp uwtable } attributes #1 = { nounwind readnone } attributes #2 = { ssp uwtable } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!23, !24} !llvm.ident = !{!25} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.5.0 ", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !3, globals: !2, imports: !2) !1 = !DIFile(filename: "linkage-name.cpp", directory: "") !2 = !{} !3 = !{!4} !4 = !DICompositeType(tag: DW_TAG_structure_type, name: "A", line: 1, size: 8, align: 8, file: !1, elements: !5, identifier: "_ZTS1A") !5 = !{!6, !12} !6 = !DISubprogram(name: "A", line: 2, isLocal: false, isDefinition: false, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, scopeLine: 2, file: !1, scope: !4, type: !7) !7 = !DISubroutineType(types: !8) !8 = !{null, !9, !10} !9 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer, baseType: !4) !10 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !12 = !DISubprogram(name: "~A", line: 3, isLocal: false, isDefinition: false, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, scopeLine: 3, file: !1, scope: !4, type: !13) !13 = !DISubroutineType(types: !14) !14 = !{null, !9} !17 = distinct !DISubprogram(name: "~A", linkageName: "_ZN1AD2Ev", line: 6, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 6, file: !1, scope: !4, type: !13, declaration: !12, retainedNodes: !2) !18 = distinct !DISubprogram(name: "~A", linkageName: "_ZN1AD1Ev", line: 6, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 6, file: !1, scope: !4, type: !13, declaration: !12, retainedNodes: !2) !19 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", line: 10, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 10, file: !1, scope: !20, type: !21, retainedNodes: !2) !20 = !DIFile(filename: "linkage-name.cpp", directory: "") !21 = !DISubroutineType(types: !22) !22 = !{null} !23 = !{i32 2, !"Dwarf Version", i32 2} !24 = !{i32 1, !"Debug Info Version", i32 3} !25 = !{!"clang version 3.5.0 "} !26 = !DILocalVariable(name: "this", arg: 1, flags: DIFlagArtificial | DIFlagObjectPointer, scope: !17, type: !27) !27 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, baseType: !4) !28 = !DILocation(line: 0, scope: !17) !29 = !DILocation(line: 8, scope: !17) !30 = !DILocalVariable(name: "this", arg: 1, flags: DIFlagArtificial | DIFlagObjectPointer, scope: !18, type: !27) !31 = !DILocation(line: 0, scope: !18) !32 = !DILocation(line: 6, scope: !18) !33 = !DILocation(line: 8, scope: !18) !34 = !DILocalVariable(name: "a", line: 11, scope: !19, file: !20, type: !4) !35 = !DILocation(line: 11, scope: !19) !36 = !DILocation(line: 12, scope: !19) SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/DW_AT_specification.ll000066400000000000000000000051121363521741200247320ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=x86_64-apple-darwin %t.ll -o %t -filetype=obj ; RUN: llvm-dwarfdump -v -debug-info %t | FileCheck %s ; test that the DW_AT_specification is a back edge in the file. ; CHECK: DW_TAG_subprogram ; CHECK-NEXT: DW_AT_linkage_name {{.*}} "_ZN3foo3barEv" ; CHECK: DW_TAG_subprogram ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_specification {{.*}} "_ZN3foo3barEv" source_filename = "test/DebugInfo/X86/DW_AT_specification.ll" @_ZZN3foo3barEvE1x = constant i32 0, align 4, !dbg !0 define void @_ZN3foo3barEv() !dbg !2 { entry: ret void, !dbg !17 } !llvm.dbg.cu = !{!8} !llvm.module.flags = !{!16} !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = !DIGlobalVariable(name: "x", scope: !2, file: !3, line: 5, type: !14, isLocal: true, isDefinition: true) !2 = distinct !DISubprogram(name: "bar", linkageName: "_ZN3foo3barEv", scope: null, file: !3, line: 4, type: !4, isLocal: false, isDefinition: true, scopeLine: 4, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !8, declaration: !11) !3 = !DIFile(filename: "nsNativeAppSupportBase.ii", directory: "/Users/espindola/mozilla-central/obj-x86_64-apple-darwin11.2.0/toolkit/library") !4 = !DISubroutineType(types: !5) !5 = !{null, !6} !6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64, align: 64, flags: DIFlagArtificial) !7 = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", file: !3, line: 1, flags: DIFlagFwdDecl) !8 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 3.0 ()", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !9, retainedTypes: !9, globals: !10, imports: !9) !9 = !{} !10 = !{!0} !11 = !DISubprogram(name: "bar", linkageName: "_ZN3foo3barEv", scope: !12, file: !3, line: 2, type: !4, isLocal: false, isDefinition: false, scopeLine: 2, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false) !12 = !DICompositeType(tag: DW_TAG_class_type, name: "foo", file: !3, line: 1, size: 8, align: 8, elements: !13) !13 = !{!11} !14 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !15) !15 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !16 = !{i32 1, !"Debug Info Version", i32 3} !17 = !DILocation(line: 6, column: 1, scope: !18) !18 = distinct !DILexicalBlock(scope: !2, file: !3, line: 4, column: 17) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/DW_AT_stmt_list_sec_offset.ll000066400000000000000000000040561363521741200263420ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=i686-w64-mingw32 -o %t -filetype=obj %t.ll ; RUN: llvm-dwarfdump -v -all %t | FileCheck %s ; RUN: llc -mtriple=i686-w64-mingw32 -o %t -filetype=obj -dwarf-version=3 %t.ll ; RUN: llvm-dwarfdump -v -all %t | FileCheck %s -check-prefix=DWARF3 ; CHECK: DW_AT_stmt_list [DW_FORM_sec_offset] ; DWARF3: DW_AT_stmt_list [DW_FORM_data4] ; ; generated from: ; clang -g -S -emit-llvm test.c -o test.ll ; int main() ; { ; return 0; ; } ; ModuleID = 'test.c' target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S32" target triple = "spir64-unknown-unknown" ; Function Attrs: nounwind define i32 @main() #0 !dbg !4 { entry: %retval = alloca i32, align 4 store i32 0, i32* %retval ret i32 0, !dbg !10 } attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!9, !11} !0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.4 ", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) !1 = !DIFile(filename: "test.c", directory: "C:\5CProjects") !2 = !{} !4 = distinct !DISubprogram(name: "main", line: 1, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !0, scopeLine: 2, file: !1, scope: !5, type: !6, retainedNodes: !2) !5 = !DIFile(filename: "test.c", directory: "C:CProjects") !6 = !DISubroutineType(types: !7) !7 = !{!8} !8 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !9 = !{i32 2, !"Dwarf Version", i32 4} !10 = !DILocation(line: 3, scope: !4) !11 = !{i32 1, !"Debug Info Version", i32 3} SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/InlinedFnLocalVar.ll000066400000000000000000000064701363521741200244360ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple i686-pc-cygwin -O2 %t.ll -o - | FileCheck %s ; Check struct X for dead variable xyz from inlined function foo. ; CHECK: Lsection_info ; CHECK: DW_TAG_structure_type ; CHECK-NEXT: info_string source_filename = "test/DebugInfo/X86/InlinedFnLocalVar.ll" @i = common global i32 0, !dbg !0 ; Function Attrs: nounwind readnone declare void @llvm.dbg.declare(metadata, metadata, metadata) #0 ; Function Attrs: nounwind readnone declare void @llvm.dbg.value(metadata, metadata, metadata) #0 ; Function Attrs: nounwind ssp define i32 @bar() #1 !dbg !8 { entry: %0 = load i32, i32* @i, align 4, !dbg !11 tail call void @llvm.dbg.value(metadata i32 %0, metadata !13, metadata !24), !dbg !25 tail call void @llvm.dbg.declare(metadata !5, metadata !18, metadata !24), !dbg !26 %1 = mul nsw i32 %0, %0, !dbg !27 store i32 %1, i32* @i, align 4, !dbg !11 ret i32 %1, !dbg !28 } attributes #0 = { nounwind readnone } attributes #1 = { nounwind ssp } !llvm.dbg.cu = !{!4} !llvm.module.flags = !{!7} !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = !DIGlobalVariable(name: "i", scope: !2, file: !2, line: 5, type: !3, isLocal: false, isDefinition: true) !2 = !DIFile(filename: "bar.c", directory: "/tmp/") !3 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !4 = distinct !DICompileUnit(language: DW_LANG_C89, file: !2, producer: "4.2.1 (Based on Apple Inc. build 5658) (LLVM build)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !5) !5 = !{} !6 = !{!0} !7 = !{i32 1, !"Debug Info Version", i32 3} !8 = distinct !DISubprogram(name: "bar", linkageName: "bar", scope: !2, file: !2, line: 14, type: !9, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: true, unit: !4) !9 = !DISubroutineType(types: !10) !10 = !{!3} !11 = !DILocation(line: 15, scope: !12) !12 = distinct !DILexicalBlock(scope: !8, file: !2, line: 14) !13 = !DILocalVariable(name: "j", arg: 1, scope: !14, file: !2, line: 9, type: !3) !14 = distinct !DISubprogram(name: "foo", scope: !2, file: !2, line: 9, type: !15, isLocal: true, isDefinition: true, scopeLine: 9, virtualIndex: 6, isOptimized: true, unit: !4, retainedNodes: !17) !15 = !DISubroutineType(types: !16) !16 = !{!3, !3} !17 = !{!13, !18} !18 = !DILocalVariable(name: "xyz", scope: !19, file: !2, line: 10, type: !20) !19 = distinct !DILexicalBlock(scope: !14, file: !2, line: 9) !20 = !DICompositeType(tag: DW_TAG_structure_type, name: "X", scope: !14, file: !2, line: 10, size: 64, align: 32, elements: !21) !21 = !{!22, !23} !22 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !20, file: !2, line: 10, baseType: !3, size: 32, align: 32) !23 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !20, file: !2, line: 10, baseType: !3, size: 32, align: 32, offset: 32) !24 = !DIExpression() !25 = !DILocation(line: 9, scope: !14, inlinedAt: !11) !26 = !DILocation(line: 9, scope: !19, inlinedAt: !11) !27 = !DILocation(line: 11, scope: !19, inlinedAt: !11) !28 = !DILocation(line: 16, scope: !12) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/abstract_origin.ll000066400000000000000000000042551363521741200243150ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -filetype=obj %t.ll -o - | llvm-dwarfdump -debug-info - | FileCheck %s ; Generated at -O2 from: ; void f(); ; __attribute__((always_inline)) void g() { ; f(); ; } ; void h() { ; g(); ; }; ; CHECK: DW_TAG_subprogram ; CHECK: DW_AT_abstract_origin {{.*}}"g" ; CHECK-NOT: DW_AT_abstract_origin {{.*}}"g" ; CHECK: DW_TAG source_filename = "test.c" target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "spir64-unknown-unknown" ; Function Attrs: alwaysinline nounwind ssp uwtable define void @g() #0 !dbg !7 { entry: tail call void (...) @f() #3, !dbg !10 ret void, !dbg !11 } declare void @f(...) ; Function Attrs: nounwind ssp uwtable define void @h() #2 !dbg !12 { entry: tail call void (...) @f() #3, !dbg !13 ret void, !dbg !15 } attributes #0 = { alwaysinline nounwind ssp uwtable } attributes #2 = { nounwind ssp uwtable } attributes #3 = { nounwind } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!3, !4, !5} !llvm.ident = !{!6} !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) !1 = !DIFile(filename: "test.c", directory: "/Volumes/Data/llvm") !2 = !{} !3 = !{i32 2, !"Dwarf Version", i32 2} !4 = !{i32 2, !"Debug Info Version", i32 3} !5 = !{i32 1, !"PIC Level", i32 2} !6 = !{!"clang version 3.9.0 "} !7 = distinct !DISubprogram(name: "g", scope: !1, file: !1, line: 2, type: !8, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !0, retainedNodes: !2) !8 = !DISubroutineType(types: !9) !9 = !{null} !10 = !DILocation(line: 3, column: 3, scope: !7) !11 = !DILocation(line: 4, column: 1, scope: !7) !12 = distinct !DISubprogram(name: "h", scope: !1, file: !1, line: 5, type: !8, isLocal: false, isDefinition: true, scopeLine: 5, isOptimized: true, unit: !0, retainedNodes: !2) !13 = !DILocation(line: 3, column: 3, scope: !7, inlinedAt: !14) !14 = distinct !DILocation(line: 6, column: 3, scope: !12) !15 = !DILocation(line: 7, column: 1, scope: !12) SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/aligned_stack_var.ll000066400000000000000000000044131363521741200245770ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc %t.ll -mtriple=x86_64-pc-linux-gnu -O0 -filetype=obj -o %t ; RUN: llvm-dwarfdump -debug-info %t | FileCheck %s ; If stack is realigned, we shouldn't describe locations of local ; variables by giving offset from the frame pointer (%rbp): ; push %rpb ; mov %rsp,%rbp ; and ALIGNMENT,%rsp ; (%rsp and %rbp are different now) ; It's better to use offset from %rsp instead. ; DW_AT_location of variable "x" shouldn't be equal to ; (DW_OP_fbreg: .*): DW_OP_fbreg has code 0x91 ; CHECK: {{0x.* DW_TAG_variable}} ; CHECK-NOT: {{DW_AT_location.*DW_FORM_block1.*0x.*91}} ; CHECK: NULL define void @_Z3runv() nounwind uwtable !dbg !5 { entry: %x = alloca i32, align 32 call void @llvm.dbg.declare(metadata i32* %x, metadata !9, metadata !DIExpression()), !dbg !12 ret void, !dbg !13 } declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!15} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.2 (trunk 155696:155697) (llvm/trunk 155696)", isOptimized: false, emissionKind: FullDebug, file: !14, enums: !1, retainedTypes: !1, globals: !1, imports: !1) !1 = !{} !5 = distinct !DISubprogram(name: "run", linkageName: "_Z3runv", line: 1, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 1, file: !14, scope: !6, type: !7, retainedNodes: !1) !6 = !DIFile(filename: "test.cc", directory: "/home/samsonov/debuginfo") !7 = !DISubroutineType(types: !8) !8 = !{null} !9 = !DILocalVariable(name: "x", line: 2, scope: !10, file: !6, type: !11) !10 = distinct !DILexicalBlock(line: 1, column: 12, file: !14, scope: !5) !11 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !12 = !DILocation(line: 2, column: 7, scope: !10) !13 = !DILocation(line: 3, column: 1, scope: !10) !14 = !DIFile(filename: "test.cc", directory: "/home/samsonov/debuginfo") !15 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/arguments.ll000066400000000000000000000073571363521741200231560ustar00rootroot00000000000000; REQUIRES: object-emission ; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=x86_64-unknown-unknown -O0 -filetype=obj < %t.ll > %t ; RUN: llvm-dwarfdump %t | FileCheck %s ; IR generated from clang -g with the following source: ; struct foo { ; foo(const foo&); ; int i; ; }; ; ; void func(foo f, foo g) { ; f.i++; ; } ; CHECK: debug_info contents ; CHECK: DW_TAG_subprogram ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_linkage_name{{.*}}"_Z4func3fooS_" ; CHECK-NOT: NULL ; CHECK: DW_TAG_formal_parameter ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name{{.*}}"f" ; CHECK-NOT: NULL ; CHECK: DW_TAG_formal_parameter ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name{{.*}}"g" %struct.foo = type { i32 } ; Function Attrs: nounwind uwtable define void @_Z4func3fooS_(%struct.foo* %f, %struct.foo* %g) #0 !dbg !4 { entry: call void @llvm.dbg.declare(metadata %struct.foo* %f, metadata !19, metadata !DIExpression()), !dbg !20 call void @llvm.dbg.declare(metadata %struct.foo* %g, metadata !21, metadata !DIExpression()), !dbg !20 %i = getelementptr inbounds %struct.foo, %struct.foo* %f, i32 0, i32 0, !dbg !22 %0 = load i32, i32* %i, align 4, !dbg !22 %inc = add nsw i32 %0, 1, !dbg !22 store i32 %inc, i32* %i, align 4, !dbg !22 ret void, !dbg !23 } ; Function Attrs: nounwind readnone declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { nounwind readnone } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!24} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.4 ", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) !1 = !DIFile(filename: "scratch.cpp", directory: "/usr/local/google/home/blaikie/dev/scratch") !2 = !{} !4 = distinct !DISubprogram(name: "func", linkageName: "_Z4func3fooS_", line: 6, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 6, file: !1, scope: !5, type: !6, retainedNodes: !2) !5 = !DIFile(filename: "scratch.cpp", directory: "/usr/local/google/home/blaikie/dev/scratch") !6 = !DISubroutineType(types: !7) !7 = !{null, !8, !8} !8 = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", line: 1, size: 32, align: 32, file: !1, elements: !9) !9 = !{!10, !12} !10 = !DIDerivedType(tag: DW_TAG_member, name: "i", line: 3, size: 32, align: 32, file: !1, scope: !8, baseType: !11) !11 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !12 = !DISubprogram(name: "foo", line: 2, isLocal: false, isDefinition: false, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, scopeLine: 2, file: !1, scope: !8, type: !13) !13 = !DISubroutineType(types: !14) !14 = !{null, !15, !16} !15 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer, baseType: !8) !16 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !17) !17 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !8) !19 = !DILocalVariable(name: "f", line: 6, arg: 1, scope: !4, file: !5, type: !8) !20 = !DILocation(line: 6, scope: !4) !21 = !DILocalVariable(name: "g", line: 6, arg: 2, scope: !4, file: !5, type: !8) !22 = !DILocation(line: 7, scope: !4) !23 = !DILocation(line: 8, scope: !4) !24 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/coff_debug_info_type.ll000066400000000000000000000043441363521741200253010ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=i686-pc-mingw32 -accel-tables=Apple -filetype=asm -O0 < %t.ll | FileCheck %s ; RUN: llc -mtriple=i686-pc-cygwin -accel-tables=Apple -filetype=asm -O0 < %t.ll | FileCheck %s ; RUN: llc -mtriple=i686-w64-mingw32 -accel-tables=Apple -filetype=asm -O0 < %t.ll | FileCheck %s ; CHECK: .section .debug_info ; CHECK: .section .apple_names ; CHECK: .section .apple_types ; RUN: sed -e 's/"Dwarf Version"/"CodeView"/' %s \ ; RUN: | llc -mtriple=i686-pc-win32 -filetype=asm -O0 \ ; RUN: | FileCheck -check-prefix=WIN32 %s ; WIN32: .section .debug$S,"dr" ; RUN: llc -mtriple=i686-pc-win32 -filetype=null -O0 < %t.ll ; generated from: ; clang -g -S -emit-llvm test.c -o test.ll ; int main() ; { ; return 0; ; } define i32 @main() #0 !dbg !4 { entry: %retval = alloca i32, align 4 store i32 0, i32* %retval ret i32 0, !dbg !10 } attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!9, !11} !0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.4 ", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) !1 = !DIFile(filename: "test.c", directory: "C:\5CProjects") !2 = !{} !4 = distinct !DISubprogram(name: "main", line: 1, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !0, scopeLine: 2, file: !1, scope: !5, type: !6, retainedNodes: !2) !5 = !DIFile(filename: "test.c", directory: "C:CProjects") !6 = !DISubroutineType(types: !7) !7 = !{!8} !8 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !9 = !{i32 2, !"Dwarf Version", i32 3} !10 = !DILocation(line: 3, scope: !4) !11 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/coff_relative_names.ll000066400000000000000000000034131363521741200251310ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=i686-w64-mingw32 -filetype=asm -O0 < %t.ll | FileCheck %s ; CHECK: .secrel32 Linfo_string0 ; CHECK: .secrel32 Linfo_string1 ; ; generated from: ; clang -g -S -emit-llvm test.c -o test.ll ; int main() ; { ; return 0; ; } ; Function Attrs: nounwind define i32 @main() #0 !dbg !4 { entry: %retval = alloca i32, align 4 store i32 0, i32* %retval ret i32 0, !dbg !10 } attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!9, !11} !0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.4 ", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) !1 = !DIFile(filename: "test.c", directory: "C:\5CProjects") !2 = !{} !4 = distinct !DISubprogram(name: "main", line: 1, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !0, scopeLine: 2, file: !1, scope: !5, type: !6, retainedNodes: !2) !5 = !DIFile(filename: "test.c", directory: "C:CProjects") !6 = !DISubroutineType(types: !7) !7 = !{!8} !8 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !9 = !{i32 2, !"Dwarf Version", i32 3} !10 = !DILocation(line: 3, scope: !4) !11 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/constant-aggregate.ll000066400000000000000000000120771363521741200247210ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple %t.ll -filetype=obj -o %t.o ; RUN: llvm-dwarfdump -v -debug-info %t.o | FileCheck %s ; Test emitting a constant for an aggregate type. ; ; clang -S -O1 -emit-llvm ; ; typedef struct { unsigned i; } S; ; ; unsigned foo(S s) { ; s.i = 1; ; return s.i; ; } ; ; class C { public: unsigned i; }; ; ; unsigned foo(C c) { ; c.i = 2; ; return c.i; ; } ; ; unsigned bar() { ; int a[1] = { 3 }; ; return a[0]; ; } ; ; CHECK: DW_TAG_formal_parameter ; CHECK-NEXT: DW_AT_const_value [DW_FORM_udata] (1) ; CHECK-NEXT: DW_AT_name {{.*}} "s" ; ; CHECK: DW_TAG_formal_parameter ; CHECK-NEXT: DW_AT_const_value [DW_FORM_udata] (2) ; CHECK-NEXT: DW_AT_name {{.*}} "c" ; ; CHECK: DW_TAG_variable ; CHECK-NEXT: DW_AT_const_value [DW_FORM_udata] (3) ; CHECK-NEXT: DW_AT_name {{.*}} "a" ; ModuleID = 'sroasplit-4.cpp' target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "spir64-unknown-unknown" ; Function Attrs: nounwind readnone ssp uwtable define i32 @_Z3foo1S(i32 %s.coerce) #0 !dbg !12 { entry: tail call void @llvm.dbg.value(metadata i32 %s.coerce, metadata !18, metadata !37), !dbg !38 tail call void @llvm.dbg.value(metadata i32 1, metadata !18, metadata !37), !dbg !38 ret i32 1, !dbg !39 } ; Function Attrs: nounwind readnone ssp uwtable define i32 @_Z3foo1C(i32 %c.coerce) #0 !dbg !19 { entry: tail call void @llvm.dbg.value(metadata i32 %c.coerce, metadata !23, metadata !37), !dbg !40 tail call void @llvm.dbg.value(metadata i32 2, metadata !23, metadata !37), !dbg !40 ret i32 2, !dbg !41 } ; Function Attrs: nounwind readnone ssp uwtable define i32 @_Z3barv() #0 !dbg !24 { entry: tail call void @llvm.dbg.value(metadata i32 3, metadata !28, metadata !37), !dbg !42 ret i32 3, !dbg !43 } ; Function Attrs: nounwind readnone declare void @llvm.dbg.value(metadata, metadata, metadata) #1 attributes #0 = { nounwind readnone ssp uwtable } attributes #1 = { nounwind readnone } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!33, !34, !35} !llvm.ident = !{!36} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.6.0 (trunk 225364) (llvm/trunk 225366)", isOptimized: true, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !3, globals: !2, imports: !2) !1 = !DIFile(filename: "sroasplit-4.cpp", directory: "") !2 = !{} !3 = !{!4, !8} !4 = !DICompositeType(tag: DW_TAG_structure_type, line: 1, size: 32, align: 32, file: !1, elements: !5, identifier: "_ZTS1S") !5 = !{!6} !6 = !DIDerivedType(tag: DW_TAG_member, name: "i", line: 1, size: 32, align: 32, file: !1, scope: !4, baseType: !7) !7 = !DIBasicType(tag: DW_TAG_base_type, name: "unsigned int", size: 32, align: 32, encoding: DW_ATE_unsigned) !8 = !DICompositeType(tag: DW_TAG_class_type, name: "C", line: 8, size: 32, align: 32, file: !1, elements: !9, identifier: "_ZTS1C") !9 = !{!10} !10 = !DIDerivedType(tag: DW_TAG_member, name: "i", line: 8, size: 32, align: 32, flags: DIFlagPublic, file: !1, scope: !8, baseType: !7) !12 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foo1S", line: 3, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 3, file: !1, scope: !13, type: !14, retainedNodes: !17) !13 = !DIFile(filename: "sroasplit-4.cpp", directory: "") !14 = !DISubroutineType(types: !15) !15 = !{!7, !16} !16 = !DIDerivedType(tag: DW_TAG_typedef, name: "S", line: 1, file: !1, baseType: !4) !17 = !{!18} !18 = !DILocalVariable(name: "s", line: 3, arg: 1, scope: !12, file: !13, type: !16) !19 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foo1C", line: 10, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 10, file: !1, scope: !13, type: !20, retainedNodes: !22) !20 = !DISubroutineType(types: !21) !21 = !{!7, !8} !22 = !{!23} !23 = !DILocalVariable(name: "c", line: 10, arg: 1, scope: !19, file: !13, type: !8) !24 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", line: 15, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 15, file: !1, scope: !13, type: !25, retainedNodes: !27) !25 = !DISubroutineType(types: !26) !26 = !{!7} !27 = !{!28} !28 = !DILocalVariable(name: "a", line: 16, scope: !24, file: !13, type: !29) !29 = !DICompositeType(tag: DW_TAG_array_type, size: 32, align: 32, baseType: !30, elements: !31) !30 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !31 = !{!32} !32 = !DISubrange(count: 1) !33 = !{i32 2, !"Dwarf Version", i32 2} !34 = !{i32 2, !"Debug Info Version", i32 3} !35 = !{i32 1, !"PIC Level", i32 2} !36 = !{!"clang version 3.6.0 (trunk 225364) (llvm/trunk 225366)"} !37 = !DIExpression() !38 = !DILocation(line: 3, column: 16, scope: !12) !39 = !DILocation(line: 5, column: 3, scope: !12) !40 = !DILocation(line: 10, column: 16, scope: !19) !41 = !DILocation(line: 12, column: 3, scope: !19) !42 = !DILocation(line: 16, column: 6, scope: !24) !43 = !DILocation(line: 17, column: 3, scope: !24) SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/constant-loclist.ll000066400000000000000000000071201363521741200244350ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -filetype=obj %t.ll -o - | llvm-dwarfdump -v -debug-info - | FileCheck %s ; A hand-written testcase to check 64-bit constant handling in location lists. ; CHECK: .debug_info contents: ; CHECK: DW_TAG_variable ; CHECK-NEXT: DW_AT_location [DW_FORM_data4] ( ; CHECK-NEXT: 0x{{.*}}, 0x{{.*}}: DW_OP_constu 0x4000000000000000) ; CHECK-NEXT: DW_AT_name {{.*}}"d" ; CHECK: DW_TAG_variable ; CHECK-NEXT: DW_AT_location [DW_FORM_data4] ( ; CHECK-NEXT: 0x{{.*}}, 0x{{.*}}: DW_OP_consts +0 ; CHECK-NEXT: 0x{{.*}}, 0x{{.*}}: DW_OP_consts +4611686018427387904) ; CHECK-NEXT: DW_AT_name {{.*}}"i" ; CHECK: DW_TAG_variable ; CHECK-NEXT: DW_AT_location [DW_FORM_data4] ( ; CHECK-NEXT: 0x{{.*}}, 0x{{.*}}: DW_OP_lit0 ; CHECK-NEXT: 0x{{.*}}, 0x{{.*}}: DW_OP_constu 0x4000000000000000) ; CHECK-NEXT: DW_AT_name {{.*}}"u" source_filename = "test.c" target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "spir64-unknown-unknown" ; Function Attrs: nounwind ssp uwtable define void @main() #0 !dbg !7 { %1 = alloca double, align 8 %2 = alloca i64, align 8 %3 = alloca i64, align 8 store double 2.000000e+00, double* %1, align 8, !dbg !21 call void @llvm.dbg.value(metadata i64 0, metadata !22, metadata !15), !dbg !24 call void @llvm.dbg.value(metadata i64 0, metadata !25, metadata !15), !dbg !27 call void @llvm.dbg.value(metadata double 2.000000e+00, metadata !19, metadata !15), !dbg !21 store i64 4611686018427387904, i64* %2, align 8, !dbg !24 call void @llvm.dbg.value(metadata i64 4611686018427387904, metadata !22, metadata !15), !dbg !24 call void @llvm.dbg.value(metadata i64 4611686018427387904, metadata !25, metadata !15), !dbg !27 store i64 4611686018427387904, i64* %3, align 8, !dbg !27 ret void, !dbg !28 } ; Function Attrs: nounwind readnone declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 declare void @llvm.dbg.value(metadata, metadata, metadata) #1 attributes #0 = { nounwind ssp uwtable } attributes #1 = { nounwind readnone } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!3, !4, !5} !llvm.ident = !{!6} !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) !1 = !DIFile(filename: "test.c", directory: "/tmp") !2 = !{} !3 = !{i32 2, !"Dwarf Version", i32 2} !4 = !{i32 2, !"Debug Info Version", i32 00000003} !5 = !{i32 1, !"PIC Level", i32 2} !6 = !{!"clang"} !7 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) !8 = !DISubroutineType(types: !{}) !15 = !DIExpression() !16 = !DILocation(line: 1, column: 14, scope: !7) !18 = !DILocation(line: 1, column: 24, scope: !7) !19 = !DILocalVariable(name: "d", scope: !7, file: !1, line: 2, type: !20) !20 = !DIBasicType(name: "double", size: 64, align: 64, encoding: DW_ATE_float) !21 = !DILocation(line: 2, column: 10, scope: !7) !22 = !DILocalVariable(name: "u", scope: !7, file: !1, line: 3, type: !23) !23 = !DIBasicType(name: "long long unsigned int", size: 64, align: 64, encoding: DW_ATE_unsigned) !24 = !DILocation(line: 3, column: 22, scope: !7) !25 = !DILocalVariable(name: "i", scope: !7, file: !1, line: 4, type: !26) !26 = !DIBasicType(name: "long long int", size: 64, align: 64, encoding: DW_ATE_signed) !27 = !DILocation(line: 4, column: 20, scope: !7) !28 = !DILocation(line: 5, column: 3, scope: !7) SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/cu-ranges.ll000066400000000000000000000075341363521741200230320ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -split-dwarf-file=foo.dwo -O0 %t.ll -function-sections -mtriple=x86_64-unknown-linux-gnu -filetype=obj -o %t ; RUN: llvm-dwarfdump -debug-abbrev %t | FileCheck --check-prefix=FUNCTION-SECTIONS %s ; RUN: llvm-readobj --relocations %t | FileCheck --check-prefix=FUNCTION-SECTIONS-RELOCS %s ; RUN: llc -split-dwarf-file=foo.dwo -O0 %t.ll -mtriple=x86_64-unknown-linux-gnu -filetype=obj -o %t ; RUN: llvm-dwarfdump -debug-abbrev %t | FileCheck --check-prefix=NO-FUNCTION-SECTIONS %s ; From: ; int foo (int a) { ; return a+1; ; } ; int bar (int b) { ; return b+2; ; } ; With function sections enabled make sure that we have a DW_AT_ranges attribute. ; FUNCTION-SECTIONS: DW_AT_ranges ; Check that we have a relocation against the .debug_ranges section. ; FUNCTION-SECTIONS-RELOCS: R_X86_64_32 .debug_ranges 0x0 ; Without function sections enabled make sure that we have no DW_AT_ranges attribute. ; NO-FUNCTION-SECTIONS-NOT: DW_AT_ranges ; NO-FUNCTION-SECTIONS: DW_AT_low_pc DW_FORM_addr ; NO-FUNCTION-SECTIONS-NOT: DW_AT_ranges ; Function Attrs: nounwind uwtable define i32 @foo(i32 %a) #0 !dbg !4 { entry: %a.addr = alloca i32, align 4 store i32 %a, i32* %a.addr, align 4 call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !13, metadata !DIExpression()), !dbg !14 %0 = load i32, i32* %a.addr, align 4, !dbg !14 %add = add nsw i32 %0, 1, !dbg !14 ret i32 %add, !dbg !14 } ; Function Attrs: nounwind readnone declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 ; Function Attrs: nounwind uwtable define i32 @bar(i32 %b) #0 !dbg !9 { entry: %b.addr = alloca i32, align 4 store i32 %b, i32* %b.addr, align 4 call void @llvm.dbg.declare(metadata i32* %b.addr, metadata !15, metadata !DIExpression()), !dbg !16 %0 = load i32, i32* %b.addr, align 4, !dbg !16 %add = add nsw i32 %0, 2, !dbg !16 ret i32 %add, !dbg !16 } attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { nounwind readnone } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!10, !11} !llvm.ident = !{!12} !0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.5.0 (trunk 204164) (llvm/trunk 204183)", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) !1 = !DIFile(filename: "z.c", directory: "/usr/local/google/home/echristo") !2 = !{} !4 = distinct !DISubprogram(name: "foo", line: 1, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 1, file: !1, scope: !5, type: !6, retainedNodes: !2) !5 = !DIFile(filename: "z.c", directory: "/usr/local/google/home/echristo") !6 = !DISubroutineType(types: !7) !7 = !{!8, !8} !8 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !9 = distinct !DISubprogram(name: "bar", line: 2, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 2, file: !1, scope: !5, type: !6, retainedNodes: !2) !10 = !{i32 2, !"Dwarf Version", i32 4} !11 = !{i32 1, !"Debug Info Version", i32 3} !12 = !{!"clang version 3.5.0 (trunk 204164) (llvm/trunk 204183)"} !13 = !DILocalVariable(name: "a", line: 1, arg: 1, scope: !4, file: !5, type: !8) !14 = !DILocation(line: 1, scope: !4) !15 = !DILocalVariable(name: "b", line: 2, arg: 1, scope: !9, file: !5, type: !8) !16 = !DILocation(line: 2, scope: !9) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/data_member_location.ll000066400000000000000000000047461363521741200253000ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=x86_64-linux -O0 -o - -filetype=obj < %t.ll | llvm-dwarfdump -v -debug-info -| FileCheck %s ; RUN: llc -mtriple=x86_64-linux -dwarf-version=2 -O0 -o - -filetype=obj < %t.ll | llvm-dwarfdump -v -debug-info -| FileCheck -check-prefix=DWARF2 %s ; Generated from Clang with the following source: ; ; struct foo { ; char c; ; int i; ; }; ; ; foo f; ; CHECK: DW_AT_name {{.*}} "c" ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_data_member_location {{.*}} (0x00) ; CHECK: DW_AT_name {{.*}} "i" ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_data_member_location {{.*}} (0x04) ; DWARF2: DW_AT_name {{.*}} "c" ; DWARF2-NOT: DW_TAG ; DWARF2: DW_AT_data_member_location {{.*}} (DW_OP_plus_uconst 0x0) ; DWARF2: DW_AT_name {{.*}} "i" ; DWARF2-NOT: DW_TAG ; DWARF2: DW_AT_data_member_location {{.*}} (DW_OP_plus_uconst 0x4) source_filename = "test/DebugInfo/X86/data_member_location.ll" %struct.foo = type { i8, i32 } @f = global %struct.foo zeroinitializer, align 4, !dbg !0 !llvm.dbg.cu = !{!9} !llvm.module.flags = !{!13, !14} !llvm.ident = !{!15} !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = !DIGlobalVariable(name: "f", scope: null, file: !2, line: 6, type: !3, isLocal: false, isDefinition: true) !2 = !DIFile(filename: "data_member_location.cpp", directory: "/tmp/dbginfo") !3 = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", file: !2, line: 1, size: 64, align: 32, elements: !4, identifier: "_ZTS3foo") !4 = !{!5, !7} !5 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !3, file: !2, line: 2, baseType: !6, size: 8, align: 8) !6 = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char) !7 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !3, file: !2, line: 3, baseType: !8, size: 32, align: 32, offset: 32) !8 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !9 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, producer: "clang version 3.4 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !10, retainedTypes: !11, globals: !12, imports: !10) !10 = !{} !11 = !{!3} !12 = !{!0} !13 = !{i32 2, !"Dwarf Version", i32 4} !14 = !{i32 1, !"Debug Info Version", i32 3} !15 = !{!"clang version 3.4 "} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/dbg-byval-parameter.ll000066400000000000000000000065701363521741200247720ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -march=x86 -asm-verbose < %t.ll | grep DW_TAG_formal_parameter %struct.Pt = type { double, double } %struct.Rect = type { %struct.Pt, %struct.Pt } define double @foo(%struct.Rect* byval %my_r0) nounwind ssp !dbg !1 { entry: %retval = alloca double ; [#uses=2] %0 = alloca double ; [#uses=2] %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] call void @llvm.dbg.declare(metadata %struct.Rect* %my_r0, metadata !0, metadata !DIExpression()), !dbg !15 %1 = getelementptr inbounds %struct.Rect, %struct.Rect* %my_r0, i32 0, i32 0, !dbg !16 ; <%struct.Pt*> [#uses=1] %2 = getelementptr inbounds %struct.Pt, %struct.Pt* %1, i32 0, i32 0, !dbg !16 ; [#uses=1] %3 = load double, double* %2, align 8, !dbg !16 ; [#uses=1] store double %3, double* %0, align 8, !dbg !16 %4 = load double, double* %0, align 8, !dbg !16 ; [#uses=1] store double %4, double* %retval, align 8, !dbg !16 br label %return, !dbg !16 return: ; preds = %entry %retval1 = load double, double* %retval, !dbg !16 ; [#uses=1] ret double %retval1, !dbg !16 } declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone !llvm.dbg.cu = !{!3} !llvm.module.flags = !{!21} !0 = !DILocalVariable(name: "my_r0", line: 11, arg: 1, scope: !1, file: !2, type: !7) !1 = distinct !DISubprogram(name: "foo", linkageName: "foo", line: 11, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !3, file: !19, scope: !2, type: !4) !2 = !DIFile(filename: "b2.c", directory: "/tmp/") !3 = distinct !DICompileUnit(language: DW_LANG_C89, producer: "4.2.1 (Based on Apple Inc. build 5658) (LLVM build)", isOptimized: false, emissionKind: FullDebug, file: !19, enums: !20, retainedTypes: !20, imports: null) !4 = !DISubroutineType(types: !5) !5 = !{!6, !7} !6 = !DIBasicType(tag: DW_TAG_base_type, name: "double", size: 64, align: 64, encoding: DW_ATE_float) !7 = !DICompositeType(tag: DW_TAG_structure_type, name: "Rect", line: 6, size: 256, align: 64, file: !19, scope: !2, elements: !8) !8 = !{!9, !14} !9 = !DIDerivedType(tag: DW_TAG_member, name: "P1", line: 7, size: 128, align: 64, file: !19, scope: !7, baseType: !10) !10 = !DICompositeType(tag: DW_TAG_structure_type, name: "Pt", line: 1, size: 128, align: 64, file: !19, scope: !2, elements: !11) !11 = !{!12, !13} !12 = !DIDerivedType(tag: DW_TAG_member, name: "x", line: 2, size: 64, align: 64, file: !19, scope: !10, baseType: !6) !13 = !DIDerivedType(tag: DW_TAG_member, name: "y", line: 3, size: 64, align: 64, offset: 64, file: !19, scope: !10, baseType: !6) !14 = !DIDerivedType(tag: DW_TAG_member, name: "P2", line: 8, size: 128, align: 64, offset: 128, file: !19, scope: !7, baseType: !10) !15 = !DILocation(line: 11, scope: !1) !16 = !DILocation(line: 12, scope: !17) !17 = distinct !DILexicalBlock(line: 11, column: 0, file: !19, scope: !1) !19 = !DIFile(filename: "b2.c", directory: "/tmp/") !20 = !{} !21 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/dbg-declare-alloca.ll000066400000000000000000000053441363521741200245250ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple < %t.ll | FileCheck %s ; RUN: llc -mtriple=%triple < %t.ll -filetype=obj | llvm-dwarfdump -v - --debug-info | FileCheck %s --check-prefix=DWARF ; This should use the frame index side table for allocas, not DBG_VALUE ; instructions. For SDAG ISel, this test would see an SDNode materializing the ; argument to escape_foo and we'd get DBG_VALUE MachineInstr. ; CHECK-LABEL: use_dbg_declare: ; CHECK-NOT: #DEBUG_VALUE ; DWARF: DW_TAG_variable ; DWARF-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_fbreg +0) ; DWARF-NEXT: DW_AT_name [DW_FORM_strp] ( {{.*}} = "o") ; ModuleID = 't.c' source_filename = "t.c" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "spir64-unknown-unknown" %struct.Foo = type { i32 } ; Function Attrs: noinline nounwind uwtable define void @use_dbg_declare() #0 !dbg !7 { entry: %o = alloca %struct.Foo, align 4 call void @llvm.dbg.declare(metadata %struct.Foo* %o, metadata !10, metadata !15), !dbg !16 call void @escape_foo(%struct.Foo* %o), !dbg !17 ret void, !dbg !18 } ; Function Attrs: nounwind readnone speculatable declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 declare void @escape_foo(%struct.Foo*) attributes #0 = { noinline nounwind uwtable } attributes #1 = { nounwind readnone speculatable } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!3, !4, !5} !llvm.ident = !{!6} !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) !1 = !DIFile(filename: "t.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild") !2 = !{} !3 = !{i32 2, !"Dwarf Version", i32 4} !4 = !{i32 2, !"Debug Info Version", i32 3} !5 = !{i32 1, !"wchar_size", i32 4} !6 = !{!"clang version 6.0.0 "} !7 = distinct !DISubprogram(name: "use_dbg_declare", scope: !1, file: !1, line: 3, type: !8, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) !8 = !DISubroutineType(types: !9) !9 = !{null} !10 = !DILocalVariable(name: "o", scope: !7, file: !1, line: 4, type: !11) !11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: !1, line: 1, size: 32, elements: !12) !12 = !{!13} !13 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !11, file: !1, line: 1, baseType: !14, size: 32) !14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) !15 = !DIExpression() !16 = !DILocation(line: 4, column: 14, scope: !7) !17 = !DILocation(line: 5, column: 3, scope: !7) !18 = !DILocation(line: 6, column: 1, scope: !7) SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/dbg-declare-arg.ll000066400000000000000000000176341363521741200240500ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 -fast-isel=true -filetype=obj -o - %t.ll | llvm-dwarfdump -v - | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "spir64-unknown-unknown" ; rdar://problem/9321650 ; C++ source: ; class A { public: int x; int y; int z; int o; ~A() { x = 1; }}; ; ; A foo(int i) { ; int j = 0; ; if (i == 42) { ; j = i + 1; ; }; ; A my_a; ; my_a.x = j; ; return my_a; ; } ; CHECK: DW_AT_name {{.*}}"j" ; CHECK: DW_TAG_variable ; CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] ( ; CHECK-NEXT: 0x{{.*}}, 0x{{.*}}: DW_OP_breg7 RSP+16, DW_OP_deref) ; CHECK-NEXT: DW_AT_name {{.*}}"my_a" %class.A = type { i32, i32, i32, i32 } define void @_Z3fooi(%class.A* sret %agg.result, i32 %i) ssp !dbg !19 { entry: %i.addr = alloca i32, align 4 %j = alloca i32, align 4 %nrvo = alloca i1 %cleanup.dest.slot = alloca i32 store i32 %i, i32* %i.addr, align 4 call void @llvm.dbg.declare(metadata i32* %i.addr, metadata !26, metadata !DIExpression()), !dbg !27 call void @llvm.dbg.declare(metadata i32* %j, metadata !28, metadata !DIExpression()), !dbg !30 store i32 0, i32* %j, align 4, !dbg !31 %tmp = load i32, i32* %i.addr, align 4, !dbg !32 %cmp = icmp eq i32 %tmp, 42, !dbg !32 br i1 %cmp, label %if.then, label %if.end, !dbg !32 if.then: ; preds = %entry %tmp1 = load i32, i32* %i.addr, align 4, !dbg !33 %add = add nsw i32 %tmp1, 1, !dbg !33 store i32 %add, i32* %j, align 4, !dbg !33 br label %if.end, !dbg !35 if.end: ; preds = %if.then, %entry store i1 false, i1* %nrvo, !dbg !36 call void @llvm.dbg.declare(metadata %class.A* %agg.result, metadata !37, metadata !DIExpression()), !dbg !39 %tmp2 = load i32, i32* %j, align 4, !dbg !40 %x = getelementptr inbounds %class.A, %class.A* %agg.result, i32 0, i32 0, !dbg !40 store i32 %tmp2, i32* %x, align 4, !dbg !40 store i1 true, i1* %nrvo, !dbg !41 store i32 1, i32* %cleanup.dest.slot %nrvo.val = load i1, i1* %nrvo, !dbg !42 br i1 %nrvo.val, label %nrvo.skipdtor, label %nrvo.unused, !dbg !42 nrvo.unused: ; preds = %if.end call void @_ZN1AD1Ev(%class.A* %agg.result), !dbg !42 br label %nrvo.skipdtor, !dbg !42 nrvo.skipdtor: ; preds = %nrvo.unused, %if.end ret void, !dbg !42 } declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone define linkonce_odr void @_ZN1AD1Ev(%class.A* %this) unnamed_addr ssp align 2 !dbg !22 { entry: %this.addr = alloca %class.A*, align 8 store %class.A* %this, %class.A** %this.addr, align 8 call void @llvm.dbg.declare(metadata %class.A** %this.addr, metadata !43, metadata !DIExpression()), !dbg !44 %this1 = load %class.A*, %class.A** %this.addr call void @_ZN1AD2Ev(%class.A* %this1), !dbg !53 ret void, !dbg !45 } define linkonce_odr void @_ZN1AD2Ev(%class.A* %this) unnamed_addr nounwind ssp align 2 !dbg !25 { entry: %this.addr = alloca %class.A*, align 8 store %class.A* %this, %class.A** %this.addr, align 8 call void @llvm.dbg.declare(metadata %class.A** %this.addr, metadata !46, metadata !DIExpression()), !dbg !47 %this1 = load %class.A*, %class.A** %this.addr %x = getelementptr inbounds %class.A, %class.A* %this1, i32 0, i32 0, !dbg !48 store i32 1, i32* %x, align 4, !dbg !48 ret void, !dbg !48 } !llvm.dbg.cu = !{!2} !llvm.module.flags = !{!52} !0 = !DISubprogram(name: "~A", line: 2, isLocal: false, isDefinition: false, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, file: !51, scope: !1, type: !11) !1 = !DICompositeType(tag: DW_TAG_class_type, name: "A", line: 2, size: 128, align: 32, file: !51, scope: !2, elements: !4) !2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.0 (trunk 130127)", isOptimized: false, emissionKind: FullDebug, file: !51, enums: !{}, retainedTypes: !{}) !3 = !DIFile(filename: "a.cc", directory: "/private/tmp") !4 = !{!5, !7, !8, !9, !0, !10, !14} !5 = !DIDerivedType(tag: DW_TAG_member, name: "x", line: 2, size: 32, align: 32, file: !51, scope: !3, baseType: !6) !6 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !7 = !DIDerivedType(tag: DW_TAG_member, name: "y", line: 2, size: 32, align: 32, offset: 32, file: !51, scope: !3, baseType: !6) !8 = !DIDerivedType(tag: DW_TAG_member, name: "z", line: 2, size: 32, align: 32, offset: 64, file: !51, scope: !3, baseType: !6) !9 = !DIDerivedType(tag: DW_TAG_member, name: "o", line: 2, size: 32, align: 32, offset: 96, file: !51, scope: !3, baseType: !6) !10 = !DISubprogram(name: "A", line: 2, isLocal: false, isDefinition: false, virtualIndex: 6, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false, file: !51, scope: !1, type: !11) !11 = !DISubroutineType(types: !12) !12 = !{null, !13} !13 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, flags: DIFlagArtificial, file: !3, baseType: !1) !14 = !DISubprogram(name: "A", line: 2, isLocal: false, isDefinition: false, virtualIndex: 6, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false, file: !51, scope: !1, type: !15) !15 = !DISubroutineType(types: !16) !16 = !{null, !13, !17} !17 = !DIDerivedType(tag: DW_TAG_reference_type, scope: !2, baseType: !18) !18 = !DIDerivedType(tag: DW_TAG_const_type, file: !3, baseType: !1) !19 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", line: 4, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !2, file: !51, scope: !3, type: !20) !20 = !DISubroutineType(types: !21) !21 = !{!1} !22 = distinct !DISubprogram(name: "~A", linkageName: "_ZN1AD1Ev", line: 2, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !2, file: !51, scope: !3, type: !23) !23 = !DISubroutineType(types: !24) !24 = !{null} !25 = distinct !DISubprogram(name: "~A", linkageName: "_ZN1AD2Ev", line: 2, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !2, file: !51, scope: !3, type: !23) !26 = !DILocalVariable(name: "i", line: 4, arg: 1, scope: !19, file: !3, type: !6) !27 = !DILocation(line: 4, column: 11, scope: !19) !28 = !DILocalVariable(name: "j", line: 5, scope: !29, file: !3, type: !6) !29 = distinct !DILexicalBlock(line: 4, column: 14, file: !51, scope: !19) !30 = !DILocation(line: 5, column: 7, scope: !29) !31 = !DILocation(line: 5, column: 12, scope: !29) !32 = !DILocation(line: 6, column: 3, scope: !29) !33 = !DILocation(line: 7, column: 5, scope: !34) !34 = distinct !DILexicalBlock(line: 6, column: 16, file: !51, scope: !29) !35 = !DILocation(line: 8, column: 3, scope: !34) !36 = !DILocation(line: 9, column: 9, scope: !29) !37 = !DILocalVariable(name: "my_a", line: 9, scope: !29, file: !3, type: !38) !38 = !DIDerivedType(tag: DW_TAG_reference_type, file: !3, baseType: !1) !39 = !DILocation(line: 9, column: 5, scope: !29) !40 = !DILocation(line: 10, column: 3, scope: !29) !41 = !DILocation(line: 11, column: 3, scope: !29) !42 = !DILocation(line: 12, column: 1, scope: !29) !43 = !DILocalVariable(name: "this", line: 2, arg: 1, flags: DIFlagArtificial, scope: !22, file: !3, type: !13) !44 = !DILocation(line: 2, column: 47, scope: !22) !45 = !DILocation(line: 2, column: 61, scope: !22) !46 = !DILocalVariable(name: "this", line: 2, arg: 1, flags: DIFlagArtificial, scope: !25, file: !3, type: !13) !47 = !DILocation(line: 2, column: 47, scope: !25) !48 = !DILocation(line: 2, column: 54, scope: !49) !49 = distinct !DILexicalBlock(line: 2, column: 52, file: !51, scope: !25) !51 = !DIFile(filename: "a.cc", directory: "/private/tmp") !52 = !{i32 1, !"Debug Info Version", i32 3} !53 = !DILocation(line: 0, scope: !22) SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/dbg-declare.ll000066400000000000000000000067161363521741200233000ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc < %t.ll -O0 -mtriple x86_64-apple-darwin | FileCheck %s ; RUN: llc < %t.ll -O0 -mtriple x86_64-apple-darwin -filetype=obj \ ; RUN: | llvm-dwarfdump -v - --debug-info | FileCheck %s --check-prefix=DWARF ; ; CHECK-LABEL: _foo: ; CHECK-NOT: #DEBUG_VALUE ; "[DW_FORM_exprloc] <0x2> 91 XX" means fbreg uleb(XX) ; DWARF-LABEL: DW_TAG_formal_parameter ; DWARF-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_fbreg +16) ; DWARF-NEXT: DW_AT_name [DW_FORM_strp] ( {{.*}} = "x") ; FIXME: There is no debug info to describe "a". define i32 @foo(i32* %x) nounwind uwtable ssp !dbg !5 { entry: %x.addr = alloca i32*, align 8 %saved_stack = alloca i8* %cleanup.dest.slot = alloca i32 store i32* %x, i32** %x.addr, align 8 call void @llvm.dbg.declare(metadata i32** %x.addr, metadata !14, metadata !DIExpression()), !dbg !15 %0 = load i32*, i32** %x.addr, align 8, !dbg !16 %1 = load i32, i32* %0, align 4, !dbg !16 %2 = zext i32 %1 to i64, !dbg !16 %3 = call i8* @llvm_stacksave(), !dbg !16 store i8* %3, i8** %saved_stack, !dbg !16 %vla = alloca i8, i64 %2, align 16, !dbg !16 call void @llvm.dbg.declare(metadata i8* %vla, metadata !18, metadata !DIExpression()), !dbg !23 store i32 1, i32* %cleanup.dest.slot %4 = load i8*, i8** %saved_stack, !dbg !24 call void @llvm_stackrestore(i8* %4), !dbg !24 ret i32 0, !dbg !25 } declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone declare i8* @llvm_stacksave() nounwind declare void @llvm_stackrestore(i8*) nounwind !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!27} !0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.1 (trunk 153698)", isOptimized: false, emissionKind: FullDebug, file: !26, enums: !1, retainedTypes: !1, globals: !1) !1 = !{} !5 = distinct !DISubprogram(name: "foo", line: 6, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, file: !26, scope: !0, type: !7) !6 = !DIFile(filename: "20020104-2.c", directory: "/Volumes/Sandbox/llvm") !7 = !DISubroutineType(types: !8) !8 = !{!9, !10} !9 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !10 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, baseType: !11) !11 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !9) !14 = !DILocalVariable(name: "x", line: 5, arg: 1, scope: !5, file: !6, type: !10) !15 = !DILocation(line: 5, column: 21, scope: !5) !16 = !DILocation(line: 7, column: 13, scope: !17) !17 = distinct !DILexicalBlock(line: 6, column: 1, file: !26, scope: !5) !18 = !DILocalVariable(name: "a", line: 7, scope: !17, file: !6, type: !19) !19 = !DICompositeType(tag: DW_TAG_array_type, align: 8, baseType: !20, elements: !21) !20 = !DIBasicType(tag: DW_TAG_base_type, name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char) !21 = !{!22} !22 = !DISubrange(count: -1) !23 = !DILocation(line: 7, column: 8, scope: !17) !24 = !DILocation(line: 9, column: 1, scope: !17) !25 = !DILocation(line: 8, column: 3, scope: !17) !26 = !DIFile(filename: "20020104-2.c", directory: "/Volumes/Sandbox/llvm") !27 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/dbg-file-name.ll000066400000000000000000000025531363521741200235310ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -enable-dwarf-directory -mtriple x86_64-apple-darwin10.0.0 < %t.ll | FileCheck %s ; Verify that the file name is relative to the directory. ; rdar://problem/8884898 ; CHECK: file 1 "/Users/manav/one/two" "simple.c" declare i32 @printf(i8*, ...) nounwind define i32 @main() nounwind !dbg !6 { ret i32 0 } !llvm.dbg.cu = !{!2} !llvm.module.flags = !{!12} !1 = !DIFile(filename: "simple.c", directory: "/Users/manav/one/two") !2 = distinct !DICompileUnit(language: DW_LANG_C89, producer: "LLVM build 00", isOptimized: true, emissionKind: FullDebug, file: !10, enums: !11, retainedTypes: !11) !5 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !6 = distinct !DISubprogram(name: "main", linkageName: "main", line: 9, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !2, file: !10, scope: !1, type: !7) !7 = !DISubroutineType(types: !8) !8 = !{!5} !10 = !DIFile(filename: "simple.c", directory: "/Users/manav/one/two") !11 = !{} !12 = !{i32 1, !"Debug Info Version", i32 3} target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/dbg-prolog-end.ll000066400000000000000000000062461363521741200237450ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O0 < %t.ll | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "spir64-unknown-unknown" ;CHECK-LABEL: foo: ;CHECK: .loc 1 2 11 prologue_end define i32 @foo(i32 %i) nounwind ssp !dbg !1 { entry: %i.addr = alloca i32, align 4 %j = alloca i32, align 4 store i32 %i, i32* %i.addr, align 4 call void @llvm.dbg.declare(metadata i32* %i.addr, metadata !7, metadata !DIExpression()), !dbg !8 call void @llvm.dbg.declare(metadata i32* %j, metadata !9, metadata !DIExpression()), !dbg !11 store i32 2, i32* %j, align 4, !dbg !12 %tmp = load i32, i32* %j, align 4, !dbg !13 %inc = add nsw i32 %tmp, 1, !dbg !13 store i32 %inc, i32* %j, align 4, !dbg !13 %tmp1 = load i32, i32* %j, align 4, !dbg !14 %tmp2 = load i32, i32* %i.addr, align 4, !dbg !14 %add = add nsw i32 %tmp1, %tmp2, !dbg !14 store i32 %add, i32* %j, align 4, !dbg !14 %tmp3 = load i32, i32* %j, align 4, !dbg !15 ret i32 %tmp3, !dbg !15 } declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone ;CHECK-LABEL: main: ;CHECK: .loc 1 0 0 prologue_end define i32 @main() nounwind ssp !dbg !6 { entry: %retval = alloca i32, align 4 store i32 0, i32* %retval, !dbg !22 %call = call i32 @foo(i32 21), !dbg !16 ret i32 %call, !dbg !16 } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!21} !18 = !{!1, !6} !0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.0 (trunk 131100)", isOptimized: false, emissionKind: FullDebug, file: !19, enums: !20, retainedTypes: !20, imports: null) !1 = distinct !DISubprogram(name: "foo", line: 1, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 1, file: !19, scope: !2, type: !3) !2 = !DIFile(filename: "/tmp/a.c", directory: "/private/tmp") !3 = !DISubroutineType(types: !4) !4 = !{!5} !5 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !6 = distinct !DISubprogram(name: "main", line: 7, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !0, scopeLine: 7, file: !19, scope: !2, type: !3) !7 = !DILocalVariable(name: "i", line: 1, arg: 1, scope: !1, file: !2, type: !5) !8 = !DILocation(line: 1, column: 13, scope: !1) !9 = !DILocalVariable(name: "j", line: 2, scope: !10, file: !2, type: !5) !10 = distinct !DILexicalBlock(line: 1, column: 16, file: !19, scope: !1) !11 = !DILocation(line: 2, column: 6, scope: !10) !12 = !DILocation(line: 2, column: 11, scope: !10) !13 = !DILocation(line: 3, column: 2, scope: !10) !14 = !DILocation(line: 4, column: 2, scope: !10) !15 = !DILocation(line: 5, column: 2, scope: !10) !16 = !DILocation(line: 8, column: 2, scope: !17) !17 = distinct !DILexicalBlock(line: 7, column: 12, file: !19, scope: !6) !19 = !DIFile(filename: "/tmp/a.c", directory: "/private/tmp") !20 = !{} !21 = !{i32 1, !"Debug Info Version", i32 3} !22 = !DILocation(line: 0, column: 0, scope: !17) SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/dbg-value-const-byref.ll000066400000000000000000000065071363521741200252440ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple -O1 -filetype=obj -o - %t.ll | llvm-dwarfdump -all - | FileCheck %s ; Generated with -O1 from: ; int f1(); ; void f2(int*); ; int f3(int); ; ; int foo() { ; int i = 3; ; f3(i); ; i = 7; ; i = f1(); ; f2(&i); ; return 0; ; } ; ; Test that we generate valid debug info for optimized code, ; particularly variables that are described as constants and passed ; by reference. ; rdar://problem/14874886 ; ; CHECK: .debug_info contents: ; CHECK: DW_TAG_variable ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_location {{.*}}({{.*}} ; CHECK-NEXT: 0x{{0*.*}}, [[C1:0x.*]]): DW_OP_consts +3 ; CHECK-NEXT: [[C1]], [[C2:0x.*]]): DW_OP_consts +7 ; CHECK-NEXT: [[C2]], [[R1:0x.*]]): DW_OP_reg0 RAX ; CHECK-NEXT: [[R1]], [[R2:0x.*]]): DW_OP_breg7 RSP+4) ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name{{.*}}"i" target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "spir64-unknown-unknown" ; Function Attrs: nounwind ssp uwtable define i32 @foo() #0 !dbg !4 { entry: %i = alloca i32, align 4 call void @llvm.dbg.value(metadata i32 3, metadata !10, metadata !DIExpression()), !dbg !15 %call = call i32 @f3(i32 3) #3, !dbg !16 call void @llvm.dbg.value(metadata i32 7, metadata !10, metadata !DIExpression()), !dbg !18 %call1 = call i32 (...) @f1() #3, !dbg !19 call void @llvm.dbg.value(metadata i32 %call1, metadata !10, metadata !DIExpression()), !dbg !19 store i32 %call1, i32* %i, align 4, !dbg !19, !tbaa !20 call void @llvm.dbg.value(metadata i32* %i, metadata !10, metadata !DIExpression(DW_OP_deref)), !dbg !24 call void @f2(i32* %i) #3, !dbg !24 ret i32 0, !dbg !25 } declare i32 @f3(i32) declare i32 @f1(...) declare void @f2(i32*) ; Function Attrs: nounwind readnone declare void @llvm.dbg.value(metadata, metadata, metadata) #2 attributes #0 = { nounwind ssp uwtable } attributes #2 = { nounwind readnone } attributes #3 = { nounwind } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!11, !12} !llvm.ident = !{!13} !0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.5.0 ", isOptimized: true, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) !1 = !DIFile(filename: "dbg-value-const-byref.c", directory: "") !2 = !{} !4 = distinct !DISubprogram(name: "foo", line: 5, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: true, unit: !0, scopeLine: 5, file: !1, scope: !5, type: !6, retainedNodes: !9) !5 = !DIFile(filename: "dbg-value-const-byref.c", directory: "") !6 = !DISubroutineType(types: !7) !7 = !{!8} !8 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !9 = !{!10} !10 = !DILocalVariable(name: "i", line: 6, scope: !4, file: !5, type: !8) !11 = !{i32 2, !"Dwarf Version", i32 2} !12 = !{i32 1, !"Debug Info Version", i32 3} !13 = !{!"clang version 3.5.0 "} !14 = !{i32 3} !15 = !DILocation(line: 6, scope: !4) !16 = !DILocation(line: 7, scope: !4) !17 = !{i32 7} !18 = !DILocation(line: 8, scope: !4) !19 = !DILocation(line: 9, scope: !4) !20 = !{!21, !21, i64 0} !21 = !{!"int", !22, i64 0} !22 = !{!"omnipotent char", !23, i64 0} !23 = !{!"Simple C/C++ TBAA"} !24 = !DILocation(line: 10, scope: !4) !25 = !DILocation(line: 11, scope: !4) SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/dbg-value-frame-index.ll000066400000000000000000000034741363521741200252100ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=x86_64-unknown-unknown -o - %t.ll | FileCheck %s ; RUN: llc -mtriple=x86_64-unknown-unknown -filetype=obj < %t.ll \ ; RUN: | llvm-dwarfdump -v - | FileCheck %s --check-prefix=DWARF define i1 @test() !dbg !4 { entry: %end = alloca i64, align 8 br label %while.cond while.cond: call void @llvm.dbg.value(metadata i64* %end, metadata !5, metadata !6), !dbg !7 %call = call i1 @fn(i64* %end, i64* %end, i64* null, i8* null, i64 0, i64* null, i32* null, i8* null), !dbg !7 br label %while.body while.body: br i1 0, label %while.end, label %while.cond while.end: ret i1 true } ; CHECK-LABEL: test ; CHECK: #DEBUG_VALUE: test:w <- [DW_OP_plus_uconst 8, DW_OP_deref] $rsp ; DWARF: DW_AT_location [DW_FORM_sec_offset] ( ; DWARF-NEXT: {{.*}}, {{.*}}: DW_OP_breg7 RSP+8) declare i1 @fn(i64*, i64*, i64*, i8*, i64, i64*, i32*, i8*) declare void @llvm.dbg.value(metadata, metadata, metadata) !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!2,!3} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 4.0.0", emissionKind: FullDebug) !1 = !DIFile(filename: "test.c", directory: "/") !2 = !{i32 2, !"Dwarf Version", i32 4} !3 = !{i32 2, !"Debug Info Version", i32 3} !4 = distinct !DISubprogram(name: "test", type: !10, unit: !0) !5 = !DILocalVariable(name: "w", scope: !4, type: !9) !6 = !DIExpression(DW_OP_deref) !7 = !DILocation(line: 210, column: 12, scope: !4) !8 = !{!9} !9 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean) !10 = !DISubroutineType(types: !8) target triple = "spir64-unknown-unknown" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" SPIRV-LLVM-Translator-10.0.0/test/DebugInfo/X86/dbg-value-isel.ll000066400000000000000000000112001363521741200237270ustar00rootroot00000000000000; RUN: llvm-as < %s -o %t.bc ; RUN: llvm-spirv %t.bc -o %t.spv -spirv-mem2reg=false ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ; RUN: llc -mtriple=%triple < %t.ll | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "spir64-unknown-unknown" ; PR 9879 ; CHECK: #DEBUG_VALUE: tid <- %0 = type { i8*, i8*, i8*, i8*, i32 } @sgv = internal addrspace(2) constant [1 x i8] zeroinitializer @fgv = internal addrspace(2) constant [1 x i8] zeroinitializer define void @__OpenCL_nbt02_kernel(i32 addrspace(1)* %ip) nounwind !dbg !0 { entry: call void @llvm.dbg.value(metadata i32 addrspace(1)* %ip, metadata !8, metadata !DIExpression()), !dbg !9 %0 = call <4 x i32> @__amdil_get_local_id_int() nounwind %1 = extractelement <4 x i32> %0, i32 0 br label %2 ;