├── Spirv.td ├── MCTargetDesc ├── CMakeLists.txt ├── SPIRVMCTargetDesc.cpp ├── SPIRVMCTargetDesc.h └── LLVMBuild.txt ├── TargetInfo ├── CMakeLists.txt ├── LLVMBuild.txt └── SPIRVTargetInfo.cpp ├── libSPIRV ├── libSPIRV.h ├── SPIRVModule.h ├── SPIRVStream.h ├── SPIRVType.cpp ├── SPIRVValue.cpp ├── SPIRVStream.cpp ├── SPIRVBasicBlock.h ├── SPIRVFunction.cpp ├── CMakeLists.txt ├── SPIRVErrorEnum.h ├── LLVMBuild.txt ├── SPIRVDebug.cpp ├── SPIRVDebug.h ├── SPIRVBasicBlock.cpp ├── SPIRVMDBuilder.h ├── SPIRVError.h ├── SPIRVMDWalker.h ├── SPIRVOpCode.h ├── SPIRVFunction.h ├── OpenCL.std.h ├── SPIRVDecorate.cpp ├── SPIRVInstruction.cpp ├── SPIRVOpCodeEnum.h ├── SPIRVDecorate.h └── SPIRVExtInst.h ├── Passes ├── SPIRVLowerBool.cpp ├── OCLTypeToSPIRV.h ├── OCL20To12.cpp ├── SPIRVLowerConstExpr.cpp ├── OCL21ToSPIRV.cpp ├── SPIRVRegularizeLLVM.cpp └── TransOCLMD.cpp ├── Mangler ├── CMakeLists.txt ├── README.md ├── LLVMBuild.txt ├── ManglingUtils.h ├── NameMangleAPI.h ├── FunctionDescriptor.h ├── Refcount.h ├── FunctionDescriptor.cpp ├── ManglingUtils.cpp ├── Mangler.cpp └── ParameterType.cpp ├── SPIRV.h ├── runtime ├── README.txt └── OpenCL │ ├── inc │ └── spirv.h │ └── src │ └── ImageQuerySize.cl ├── CMakeLists.txt ├── LLVMBuild.txt ├── README.md ├── SPIRVWriterPass.cpp ├── SPIRVWriterPass.h ├── SPIRVTargetMachine.h ├── SPIRVTargetMachine.cpp ├── InstructionsExt.td ├── InstructionsOCL.td └── Operands.td /Spirv.td: -------------------------------------------------------------------------------- 1 | include "Operands.td" 2 | include "Enums.td" 3 | include "Instructuins.td" 4 | 5 | -------------------------------------------------------------------------------- /MCTargetDesc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_llvm_library(LLVMSPIRVDesc 2 | SPIRVMCTargetDesc.cpp 3 | ) 4 | -------------------------------------------------------------------------------- /TargetInfo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_llvm_library(LLVMSPIRVInfo 2 | SPIRVTargetInfo.cpp 3 | ) 4 | -------------------------------------------------------------------------------- /libSPIRV/libSPIRV.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thewilsonator/llvm-target-spirv/HEAD/libSPIRV/libSPIRV.h -------------------------------------------------------------------------------- /libSPIRV/SPIRVModule.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thewilsonator/llvm-target-spirv/HEAD/libSPIRV/SPIRVModule.h -------------------------------------------------------------------------------- /libSPIRV/SPIRVStream.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thewilsonator/llvm-target-spirv/HEAD/libSPIRV/SPIRVStream.h -------------------------------------------------------------------------------- /libSPIRV/SPIRVType.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thewilsonator/llvm-target-spirv/HEAD/libSPIRV/SPIRVType.cpp -------------------------------------------------------------------------------- /libSPIRV/SPIRVValue.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thewilsonator/llvm-target-spirv/HEAD/libSPIRV/SPIRVValue.cpp -------------------------------------------------------------------------------- /Passes/SPIRVLowerBool.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thewilsonator/llvm-target-spirv/HEAD/Passes/SPIRVLowerBool.cpp -------------------------------------------------------------------------------- /libSPIRV/SPIRVStream.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thewilsonator/llvm-target-spirv/HEAD/libSPIRV/SPIRVStream.cpp -------------------------------------------------------------------------------- /libSPIRV/SPIRVBasicBlock.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thewilsonator/llvm-target-spirv/HEAD/libSPIRV/SPIRVBasicBlock.h -------------------------------------------------------------------------------- /libSPIRV/SPIRVFunction.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thewilsonator/llvm-target-spirv/HEAD/libSPIRV/SPIRVFunction.cpp -------------------------------------------------------------------------------- /Mangler/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_definitions(-D_SPIRV_LLVM_API) 2 | add_llvm_library(LLVMSPIRVMangler 3 | FunctionDescriptor.cpp 4 | Mangler.cpp 5 | ManglingUtils.cpp 6 | ParameterType.cpp 7 | ) 8 | -------------------------------------------------------------------------------- /SPIRV.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPIRV.h 3 | // LLVM 4 | // 5 | // Created by Nicholas Wilson on 16/7/17. 6 | // 7 | // 8 | 9 | #ifndef SPIRV_h 10 | #define SPIRV_h 11 | 12 | 13 | #endif /* SPIRV_h */ 14 | -------------------------------------------------------------------------------- /libSPIRV/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_definitions(-D_SPIRV_LLVM_API) 2 | include_directories(..) 3 | add_llvm_library(LLVMSPIRVlibSPIRV 4 | SPIRVBasicBlock.cpp 5 | SPIRVDebug.cpp 6 | SPIRVDecorate.cpp 7 | SPIRVEntry.cpp 8 | SPIRVFunction.cpp 9 | SPIRVInstruction.cpp 10 | SPIRVModule.cpp 11 | SPIRVStream.cpp 12 | SPIRVType.cpp 13 | SPIRVUtil.cpp 14 | SPIRVValue.cpp 15 | ) 16 | -------------------------------------------------------------------------------- /libSPIRV/SPIRVErrorEnum.h: -------------------------------------------------------------------------------- 1 | /* The error code name should be meaningful since it is part of error message */ 2 | _SPIRV_OP(Success,"") 3 | _SPIRV_OP(InvalidTargetTriple, "Expects spir-unknown-unknown or spir64-unknown-unknown.") 4 | _SPIRV_OP(InvalidAddressingModel, "Expects 0-2.") 5 | _SPIRV_OP(InvalidMemoryModel, "Expects 0-3.") 6 | _SPIRV_OP(InvalidFunctionControlMask,"") 7 | _SPIRV_OP(InvalidBuiltinSetName, "Expects OpenCL.std.") 8 | -------------------------------------------------------------------------------- /runtime/README.txt: -------------------------------------------------------------------------------- 1 | This directory contains SPIR-V builtin functions used by 2 | the LLVM module converted from SPIR-V by the SPIR-V/LLVM 3 | converter. The SPIR-V consumers need to add these builtin 4 | functions to their runtime library. 5 | 6 | For OpenCL, most of the SPIR-V instructions are translated 7 | to either LLVM instructions or OpenCL builtin function calls 8 | by the converter. Therefore only a few SPIR-V instructions 9 | need to be implemented in the runtime. -------------------------------------------------------------------------------- /Mangler/README.md: -------------------------------------------------------------------------------- 1 | Contributed by: Intel Corporation. 2 | 3 | SPIR Name Mangler 4 | ================= 5 | 6 | The NameMangler Library Converts the given function descriptor to a string 7 | that represents the function's prototype. 8 | 9 | The mangling algorithm is based on clang 3.0 Itanium mangling algorithm 10 | (http://sourcery.mentor.com/public/cxx-abi/abi.html#mangling). 11 | 12 | The algorithm is adapted to support mangling of SPIR built-in 13 | functions and was tested on SPIR built-ins only. 14 | 15 | The mangler supports mangling according to SPIR 1.2 and SPIR 2.0 16 | For usage examples see unittest/spir_name_mangler. 17 | -------------------------------------------------------------------------------- /MCTargetDesc/SPIRVMCTargetDesc.cpp: -------------------------------------------------------------------------------- 1 | //===-- SPIRVMCTargetDesc.cpp - RISCV Target Descriptions -----------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | /// 10 | /// This file provides SPIRV-specific target descriptions. 11 | /// 12 | //===----------------------------------------------------------------------===// 13 | 14 | extern "C" void LLVMInitializeSPIRVTargetMC() { 15 | //We do not support Jitting 16 | } 17 | -------------------------------------------------------------------------------- /MCTargetDesc/SPIRVMCTargetDesc.h: -------------------------------------------------------------------------------- 1 | //===-- SPIRVMCTargetDesc.h - RISCV Target Descriptions ---------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file provides SPIRV specific target descriptions. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef LLVM_LIB_TARGET_SPIRV_MCTARGETDESC_SPIRVMCTARGETDESC_H 15 | #define LLVM_LIB_TARGET_SPIRV_MCTARGETDESC_SPIRVMCTARGETDESC_H 16 | 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LLVM_TARGET_DEFINITIONS SPIRV.td) 2 | add_subdirectory(libSPIRV) 3 | add_subdirectory(Mangler) 4 | add_subdirectory(TargetInfo) 5 | add_subdirectory(MCTargetDesc) 6 | 7 | add_definitions(-D_SPIRV_LLVM_API) 8 | 9 | add_llvm_target(SPIRVCodeGen 10 | Passes/OCL20To12.cpp 11 | Passes/OCL20ToSPIRV.cpp 12 | Passes/OCL21ToSPIRV.cpp 13 | Passes/OCLTypeToSPIRV.cpp 14 | Passes/SPIRVLowerBool.cpp 15 | Passes/SPIRVLowerConstExpr.cpp 16 | Passes/SPIRVLowerOCLBlocks.cpp 17 | Passes/SPIRVRegularizeLLVM.cpp 18 | Passes/SPIRVToOCL20.cpp 19 | Passes/TransOCLMD.cpp 20 | OCLUtil.cpp 21 | SPIRVReader.cpp 22 | SPIRVTargetMachine.cpp 23 | SPIRVWriter.cpp 24 | SPIRVWriterPass.cpp 25 | 26 | ) 27 | 28 | #add_dependencies(Spirv intrinsics_gen) 29 | -------------------------------------------------------------------------------- /TargetInfo/LLVMBuild.txt: -------------------------------------------------------------------------------- 1 | ;===- ./lib/Target/RISCV/TargetInfo/LLVMBuild.txt --------------*- Conf -*--===; 2 | ; 3 | ; The LLVM Compiler Infrastructure 4 | ; 5 | ; This file is distributed under the University of Illinois Open Source 6 | ; License. See LICENSE.TXT for details. 7 | ; 8 | ;===------------------------------------------------------------------------===; 9 | ; 10 | ; This is an LLVMBuild description file for the components in this subdirectory. 11 | ; 12 | ; For more information on the LLVMBuild system, please see: 13 | ; 14 | ; http://llvm.org/docs/LLVMBuild.html 15 | ; 16 | ;===------------------------------------------------------------------------===; 17 | 18 | [component_0] 19 | type = Library 20 | name = SPIRVInfo 21 | parent = SPIRV 22 | required_libraries = Support 23 | add_to_library_groups = SPIRV 24 | -------------------------------------------------------------------------------- /MCTargetDesc/LLVMBuild.txt: -------------------------------------------------------------------------------- 1 | ;===- ./lib/Target/RISCV/MCTargetDesc/LLVMBuild.txt ------------*- Conf -*--===; 2 | ; 3 | ; The LLVM Compiler Infrastructure 4 | ; 5 | ; This file is distributed under the University of Illinois Open Source 6 | ; License. See LICENSE.TXT for details. 7 | ; 8 | ;===------------------------------------------------------------------------===; 9 | ; 10 | ; This is an LLVMBuild description file for the components in this subdirectory. 11 | ; 12 | ; For more information on the LLVMBuild system, please see: 13 | ; 14 | ; http://llvm.org/docs/LLVMBuild.html 15 | ; 16 | ;===------------------------------------------------------------------------===; 17 | 18 | [component_0] 19 | type = Library 20 | name = SPIRVDesc 21 | parent = SPIRV 22 | required_libraries = MC SPIRVInfo Support 23 | add_to_library_groups = SPIRV 24 | -------------------------------------------------------------------------------- /Mangler/LLVMBuild.txt: -------------------------------------------------------------------------------- 1 | ;===- ./lib/Target/SPIRV/Common/LLVMBuild.txt ------------------*- Conf -*--===; 2 | ; 3 | ; The LLVM Compiler Infrastructure 4 | ; 5 | ; This file is distributed under the University of Illinois Open Source 6 | ; License. See LICENSE.TXT for details. 7 | ; 8 | ;===------------------------------------------------------------------------===; 9 | ; 10 | ; This is an LLVMBuild description file for the components in this subdirectory. 11 | ; 12 | ; For more information on the LLVMBuild system, please see: 13 | ; 14 | ; http://llvm.org/docs/LLVMBuild.html 15 | ; 16 | ;===------------------------------------------------------------------------===; 17 | 18 | [component_0] 19 | type = Library 20 | name = SPIRVMangler 21 | parent = SPIRV 22 | required_libraries = Core Support Analysis IPO 23 | add_to_library_groups = SPIRV 24 | 25 | 26 | -------------------------------------------------------------------------------- /libSPIRV/LLVMBuild.txt: -------------------------------------------------------------------------------- 1 | ;===- ./lib/Target/SPIRV/Common/LLVMBuild.txt ------------------*- Conf -*--===; 2 | ; 3 | ; The LLVM Compiler Infrastructure 4 | ; 5 | ; This file is distributed under the University of Illinois Open Source 6 | ; License. See LICENSE.TXT for details. 7 | ; 8 | ;===------------------------------------------------------------------------===; 9 | ; 10 | ; This is an LLVMBuild description file for the components in this subdirectory. 11 | ; 12 | ; For more information on the LLVMBuild system, please see: 13 | ; 14 | ; http://llvm.org/docs/LLVMBuild.html 15 | ; 16 | ;===------------------------------------------------------------------------===; 17 | 18 | [component_0] 19 | type = Library 20 | name = SPIRVlibSPIRV 21 | parent = SPIRV 22 | required_libraries = Core Support Analysis IPO 23 | add_to_library_groups = SPIRV 24 | 25 | 26 | -------------------------------------------------------------------------------- /LLVMBuild.txt: -------------------------------------------------------------------------------- 1 | ;===- ./lib/Target/SPIRV/Common/LLVMBuild.txt ------------------*- Conf -*--===; 2 | ; 3 | ; The LLVM Compiler Infrastructure 4 | ; 5 | ; This file is distributed under the University of Illinois Open Source 6 | ; License. See LICENSE.TXT for details. 7 | ; 8 | ;===------------------------------------------------------------------------===; 9 | ; 10 | ; This is an LLVMBuild description file for the components in this subdirectory. 11 | ; 12 | ; For more information on the LLVMBuild system, please see: 13 | ; 14 | ; http://llvm.org/docs/LLVMBuild.html 15 | ; 16 | ;===------------------------------------------------------------------------===; 17 | [common] 18 | subdirectories = libSPIRV Mangler TargetInfo MCTargetDesc 19 | 20 | [component_0] 21 | type = TargetGroup 22 | name = SPIRV 23 | parent = Target 24 | 25 | [component_1] 26 | type = Library 27 | name = SPIRVCodeGen 28 | parent = SPIRV 29 | required_libraries = Core Support Analysis IPO SPIRVlibSPIRV SPIRVMangler 30 | add_to_library_groups = SPIRV 31 | 32 | 33 | -------------------------------------------------------------------------------- /Mangler/ManglingUtils.h: -------------------------------------------------------------------------------- 1 | //===------------------------- ManglingUtils.h ---------------------------===// 2 | // 3 | // SPIR Tools 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===---------------------------------------------------------------------===// 9 | /* 10 | * Contributed by: Intel Corporation. 11 | */ 12 | 13 | #ifndef __MANGLING_UTILS_H__ 14 | #define __MANGLING_UTILS_H__ 15 | 16 | #include "ParameterType.h" 17 | 18 | namespace SPIR { 19 | 20 | const char* mangledPrimitiveString(TypePrimitiveEnum primitive); 21 | const char* readablePrimitiveString(TypePrimitiveEnum primitive); 22 | 23 | const char* getMangledAttribute(TypeAttributeEnum attribute); 24 | const char* getReadableAttribute(TypeAttributeEnum attribute); 25 | 26 | const SPIRversion getSupportedVersion(TypePrimitiveEnum t); 27 | const char* getSPIRVersionAsString(SPIRversion version); 28 | 29 | const char* mangledPrimitiveStringfromName(std::string type); 30 | } // End SPIR namespace 31 | 32 | #endif //__MANGLING_UTILS_H__ 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | File Groups & Folders 3 | ===================== 4 | 5 | Runtime 6 | ------- 7 | 8 | Actually implemented: 9 | query_image_size_[lod] (various_image_types image) { ... } 10 | 11 | Declared 12 | 13 | convert [vector of] float type to [vector of] unsigned type [saturated] [rounding mode] 14 | convert [vector of] float type to [vector of] signed type [saturated] [rounding mode] 15 | 16 | convert [vector of] unsigned type to [vector of] float type [saturated] [rounding mode] 17 | convert [vector of] signed type to [vector of] float type [saturated] [rounding mode] 18 | 19 | integer conversion function 20 | 21 | floating point conversion functions from and to half float double [round mode] 22 | 23 | signed <-> unsigned saturated conversion 24 | 25 | Course of Action: replace with an intrinsics.td 26 | 27 | OCL* 28 | ---- 29 | 30 | Largely if not completely redundant with the use of an intrinsics.td 31 | 32 | Course of Action: 33 | remove if completely redundant or replace if not 34 | 35 | Mangling 36 | -------- 37 | 38 | Completely redundant with the use of an intrinsics.td 39 | 40 | Course of Action: remove 41 | 42 | libSPIRV 43 | -------- 44 | 45 | "AST" of SPIRV Modules 46 | 47 | SPIRV* 48 | ------ 49 | -------------------------------------------------------------------------------- /TargetInfo/SPIRVTargetInfo.cpp: -------------------------------------------------------------------------------- 1 | //===-- SPIRVTargetInfo.cpp - SPIRV Target Implementation -----------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | 10 | #include "llvm/Support/TargetRegistry.h" 11 | using namespace llvm; 12 | 13 | namespace llvm { 14 | Target &getTheSPIRV32Target() { 15 | static Target TheSPIRV32Target; 16 | return TheSPIRV32Target; 17 | } 18 | 19 | Target &getTheSPIRV64Target() { 20 | static Target TheSPIRV64Target; 21 | return TheSPIRV64Target; 22 | } 23 | /* 24 | Target &getTheSPIRVLTarget() { 25 | static Target TheSPIRVLTarget; 26 | return TheSPIRVLTarget; 27 | } 28 | */ 29 | } 30 | 31 | extern "C" void LLVMInitializeSPIRVTargetInfo() { 32 | RegisterTarget X(getTheSPIRV32Target(), "spirv32", 33 | "32-bit SPIR-V", "SPIRV"); 34 | RegisterTarget Y(getTheSPIRV64Target(), "spirv64", 35 | "64-bit SPIR-V", "SPIRV"); 36 | //RegisterTarget Z(getTheSPIRVLTarget(), "spirvlogical", 37 | // "SPIR-V Logical", "SPIRV"); 38 | } 39 | -------------------------------------------------------------------------------- /runtime/OpenCL/inc/spirv.h: -------------------------------------------------------------------------------- 1 | __attribute__((overloadable, always_inline)) int __spirv_ImageQuerySize(image1d_buffer_t img); 2 | __attribute__((overloadable, always_inline)) int2 __spirv_ImageQuerySize(image1d_array_t img); 3 | __attribute__((overloadable, always_inline)) int2 __spirv_ImageQuerySize(image2d_t img); 4 | __attribute__((overloadable, always_inline)) int2 __spirv_ImageQuerySize(image2d_depth_t img); 5 | __attribute__((overloadable, always_inline)) int3 __spirv_ImageQuerySize(image2d_array_t img); 6 | __attribute__((overloadable, always_inline)) int3 __spirv_ImageQuerySize(image2d_array_depth_t img); 7 | 8 | __attribute__((overloadable, always_inline)) int __spirv_ImageQuerySizeLod(image1d_t img, int lod); 9 | __attribute__((overloadable, always_inline)) int2 __spirv_ImageQuerySizeLod(image1d_array_t img, int lod); 10 | __attribute__((overloadable, always_inline)) int2 __spirv_ImageQuerySizeLod(image2d_t img, int lod); 11 | __attribute__((overloadable, always_inline)) int2 __spirv_ImageQuerySizeLod(image2d_depth_t img, int lod); 12 | __attribute__((overloadable, always_inline)) int3 __spirv_ImageQuerySizeLod(image2d_array_t img, int lod); 13 | __attribute__((overloadable, always_inline)) int3 __spirv_ImageQuerySizeLod(image2d_array_depth_t img, int lod); 14 | __attribute__((overloadable, always_inline)) int3 __spirv_ImageQuerySizeLod(image3d_t img, int lod); 15 | 16 | -------------------------------------------------------------------------------- /Mangler/NameMangleAPI.h: -------------------------------------------------------------------------------- 1 | //===------------------------- NameMangleAPI.h ---------------------------===// 2 | // 3 | // SPIR Tools 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===---------------------------------------------------------------------===// 9 | /* 10 | * Contributed by: Intel Corporation. 11 | */ 12 | #ifndef __NAME_MANGLE_API_H__ 13 | #define __NAME_MANGLE_API_H__ 14 | 15 | #include "FunctionDescriptor.h" 16 | #include 17 | 18 | namespace SPIR { 19 | struct NameMangler { 20 | 21 | /// @brief Constructor. 22 | /// @param SPIRversion spir version to mangle according to. 23 | NameMangler(SPIRversion); 24 | 25 | /// @brief Converts the given function descriptor to string that represents 26 | /// the function's prototype. 27 | /// The mangling algorithm is based on Itanium mangling algorithm 28 | /// (http://sourcery.mentor.com/public/cxx-abi/abi.html#mangling), with 29 | /// SPIR extensions. 30 | /// @param FunctionDescriptor function to be mangled. 31 | /// @param std::string the mangled name if the mangling succeeds, 32 | /// the error otherwise. 33 | /// @return MangleError enum representing the status - success or the error. 34 | MangleError mangle(const FunctionDescriptor&, std::string &); 35 | private: 36 | SPIRversion m_spir_version; 37 | }; 38 | } // End SPIR namespace 39 | 40 | #endif //__NAME_MANGLE_API_H__ 41 | -------------------------------------------------------------------------------- /SPIRVWriterPass.cpp: -------------------------------------------------------------------------------- 1 | //===- SPIRVWriterPass.cpp - SPIRV writing pass -----------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // SPIRVWriterPass implementation. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "SPIRVWriterPass.h" 15 | #include "llvm/IR/Module.h" 16 | #include "llvm/IR/PassManager.h" 17 | #include "llvm/Pass.h" 18 | #include "llvm/Support/SPIRV.h" 19 | using namespace llvm; 20 | 21 | PreservedAnalyses SPIRVWriterPass::run(Module &M) { 22 | // FIXME: at the moment LLVM/SPIR-V translation errors are ignored. 23 | std::string err; 24 | WriteSPIRV(&M, OS, err); 25 | return PreservedAnalyses::all(); 26 | } 27 | 28 | namespace { 29 | class WriteSPIRVPass : public ModulePass { 30 | raw_ostream &OS; // raw_ostream to print on 31 | public: 32 | static char ID; // Pass identification, replacement for typeid 33 | explicit WriteSPIRVPass(raw_ostream &o) 34 | : ModulePass(ID), OS(o) {} 35 | 36 | StringRef getPassName() const override { return "SPIRV Writer"; } 37 | 38 | bool runOnModule(Module &M) override { 39 | // FIXME: at the moment LLVM/SPIR-V translation errors are ignored. 40 | std::string err; 41 | WriteSPIRV(&M, OS, err); 42 | return false; 43 | } 44 | }; 45 | } 46 | 47 | char WriteSPIRVPass::ID = 0; 48 | 49 | ModulePass *llvm::createSPIRVWriterPass(raw_ostream &Str) { 50 | return new WriteSPIRVPass(Str); 51 | } 52 | -------------------------------------------------------------------------------- /SPIRVWriterPass.h: -------------------------------------------------------------------------------- 1 | //===------ SPIRVWriterPass.h - SPIRV writing pass --------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | /// \file 10 | /// 11 | /// This file provides a SPIRV writing pass. 12 | /// 13 | //===----------------------------------------------------------------------===// 14 | 15 | #ifndef LLVM_SPIRVWRITERPASS_H 16 | #define LLVM_SPIRVWRITERPASS_H 17 | 18 | #include "llvm/ADT/StringRef.h" 19 | 20 | namespace llvm { 21 | class Module; 22 | class ModulePass; 23 | class raw_ostream; 24 | class PreservedAnalyses; 25 | 26 | /// \brief Create and return a pass that writes the module to the specified 27 | /// ostream. Note that this pass is designed for use with the legacy pass 28 | /// manager. 29 | ModulePass *createSPIRVWriterPass(raw_ostream &Str); 30 | 31 | /// \brief Pass for writing a module of IR out to a SPIRV file. 32 | /// 33 | /// Note that this is intended for use with the new pass manager. To construct 34 | /// a pass for the legacy pass manager, use the function above. 35 | class SPIRVWriterPass { 36 | raw_ostream &OS; 37 | 38 | public: 39 | /// \brief Construct a SPIRV writer pass around a particular output stream. 40 | explicit SPIRVWriterPass(raw_ostream &OS) : OS(OS) {} 41 | 42 | /// \brief Run the SPIRV writer pass, and output the module to the selected 43 | /// output stream. 44 | PreservedAnalyses run(Module &M); 45 | 46 | static StringRef name() { return "SPIRVWriterPass"; } 47 | }; 48 | 49 | } 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /Mangler/FunctionDescriptor.h: -------------------------------------------------------------------------------- 1 | //===----------------------- FunctionDescriptor.h ------------------------===// 2 | // 3 | // SPIR Tools 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===---------------------------------------------------------------------===// 9 | /* 10 | * Contributed by: Intel Corporation. 11 | */ 12 | 13 | #ifndef __FUNCTION_DESCRIPTOR_H__ 14 | #define __FUNCTION_DESCRIPTOR_H__ 15 | 16 | #include "ParameterType.h" 17 | #include "Refcount.h" 18 | #include 19 | #include 20 | 21 | namespace SPIR { 22 | typedef std::vector > TypeVector; 23 | 24 | struct FunctionDescriptor { 25 | /// @brief Returns a human readable string representation of the function's 26 | /// prototype. 27 | /// @returns std::string representing the function's prototype. 28 | std::string toString() const; 29 | 30 | /// The name of the function (stripped). 31 | std::string name; 32 | /// Parameter list of the function. 33 | TypeVector parameters; 34 | 35 | bool operator == (const FunctionDescriptor&) const; 36 | 37 | /// @brief Enables function descriptors to serve as keys in stl maps. 38 | bool operator < (const FunctionDescriptor&) const; 39 | bool isNull() const; 40 | 41 | /// @brief Create a singular value, that represents a 'null' FunctionDescriptor. 42 | static FunctionDescriptor null(); 43 | 44 | static std::string nullString(); 45 | }; 46 | 47 | template 48 | std::ostream& operator<< (T& o, const SPIR::FunctionDescriptor& fd) { 49 | o << fd.toString(); 50 | return o; 51 | } 52 | } // End SPIR namespace 53 | 54 | #endif //__FUNCTION_DESCRIPTOR_H__ 55 | -------------------------------------------------------------------------------- /runtime/OpenCL/src/ImageQuerySize.cl: -------------------------------------------------------------------------------- 1 | #include "../inc/spirv.h" 2 | 3 | __attribute__((overloadable, always_inline)) int __spirv_ImageQuerySize(image1d_buffer_t img) { 4 | return get_image_width(img); 5 | } 6 | 7 | __attribute__((overloadable, always_inline)) int __spirv_ImageQuerySizeLod(image1d_t img, int lod) { 8 | return get_image_width(img) >> lod; 9 | } 10 | __attribute__((overloadable, always_inline)) int2 __spirv_ImageQuerySize(image1d_array_t img) { 11 | return (int2)(get_image_width(img), get_image_array_size(img)); 12 | } 13 | __attribute__((overloadable, always_inline)) int2 __spirv_ImageQuerySizeLod(image1d_array_t img, int lod) { 14 | return (int2)(get_image_width(img) >> lod, get_image_array_size(img) >> lod); 15 | } 16 | 17 | #define DEFINE_SPIRV_ImageQuerySizeLod_2d(ImgTy) \ 18 | __attribute__((overloadable, always_inline)) int2 __spirv_ImageQuerySizeLod(ImgTy img, int lod) { \ 19 | return get_image_dim(img) >> lod; \ 20 | } 21 | 22 | #define DEFINE_SPIRV_ImageQuerySizeLod_2darray(ImgTy) \ 23 | __attribute__((overloadable, always_inline)) int3 __spirv_ImageQuerySizeLod(ImgTy img, int lod) { \ 24 | return (int3)(get_image_dim(img) >> lod, get_image_array_size(img) >> lod); \ 25 | } 26 | 27 | #define DEFINE_SPIRV_ImageQuerySize_2d(ImgTy) \ 28 | __attribute__((overloadable, always_inline)) int2 __spirv_ImageQuerySize(ImgTy img) { \ 29 | return get_image_dim(img); \ 30 | } 31 | 32 | #define DEFINE_SPIRV_ImageQuerySize_2darray(ImgTy) \ 33 | __attribute__((overloadable, always_inline)) int3 __spirv_ImageQuerySize(ImgTy img) { \ 34 | return (int3)(get_image_dim(img), get_image_array_size(img)); \ 35 | } 36 | 37 | __attribute__((overloadable, always_inline)) int3 __spirv_ImageQuerySizeLod(image3d_t img, int lod) { 38 | return get_image_dim(img).xyz >> lod; 39 | } 40 | 41 | DEFINE_SPIRV_ImageQuerySize_2d(image2d_t) 42 | DEFINE_SPIRV_ImageQuerySize_2d(image2d_depth_t) 43 | DEFINE_SPIRV_ImageQuerySizeLod_2d(image2d_t) 44 | DEFINE_SPIRV_ImageQuerySizeLod_2d(image2d_depth_t) 45 | DEFINE_SPIRV_ImageQuerySize_2darray(image2d_array_t) 46 | DEFINE_SPIRV_ImageQuerySize_2darray(image2d_array_depth_t) 47 | DEFINE_SPIRV_ImageQuerySizeLod_2darray(image2d_array_t) 48 | DEFINE_SPIRV_ImageQuerySizeLod_2darray(image2d_array_depth_t) 49 | -------------------------------------------------------------------------------- /libSPIRV/SPIRVDebug.cpp: -------------------------------------------------------------------------------- 1 | //===- SPIRVDebug.cpp - SPIR-V Debug Utility ---------------------*- C++ -*-===// 2 | // 3 | // The LLVM/SPIRV Translator 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a 11 | // copy of this software and associated documentation files (the "Software"), 12 | // to deal with the Software without restriction, including without limitation 13 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 | // and/or sell copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following conditions: 16 | // 17 | // Redistributions of source code must retain the above copyright notice, 18 | // this list of conditions and the following disclaimers. 19 | // Redistributions in binary form must reproduce the above copyright notice, 20 | // this list of conditions and the following disclaimers in the documentation 21 | // and/or other materials provided with the distribution. 22 | // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 | // contributors may be used to endorse or promote products derived from this 24 | // Software without specific prior written permission. 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 | // THE SOFTWARE. 32 | // 33 | //===----------------------------------------------------------------------===// 34 | /// \file 35 | /// 36 | /// This file defines variables for enabling/disabling SPIR-V debug macro. 37 | /// 38 | //===----------------------------------------------------------------------===// 39 | 40 | #include "SPIRVDebug.h" 41 | 42 | using namespace SPIRV; 43 | 44 | bool SPIRV::SPIRVDbgEnable = false; 45 | bool SPIRV::SPIRVDbgAssertOnError = true; 46 | bool SPIRV::SPIRVDbgErrorMsgIncludesSourceInfo = true; 47 | -------------------------------------------------------------------------------- /Mangler/Refcount.h: -------------------------------------------------------------------------------- 1 | //===--------------------------- Refcount.h ------------------------------===// 2 | // 3 | // SPIR Tools 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===---------------------------------------------------------------------===// 9 | /* 10 | * Contributed by: Intel Corporation 11 | */ 12 | 13 | #ifndef __REF_COUNT_H__ 14 | #define __REF_COUNT_H__ 15 | 16 | #include 17 | 18 | namespace SPIR { 19 | 20 | template 21 | class RefCount{ 22 | public: 23 | RefCount(): m_refCount(0), m_ptr(0) { 24 | } 25 | 26 | RefCount(T* ptr): m_ptr(ptr) { 27 | m_refCount = new int(1); 28 | } 29 | 30 | RefCount(const RefCount& other) { 31 | cpy(other); 32 | } 33 | 34 | ~RefCount() { 35 | if (m_refCount) 36 | dispose(); 37 | } 38 | 39 | RefCount& operator=(const RefCount& other) { 40 | if(this == &other) 41 | return *this; 42 | if (m_refCount) 43 | dispose(); 44 | cpy(other); 45 | return *this; 46 | } 47 | 48 | void init(T* ptr) { 49 | assert(!m_ptr && "overrunning non NULL pointer"); 50 | assert(!m_refCount && "overrunning non NULL pointer"); 51 | m_refCount = new int(1); 52 | m_ptr = ptr; 53 | } 54 | 55 | bool isNull() const { 56 | return (!m_ptr); 57 | } 58 | 59 | // Pointer access 60 | const T& operator*() const{ 61 | sanity(); 62 | return *m_ptr; 63 | } 64 | 65 | T& operator*() { 66 | sanity(); 67 | return *m_ptr; 68 | } 69 | 70 | operator T*() { 71 | return m_ptr; 72 | } 73 | 74 | operator const T*() const{ 75 | return m_ptr; 76 | } 77 | 78 | T* operator->() { 79 | return m_ptr; 80 | } 81 | 82 | const T* operator->() const{ 83 | return m_ptr; 84 | } 85 | private: 86 | void sanity() const{ 87 | assert(m_ptr && "NULL pointer"); 88 | assert(m_refCount && "NULL ref counter"); 89 | assert(*m_refCount && "zero ref counter"); 90 | } 91 | 92 | void cpy(const RefCount& other) { 93 | m_refCount = other.m_refCount; 94 | m_ptr = other.m_ptr; 95 | if (m_refCount) ++*m_refCount; 96 | } 97 | 98 | void dispose() { 99 | sanity(); 100 | if (0 == --*m_refCount) { 101 | delete m_refCount; 102 | delete m_ptr; 103 | m_ptr = 0; 104 | m_refCount = 0; 105 | } 106 | } 107 | 108 | int* m_refCount; 109 | T* m_ptr; 110 | };// End RefCount 111 | 112 | } // End SPIR namespace 113 | 114 | #endif//__REF_COUNT_H__ 115 | -------------------------------------------------------------------------------- /Mangler/FunctionDescriptor.cpp: -------------------------------------------------------------------------------- 1 | //===---------------------- FunctionDescriptor.cpp -----------------------===// 2 | // 3 | // SPIR Tools 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===---------------------------------------------------------------------===// 9 | /* 10 | * Contributed by: Intel Corporation. 11 | */ 12 | 13 | #include "FunctionDescriptor.h" 14 | #include "ParameterType.h" 15 | #include 16 | 17 | namespace SPIR { 18 | 19 | std::string FunctionDescriptor::nullString() { 20 | return std::string(""); 21 | } 22 | 23 | std::string FunctionDescriptor::toString() const { 24 | std::stringstream stream; 25 | if (isNull()) { 26 | return FunctionDescriptor::nullString(); 27 | } 28 | stream << name << "("; 29 | size_t paramCount = parameters.size(); 30 | if (paramCount > 0) { 31 | for (size_t i=0 ; itoString() << ", "; 33 | stream << parameters[paramCount-1]->toString(); 34 | } 35 | stream << ")"; 36 | return stream.str(); 37 | } 38 | 39 | static bool equal(const TypeVector& l, const TypeVector& r) { 40 | if (&l == &r) 41 | return true; 42 | if (l.size() != r.size()) 43 | return false; 44 | TypeVector::const_iterator itl = l.begin(), itr = r.begin(), 45 | endl = l.end(); 46 | while (itl != endl) { 47 | if (!(*itl)->equals(*itr)) 48 | return false; 49 | ++itl; 50 | ++itr; 51 | } 52 | return true; 53 | } 54 | 55 | // 56 | // FunctionDescriptor 57 | // 58 | 59 | bool FunctionDescriptor::operator == (const FunctionDescriptor& that) const { 60 | if (this == &that) 61 | return true; 62 | if (name != that.name) 63 | return false; 64 | return equal(parameters, that.parameters); 65 | } 66 | 67 | bool FunctionDescriptor::operator < (const FunctionDescriptor& that) const { 68 | int strCmp = name.compare(that.name); 69 | if (strCmp) 70 | return (strCmp < 0); 71 | size_t len = parameters.size(), thatLen = that.parameters.size(); 72 | if (len != thatLen) 73 | return len < thatLen; 74 | TypeVector::const_iterator it = parameters.begin(), 75 | e = parameters.end(), thatit = that.parameters.begin(); 76 | while (it != e) { 77 | int cmp = (*it)->toString().compare((*thatit)->toString()); 78 | if (cmp) 79 | return (cmp < 0); 80 | ++thatit; 81 | ++it; 82 | } 83 | return false; 84 | } 85 | 86 | bool FunctionDescriptor::isNull() const { 87 | return (name.empty() && parameters.empty()); 88 | } 89 | 90 | FunctionDescriptor FunctionDescriptor::null() { 91 | FunctionDescriptor fd; 92 | fd.name = ""; 93 | return fd; 94 | } 95 | 96 | } // End SPIR namespace 97 | -------------------------------------------------------------------------------- /SPIRVTargetMachine.h: -------------------------------------------------------------------------------- 1 | //===-- SPIRVTargetMachine.h - Define TargetMachine for SPIRV ---*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file declares the SPIRV specific subclass of TargetMachine. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef LLVM_LIB_TARGET_SPIRV_SPIRVTARGETMACHINE_H 15 | #define LLVM_LIB_TARGET_SPIRV_SPIRVTARGETMACHINE_H 16 | 17 | #include "SPIRVInternal.h" 18 | #include "llvm/Target/TargetMachine.h" 19 | enum SPIRVTargetMachineType 20 | { 21 | STMT_OCL32, 22 | STMT_OCL64, 23 | STMT_VK 24 | }; 25 | 26 | namespace llvm { 27 | 28 | class SPIRVTargetMachine : public LLVMTargetMachine { 29 | int version; //e.g. 120 for OpenCL 1.2,450 for GLSL450 30 | SPIRVTargetMachineType stmt; 31 | // TODO: capabilities 32 | public: 33 | SPIRVTargetMachine(const Target &T, StringRef DL, const Triple &TT, 34 | StringRef CPU, StringRef FS, const TargetOptions &Options, 35 | SPIRVTargetMachineType stmt, Reloc::Model RM, 36 | CodeModel::Model CM, CodeGenOpt::Level OL, bool Jit); 37 | ~SPIRVTargetMachine() override; 38 | 39 | virtual bool addPassesToEmitFile(PassManagerBase &PM, raw_pwrite_stream &Out, 40 | raw_pwrite_stream *DwoOut, CodeGenFileType FileType, 41 | bool DisableVerify = true, MachineModuleInfo* MMI = nullptr) override; 42 | }; 43 | 44 | class SPIRV32TargetMachine : public SPIRVTargetMachine { 45 | 46 | public: 47 | SPIRV32TargetMachine(const Target &T, const Triple &TT, StringRef CPU, 48 | StringRef FS, const TargetOptions &Options, Optional RM, 49 | Optional CM, CodeGenOpt::Level OL, bool Jit); 50 | }; 51 | 52 | /// SPIRV 64-bit target machine 53 | /// 54 | class SPIRV64TargetMachine : public SPIRVTargetMachine { 55 | 56 | public: 57 | SPIRV64TargetMachine(const Target &T, const Triple &TT, StringRef CPU, 58 | StringRef FS, const TargetOptions &Options, Optional RM, 59 | Optional CM, CodeGenOpt::Level OL, bool Jit); 60 | }; 61 | 62 | class SPIRVLTargetMachine : public SPIRVTargetMachine { 63 | 64 | 65 | public: 66 | SPIRVLTargetMachine(const Target &T, const Triple &TT, StringRef CPU, 67 | StringRef FS, const TargetOptions &Options, Optional RM, 68 | Optional CM, CodeGenOpt::Level OL, bool Jit); 69 | }; 70 | 71 | 72 | 73 | } // end namespace llvm 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /libSPIRV/SPIRVDebug.h: -------------------------------------------------------------------------------- 1 | //===- SPIRVDebug.h - SPIR-V Debug Utility -----------------------*- C++ -*-===// 2 | // 3 | // The LLVM/SPIRV Translator 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a 11 | // copy of this software and associated documentation files (the "Software"), 12 | // to deal with the Software without restriction, including without limitation 13 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 | // and/or sell copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following conditions: 16 | // 17 | // Redistributions of source code must retain the above copyright notice, 18 | // this list of conditions and the following disclaimers. 19 | // Redistributions in binary form must reproduce the above copyright notice, 20 | // this list of conditions and the following disclaimers in the documentation 21 | // and/or other materials provided with the distribution. 22 | // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 | // contributors may be used to endorse or promote products derived from this 24 | // Software without specific prior written permission. 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 | // THE SOFTWARE. 32 | // 33 | //===----------------------------------------------------------------------===// 34 | /// \file 35 | /// 36 | /// This file defines Macros and variables for debugging SPIRV. 37 | /// 38 | //===----------------------------------------------------------------------===// 39 | 40 | #ifndef SPIRVDEBUG_HPP_ 41 | #define SPIRVDEBUG_HPP_ 42 | 43 | #include "SPIRVUtil.h" 44 | #ifdef _SPIRV_LLVM_API 45 | #include "llvm/Support/Debug.h" 46 | #endif 47 | #include 48 | 49 | namespace SPIRV{ 50 | 51 | #define _SPIRVDBG 52 | #ifdef _SPIRVDBG 53 | 54 | #define SPIRVDBG(x) if(SPIRVDbgEnable) {x;} 55 | 56 | // Enable debug output. 57 | extern bool SPIRVDbgEnable; 58 | 59 | // Include source file and line number in error message. 60 | extern bool SPIRVDbgErrorMsgIncludesSourceInfo; 61 | 62 | // Enable assert on error 63 | extern bool SPIRVDbgAssertOnError; 64 | 65 | // Output stream for SPIRV debug information. 66 | inline spv_ostream &spvdbgs() { 67 | #ifdef _SPIRV_LLVM_API 68 | return llvm::dbgs(); 69 | #else 70 | return std::cerr; 71 | #endif 72 | } 73 | 74 | #else 75 | 76 | #define SPIRVDBG(x) 77 | 78 | #endif 79 | 80 | } 81 | #endif /* SPIRVDEBUG_HPP_ */ 82 | -------------------------------------------------------------------------------- /libSPIRV/SPIRVBasicBlock.cpp: -------------------------------------------------------------------------------- 1 | //===- SPIRVBasicBlock.cpp - SPIR-V Basic Block ------------------*- C++ -*-===// 2 | // 3 | // The LLVM/SPIRV Translator 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a 11 | // copy of this software and associated documentation files (the "Software"), 12 | // to deal with the Software without restriction, including without limitation 13 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 | // and/or sell copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following conditions: 16 | // 17 | // Redistributions of source code must retain the above copyright notice, 18 | // this list of conditions and the following disclaimers. 19 | // Redistributions in binary form must reproduce the above copyright notice, 20 | // this list of conditions and the following disclaimers in the documentation 21 | // and/or other materials provided with the distribution. 22 | // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 | // contributors may be used to endorse or promote products derived from this 24 | // Software without specific prior written permission. 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 | // THE SOFTWARE. 32 | // 33 | //===----------------------------------------------------------------------===// 34 | /// \file 35 | /// 36 | /// This file implements SPIRV basic block. 37 | /// 38 | //===----------------------------------------------------------------------===// 39 | 40 | #include "SPIRVEntry.h" 41 | #include "SPIRVValue.h" 42 | #include "SPIRVBasicBlock.h" 43 | #include "SPIRVInstruction.h" 44 | #include "SPIRVFunction.h" 45 | #include "SPIRVStream.h" 46 | 47 | #include 48 | 49 | using namespace SPIRV; 50 | 51 | SPIRVBasicBlock::SPIRVBasicBlock(SPIRVId TheId, SPIRVFunction *Func) 52 | :SPIRVValue(Func->getModule(), 2, OpLabel, TheId), ParentF(Func) { 53 | setAttr(); 54 | validate(); 55 | } 56 | 57 | SPIRVDecoder 58 | SPIRVBasicBlock::getDecoder(std::istream &IS){ 59 | return SPIRVDecoder(IS, *this); 60 | } 61 | 62 | /// Assume I contains valid Id. 63 | SPIRVInstruction * 64 | SPIRVBasicBlock::addInstruction(SPIRVInstruction *I) { 65 | assert(I && "Invalid instruction"); 66 | Module->add(I); 67 | I->setParent(this); 68 | InstVec.push_back(I); 69 | return I; 70 | } 71 | 72 | void 73 | SPIRVBasicBlock::encodeChildren(spv_ostream &O) const { 74 | O << SPIRVNL(); 75 | for (size_t i = 0, e = InstVec.size(); i != e; ++i) 76 | O << *InstVec[i]; 77 | } 78 | 79 | _SPIRV_IMP_ENCDEC1(SPIRVBasicBlock, Id) 80 | 81 | void 82 | SPIRVBasicBlock::setScope(SPIRVEntry *Scope) { 83 | assert(Scope && Scope->getOpCode() == OpFunction && "Invalid scope"); 84 | setParent(static_cast(Scope)); 85 | } 86 | -------------------------------------------------------------------------------- /Passes/OCLTypeToSPIRV.h: -------------------------------------------------------------------------------- 1 | //===- OCLTypeToSPIRV.h - Adapt types from OCL for SPIRV --------*- C++ -*-===// 2 | // 3 | // The LLVM/SPIRV Translator 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a 11 | // copy of this software and associated documentation files (the "Software"), 12 | // to deal with the Software without restriction, including without limitation 13 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 | // and/or sell copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following conditions: 16 | // 17 | // Redistributions of source code must retain the above copyright notice, 18 | // this list of conditions and the following disclaimers. 19 | // Redistributions in binary form must reproduce the above copyright notice, 20 | // this list of conditions and the following disclaimers in the documentation 21 | // and/or other materials provided with the distribution. 22 | // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 | // contributors may be used to endorse or promote products derived from this 24 | // Software without specific prior written permission. 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 | // THE SOFTWARE. 32 | // 33 | //===----------------------------------------------------------------------===// 34 | // 35 | // This file implements adaptation of OCL types for SPIRV. It does not modify 36 | // the module. Instead, it returns adapted function type based on kernel 37 | // argument metadata. Later LLVM/SPIRV translator will translate the adapted 38 | // type instead of the original type. 39 | // 40 | //===----------------------------------------------------------------------===// 41 | #include "llvm/Support/SPIRV.h" 42 | #include "llvm/Pass.h" 43 | #include "llvm/IR/LLVMContext.h" 44 | #include "llvm/IR/Function.h" 45 | 46 | #include 47 | #include 48 | 49 | using namespace llvm; 50 | 51 | namespace SPIRV { 52 | 53 | class OCLTypeToSPIRV: public ModulePass { 54 | public: 55 | OCLTypeToSPIRV(); 56 | virtual void getAnalysisUsage(AnalysisUsage &AU) const; 57 | virtual bool runOnModule(Module &M); 58 | 59 | /// \return Adapted type based on kernel argument metadata. If \p V is 60 | /// a function, returns function type. 61 | /// E.g. for a function with argument of read only opencl.image_2d_t* type 62 | /// returns a function with argument of type opencl.image2d_t.read_only*. 63 | Type *getAdaptedType(Value *V); 64 | 65 | static char ID; 66 | private: 67 | Module *M; 68 | LLVMContext *Ctx; 69 | unsigned CLVer; 70 | std::map AdaptedTy; // Adapted types for values 71 | std::set WorkSet; // Functions to be adapted 72 | 73 | MDNode *getArgBaseTypeMetadata(Function *); 74 | MDNode *getArgAccessQualifierMetadata(Function *); 75 | MDNode *getArgMetadata(Function *, const std::string& MDName); 76 | MDNode *getKernelMetadata(Function *F); 77 | void adaptArgumentsByMetadata(Function* F); 78 | void adaptArgumentsBySamplerUse(Module &M); 79 | void adaptFunction(Function *F); 80 | void addAdaptedType(Value *V, Type *T); 81 | void addWork(Function *F); 82 | }; 83 | 84 | } 85 | 86 | 87 | -------------------------------------------------------------------------------- /SPIRVTargetMachine.cpp: -------------------------------------------------------------------------------- 1 | //===-- SPIRCTargetMachine.cpp - Define TargetMachine for SPIRV -----------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "SPIRVTargetMachine.h" 14 | #include "SPIRVWriterPass.h" 15 | 16 | #include "llvm/CodeGen/Passes.h" 17 | #include "llvm/CodeGen/TargetPassConfig.h" 18 | #include "llvm/IR/LegacyPassManager.h" 19 | #include "llvm/Support/TargetRegistry.h" 20 | using namespace llvm; 21 | 22 | /// Create an ILP32 architecture model 23 | SPIRVTargetMachine::SPIRVTargetMachine(const Target &T, StringRef _DL, 24 | const Triple &TT, 25 | StringRef CPU, StringRef FS, 26 | const TargetOptions &Options, 27 | SPIRVTargetMachineType stmt, 28 | Reloc::Model RM, 29 | CodeModel::Model CM, CodeGenOpt::Level OL, 30 | bool Jit) 31 | : LLVMTargetMachine(T, _DL, TT, CPU, FS, Options,RM,CM,OL), stmt(stmt) { 32 | } 33 | 34 | SPIRVTargetMachine::~SPIRVTargetMachine() {} 35 | 36 | bool SPIRVTargetMachine::addPassesToEmitFile(PassManagerBase &PM, raw_pwrite_stream &Out, 37 | raw_pwrite_stream *DwoOut, CodeGenFileType FileType, 38 | bool DisableVerify, MachineModuleInfo* MMI) 39 | { 40 | PM.add(createSPIRVWriterPass(Out)); 41 | return false; 42 | 43 | } 44 | 45 | SPIRV32TargetMachine::SPIRV32TargetMachine(const Target &T, const Triple &TT, 46 | StringRef CPU, StringRef FS, 47 | const TargetOptions &_Options, Optional RM, 48 | Optional CM, CodeGenOpt::Level OL, bool Jit) 49 | : SPIRVTargetMachine(T,SPIR_DATALAYOUT32,TT,CPU,FS,_Options,STMT_OCL32, 50 | Reloc::Static, 51 | CM ? *CM : CodeModel::Medium, 52 | OL,false) {} 53 | 54 | 55 | SPIRV64TargetMachine::SPIRV64TargetMachine(const Target &T, const Triple &TT, 56 | StringRef CPU, StringRef FS, 57 | const TargetOptions &_Options,Optional RM, 58 | Optional CM, CodeGenOpt::Level OL, bool Jit) 59 | : SPIRVTargetMachine(T,SPIR_DATALAYOUT64,TT,CPU,FS,_Options,STMT_OCL64, 60 | Reloc::Static, 61 | CM ? *CM : CodeModel::Medium, 62 | OL, false) {} 63 | 64 | 65 | 66 | SPIRVLTargetMachine::SPIRVLTargetMachine(const Target &T, const Triple &TT, 67 | StringRef CPU, StringRef FS, 68 | const TargetOptions &_Options,Optional RM, 69 | Optional CM, CodeGenOpt::Level OL, bool Jit) 70 | // TODO: data layout 71 | : SPIRVTargetMachine(T,"",TT,CPU,FS,_Options,STMT_VK,Reloc::Static, 72 | CM ? *CM : CodeModel::Medium, 73 | OL, false) {} 74 | 75 | 76 | namespace llvm { 77 | Target &getTheSPIRV32Target(); 78 | Target &getTheSPIRV64Target(); 79 | //Target &getTheSPIRVLTarget(); 80 | } 81 | extern "C" void LLVMInitializeSPIRVTarget() { 82 | // Register the target. 83 | RegisterTargetMachine X(getTheSPIRV32Target()); 84 | RegisterTargetMachine Y(getTheSPIRV64Target()); 85 | //RegisterTargetMachine Z(getTheSPIRVLTarget()); 86 | } 87 | -------------------------------------------------------------------------------- /libSPIRV/SPIRVMDBuilder.h: -------------------------------------------------------------------------------- 1 | //===- SPIRVMDBuilder.h - SPIR-V metadata builder header file --*- C++ -*-===// 2 | // 3 | // The LLVM/SPIRV Translator 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a 11 | // copy of this software and associated documentation files (the "Software"), 12 | // to deal with the Software without restriction, including without limitation 13 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 | // and/or sell copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following conditions: 16 | // 17 | // Redistributions of source code must retain the above copyright notice, 18 | // this list of conditions and the following disclaimers. 19 | // Redistributions in binary form must reproduce the above copyright notice, 20 | // this list of conditions and the following disclaimers in the documentation 21 | // and/or other materials provided with the distribution. 22 | // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 | // contributors may be used to endorse or promote products derived from this 24 | // Software without specific prior written permission. 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 | // THE SOFTWARE. 32 | // 33 | //===----------------------------------------------------------------------===// 34 | /// \file 35 | /// 36 | /// This file declares classes for creating SPIR-V metadata. 37 | /// 38 | //===----------------------------------------------------------------------===// 39 | 40 | #ifndef LIB_SPIRV_SPIRVMDBUILDER_H_ 41 | #define LIB_SPIRV_SPIRVMDBUILDER_H_ 42 | 43 | #include "llvm/IR/Metadata.h" 44 | #include "SPIRVInternal.h" 45 | 46 | #include 47 | using namespace llvm; 48 | 49 | namespace SPIRV { 50 | 51 | class SPIRVMDBuilder { 52 | public: 53 | template struct MDWrapper; 54 | struct NamedMDWrapper { 55 | NamedMDWrapper(NamedMDNode &Named, SPIRVMDBuilder& BB) 56 | :NMD(Named), B(BB){} 57 | MDWrapper addOp() { 58 | return MDWrapper(*this, B); 59 | } 60 | NamedMDWrapper &addOp(MDWrapper &MD) { 61 | NMD.addOperand(MD.M); 62 | return *this; 63 | } 64 | NamedMDNode &NMD; 65 | SPIRVMDBuilder &B; 66 | }; 67 | template 68 | struct MDWrapper { 69 | MDWrapper(ParentT &Parent, SPIRVMDBuilder &Builder) 70 | :M(nullptr), P(Parent), B(Builder){} 71 | MDWrapper &add(unsigned I) { 72 | V.push_back(ConstantAsMetadata::get(getUInt32(&B.M, I))); 73 | return *this; 74 | } 75 | MDWrapper &addU16(unsigned short I) { 76 | V.push_back(ConstantAsMetadata::get(getUInt16(&B.M, I))); 77 | return *this; 78 | } 79 | MDWrapper &add(StringRef S) { 80 | V.push_back(MDString::get(B.C, S)); 81 | return *this; 82 | } 83 | MDWrapper &add(Function *F) { 84 | V.push_back(ConstantAsMetadata::get(F)); 85 | return *this; 86 | } 87 | MDWrapper &add(SmallVectorImpl &S) { 88 | for (auto &I:S) 89 | add(I); 90 | return *this; 91 | } 92 | MDWrapper &addOp(MDNode *Node) { 93 | V.push_back(Node); 94 | return *this; 95 | } 96 | MDWrapper addOp() { 97 | return MDWrapper(*this, B); 98 | } 99 | MDWrapper &addOp(MDWrapper &MD) { 100 | V.push_back(MD.M); 101 | return *this; 102 | } 103 | /// Generate the scheduled MDNode and return the parent. 104 | /// If \param Ptr is not nullptr, save the generated MDNode. 105 | ParentT &done(MDNode **Ptr = nullptr) { 106 | M = MDNode::get(B.C, V); 107 | if (Ptr) 108 | *Ptr = M; 109 | return P.addOp(*this); 110 | } 111 | MDNode *M; 112 | ParentT &P; 113 | SPIRVMDBuilder &B; 114 | SmallVector V; 115 | }; 116 | explicit SPIRVMDBuilder(Module &Mod):M(Mod), C(Mod.getContext()){} 117 | NamedMDWrapper addNamedMD(StringRef Name) { 118 | return NamedMDWrapper(*M.getOrInsertNamedMetadata(Name), *this); 119 | } 120 | SPIRVMDBuilder &eraseNamedMD(StringRef Name) { 121 | if (auto N = M.getNamedMetadata(Name)) 122 | M.eraseNamedMetadata(N); 123 | return *this; 124 | } 125 | friend struct NamedMDWrapper; 126 | private: 127 | Module& M; 128 | LLVMContext& C; 129 | }; 130 | 131 | } /* namespace SPIRV */ 132 | 133 | #endif /* LIB_SPIRV_SPIRVMDBUILDER_H_ */ 134 | -------------------------------------------------------------------------------- /libSPIRV/SPIRVError.h: -------------------------------------------------------------------------------- 1 | //===- SPIRVError.h - SPIR-V error code and checking -------------*- C++ -*-===// 2 | // 3 | // The LLVM/SPIRV Translator 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a 11 | // copy of this software and associated documentation files (the "Software"), 12 | // to deal with the Software without restriction, including without limitation 13 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 | // and/or sell copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following conditions: 16 | // 17 | // Redistributions of source code must retain the above copyright notice, 18 | // this list of conditions and the following disclaimers. 19 | // Redistributions in binary form must reproduce the above copyright notice, 20 | // this list of conditions and the following disclaimers in the documentation 21 | // and/or other materials provided with the distribution. 22 | // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 | // contributors may be used to endorse or promote products derived from this 24 | // Software without specific prior written permission. 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 | // THE SOFTWARE. 32 | // 33 | //===----------------------------------------------------------------------===// 34 | // 35 | // This file defines SPIRV error code and checking utility. 36 | // 37 | //===----------------------------------------------------------------------===// 38 | 39 | #ifndef SPIRVERROR_HPP_ 40 | #define SPIRVERROR_HPP_ 41 | 42 | #include "SPIRVUtil.h" 43 | #include "SPIRVDebug.h" 44 | #include 45 | #include 46 | 47 | namespace SPIRV{ 48 | 49 | // Check condition and set error code and error msg. 50 | // To use this macro, function checkError must be defined in the scope. 51 | #define SPIRVCK(Condition,ErrCode,ErrMsg) \ 52 | getErrorLog().checkError(Condition, SPIRVEC_##ErrCode, std::string()+ErrMsg,\ 53 | #Condition, __FILE__, __LINE__) 54 | 55 | // Check condition and set error code and error msg. If fail returns false. 56 | #define SPIRVCKRT(Condition,ErrCode,ErrMsg) \ 57 | if (!getErrorLog().checkError(Condition, SPIRVEC_##ErrCode,\ 58 | std::string()+ErrMsg, #Condition, __FILE__, __LINE__))\ 59 | return false; 60 | 61 | // Defines error code enum type SPIRVErrorCode. 62 | enum SPIRVErrorCode { 63 | #define _SPIRV_OP(x,y) SPIRVEC_##x, 64 | #include "SPIRVErrorEnum.h" 65 | #undef _SPIRV_OP 66 | }; 67 | 68 | // Defines OpErorMap which maps error code to a string describing the error. 69 | template<> inline void 70 | SPIRVMap::init() { 71 | #define _SPIRV_OP(x,y) add(SPIRVEC_##x, std::string(#x)+": "+y); 72 | #include "SPIRVErrorEnum.h" 73 | #undef _SPIRV_OP 74 | } 75 | 76 | typedef SPIRVMap SPIRVErrorMap; 77 | 78 | class SPIRVErrorLog { 79 | public: 80 | SPIRVErrorLog():ErrorCode(SPIRVEC_Success){} 81 | SPIRVErrorCode getError(std::string& ErrMsg) { 82 | ErrMsg = ErrorMsg; 83 | return ErrorCode; 84 | } 85 | void setError(SPIRVErrorCode ErrCode, const std::string& ErrMsg) { 86 | ErrorCode = ErrCode; 87 | ErrorMsg = ErrMsg; 88 | } 89 | // Check if Condition is satisfied and set ErrCode and DetailedMsg 90 | // if not. Returns true if no error. 91 | bool checkError(bool Condition, SPIRVErrorCode ErrCode, 92 | const std::string& DetailedMsg = "", 93 | const char *CondString = nullptr, 94 | const char *FileName = nullptr, 95 | unsigned LineNumber = 0); 96 | protected: 97 | SPIRVErrorCode ErrorCode; 98 | std::string ErrorMsg; 99 | 100 | }; 101 | 102 | inline bool 103 | SPIRVErrorLog::checkError(bool Cond, SPIRVErrorCode ErrCode, 104 | const std::string& Msg, const char *CondString, const char *FileName, 105 | unsigned LineNo) { 106 | std::stringstream SS; 107 | if (Cond) 108 | return Cond; 109 | // Do not overwrite previous failure. 110 | if (ErrorCode != SPIRVEC_Success) 111 | return Cond; 112 | SS << SPIRVErrorMap::map(ErrCode) << " " << Msg; 113 | if (SPIRVDbgErrorMsgIncludesSourceInfo) 114 | SS <<" [Src: " << FileName << ":" << LineNo << " " << CondString << " ]"; 115 | setError(ErrCode, SS.str()); 116 | if (SPIRVDbgAssertOnError) { 117 | spvdbgs() << SS.str() << '\n'; 118 | spvdbgs().flush(); 119 | assert (0); 120 | } 121 | return Cond; 122 | } 123 | 124 | } 125 | 126 | 127 | #endif /* SPIRVERROR_HPP_ */ 128 | -------------------------------------------------------------------------------- /Passes/OCL20To12.cpp: -------------------------------------------------------------------------------- 1 | //===- OCL20To12.cpp - Transform OCL 2.0 builtins to OCL 1.2 builtins -----===// 2 | // 3 | // The LLVM/SPIRV Translator 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a 11 | // copy of this software and associated documentation files (the "Software"), 12 | // to deal with the Software without restriction, including without limitation 13 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 | // and/or sell copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following conditions: 16 | // 17 | // Redistributions of source code must retain the above copyright notice, 18 | // this list of conditions and the following disclaimers. 19 | // Redistributions in binary form must reproduce the above copyright notice, 20 | // this list of conditions and the following disclaimers in the documentation 21 | // and/or other materials provided with the distribution. 22 | // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 | // contributors may be used to endorse or promote products derived from this 24 | // Software without specific prior written permission. 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 | // THE SOFTWARE. 32 | // 33 | //===----------------------------------------------------------------------===// 34 | // 35 | // This file implements transform OCL 2.0 builtins to OCL 1.2 builtins. 36 | // 37 | //===----------------------------------------------------------------------===// 38 | #define DEBUG_TYPE "ocl20to12" 39 | 40 | #include "SPIRVInternal.h" 41 | #include "OCLUtil.h" 42 | #include "llvm/ADT/StringSwitch.h" 43 | #include "llvm/IR/InstVisitor.h" 44 | #include "llvm/IR/Instructions.h" 45 | #include "llvm/IR/IRBuilder.h" 46 | #include "llvm/IR/Verifier.h" 47 | #include "llvm/Pass.h" 48 | #include "llvm/PassSupport.h" 49 | #include "llvm/Support/Debug.h" 50 | #include "llvm/Support/ErrorHandling.h" 51 | #include "llvm/Support/raw_ostream.h" 52 | 53 | using namespace llvm; 54 | using namespace SPIRV; 55 | using namespace OCLUtil; 56 | 57 | namespace SPIRV { 58 | class OCL20To12: public ModulePass, 59 | public InstVisitor { 60 | public: 61 | OCL20To12():ModulePass(ID), M(nullptr), Ctx(nullptr) { 62 | initializeOCL20To12Pass(*PassRegistry::getPassRegistry()); 63 | } 64 | virtual bool runOnModule(Module &M); 65 | virtual void visitCallInst(CallInst &CI); 66 | 67 | /// Transform atomic_work_item_fence to mem_fence. 68 | /// atomic_work_item_fence(flag, relaxed, work_group) => 69 | /// mem_fence(flag) 70 | void visitCallAtomicWorkItemFence(CallInst *CI); 71 | 72 | static char ID; 73 | private: 74 | Module *M; 75 | LLVMContext *Ctx; 76 | }; 77 | 78 | char OCL20To12::ID = 0; 79 | 80 | bool 81 | OCL20To12::runOnModule(Module& Module) { 82 | M = &Module; 83 | if (getOCLVersion(M) >= kOCLVer::CL20) 84 | return false; 85 | 86 | Ctx = &M->getContext(); 87 | visit(*M); 88 | 89 | DEBUG(dbgs() << "After OCL20To12:\n" << *M); 90 | 91 | std::string Err; 92 | raw_string_ostream ErrorOS(Err); 93 | if (verifyModule(*M, &ErrorOS)){ 94 | DEBUG(errs() << "Fails to verify module: " << ErrorOS.str()); 95 | } 96 | return true; 97 | } 98 | 99 | void 100 | OCL20To12::visitCallInst(CallInst& CI) { 101 | DEBUG(dbgs() << "[visistCallInst] " << CI << '\n'); 102 | auto F = CI.getCalledFunction(); 103 | if (!F) 104 | return; 105 | 106 | auto MangledName = F->getName(); 107 | std::string DemangledName; 108 | if (!oclIsBuiltin(MangledName, &DemangledName)) 109 | return; 110 | DEBUG(dbgs() << "DemangledName = " << DemangledName.c_str() << '\n'); 111 | 112 | if (DemangledName == kOCLBuiltinName::AtomicWorkItemFence) { 113 | visitCallAtomicWorkItemFence(&CI); 114 | return; 115 | } 116 | } 117 | 118 | void OCL20To12::visitCallAtomicWorkItemFence(CallInst* CI) { 119 | auto Lit = getAtomicWorkItemFenceLiterals(CI); 120 | if (std::get<1>(Lit) != OCLLegacyAtomicMemOrder || 121 | std::get<2>(Lit) != OCLLegacyAtomicMemScope) 122 | report_fatal_error("OCL 2.0 builtin atomic_work_item_fence used in 1.2", 123 | false); 124 | 125 | auto Attrs = CI->getCalledFunction()->getAttributes(); 126 | mutateCallInstOCL(M, CI, [=](CallInst *, std::vector &Args){ 127 | Args.resize(1); 128 | Args[0] = getInt32(M, std::get<0>(Lit)); 129 | return kOCLBuiltinName::MemFence; 130 | }, &Attrs); 131 | } 132 | 133 | } 134 | 135 | INITIALIZE_PASS(OCL20To12, "ocl20to12", 136 | "Translate OCL 2.0 builtins to OCL 1.2 builtins", false, false) 137 | 138 | ModulePass *llvm::createOCL20To12() { 139 | return new OCL20To12(); 140 | } 141 | -------------------------------------------------------------------------------- /InstructionsExt.td: -------------------------------------------------------------------------------- 1 | //===-- InstructionsOCL.td - SPIRV Core Instructions -------*- tablegen -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // File contains prototypes for extensions instructions 10 | //===----------------------------------------------------------------------===// 11 | 12 | //===----------------------------------------------------------------------===// 13 | // Float prototypes 14 | //===----------------------------------------------------------------------===// 15 | // float_t(float_t) 16 | class ExtInstFPUnary op> : SPIRVInstruction<6,12,2,[oper_FloatVecScalType,oper_FloatVecScalVar, 17 | oper_InstructionSet,oper_ImmInt32, // the opcode 18 | oper_FloatVecScalVar]> 19 | { let Op2 = op; }; 20 | 21 | // float_t(float_t,float_t) 22 | class ExtInstFPBinary op> : SPIRVInstruction<7,12,2,[oper_FloatVecScalType,oper_FloatVecScalVar, 23 | oper_InstructionSet,oper_ImmInt32, 24 | oper_FloatVecScalVar,oper_FloatVecScalVar]> 25 | { let Op2 = op; }; 26 | // float_t(float_t,float_t,float_t) 27 | class ExtInstFPTrinary op> : SPIRVInstruction<8,12,2,[oper_FloatVecScalType,oper_FloatVecScalVar, 28 | oper_InstructionSet,oper_ImmInt32, 29 | oper_FloatVecScalVar,oper_FloatVecScalVar, 30 | oper_FloatVecScalVar]> 31 | { let Op2 = op; }; 32 | 33 | // FIXME: Should be oper_FloatVecScalVarPointer / oper_Int32VecScalVarPointer 34 | // See fract / frexp in InstructionOCL.td 35 | // float_t(float_t,any*) 36 | class ExtInstFP2ArgReturn op> : SPIRVInstruction<7,12,2,[oper_FloatVecScalType,oper_FloatVecScalVar, 37 | oper_InstructionSet,oper_ImmInt32, 38 | oper_FloatVecScalVar,oper_AnyPointerVar]> 39 | { let Op2 = op; }; 40 | 41 | // i32_t(float_t) 42 | class ExtInstFPtoI32 op> : SPIRVInstruction<6,12,2,[oper_Int32VecScalType,oper_Int32VecScalVar, 43 | oper_InstructionSet,oper_ImmInt32, 44 | oper_FloatVecScalVar]> 45 | { let Op2 = op; }; 46 | 47 | // float_t(float_t,i32_t) 48 | class ExtInstFPArgFPInt32 op> : SPIRVInstruction<7,12,2,[oper_FloatVecScalType,oper_FloatVecScalVar, 49 | oper_InstructionSet,oper_ImmInt32, 50 | oper_FloatVecScalVar,oper_Int32VecScalVar]> 51 | { let Op2 = op; }; 52 | 53 | // float_t(i32_t) 54 | class ExtInstI32toFP op> : SPIRVInstruction<6,12,2,[oper_FloatVecScalType,oper_FloatVecScalVar, 55 | oper_InstructionSet,oper_ImmInt32, 56 | oper_Int32VecScalVar]> 57 | { let Op2 = op; }; 58 | 59 | // float_t(float_t,float_t,any*) 60 | class ExtInstFP2BinaryArgReturn op> : SPIRVInstruction<8,12,2, 61 | [oper_FloatVecScalType,oper_FloatVecScalVar, 62 | oper_InstructionSet,oper_ImmInt32, 63 | oper_FloatVecScalVar,oper_AnyPointerVar]> 64 | { let Op2 = op; }; 65 | 66 | //===----------------------------------------------------------------------===// 67 | // Integer prototypes 68 | //===----------------------------------------------------------------------===// 69 | 70 | //int_t(int_t) 71 | class ExtInstIntUnary op> : SPIRVInstruction<6,12,2, [oper_IntVecScalType,oper_IntVecScalVar, 72 | oper_InstructionSet,oper_ImmInt32, 73 | oper_IntVecScalVar]> 74 | { let Op2 = op; }; 75 | 76 | //int_t(int_t,int_t) 77 | class ExtInstIntBinary op> : SPIRVInstruction<7,12,2, [oper_IntVecScalType,oper_IntVecScalVar, 78 | oper_InstructionSet,oper_ImmInt32, 79 | oper_IntVecScalVar,oper_IntVecScalVar]> 80 | { let Op2 = op; }; 81 | 82 | //int_t(int_t,int_t,int_t) 83 | class ExtInstIntTrinary op> : SPIRVInstruction<8,12,2, [oper_IntVecScalType,oper_IntVecScalVar, 84 | oper_InstructionSet,oper_ImmInt32, 85 | oper_IntVecScalVar,oper_IntVecScalVar, 86 | oper_IntVecScalVar]> 87 | { let Op2 = op; }; 88 | 89 | //any_t(any_t,any_t,any_t) 90 | class ExtInstAnyTrinary op> : SPIRVInstruction<8,12,2, [oper_AnyVecScalType,oper_AnyVecScalVar, 91 | oper_InstructionSet,oper_ImmInt32, 92 | oper_AnyVecScalVar,oper_AnyVecScalVar, 93 | oper_AnyVecScalVar]> 94 | { let Op2 = op; }; 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /libSPIRV/SPIRVMDWalker.h: -------------------------------------------------------------------------------- 1 | //===- SPIRVMDWalker.h - SPIR-V metadata walker header file ----*- C++ -*-===// 2 | // 3 | // The LLVM/SPIRV Translator 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a 11 | // copy of this software and associated documentation files (the "Software"), 12 | // to deal with the Software without restriction, including without limitation 13 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 | // and/or sell copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following conditions: 16 | // 17 | // Redistributions of source code must retain the above copyright notice, 18 | // this list of conditions and the following disclaimers. 19 | // Redistributions in binary form must reproduce the above copyright notice, 20 | // this list of conditions and the following disclaimers in the documentation 21 | // and/or other materials provided with the distribution. 22 | // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 | // contributors may be used to endorse or promote products derived from this 24 | // Software without specific prior written permission. 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 | // THE SOFTWARE. 32 | // 33 | //===----------------------------------------------------------------------===// 34 | /// \file 35 | /// 36 | /// This file declares classes for walking SPIR-V metadata. 37 | /// 38 | //===----------------------------------------------------------------------===// 39 | 40 | #ifndef LIB_SPIRV_SPIRVMDWALKER_H_ 41 | #define LIB_SPIRV_SPIRVMDWALKER_H_ 42 | 43 | #include "llvm/IR/Metadata.h" 44 | #include "SPIRVInternal.h" 45 | 46 | #include 47 | using namespace llvm; 48 | 49 | namespace SPIRV { 50 | 51 | class SPIRVMDWalker { 52 | public: 53 | template struct MDWrapper; 54 | 55 | struct NamedMDWrapper { 56 | NamedMDWrapper(NamedMDNode *Named, SPIRVMDWalker& WW) 57 | :NMD(Named), W(WW), I(0), Q(true){ 58 | E = Named ? Named->getNumOperands() : 0; 59 | } 60 | 61 | operator bool() const { return NMD;} 62 | 63 | bool atEnd() const { return !(NMD && I < E);} 64 | 65 | MDWrapper nextOp() { 66 | if (!Q) 67 | assert(I < E && "out of bound"); 68 | return MDWrapper((NMD && I < E) ? NMD->getOperand(I++) 69 | : nullptr, *this, W); 70 | } 71 | 72 | NamedMDWrapper &setQuiet(bool Quiet) { 73 | Q = Quiet; 74 | return *this; 75 | } 76 | 77 | NamedMDNode *NMD; 78 | SPIRVMDWalker &W; 79 | unsigned I; 80 | unsigned E; 81 | bool Q; // Quiet 82 | }; 83 | 84 | template 85 | struct MDWrapper { 86 | MDWrapper(MDNode *Node, ParentT &Parent, SPIRVMDWalker &Walker) 87 | :M(Node), P(Parent), W(Walker), I(0), Q(false){ 88 | E = Node ? Node->getNumOperands() : 0; 89 | } 90 | 91 | operator bool() const { return M;} 92 | 93 | bool atEnd() const { return !(M && I < E);} 94 | 95 | template 96 | MDWrapper &get(T &V) { 97 | if (!Q) 98 | assert(I < E && "out of bound"); 99 | if (atEnd()) 100 | return *this; 101 | V = mdconst::dyn_extract(M->getOperand(I++)) 102 | ->getZExtValue(); 103 | return *this; 104 | } 105 | 106 | MDWrapper &get(std::string &S) { 107 | if (!Q) 108 | assert (I < E && "out of bound"); 109 | if (atEnd()) 110 | return *this; 111 | Metadata* Op = M->getOperand(I++); 112 | if (!Op) 113 | S = ""; 114 | else if (auto Str = dyn_cast(Op)) 115 | S = Str->getString().str(); 116 | else 117 | S = ""; 118 | return *this; 119 | } 120 | 121 | MDWrapper &get(Function *&F) { 122 | if (!Q) 123 | assert (I < E && "out of bound"); 124 | if (atEnd()) 125 | return *this; 126 | F = mdconst::dyn_extract(M->getOperand(I++)); 127 | return *this; 128 | } 129 | 130 | MDWrapper &get(SmallVectorImpl &SV) { 131 | if (atEnd()) 132 | return *this; 133 | while (I < E) { 134 | std::string S; 135 | get(S); 136 | SV.push_back(S); 137 | } 138 | return *this; 139 | } 140 | 141 | MDWrapper nextOp() { 142 | if (!Q) 143 | assert (I < E && "out of bound"); 144 | return MDWrapper((M && I < E) ? 145 | dyn_cast(M->getOperand(I++)) : nullptr, *this, W); 146 | } 147 | 148 | ParentT &done() { 149 | return P; 150 | } 151 | 152 | MDWrapper &setQuiet(bool Quiet) { 153 | Q = Quiet; 154 | return *this; 155 | } 156 | 157 | MDNode *M; 158 | ParentT &P; 159 | SPIRVMDWalker &W; 160 | SmallVector V; 161 | unsigned I; 162 | unsigned E; 163 | bool Q; // Quiet 164 | }; 165 | 166 | explicit SPIRVMDWalker(Module &Mod):M(Mod), C(Mod.getContext()){} 167 | 168 | NamedMDWrapper getNamedMD(StringRef Name) { 169 | return NamedMDWrapper(M.getNamedMetadata(Name), *this); 170 | } 171 | 172 | friend struct NamedMDWrapper; 173 | private: 174 | Module& M; 175 | LLVMContext& C; 176 | }; 177 | 178 | } /* namespace SPIRV */ 179 | 180 | #endif /* LIB_SPIRV_SPIRVMDBUILDER_H_ */ 181 | -------------------------------------------------------------------------------- /libSPIRV/SPIRVOpCode.h: -------------------------------------------------------------------------------- 1 | //===- SPIRVOpCode.h - Class to represent SPIR-V Operation Codes -*- C++ -*-==// 2 | // 3 | // The LLVM/SPIRV Translator 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a 11 | // copy of this software and associated documentation files (the "Software"), 12 | // to deal with the Software without restriction, including without limitation 13 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 | // and/or sell copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following conditions: 16 | // 17 | // Redistributions of source code must retain the above copyright notice, 18 | // this list of conditions and the following disclaimers. 19 | // Redistributions in binary form must reproduce the above copyright notice, 20 | // this list of conditions and the following disclaimers in the documentation 21 | // and/or other materials provided with the distribution. 22 | // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 | // contributors may be used to endorse or promote products derived from this 24 | // Software without specific prior written permission. 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 | // THE SOFTWARE. 32 | // 33 | //===----------------------------------------------------------------------===// 34 | /// \file 35 | /// 36 | /// This file defines Operation Code class for SPIR-V. 37 | /// 38 | //===----------------------------------------------------------------------===// 39 | 40 | #ifndef SPIRVOPCODE_HPP_ 41 | #define SPIRVOPCODE_HPP_ 42 | 43 | #include "SPIRVUtil.h" 44 | #include "spirv.hpp" 45 | #include 46 | 47 | using namespace spv; 48 | namespace SPIRV{ 49 | 50 | template<> inline void 51 | SPIRVMap::init() { 52 | #define _SPIRV_OP(x, ...) add(Op##x, #x); 53 | #include "SPIRVOpCodeEnum.h" 54 | #undef _SPIRV_OP 55 | } 56 | SPIRV_DEF_NAMEMAP(Op, OpCodeNameMap) 57 | 58 | inline bool isAtomicOpCode(Op OpCode) { 59 | assert(OpAtomicLoad < OpAtomicXor); 60 | return ((unsigned)OpCode >= OpAtomicLoad 61 | && (unsigned)OpCode <= OpAtomicXor) 62 | || OpCode == OpAtomicFlagTestAndSet 63 | || OpCode == OpAtomicFlagClear; 64 | } 65 | inline bool isBinaryOpCode(Op OpCode) { 66 | return ((unsigned)OpCode >= OpIAdd && 67 | (unsigned)OpCode <= OpFMod) || 68 | OpCode == OpDot; 69 | } 70 | 71 | inline bool isShiftOpCode(Op OpCode) { 72 | return (unsigned)OpCode >= OpShiftRightLogical && 73 | (unsigned)OpCode <= OpShiftLeftLogical; 74 | } 75 | 76 | inline bool isLogicalOpCode(Op OpCode) { 77 | return (unsigned)OpCode >= OpLogicalEqual && 78 | (unsigned)OpCode <= OpLogicalNot; 79 | } 80 | 81 | inline bool isBitwiseOpCode(Op OpCode) { 82 | return (unsigned)OpCode >= OpBitwiseOr && 83 | (unsigned)OpCode <= OpBitwiseAnd; 84 | } 85 | 86 | inline bool isBinaryShiftLogicalBitwiseOpCode(Op OpCode) { 87 | return (((unsigned)OpCode >= OpShiftRightLogical && 88 | (unsigned)OpCode <= OpBitwiseAnd) || 89 | isBinaryOpCode(OpCode)); 90 | } 91 | 92 | inline bool isCmpOpCode(Op OpCode) { 93 | return ((unsigned)OpCode >= OpIEqual && 94 | (unsigned)OpCode <= OpFUnordGreaterThanEqual) || 95 | (OpCode >= OpLessOrGreater && OpCode <= OpLogicalNotEqual); 96 | } 97 | 98 | inline bool isCvtOpCode(Op OpCode) { 99 | return ((unsigned)OpCode >= OpConvertFToU && 100 | (unsigned)OpCode <= OpBitcast) || 101 | OpCode == OpSatConvertSToU || 102 | OpCode == OpSatConvertUToS; 103 | } 104 | 105 | inline bool isCvtToUnsignedOpCode(Op OpCode) { 106 | return OpCode == OpConvertFToU || 107 | OpCode == OpUConvert || 108 | OpCode == OpSatConvertSToU; 109 | } 110 | 111 | inline bool isCvtFromUnsignedOpCode(Op OpCode) { 112 | return OpCode == OpConvertUToF || 113 | OpCode == OpUConvert || 114 | OpCode == OpSatConvertUToS; 115 | } 116 | 117 | inline bool isOpaqueGenericTypeOpCode(Op OpCode) { 118 | return (unsigned)OpCode >= OpTypeEvent && 119 | (unsigned)OpCode <= OpTypeQueue; 120 | } 121 | 122 | inline bool isGenericNegateOpCode(Op OpCode) { 123 | return (unsigned)OpCode == OpSNegate || 124 | (unsigned)OpCode == OpFNegate || 125 | (unsigned)OpCode == OpNot; 126 | } 127 | 128 | inline bool isAccessChainOpCode(Op OpCode) { 129 | return OpCode == OpAccessChain || 130 | OpCode == OpInBoundsAccessChain; 131 | } 132 | 133 | inline bool hasExecScope(Op OpCode) { 134 | unsigned OC = OpCode; 135 | return (OpGroupWaitEvents <= OC && 136 | OC <= OpGroupSMax) || 137 | (OpGroupReserveReadPipePackets <= OC && 138 | OC <= OpGroupCommitWritePipe); 139 | } 140 | 141 | inline bool hasGroupOperation(Op OpCode) { 142 | unsigned OC = OpCode; 143 | return OpGroupIAdd <= OC && OC <= OpGroupSMax; 144 | } 145 | 146 | inline bool isGroupOpCode(Op OpCode) { 147 | unsigned OC = OpCode; 148 | return OpGroupAll <= OC && OC <= OpGroupSMax; 149 | } 150 | 151 | inline bool isPipeOpCode(Op OpCode) { 152 | unsigned OC = OpCode; 153 | return OpReadPipe <= OC && OC <= OpGroupCommitWritePipe; 154 | } 155 | inline bool isTypeOpCode(Op OpCode) { 156 | unsigned OC = OpCode; 157 | return OpTypeVoid <= OC && OC <= OpTypePipe; 158 | } 159 | 160 | inline bool isConstantOpCode(Op OpCode) { 161 | unsigned OC = OpCode; 162 | return (OpConstantTrue <= OC 163 | && OC <= OpSpecConstantOp) 164 | || OC == OpUndef; 165 | } 166 | 167 | inline bool isModuleScopeAllowedOpCode(Op OpCode) { 168 | return OpCode == OpVariable || 169 | isConstantOpCode(OpCode); 170 | } 171 | 172 | } 173 | 174 | #endif /* SPIRVOPCODE_HPP_ */ 175 | -------------------------------------------------------------------------------- /Passes/SPIRVLowerConstExpr.cpp: -------------------------------------------------------------------------------- 1 | //===- SPIRVLowerConstExpr.cpp - Regularize LLVM for SPIR-V ------- C++ -*-===// 2 | // 3 | // The LLVM/SPIRV Translator 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a 11 | // copy of this software and associated documentation files (the "Software"), 12 | // to deal with the Software without restriction, including without limitation 13 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 | // and/or sell copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following conditions: 16 | // 17 | // Redistributions of source code must retain the above copyright notice, 18 | // this list of conditions and the following disclaimers. 19 | // Redistributions in binary form must reproduce the above copyright notice, 20 | // this list of conditions and the following disclaimers in the documentation 21 | // and/or other materials provided with the distribution. 22 | // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 | // contributors may be used to endorse or promote products derived from this 24 | // Software without specific prior written permission. 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 | // THE SOFTWARE. 32 | // 33 | //===----------------------------------------------------------------------===// 34 | // 35 | // This file implements regularization of LLVM module for SPIR-V. 36 | // 37 | //===----------------------------------------------------------------------===// 38 | #define DEBUG_TYPE "spv-lower-const-expr" 39 | 40 | #include "SPIRVInternal.h" 41 | #include "OCLUtil.h" 42 | #include "libSPIRV/SPIRVMDBuilder.h" 43 | #include "libSPIRV/SPIRVMDWalker.h" 44 | 45 | #include "llvm/ADT/StringSwitch.h" 46 | #include "llvm/ADT/Triple.h" 47 | #include "llvm/IR/InstVisitor.h" 48 | #include "llvm/IR/Instructions.h" 49 | #include "llvm/IR/IRBuilder.h" 50 | #include "llvm/IR/Verifier.h" 51 | #include "llvm/Pass.h" 52 | #include "llvm/PassSupport.h" 53 | #include "llvm/Support/CommandLine.h" 54 | #include "llvm/Support/Debug.h" 55 | #include "llvm/Support/raw_ostream.h" 56 | 57 | #include 58 | #include 59 | 60 | using namespace llvm; 61 | using namespace SPIRV; 62 | using namespace OCLUtil; 63 | 64 | namespace SPIRV { 65 | 66 | cl::opt SPIRVLowerConst(DEBUG_TYPE, cl::init(true), 67 | cl::desc("LLVM/SPIR-V translation enable lowering constant expression")); 68 | 69 | class SPIRVLowerConstExpr: public ModulePass { 70 | public: 71 | SPIRVLowerConstExpr():ModulePass(ID), M(nullptr), Ctx(nullptr) { 72 | initializeSPIRVLowerConstExprPass(*PassRegistry::getPassRegistry()); 73 | } 74 | 75 | virtual bool runOnModule(Module &M); 76 | void visit(Module *M); 77 | 78 | static char ID; 79 | private: 80 | Module *M; 81 | LLVMContext *Ctx; 82 | }; 83 | 84 | char SPIRVLowerConstExpr::ID = 0; 85 | 86 | bool 87 | SPIRVLowerConstExpr::runOnModule(Module& Module) { 88 | if (!SPIRVLowerConst) 89 | return false; 90 | 91 | M = &Module; 92 | Ctx = &M->getContext(); 93 | 94 | DEBUG(dbgs() << "Enter SPIRVLowerConstExpr:\n"); 95 | visit(M); 96 | 97 | DEBUG(dbgs() << "After SPIRVLowerConstExpr:\n" << *M); 98 | std::string Err; 99 | raw_string_ostream ErrorOS(Err); 100 | if (verifyModule(*M, &ErrorOS)){ 101 | DEBUG(errs() << "Fails to verify module: " << ErrorOS.str()); 102 | } 103 | return true; 104 | } 105 | 106 | /// Since SPIR-V cannot represent constant expression, constant expressions 107 | /// in LLVM needs to be lowered to instructions. 108 | /// For each function, the constant expressions used by instructions of the 109 | /// function are replaced by instructions placed in the entry block since it 110 | /// dominates all other BB's. Each constant expression only needs to be lowered 111 | /// once in each function and all uses of it by instructions in that function 112 | /// is replaced by one instruction. 113 | /// ToDo: remove redundant instructions for common subexpression 114 | 115 | void 116 | SPIRVLowerConstExpr::visit(Module *M) { 117 | for (auto I = M->begin(), E = M->end(); I != E; ++I) { 118 | std::map CMap; 119 | std::list WorkList; 120 | auto FBegin = I->begin(); 121 | for (auto BI = FBegin, BE = I->end(); BI != BE; ++BI) { 122 | for (auto II = BI->begin(), IE = BI->end(); II != IE; ++II) { 123 | WorkList.push_back(&*II); 124 | } 125 | } 126 | while (!WorkList.empty()) { 127 | auto II = WorkList.front(); 128 | WorkList.pop_front(); 129 | for (unsigned OI = 0, OE = II->getNumOperands(); OI != OE; ++OI) { 130 | auto Op = II->getOperand(OI); 131 | 132 | if (auto CE = dyn_cast(Op)) { 133 | SPIRVDBG(dbgs() << "[lowerConstantExpressions] " << *CE;) 134 | auto ReplInst = CE->getAsInstruction(); 135 | ReplInst->insertBefore(&*FBegin->begin()); 136 | SPIRVDBG(dbgs() << " -> " << *ReplInst << '\n';) 137 | WorkList.push_front(ReplInst); 138 | std::vector Users; 139 | // Do not replace use during iteration of use. Do it in another loop. 140 | for (auto U:CE->users()){ 141 | SPIRVDBG(dbgs() << "[lowerConstantExpressions] Use: " << 142 | *U << '\n';) 143 | if (auto InstUser = dyn_cast(U)) { 144 | if (InstUser->getParent()->getParent() != &*I) 145 | continue; 146 | Users.push_back(InstUser); 147 | } 148 | } 149 | for (auto &User:Users) 150 | User->replaceUsesOfWith(CE, ReplInst); 151 | } 152 | } 153 | } 154 | } 155 | } 156 | 157 | } 158 | 159 | INITIALIZE_PASS(SPIRVLowerConstExpr, DEBUG_TYPE, "Regularize LLVM for SPIR-V", false, false) 160 | 161 | ModulePass *llvm::createSPIRVLowerConstExpr() { 162 | return new SPIRVLowerConstExpr(); 163 | } 164 | -------------------------------------------------------------------------------- /Mangler/ManglingUtils.cpp: -------------------------------------------------------------------------------- 1 | //===------------------------- ManglingUtils.cpp -------------------------===// 2 | // 3 | // SPIR Tools 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===---------------------------------------------------------------------===// 9 | /* 10 | * Contributed by: Intel Corporation. 11 | */ 12 | 13 | #include "ManglingUtils.h" 14 | 15 | namespace SPIR { 16 | 17 | // String represenration for the primitive types. 18 | static const char* PrimitiveNames[PRIMITIVE_NUM] ={ 19 | "bool", 20 | "uchar", 21 | "char", 22 | "ushort", 23 | "short", 24 | "uint", 25 | "int", 26 | "ulong", 27 | "long", 28 | "half", 29 | "float", 30 | "double", 31 | "void", 32 | "...", 33 | "image1d_t", 34 | "image1d_array_t", 35 | "image1d_buffer_t", 36 | "image2d_t", 37 | "image2d_array_t", 38 | "image3d_t", 39 | "image2d_msaa_t", 40 | "image2d_array_msaa_t", 41 | "image2d_msaa_depth_t", 42 | "image2d_array_msaa_depth_t", 43 | "image2d_depth_t", 44 | "image2d_array_depth_t", 45 | "event_t", 46 | "pipe_t", 47 | "reserve_id_t", 48 | "queue_t", 49 | "ndrange_t", 50 | "clk_event_t", 51 | "sampler_t", 52 | "kernel_enqueue_flags_t", 53 | "clk_profiling_info", 54 | }; 55 | 56 | const char* mangledTypes[PRIMITIVE_NUM] = { 57 | "b", //BOOL 58 | "h", //UCHAR 59 | "c", //CHAR 60 | "t", //USHORT 61 | "s", //SHORT 62 | "j", //UINT 63 | "i", //INT 64 | "m", //ULONG 65 | "l", //LONG 66 | "Dh", //HALF 67 | "f", //FLOAT 68 | "d", //DOUBLE 69 | "v", //VOID 70 | "z", //VarArg 71 | "11ocl_image1d", //PRIMITIVE_IMAGE_1D_T 72 | "16ocl_image1darray", //PRIMITIVE_IMAGE_1D_ARRAY_T 73 | "17ocl_image1dbuffer", //PRIMITIVE_IMAGE_1D_BUFFER_T 74 | "11ocl_image2d", //PRIMITIVE_IMAGE_2D_T 75 | "16ocl_image2darray", //PRIMITIVE_IMAGE_2D_ARRAY_T 76 | "11ocl_image3d", //PRIMITIVE_IMAGE_3D_T 77 | "15ocl_image2dmsaa", //PRIMITIVE_IMAGE_2D_MSAA_T 78 | "20ocl_image2darraymsaa", //PRIMITIVE_IMAGE_2D_ARRAY_MSAA_T 79 | "20ocl_image2dmsaadepth", //PRIMITIVE_IMAGE_2D_MSAA_DEPTH_T 80 | "25ocl_image2darraymsaadepth", //PRIMITIVE_IMAGE_2D_ARRAY_MSAA_DEPTH_T 81 | "16ocl_image2ddepth", //PRIMITIVE_IMAGE_2D_DEPTH_T 82 | "21ocl_image2darraydepth", //PRIMITIVE_IMAGE_2D_ARRAY_DEPTH_T 83 | "9ocl_event", //PRIMITIVE_EVENT_T 84 | "8ocl_pipe", //PRIMITIVE_PIPE_T 85 | "13ocl_reserveid", //PRIMITIVE_RESERVE_ID_T 86 | "9ocl_queue", //PRIMITIVE_QUEUE_T 87 | "9ndrange_t", //PRIMITIVE_NDRANGE_T 88 | "12ocl_clkevent", //PRIMITIVE_CLK_EVENT_T 89 | "11ocl_sampler", //PRIMITIVE_SAMPLER_T 90 | #if defined(SPIRV_SPIR20_MANGLING_REQUIREMENTS) 91 | "i", //PRIMITIVE_KERNEL_ENQUEUE_FLAGS_T 92 | "i", //PRIMITIVE_CLK_PROFILING_INFO 93 | #else 94 | "22kernel_enqueue_flags_t", //PRIMITIVE_KERNEL_ENQUEUE_FLAGS_T 95 | "18clk_profiling_info", //PRIMITIVE_CLK_PROFILING_INFO 96 | #endif 97 | }; 98 | 99 | const char* readableAttribute[ATTR_NUM] = { 100 | "restrict", 101 | "volatile", 102 | "const", 103 | "__private", 104 | "__global", 105 | "__constant", 106 | "__local", 107 | "__generic", 108 | }; 109 | 110 | const char* mangledAttribute[ATTR_NUM] = { 111 | "r", 112 | "V", 113 | "K", 114 | "", 115 | "U3AS1", 116 | "U3AS2", 117 | "U3AS3", 118 | "U3AS4", 119 | }; 120 | 121 | // SPIR supported version - stated version is oldest supported version. 122 | static const SPIRversion primitiveSupportedVersions[PRIMITIVE_NUM] ={ 123 | SPIR12, //BOOL 124 | SPIR12, //UCHAR 125 | SPIR12, //CHAR 126 | SPIR12, //USHORT 127 | SPIR12, //SHORT 128 | SPIR12, //UINT 129 | SPIR12, //INT 130 | SPIR12, //ULONG 131 | SPIR12, //LONG 132 | SPIR12, //HALF 133 | SPIR12, //FLOAT 134 | SPIR12, //DOUBLE 135 | SPIR12, //VOID 136 | SPIR12, //VarArg 137 | SPIR12, //PRIMITIVE_IMAGE_1D_T 138 | SPIR12, //PRIMITIVE_IMAGE_1D_ARRAY_T 139 | SPIR12, //PRIMITIVE_IMAGE_1D_BUFFER_T 140 | SPIR12, //PRIMITIVE_IMAGE_2D_T 141 | SPIR12, //PRIMITIVE_IMAGE_2D_ARRAY_T 142 | SPIR12, //PRIMITIVE_IMAGE_3D_T 143 | SPIR12, //PRIMITIVE_IMAGE_2D_MSAA_T 144 | SPIR12, //PRIMITIVE_IMAGE_2D_ARRAY_MSAA_T 145 | SPIR12, //PRIMITIVE_IMAGE_2D_MSAA_DEPTH_T 146 | SPIR12, //PRIMITIVE_IMAGE_2D_ARRAY_MSAA_DEPTH_T 147 | SPIR12, //PRIMITIVE_IMAGE_2D_DEPTH_T 148 | SPIR12, //PRIMITIVE_IMAGE_2D_ARRAY_DEPTH_T 149 | SPIR12, //PRIMITIVE_EVENT_T 150 | SPIR20, //PRIMITIVE_PIPE_T 151 | SPIR20, //PRIMITIVE_RESERVE_ID_T 152 | SPIR20, //PRIMITIVE_QUEUE_T 153 | SPIR20, //PRIMITIVE_NDRANGE_T 154 | SPIR20, //PRIMITIVE_CLK_EVENT_T 155 | SPIR12 //PRIMITIVE_SAMPLER_T 156 | }; 157 | 158 | const char* mangledPrimitiveString(TypePrimitiveEnum t) { 159 | return mangledTypes[t]; 160 | } 161 | 162 | const char* readablePrimitiveString(TypePrimitiveEnum t) { 163 | return PrimitiveNames[t]; 164 | } 165 | 166 | const char* getMangledAttribute(TypeAttributeEnum attribute) { 167 | return mangledAttribute[attribute]; 168 | } 169 | 170 | const char* getReadableAttribute(TypeAttributeEnum attribute) { 171 | return readableAttribute[attribute]; 172 | } 173 | 174 | const SPIRversion getSupportedVersion(TypePrimitiveEnum t) { 175 | return primitiveSupportedVersions[t]; 176 | } 177 | 178 | const char* mangledPrimitiveStringfromName(std::string type) { 179 | for (size_t i = 0; i < (sizeof(PrimitiveNames) / sizeof(PrimitiveNames[0])); i++) 180 | if (type.compare(PrimitiveNames[i]) == 0) 181 | return mangledTypes[i]; 182 | return NULL; 183 | } 184 | 185 | const char* getSPIRVersionAsString(SPIRversion version) { 186 | switch (version) { 187 | case SPIR12: return "SPIR 1.2"; 188 | case SPIR20: return "SPIR 2.0"; 189 | default: 190 | assert(false && "Unknown SPIR Version"); 191 | return "Unknown SPIR Version"; 192 | } 193 | } 194 | 195 | } // End SPIR namespace 196 | -------------------------------------------------------------------------------- /Mangler/Mangler.cpp: -------------------------------------------------------------------------------- 1 | //===--------------------------- Mangler.cpp -----------------------------===// 2 | // 3 | // SPIR Tools 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===---------------------------------------------------------------------===// 9 | /* 10 | * Contributed by: Intel Corporation. 11 | */ 12 | 13 | #include "FunctionDescriptor.h" 14 | #include "ManglingUtils.h" 15 | #include "NameMangleAPI.h" 16 | #include "ParameterType.h" 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | // According to IA64 name mangling spec, 23 | // builtin vector types should not be substituted 24 | // This is a workaround till this gets fixed in CLang 25 | #define ENABLE_MANGLER_VECTOR_SUBSTITUTION 1 26 | 27 | namespace SPIR { 28 | 29 | class MangleVisitor: public TypeVisitor { 30 | public: 31 | 32 | MangleVisitor(SPIRversion ver, std::stringstream& s) : TypeVisitor(ver), m_stream(s), seqId(0) { 33 | } 34 | 35 | // 36 | // mangle substitution methods 37 | // 38 | void mangleSequenceID(unsigned SeqID) { 39 | if (SeqID == 1) 40 | m_stream << '0'; 41 | else if (SeqID > 1) { 42 | std::string bstr; 43 | std::string charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 44 | SeqID--; 45 | bstr.reserve(7); 46 | for (; SeqID != 0; SeqID /= 36) 47 | bstr += charset.substr(SeqID % 36, 1); 48 | std::reverse(bstr.begin(), bstr.end()); 49 | m_stream << bstr; 50 | } 51 | m_stream << '_'; 52 | } 53 | 54 | bool mangleSubstitution(const ParamType* type, std::string typeStr) { 55 | size_t fpos; 56 | std::stringstream thistypeStr; 57 | thistypeStr << typeStr; 58 | if ((fpos = m_stream.str().find(typeStr)) != std::string::npos) { 59 | const char* nType; 60 | if (const PointerType* p = SPIR::dyn_cast(type)) { 61 | if ((nType = mangledPrimitiveStringfromName(p->getPointee()->toString()))) 62 | thistypeStr << nType; 63 | } 64 | #if defined(ENABLE_MANGLER_VECTOR_SUBSTITUTION) 65 | else if (const VectorType* pVec = SPIR::dyn_cast(type)) { 66 | if ((nType = mangledPrimitiveStringfromName(pVec->getScalarType()->toString()))) 67 | thistypeStr << nType; 68 | } 69 | #endif 70 | std::map::iterator I = substitutions.find(thistypeStr.str()); 71 | if (I == substitutions.end()) 72 | return false; 73 | 74 | unsigned SeqID = I->second; 75 | m_stream << 'S'; 76 | mangleSequenceID(SeqID); 77 | return true; 78 | } 79 | return false; 80 | } 81 | 82 | // 83 | // Visit methods 84 | // 85 | MangleError visit(const PrimitiveType* t) { 86 | m_stream << mangledPrimitiveString(t->getPrimitive()); 87 | return MANGLE_SUCCESS; 88 | } 89 | 90 | MangleError visit(const PointerType* p) { 91 | size_t fpos = m_stream.str().size(); 92 | std::string qualStr; 93 | MangleError me = MANGLE_SUCCESS; 94 | for (unsigned int i = ATTR_QUALIFIER_FIRST; i <= ATTR_QUALIFIER_LAST; i++) { 95 | TypeAttributeEnum qualifier = (TypeAttributeEnum)i; 96 | if (p->hasQualifier(qualifier)) { 97 | qualStr += getMangledAttribute(qualifier); 98 | } 99 | } 100 | qualStr += getMangledAttribute((p->getAddressSpace())); 101 | if (!mangleSubstitution(p, "P" + qualStr)) { 102 | // A pointee type is substituted when it is a user type, a vector type 103 | // (but see a comment in the beginning of this file), a pointer type, 104 | // or a primitive type with qualifiers (addr. space and/or CV qualifiers). 105 | // So, stream "P", type qualifiers 106 | m_stream << "P" << qualStr; 107 | // and the pointee type itself. 108 | me = p->getPointee()->accept(this); 109 | // The type qualifiers plus a pointee type is a substitutable entity 110 | if(qualStr.length() > 0) 111 | substitutions[m_stream.str().substr(fpos + 1)] = seqId++; 112 | // The complete pointer type is substitutable as well 113 | substitutions[m_stream.str().substr(fpos)] = seqId++; 114 | } 115 | return me; 116 | } 117 | 118 | MangleError visit(const VectorType* v) { 119 | size_t index = m_stream.str().size(); 120 | std::stringstream typeStr; 121 | typeStr << "Dv" << v->getLength() << "_"; 122 | MangleError me = MANGLE_SUCCESS; 123 | #if defined(ENABLE_MANGLER_VECTOR_SUBSTITUTION) 124 | if (!mangleSubstitution(v, typeStr.str())) 125 | #endif 126 | { 127 | m_stream << typeStr.str(); 128 | me = v->getScalarType()->accept(this); 129 | substitutions[m_stream.str().substr(index)] = seqId++; 130 | } 131 | return me; 132 | } 133 | 134 | MangleError visit(const AtomicType* p) { 135 | m_stream << "U" << "7_Atomic"; 136 | return p->getBaseType()->accept(this); 137 | } 138 | 139 | MangleError visit(const BlockType* p) { 140 | m_stream << "U" << "13block_pointerFv"; 141 | if (p->getNumOfParams() == 0) 142 | m_stream << "v"; 143 | else 144 | for (unsigned int i=0; i < p->getNumOfParams(); ++i) { 145 | MangleError err = p->getParam(i)->accept(this); 146 | if (err != MANGLE_SUCCESS) { 147 | return err; 148 | } 149 | } 150 | m_stream << "E"; 151 | return MANGLE_SUCCESS; 152 | } 153 | 154 | MangleError visit(const UserDefinedType* pTy) { 155 | std::string name = pTy->toString(); 156 | m_stream << name.size() << name; 157 | return MANGLE_SUCCESS; 158 | } 159 | 160 | private: 161 | 162 | // Holds the mangled string representing the prototype of the function. 163 | std::stringstream& m_stream; 164 | unsigned seqId; 165 | std::map substitutions; 166 | }; 167 | 168 | // 169 | // NameMangler 170 | // 171 | NameMangler::NameMangler(SPIRversion version):m_spir_version(version) {}; 172 | 173 | MangleError NameMangler::mangle(const FunctionDescriptor& fd, std::string& mangledName ) { 174 | if (fd.isNull()) { 175 | mangledName.assign(FunctionDescriptor::nullString()); 176 | return MANGLE_NULL_FUNC_DESCRIPTOR; 177 | } 178 | std::stringstream ret; 179 | ret << "_Z" << fd.name.length() << fd.name; 180 | MangleVisitor visitor(m_spir_version, ret); 181 | for (unsigned int i=0; i < fd.parameters.size(); ++i) { 182 | MangleError err = fd.parameters[i]->accept(&visitor); 183 | if(err == MANGLE_TYPE_NOT_SUPPORTED) { 184 | mangledName.assign("Type "); 185 | mangledName.append(fd.parameters[i]->toString()); 186 | mangledName.append(" is not supported in "); 187 | std::string ver = getSPIRVersionAsString(m_spir_version); 188 | mangledName.append(ver); 189 | return err; 190 | } 191 | } 192 | mangledName.assign(ret.str()); 193 | return MANGLE_SUCCESS; 194 | } 195 | 196 | } // End SPIR namespace 197 | -------------------------------------------------------------------------------- /libSPIRV/SPIRVFunction.h: -------------------------------------------------------------------------------- 1 | //===- SPIRVFunction.h - Class to represent a SPIR-V function ----*- C++ -*-===// 2 | // 3 | // The LLVM/SPIRV Translator 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines Function class for SPIRV. 11 | // 12 | // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 13 | // 14 | // Permission is hereby granted, free of charge, to any person obtaining a 15 | // copy of this software and associated documentation files (the "Software"), 16 | // to deal with the Software without restriction, including without limitation 17 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 18 | // and/or sell copies of the Software, and to permit persons to whom the 19 | // Software is furnished to do so, subject to the following conditions: 20 | // 21 | // Redistributions of source code must retain the above copyright notice, 22 | // this list of conditions and the following disclaimers. 23 | // Redistributions in binary form must reproduce the above copyright notice, 24 | // this list of conditions and the following disclaimers in the documentation 25 | // and/or other materials provided with the distribution. 26 | // Neither the names of Advanced Micro Devices, Inc., nor the names of its 27 | // contributors may be used to endorse or promote products derived from this 28 | // Software without specific prior written permission. 29 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 35 | // THE SOFTWARE. 36 | // 37 | //===----------------------------------------------------------------------===// 38 | 39 | #ifndef SPIRVFUNCTION_HPP_ 40 | #define SPIRVFUNCTION_HPP_ 41 | #include "SPIRVValue.h" 42 | #include "SPIRVBasicBlock.h" 43 | #include 44 | 45 | namespace SPIRV{ 46 | 47 | class BIFunction; 48 | class SPIRVDecoder; 49 | 50 | class SPIRVFunctionParameter: public SPIRVValue { 51 | public: 52 | SPIRVFunctionParameter(SPIRVType *TheType, SPIRVId TheId, 53 | SPIRVFunction *TheParent, unsigned TheArgNo); 54 | SPIRVFunctionParameter():SPIRVValue(OpFunctionParameter), 55 | ParentFunc(nullptr), ArgNo(0){} 56 | unsigned getArgNo()const { return ArgNo;} 57 | void foreachAttr(std::function); 58 | void addAttr(SPIRVFuncParamAttrKind Kind) { 59 | addDecorate(new SPIRVDecorate(DecorationFuncParamAttr, this, Kind)); 60 | } 61 | void setParent(SPIRVFunction *Parent) { ParentFunc = Parent;} 62 | bool hasAttr(SPIRVFuncParamAttrKind Kind) const { 63 | return getDecorate(DecorationFuncParamAttr).count(Kind) ; 64 | } 65 | bool isByVal()const { return hasAttr(FunctionParameterAttributeByVal);} 66 | bool isZext()const { return hasAttr(FunctionParameterAttributeZext);} 67 | SPIRVCapVec getRequiredCapability() const { 68 | if (hasLinkageType() && getLinkageType() == LinkageTypeImport) 69 | return getVec(CapabilityLinkage); 70 | return SPIRVCapVec(); 71 | } 72 | protected: 73 | void validate()const { 74 | SPIRVValue::validate(); 75 | assert(ParentFunc && "Invalid parent function"); 76 | } 77 | _SPIRV_DEF_ENCDEC2(Type, Id) 78 | private: 79 | SPIRVFunction *ParentFunc; 80 | unsigned ArgNo; 81 | }; 82 | 83 | class SPIRVFunction: public SPIRVValue, public SPIRVComponentExecutionModes { 84 | public: 85 | // Complete constructor. It does not construct basic blocks. 86 | SPIRVFunction(SPIRVModule *M, SPIRVTypeFunction *FunctionType, SPIRVId TheId) 87 | :SPIRVValue(M, 5, OpFunction, FunctionType->getReturnType(), TheId), 88 | FuncType(FunctionType), FCtrlMask(FunctionControlMaskNone) { 89 | addAllArguments(TheId + 1); 90 | validate(); 91 | } 92 | 93 | // Incomplete constructor 94 | SPIRVFunction():SPIRVValue(OpFunction),FuncType(NULL), 95 | FCtrlMask(FunctionControlMaskNone){} 96 | 97 | SPIRVDecoder getDecoder(std::istream &IS); 98 | SPIRVTypeFunction *getFunctionType() const { return FuncType;} 99 | SPIRVWord getFuncCtlMask() const { return FCtrlMask;} 100 | size_t getNumBasicBlock() const { return BBVec.size();} 101 | SPIRVBasicBlock *getBasicBlock(size_t i) const { return BBVec[i];} 102 | size_t getNumArguments() const { 103 | return getFunctionType()->getNumParameters(); 104 | } 105 | SPIRVId getArgumentId(size_t i)const { return Parameters[i]->getId();} 106 | SPIRVFunctionParameter *getArgument(size_t i) const { 107 | return Parameters[i]; 108 | } 109 | void foreachArgument(std::functionFunc) { 110 | for (size_t I = 0, E = getNumArguments(); I != E; ++I) 111 | Func(getArgument(I)); 112 | } 113 | 114 | void foreachReturnValueAttr(std::function); 115 | 116 | void setFunctionControlMask(SPIRVWord Mask) { 117 | FCtrlMask = Mask; 118 | } 119 | 120 | void takeExecutionModes(SPIRVForward *Forward) { 121 | ExecModes = std::move(Forward->ExecModes); 122 | } 123 | 124 | // Assume BB contains valid Id. 125 | SPIRVBasicBlock *addBasicBlock(SPIRVBasicBlock *BB) { 126 | Module->add(BB); 127 | BB->setParent(this); 128 | BBVec.push_back(BB); 129 | return BB; 130 | } 131 | 132 | void encodeChildren(spv_ostream &)const; 133 | void encodeExecutionModes(spv_ostream &)const; 134 | _SPIRV_DCL_ENCDEC 135 | void validate()const { 136 | SPIRVValue::validate(); 137 | assert(FuncType && "Invalid func type"); 138 | } 139 | 140 | private: 141 | SPIRVFunctionParameter *addArgument(unsigned TheArgNo, SPIRVId TheId) { 142 | SPIRVFunctionParameter *Arg = new SPIRVFunctionParameter( 143 | getFunctionType()->getParameterType(TheArgNo), 144 | TheId, this, TheArgNo); 145 | Module->add(Arg); 146 | Parameters.push_back(Arg); 147 | return Arg; 148 | } 149 | 150 | void addAllArguments(SPIRVId FirstArgId) { 151 | for (size_t i = 0, e = getFunctionType()->getNumParameters(); i != e; ++i) 152 | addArgument(i, FirstArgId + i); 153 | } 154 | void decodeBB(SPIRVDecoder &); 155 | 156 | SPIRVTypeFunction *FuncType; // Function type 157 | SPIRVWord FCtrlMask; // Function control mask 158 | 159 | std::vector Parameters; 160 | typedef std::vector SPIRVLBasicBlockVector; 161 | SPIRVLBasicBlockVector BBVec; 162 | }; 163 | 164 | typedef SPIRVEntryOpCodeOnly SPIRVFunctionEnd; 165 | 166 | } 167 | 168 | #endif /* SPIRVFUNCTION_HPP_ */ 169 | -------------------------------------------------------------------------------- /libSPIRV/OpenCL.std.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2015 The Khronos Group Inc. 3 | ** 4 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 5 | ** of this software and/or associated documentation files (the "Materials"), 6 | ** to deal in the Materials without restriction, including without limitation 7 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | ** and/or sell copies of the Materials, and to permit persons to whom the 9 | ** Materials are furnished to do so, subject to the following conditions: 10 | ** 11 | ** The above copyright notice and this permission notice shall be included in 12 | ** all copies or substantial portions of the Materials. 13 | ** 14 | ** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS 15 | ** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND 16 | ** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ 17 | ** 18 | ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | ** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | ** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS 24 | ** IN THE MATERIALS. 25 | */ 26 | 27 | // 28 | // Author: Boaz Ouriel, Intel 29 | // 30 | 31 | namespace OpenCLLIB { 32 | 33 | enum Entrypoints { 34 | 35 | // math functions 36 | Acos = 0, 37 | Acosh = 1, 38 | Acospi = 2, 39 | Asin = 3, 40 | Asinh = 4, 41 | Asinpi = 5, 42 | Atan = 6, 43 | Atan2 = 7, 44 | Atanh = 8, 45 | Atanpi = 9, 46 | Atan2pi = 10, 47 | Cbrt = 11, 48 | Ceil = 12, 49 | Copysign = 13, 50 | Cos = 14, 51 | Cosh = 15, 52 | Cospi = 16, 53 | Erfc = 17, 54 | Erf = 18, 55 | Exp = 19, 56 | Exp2 = 20, 57 | Exp10 = 21, 58 | Expm1 = 22, 59 | Fabs = 23, 60 | Fdim = 24, 61 | Floor = 25, 62 | Fma = 26, 63 | Fmax = 27, 64 | Fmin = 28, 65 | Fmod = 29, 66 | Fract = 30, 67 | Frexp = 31, 68 | Hypot = 32, 69 | Ilogb = 33, 70 | Ldexp = 34, 71 | Lgamma = 35, 72 | Lgamma_r = 36, 73 | Log = 37, 74 | Log2 = 38, 75 | Log10 = 39, 76 | Log1p = 40, 77 | Logb = 41, 78 | Mad = 42, 79 | Maxmag = 43, 80 | Minmag = 44, 81 | Modf = 45, 82 | Nan = 46, 83 | Nextafter = 47, 84 | Pow = 48, 85 | Pown = 49, 86 | Powr = 50, 87 | Remainder = 51, 88 | Remquo = 52, 89 | Rint = 53, 90 | Rootn = 54, 91 | Round = 55, 92 | Rsqrt = 56, 93 | Sin = 57, 94 | Sincos = 58, 95 | Sinh = 59, 96 | Sinpi = 60, 97 | Sqrt = 61, 98 | Tan = 62, 99 | Tanh = 63, 100 | Tanpi = 64, 101 | Tgamma = 65, 102 | Trunc = 66, 103 | Half_cos = 67, 104 | Half_divide = 68, 105 | Half_exp = 69, 106 | Half_exp2 = 70, 107 | Half_exp10 = 71, 108 | Half_log = 72, 109 | Half_log2 = 73, 110 | Half_log10 = 74, 111 | Half_powr = 75, 112 | Half_recip = 76, 113 | Half_rsqrt = 77, 114 | Half_sin = 78, 115 | Half_sqrt = 79, 116 | Half_tan = 80, 117 | Native_cos = 81, 118 | Native_divide = 82, 119 | Native_exp = 83, 120 | Native_exp2 = 84, 121 | Native_exp10 = 85, 122 | Native_log = 86, 123 | Native_log2 = 87, 124 | Native_log10 = 88, 125 | Native_powr = 89, 126 | Native_recip = 90, 127 | Native_rsqrt = 91, 128 | Native_sin = 92, 129 | Native_sqrt = 93, 130 | Native_tan = 94, 131 | 132 | // Common 133 | FClamp = 95, 134 | Degrees = 96, 135 | FMax_common = 97, 136 | FMin_common = 98, 137 | Mix = 99, 138 | Radians = 100, 139 | Step = 101, 140 | Smoothstep = 102, 141 | Sign = 103, 142 | 143 | // Geometrics 144 | Cross = 104, 145 | Distance = 105, 146 | Length = 106, 147 | Normalize = 107, 148 | Fast_distance = 108, 149 | Fast_length = 109, 150 | Fast_normalize = 110, 151 | 152 | // Images - Deprecated 153 | Read_imagef = 111, 154 | Read_imagei = 112, 155 | Read_imageui = 113, 156 | Read_imageh = 114, 157 | 158 | Read_imagef_samplerless = 115, 159 | Read_imagei_samplerless = 116, 160 | Read_imageui_samplerless = 117, 161 | Read_imageh_samplerless = 118, 162 | 163 | Write_imagef = 119, 164 | Write_imagei = 120, 165 | Write_imageui = 121, 166 | Write_imageh = 122, 167 | Read_imagef_mipmap_lod = 123, 168 | Read_imagei_mipmap_lod = 124, 169 | Read_imageui_mipmap_lod = 125, 170 | Read_imagef_mipmap_grad = 126, 171 | Read_imagei_mipmap_grad = 127, 172 | Read_imageui_mipmap_grad = 128, 173 | 174 | // Image write with LOD 175 | Write_imagef_mipmap_lod = 129, 176 | Write_imagei_mipmap_lod = 130, 177 | Write_imageui_mipmap_lod = 131, 178 | 179 | // Images - Deprecated 180 | Get_image_width = 132, 181 | Get_image_height = 133, 182 | Get_image_depth = 134, 183 | Get_image_channel_data_type = 135, 184 | Get_image_channel_order = 136, 185 | Get_image_dim = 137, 186 | Get_image_array_size = 138, 187 | Get_image_num_samples = 139, 188 | Get_image_num_mip_levels = 140, 189 | 190 | // Integers 191 | SAbs = 141, 192 | SAbs_diff = 142, 193 | SAdd_sat = 143, 194 | UAdd_sat = 144, 195 | SHadd = 145, 196 | UHadd = 146, 197 | SRhadd = 147, 198 | URhadd = 148, 199 | SClamp = 149, 200 | UClamp = 150, 201 | Clz = 151, 202 | Ctz = 152, 203 | SMad_hi = 153, 204 | UMad_sat = 154, 205 | SMad_sat = 155, 206 | SMax = 156, 207 | UMax = 157, 208 | SMin = 158, 209 | UMin = 159, 210 | SMul_hi = 160, 211 | Rotate = 161, 212 | SSub_sat = 162, 213 | USub_sat = 163, 214 | U_Upsample = 164, 215 | S_Upsample = 165, 216 | Popcount = 166, 217 | SMad24 = 167, 218 | UMad24 = 168, 219 | SMul24 = 169, 220 | UMul24 = 170, 221 | 222 | // Vector Loads/Stores 223 | Vloadn = 171, 224 | Vstoren = 172, 225 | Vload_half = 173, 226 | Vload_halfn = 174, 227 | Vstore_half = 175, 228 | Vstore_half_r = 176, 229 | Vstore_halfn = 177, 230 | Vstore_halfn_r = 178, 231 | Vloada_halfn = 179, 232 | Vstorea_halfn = 180, 233 | Vstorea_halfn_r = 181, 234 | 235 | // Vector Misc 236 | Shuffle = 182, 237 | Shuffle2 = 183, 238 | 239 | // 240 | Printf = 184, 241 | Prefetch = 185, 242 | 243 | // Relationals 244 | Bitselect = 186, 245 | Select = 187, 246 | 247 | // pipes 248 | Read_pipe = 188, 249 | Write_pipe = 189, 250 | Reserve_read_pipe = 190, 251 | Reserve_write_pipe = 191, 252 | Commit_read_pipe = 192, 253 | Commit_write_pipe = 193, 254 | Is_valid_reserve_id = 194, 255 | Work_group_reserve_read_pipe = 195, 256 | Work_group_reserve_write_pipe = 196, 257 | Work_group_commit_read_pipe = 197, 258 | Work_group_commit_write_pipe = 198, 259 | Get_pipe_num_packets = 199, 260 | Get_pipe_max_packets = 200, 261 | 262 | // more integers 263 | UAbs = 201, 264 | UAbs_diff = 202, 265 | UMul_hi = 203, 266 | UMad_hi = 204, 267 | }; 268 | 269 | } // end namespace OpenCL20 270 | -------------------------------------------------------------------------------- /Mangler/ParameterType.cpp: -------------------------------------------------------------------------------- 1 | //===------------------------ ParameterType.cpp --------------------------===// 2 | // 3 | // SPIR Tools 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===---------------------------------------------------------------------===// 9 | /* 10 | * Contributed by: Intel Corporation. 11 | */ 12 | #include "ParameterType.h" 13 | #include "ManglingUtils.h" 14 | #include 15 | #include 16 | #include 17 | 18 | namespace SPIR { 19 | // 20 | // Primitive Type 21 | // 22 | 23 | PrimitiveType::PrimitiveType(TypePrimitiveEnum primitive) : 24 | ParamType(TYPE_ID_PRIMITIVE), m_primitive(primitive) { 25 | } 26 | 27 | 28 | MangleError PrimitiveType::accept(TypeVisitor* visitor) const { 29 | if (getSupportedVersion(this->getPrimitive()) >= SPIR20 && visitor->spirVer < SPIR20) { 30 | return MANGLE_TYPE_NOT_SUPPORTED; 31 | } 32 | return visitor->visit(this); 33 | } 34 | 35 | std::string PrimitiveType::toString() const { 36 | assert( (m_primitive >= PRIMITIVE_FIRST 37 | && m_primitive <= PRIMITIVE_LAST) && "illegal primitive"); 38 | std::stringstream myName; 39 | myName << readablePrimitiveString(m_primitive); 40 | return myName.str(); 41 | } 42 | 43 | bool PrimitiveType::equals(const ParamType* type) const { 44 | const PrimitiveType* p = SPIR::dyn_cast(type); 45 | return p && (m_primitive == p->m_primitive); 46 | } 47 | 48 | 49 | // 50 | // Pointer Type 51 | // 52 | 53 | PointerType::PointerType(const RefParamType type) : 54 | ParamType(TYPE_ID_POINTER), m_pType(type) { 55 | for (unsigned int i = ATTR_QUALIFIER_FIRST; i <= ATTR_QUALIFIER_LAST; i++) { 56 | setQualifier((TypeAttributeEnum)i, false); 57 | } 58 | m_address_space = ATTR_PRIVATE; 59 | } 60 | 61 | MangleError PointerType::accept(TypeVisitor* visitor) const { 62 | return visitor->visit(this); 63 | } 64 | 65 | void PointerType::setAddressSpace(TypeAttributeEnum attr) { 66 | if (attr < ATTR_ADDR_SPACE_FIRST || attr > ATTR_ADDR_SPACE_LAST) { 67 | return; 68 | } 69 | m_address_space = attr; 70 | } 71 | 72 | TypeAttributeEnum PointerType::getAddressSpace() const { 73 | return m_address_space; 74 | } 75 | 76 | void PointerType::setQualifier(TypeAttributeEnum qual, bool enabled) { 77 | if (qual < ATTR_QUALIFIER_FIRST || qual > ATTR_QUALIFIER_LAST) { 78 | return; 79 | } 80 | m_qualifiers[qual - ATTR_QUALIFIER_FIRST] = enabled; 81 | } 82 | 83 | bool PointerType::hasQualifier(TypeAttributeEnum qual) const { 84 | if (qual < ATTR_QUALIFIER_FIRST || qual > ATTR_QUALIFIER_LAST) { 85 | return false; 86 | } 87 | return m_qualifiers[qual - ATTR_QUALIFIER_FIRST]; 88 | } 89 | 90 | std::string PointerType::toString() const { 91 | std::stringstream myName; 92 | for (unsigned int i = ATTR_QUALIFIER_FIRST; i <= ATTR_QUALIFIER_LAST; i++) { 93 | TypeAttributeEnum qual = (TypeAttributeEnum)i; 94 | if (hasQualifier(qual)) { 95 | myName << getReadableAttribute(qual) << " "; 96 | } 97 | } 98 | myName << getReadableAttribute(TypeAttributeEnum(m_address_space)) << " "; 99 | myName << getPointee()->toString() << " *"; 100 | return myName.str(); 101 | } 102 | 103 | bool PointerType::equals(const ParamType* type) const { 104 | const PointerType* p = SPIR::dyn_cast(type); 105 | if (!p) { 106 | return false; 107 | } 108 | if (getAddressSpace() != p->getAddressSpace()) { 109 | return false; 110 | } 111 | for (unsigned int i = ATTR_QUALIFIER_FIRST; i <= ATTR_QUALIFIER_LAST; i++) { 112 | TypeAttributeEnum qual = (TypeAttributeEnum)i; 113 | if (hasQualifier(qual) != p->hasQualifier(qual)) { 114 | return false; 115 | } 116 | } 117 | return (*getPointee()).equals(&*(p->getPointee())); 118 | } 119 | 120 | // 121 | // Vector Type 122 | // 123 | 124 | VectorType::VectorType(const RefParamType type, int len) : 125 | ParamType(TYPE_ID_VECTOR), m_pType(type), m_len(len) { 126 | } 127 | 128 | MangleError VectorType::accept(TypeVisitor* visitor) const { 129 | return visitor->visit(this); 130 | } 131 | 132 | std::string VectorType::toString() const { 133 | std::stringstream myName; 134 | myName << getScalarType()->toString(); 135 | myName << m_len; 136 | return myName.str(); 137 | } 138 | 139 | bool VectorType::equals(const ParamType* type) const { 140 | const VectorType* pVec = SPIR::dyn_cast(type); 141 | return pVec && (m_len == pVec->m_len) && 142 | (*getScalarType()).equals(&*(pVec->getScalarType())); 143 | } 144 | 145 | // 146 | //Atomic Type 147 | // 148 | 149 | AtomicType::AtomicType(const RefParamType type) : 150 | ParamType(TYPE_ID_ATOMIC), m_pType(type) { 151 | } 152 | 153 | MangleError AtomicType::accept(TypeVisitor* visitor) const { 154 | if (visitor->spirVer < SPIR20) { 155 | return MANGLE_TYPE_NOT_SUPPORTED; 156 | } 157 | return visitor->visit(this); 158 | } 159 | 160 | std::string AtomicType::toString() const { 161 | std::stringstream myName; 162 | myName << "atomic_" << getBaseType()->toString(); 163 | return myName.str(); 164 | } 165 | 166 | bool AtomicType::equals(const ParamType* type) const { 167 | const AtomicType* a = dyn_cast(type); 168 | return (a && (*getBaseType()).equals(&*(a->getBaseType()))); 169 | } 170 | 171 | // 172 | //Block Type 173 | // 174 | 175 | BlockType::BlockType() : 176 | ParamType(TYPE_ID_BLOCK) { 177 | } 178 | 179 | MangleError BlockType::accept(TypeVisitor* visitor) const { 180 | if (visitor->spirVer < SPIR20) { 181 | return MANGLE_TYPE_NOT_SUPPORTED; 182 | } 183 | return visitor->visit(this); 184 | } 185 | 186 | std::string BlockType::toString() const { 187 | std::stringstream myName; 188 | myName << "void ("; 189 | for (unsigned int i=0; i0) myName << ", "; 191 | myName << m_params[i]->toString(); 192 | } 193 | myName << ")*"; 194 | return myName.str(); 195 | } 196 | 197 | bool BlockType::equals(const ParamType* type) const { 198 | const BlockType* pBlock = dyn_cast(type); 199 | if (!pBlock || getNumOfParams() != pBlock->getNumOfParams() ) { 200 | return false; 201 | } 202 | for (unsigned int i=0; iequals(&*pBlock->getParam(i))) { 204 | return false; 205 | } 206 | } 207 | return true; 208 | } 209 | 210 | // 211 | // User Defined Type 212 | // 213 | UserDefinedType::UserDefinedType(const std::string& name): 214 | ParamType(TYPE_ID_STRUCTURE), m_name(name) { 215 | } 216 | 217 | MangleError UserDefinedType::accept(TypeVisitor* visitor) const { 218 | return visitor->visit(this); 219 | } 220 | 221 | std::string UserDefinedType::toString() const { 222 | std::stringstream myName; 223 | myName << m_name; 224 | return myName.str(); 225 | } 226 | 227 | bool UserDefinedType::equals(const ParamType* pType) const { 228 | const UserDefinedType* pTy = SPIR::dyn_cast(pType); 229 | return pTy && (m_name == pTy->m_name); 230 | } 231 | 232 | 233 | // 234 | // Static enums 235 | // 236 | const TypeEnum PrimitiveType::enumTy = TYPE_ID_PRIMITIVE; 237 | const TypeEnum PointerType::enumTy = TYPE_ID_POINTER; 238 | const TypeEnum VectorType::enumTy = TYPE_ID_VECTOR; 239 | const TypeEnum AtomicType::enumTy = TYPE_ID_ATOMIC; 240 | const TypeEnum BlockType::enumTy = TYPE_ID_BLOCK; 241 | const TypeEnum UserDefinedType::enumTy = TYPE_ID_STRUCTURE; 242 | 243 | } // End SPIR namespace 244 | -------------------------------------------------------------------------------- /Passes/OCL21ToSPIRV.cpp: -------------------------------------------------------------------------------- 1 | //===- OCL21ToSPIRV.cpp - Transform OCL21 to SPIR-V builtins -----*- C++ -*-===// 2 | // 3 | // The LLVM/SPIRV Translator 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a 11 | // copy of this software and associated documentation files (the "Software"), 12 | // to deal with the Software without restriction, including without limitation 13 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 | // and/or sell copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following conditions: 16 | // 17 | // Redistributions of source code must retain the above copyright notice, 18 | // this list of conditions and the following disclaimers. 19 | // Redistributions in binary form must reproduce the above copyright notice, 20 | // this list of conditions and the following disclaimers in the documentation 21 | // and/or other materials provided with the distribution. 22 | // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 | // contributors may be used to endorse or promote products derived from this 24 | // Software without specific prior written permission. 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 | // THE SOFTWARE. 32 | // 33 | //===----------------------------------------------------------------------===// 34 | // 35 | // This file implements translation of OCL21 builtin functions. 36 | // 37 | //===----------------------------------------------------------------------===// 38 | #define DEBUG_TYPE "cl21tospv" 39 | 40 | #include "SPIRVInternal.h" 41 | #include "OCLUtil.h" 42 | #include "llvm/ADT/StringSwitch.h" 43 | #include "llvm/IR/InstVisitor.h" 44 | #include "llvm/IR/Instructions.h" 45 | #include "llvm/IR/IRBuilder.h" 46 | #include "llvm/IR/Verifier.h" 47 | #include "llvm/Pass.h" 48 | #include "llvm/PassSupport.h" 49 | #include "llvm/Support/Debug.h" 50 | #include "llvm/Support/raw_ostream.h" 51 | 52 | #include 53 | 54 | using namespace llvm; 55 | using namespace SPIRV; 56 | using namespace OCLUtil; 57 | 58 | namespace SPIRV { 59 | 60 | class OCL21ToSPIRV: public ModulePass, 61 | public InstVisitor { 62 | public: 63 | OCL21ToSPIRV():ModulePass(ID), M(nullptr), Ctx(nullptr), CLVer(0) { 64 | initializeOCL21ToSPIRVPass(*PassRegistry::getPassRegistry()); 65 | } 66 | virtual bool runOnModule(Module &M); 67 | virtual void visitCallInst(CallInst &CI); 68 | 69 | /// Transform SPIR-V convert function 70 | // __spirv{N}Op{ConvertOpName}(src, dummy) 71 | /// => 72 | /// __spirv_{ConvertOpName}_R{TargeTyName} 73 | void visitCallConvert(CallInst *CI, StringRef MangledName, Op OC); 74 | 75 | /// Transform SPIR-V decoration 76 | /// x = __spirv_{OpName}; 77 | /// y = __spirv{N}Op{Decorate}(x, type, value, dummy) 78 | /// => 79 | /// y = __spirv_{OpName}{Postfix(type,value)} 80 | void visitCallDecorate(CallInst *CI, StringRef MangledName); 81 | 82 | /// Transform OCL C++ builtin function to SPIR-V builtin function. 83 | /// Assuming there is no argument changes. 84 | /// Should be called at last. 85 | void transBuiltin(CallInst *CI, Op OC); 86 | 87 | static char ID; 88 | private: 89 | Module *M; 90 | LLVMContext *Ctx; 91 | unsigned CLVer; /// OpenCL version as major*10+minor 92 | std::set ValuesToDelete; 93 | }; 94 | 95 | char OCL21ToSPIRV::ID = 0; 96 | 97 | bool 98 | OCL21ToSPIRV::runOnModule(Module& Module) { 99 | M = &Module; 100 | Ctx = &M->getContext(); 101 | 102 | auto Src = getSPIRVSource(&Module); 103 | if (std::get<0>(Src) != spv::SourceLanguageOpenCL_CPP) 104 | return false; 105 | 106 | CLVer = std::get<1>(Src); 107 | if (CLVer < kOCLVer::CL21) 108 | return false; 109 | 110 | DEBUG(dbgs() << "Enter OCL21ToSPIRV:\n"); 111 | visit(*M); 112 | 113 | for (auto &I:ValuesToDelete) 114 | if (auto Inst = dyn_cast(I)) 115 | Inst->eraseFromParent(); 116 | for (auto &I:ValuesToDelete) 117 | if (auto GV = dyn_cast(I)) 118 | GV->eraseFromParent(); 119 | 120 | DEBUG(dbgs() << "After OCL21ToSPIRV:\n" << *M); 121 | std::string Err; 122 | raw_string_ostream ErrorOS(Err); 123 | if (verifyModule(*M, &ErrorOS)){ 124 | DEBUG(errs() << "Fails to verify module: " << ErrorOS.str()); 125 | } 126 | return true; 127 | } 128 | 129 | // The order of handling OCL builtin functions is important. 130 | // Workgroup functions need to be handled before pipe functions since 131 | // there are functions fall into both categories. 132 | void 133 | OCL21ToSPIRV::visitCallInst(CallInst& CI) { 134 | DEBUG(dbgs() << "[visistCallInst] " << CI << '\n'); 135 | auto F = CI.getCalledFunction(); 136 | if (!F) 137 | return; 138 | 139 | auto MangledName = F->getName(); 140 | std::string DemangledName; 141 | if (!oclIsBuiltin(MangledName, &DemangledName, true)) 142 | return; 143 | DEBUG(dbgs() << "DemangledName:" << DemangledName << '\n'); 144 | StringRef Ref(DemangledName); 145 | 146 | Op OC = OpNop; 147 | if (!OpCodeNameMap::rfind(Ref.str(), &OC)) 148 | return; 149 | DEBUG(dbgs() << "maps to opcode " << OC << '\n'); 150 | 151 | if (isCvtOpCode(OC)) { 152 | visitCallConvert(&CI, MangledName, OC); 153 | return; 154 | } 155 | if (OC == OpDecorate) { 156 | visitCallDecorate(&CI, MangledName); 157 | return; 158 | } 159 | transBuiltin(&CI, OC); 160 | } 161 | 162 | void OCL21ToSPIRV::visitCallConvert(CallInst* CI, 163 | StringRef MangledName, Op OC) { 164 | auto Attrs = CI->getCalledFunction()->getAttributes(); 165 | mutateCallInstSPIRV(M, CI, [=](CallInst *, std::vector &Args){ 166 | Args.pop_back(); 167 | return getSPIRVFuncName(OC, kSPIRVPostfix::Divider + 168 | getPostfixForReturnType(CI, 169 | OC == OpSConvert || OC == OpConvertFToS || OC == OpSatConvertUToS)); 170 | }, &Attrs); 171 | ValuesToDelete.insert(CI); 172 | ValuesToDelete.insert(CI->getCalledFunction()); 173 | } 174 | 175 | void OCL21ToSPIRV::visitCallDecorate(CallInst* CI, 176 | StringRef MangledName) { 177 | auto Target = cast(CI->getArgOperand(0)); 178 | auto F = Target->getCalledFunction(); 179 | auto Name = F->getName().str(); 180 | std::string DemangledName; 181 | oclIsBuiltin(Name, &DemangledName); 182 | BuiltinFuncMangleInfo Info; 183 | F->setName(mangleBuiltin(DemangledName + kSPIRVPostfix::Divider + 184 | getPostfix(getArgAsDecoration(CI, 1), getArgAsInt(CI, 2)), 185 | getTypes(getArguments(CI)), &Info)); 186 | CI->replaceAllUsesWith(Target); 187 | ValuesToDelete.insert(CI); 188 | ValuesToDelete.insert(CI->getCalledFunction()); 189 | } 190 | 191 | void 192 | OCL21ToSPIRV::transBuiltin(CallInst* CI, Op OC) { 193 | auto Attrs = CI->getCalledFunction()->getAttributes(); 194 | assert(OC != OpExtInst && "not supported"); 195 | mutateCallInstSPIRV(M, CI, [=](CallInst *, std::vector &Args){ 196 | return getSPIRVFuncName(OC); 197 | }, &Attrs); 198 | ValuesToDelete.insert(CI); 199 | ValuesToDelete.insert(CI->getCalledFunction()); 200 | } 201 | 202 | } 203 | 204 | INITIALIZE_PASS(OCL21ToSPIRV, "cl21tospv", "Transform OCL 2.1 to SPIR-V", 205 | false, false) 206 | 207 | ModulePass *llvm::createOCL21ToSPIRV() { 208 | return new OCL21ToSPIRV(); 209 | } 210 | -------------------------------------------------------------------------------- /Passes/SPIRVRegularizeLLVM.cpp: -------------------------------------------------------------------------------- 1 | //===- SPIRVRegularizeLLVM.cpp - Regularize LLVM for SPIR-V ------- C++ -*-===// 2 | // 3 | // The LLVM/SPIRV Translator 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a 11 | // copy of this software and associated documentation files (the "Software"), 12 | // to deal with the Software without restriction, including without limitation 13 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 | // and/or sell copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following conditions: 16 | // 17 | // Redistributions of source code must retain the above copyright notice, 18 | // this list of conditions and the following disclaimers. 19 | // Redistributions in binary form must reproduce the above copyright notice, 20 | // this list of conditions and the following disclaimers in the documentation 21 | // and/or other materials provided with the distribution. 22 | // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 | // contributors may be used to endorse or promote products derived from this 24 | // Software without specific prior written permission. 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 | // THE SOFTWARE. 32 | // 33 | //===----------------------------------------------------------------------===// 34 | // 35 | // This file implements regularization of LLVM moduel for SPIR-V. 36 | // 37 | //===----------------------------------------------------------------------===// 38 | #define DEBUG_TYPE "spvregular" 39 | 40 | #include "SPIRVInternal.h" 41 | #include "OCLUtil.h" 42 | #include "libSPIRV/SPIRVMDBuilder.h" 43 | #include "libSPIRV/SPIRVMDWalker.h" 44 | 45 | #include "llvm/ADT/StringSwitch.h" 46 | #include "llvm/ADT/Triple.h" 47 | #include "llvm/IR/InstVisitor.h" 48 | #include "llvm/IR/Instructions.h" 49 | #include "llvm/IR/IRBuilder.h" 50 | #include "llvm/IR/Verifier.h" 51 | #include "llvm/Pass.h" 52 | #include "llvm/PassSupport.h" 53 | #include "llvm/Support/CommandLine.h" 54 | #include "llvm/Support/Debug.h" 55 | #include "llvm/Support/raw_ostream.h" 56 | 57 | #include 58 | 59 | using namespace llvm; 60 | using namespace SPIRV; 61 | using namespace OCLUtil; 62 | 63 | namespace SPIRV { 64 | 65 | static bool SPIRVDbgSaveRegularizedModule = false; 66 | static std::string RegularizedModuleTmpFile = "regularized.bc"; 67 | 68 | class SPIRVRegularizeLLVM: public ModulePass { 69 | public: 70 | SPIRVRegularizeLLVM():ModulePass(ID), M(nullptr), Ctx(nullptr) { 71 | initializeSPIRVRegularizeLLVMPass(*PassRegistry::getPassRegistry()); 72 | } 73 | 74 | virtual bool runOnModule(Module &M); 75 | 76 | // Lower functions 77 | bool regularize(); 78 | 79 | /// Erase cast inst of function and replace with the function. 80 | /// Assuming F is a SPIR-V builtin function with op code \param OC. 81 | void lowerFuncPtr(Function *F, Op OC); 82 | void lowerFuncPtr(Module *M); 83 | 84 | static char ID; 85 | private: 86 | Module *M; 87 | LLVMContext *Ctx; 88 | }; 89 | 90 | char SPIRVRegularizeLLVM::ID = 0; 91 | 92 | bool 93 | SPIRVRegularizeLLVM::runOnModule(Module& Module) { 94 | M = &Module; 95 | Ctx = &M->getContext(); 96 | 97 | DEBUG(dbgs() << "Enter SPIRVRegularizeLLVM:\n"); 98 | regularize(); 99 | 100 | DEBUG(dbgs() << "After SPIRVRegularizeLLVM:\n" << *M); 101 | std::string Err; 102 | raw_string_ostream ErrorOS(Err); 103 | if (verifyModule(*M, &ErrorOS)){ 104 | DEBUG(errs() << "Fails to verify module: " << ErrorOS.str()); 105 | } 106 | return true; 107 | } 108 | 109 | /// Remove entities not representable by SPIR-V 110 | bool 111 | SPIRVRegularizeLLVM::regularize() { 112 | LLVMContext *Context = &M->getContext(); 113 | 114 | eraseUselessFunctions(M); 115 | lowerFuncPtr(M); 116 | //lowerConstantExpressions(); 117 | 118 | for (auto I = M->begin(), E = M->end(); I != E;) { 119 | Function *F = &*I++; 120 | if (F->isDeclaration() && F->use_empty()) { 121 | F->eraseFromParent(); 122 | continue; 123 | } 124 | 125 | for (auto BI = F->begin(), BE = F->end(); BI != BE; ++BI) { 126 | for (auto II = BI->begin(), IE = BI->end(); II != IE; ++II) { 127 | if (auto Call = dyn_cast(II)) { 128 | Call->setTailCall(false); 129 | if (Call->getCalledFunction()->isIntrinsic()) 130 | removeFnAttr(Context, Call, Attribute::NoUnwind); 131 | } 132 | 133 | // Remove optimization info not supported by SPIRV 134 | if (auto BO = dyn_cast(II)) { 135 | if (isa(BO)) { 136 | if (BO->hasNoUnsignedWrap()) 137 | BO->setHasNoUnsignedWrap(false); 138 | if (BO->hasNoSignedWrap()) 139 | BO->setHasNoSignedWrap(false); 140 | } 141 | if (isa(BO) && BO->isExact()) 142 | BO->setIsExact(false); 143 | } 144 | // Remove metadata not supported by SPIRV 145 | static const char *MDs[] = { 146 | "fpmath", 147 | "tbaa", 148 | "range", 149 | }; 150 | for (auto &MDName:MDs) { 151 | if (II->getMetadata(MDName)) { 152 | II->setMetadata(MDName, nullptr); 153 | } 154 | } 155 | } 156 | } 157 | } 158 | 159 | std::string Err; 160 | raw_string_ostream ErrorOS(Err); 161 | if (verifyModule(*M, &ErrorOS)){ 162 | SPIRVDBG(errs() << "Fails to verify module: " << ErrorOS.str();) 163 | return false; 164 | } 165 | 166 | if (SPIRVDbgSaveRegularizedModule) 167 | saveLLVMModule(M, RegularizedModuleTmpFile); 168 | return true; 169 | } 170 | 171 | // Assume F is a SPIR-V builtin function with a function pointer argument which 172 | // is a bitcast instruction casting a function to a void(void) function pointer. 173 | void SPIRVRegularizeLLVM::lowerFuncPtr(Function* F, Op OC) { 174 | DEBUG(dbgs() << "[lowerFuncPtr] " << *F << '\n'); 175 | auto Name = decorateSPIRVFunction(getName(OC)); 176 | std::set InvokeFuncPtrs; 177 | auto Attrs = F->getAttributes(); 178 | mutateFunction(F, [=, &InvokeFuncPtrs]( 179 | CallInst *CI, std::vector &Args) { 180 | for (auto &I:Args) { 181 | if (isFunctionPointerType(I->getType())) { 182 | InvokeFuncPtrs.insert(I); 183 | I = removeCast(I); 184 | } 185 | } 186 | return Name; 187 | }, nullptr, &Attrs, false); 188 | for (auto &I:InvokeFuncPtrs) 189 | eraseIfNoUse(I); 190 | } 191 | 192 | void 193 | SPIRVRegularizeLLVM::lowerFuncPtr(Module* M) { 194 | std::vector> Work; 195 | for (auto I = M->begin(), E = M->end(); I != E;) { 196 | Function *F = &*I++; 197 | auto AI = F->arg_begin(); 198 | if (hasFunctionPointerArg(F, AI)) { 199 | auto OC = getSPIRVFuncOC(F->getName()); 200 | assert(OC != OpNop && "Invalid function pointer usage"); 201 | Work.push_back(std::make_pair(F, OC)); 202 | } 203 | } 204 | for (auto &I:Work) 205 | lowerFuncPtr(I.first, I.second); 206 | } 207 | 208 | } 209 | 210 | 211 | INITIALIZE_PASS(SPIRVRegularizeLLVM, "spvregular", 212 | "Regularize LLVM for SPIR-V", false, false) 213 | 214 | ModulePass *llvm::createSPIRVRegularizeLLVM() { 215 | return new SPIRVRegularizeLLVM(); 216 | } 217 | -------------------------------------------------------------------------------- /Passes/TransOCLMD.cpp: -------------------------------------------------------------------------------- 1 | //===- TransOCLMD.cpp - Transform OCL metadata to SPIR-V metadata - C++ -*-===// 2 | // 3 | // The LLVM/SPIRV Translator 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a 11 | // copy of this software and associated documentation files (the "Software"), 12 | // to deal with the Software without restriction, including without limitation 13 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 | // and/or sell copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following conditions: 16 | // 17 | // Redistributions of source code must retain the above copyright notice, 18 | // this list of conditions and the following disclaimers. 19 | // Redistributions in binary form must reproduce the above copyright notice, 20 | // this list of conditions and the following disclaimers in the documentation 21 | // and/or other materials provided with the distribution. 22 | // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 | // contributors may be used to endorse or promote products derived from this 24 | // Software without specific prior written permission. 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 | // THE SOFTWARE. 32 | // 33 | //===----------------------------------------------------------------------===// 34 | // 35 | // This file implements translation of OCL metadata to SPIR-V metadata. 36 | // 37 | //===----------------------------------------------------------------------===// 38 | #define DEBUG_TYPE "clmdtospv" 39 | 40 | #include "SPIRVInternal.h" 41 | #include "OCLUtil.h" 42 | #include "libSPIRV/SPIRVMDBuilder.h" 43 | #include "libSPIRV/SPIRVMDWalker.h" 44 | 45 | #include "llvm/ADT/StringSwitch.h" 46 | #include "llvm/ADT/Triple.h" 47 | #include "llvm/IR/InstVisitor.h" 48 | #include "llvm/IR/Instructions.h" 49 | #include "llvm/IR/IRBuilder.h" 50 | #include "llvm/IR/Verifier.h" 51 | #include "llvm/Pass.h" 52 | #include "llvm/PassSupport.h" 53 | #include "llvm/Support/CommandLine.h" 54 | #include "llvm/Support/Debug.h" 55 | #include "llvm/Support/raw_ostream.h" 56 | 57 | #include 58 | 59 | using namespace llvm; 60 | using namespace SPIRV; 61 | using namespace OCLUtil; 62 | 63 | namespace SPIRV { 64 | 65 | cl::opt EraseOCLMD("spirv-erase-cl-md", cl::init(true), 66 | cl::desc("Erase OpenCL metadata")); 67 | 68 | class TransOCLMD: public ModulePass { 69 | public: 70 | TransOCLMD():ModulePass(ID), M(nullptr), Ctx(nullptr), CLVer(0) { 71 | initializeTransOCLMDPass(*PassRegistry::getPassRegistry()); 72 | } 73 | 74 | virtual bool runOnModule(Module &M); 75 | void visit(Module *M); 76 | 77 | static char ID; 78 | private: 79 | Module *M; 80 | LLVMContext *Ctx; 81 | unsigned CLVer; /// OpenCL version as major*10+minor 82 | }; 83 | 84 | char TransOCLMD::ID = 0; 85 | 86 | bool 87 | TransOCLMD::runOnModule(Module& Module) { 88 | M = &Module; 89 | Ctx = &M->getContext(); 90 | CLVer = getOCLVersion(M, true); 91 | if (CLVer == 0) 92 | return false; 93 | 94 | DEBUG(dbgs() << "Enter TransOCLMD:\n"); 95 | visit(M); 96 | 97 | DEBUG(dbgs() << "After TransOCLMD:\n" << *M); 98 | std::string Err; 99 | raw_string_ostream ErrorOS(Err); 100 | if (verifyModule(*M, &ErrorOS)){ 101 | DEBUG(errs() << "Fails to verify module: " << ErrorOS.str()); 102 | } 103 | return true; 104 | } 105 | 106 | void 107 | TransOCLMD::visit(Module *M) { 108 | SPIRVMDBuilder B(*M); 109 | SPIRVMDWalker W(*M); 110 | B.addNamedMD(kSPIRVMD::Source) 111 | .addOp() 112 | .add(CLVer < kOCLVer::CL21 ? spv::SourceLanguageOpenCL_C 113 | : spv::SourceLanguageOpenCL_CPP) 114 | .add(CLVer) 115 | .done(); 116 | if (EraseOCLMD) 117 | B.eraseNamedMD(kSPIR2MD::OCLVer) 118 | .eraseNamedMD(kSPIR2MD::SPIRVer); 119 | 120 | Triple TT(M->getTargetTriple()); 121 | auto Arch = TT.getArch(); 122 | assert((Arch == Triple::spir || Arch == Triple::spir64) && "Invalid triple"); 123 | B.addNamedMD(kSPIRVMD::MemoryModel) 124 | .addOp() 125 | .add(Arch == Triple::spir ? spv::AddressingModelPhysical32 : 126 | AddressingModelPhysical64) 127 | .add(spv::MemoryModelOpenCL) 128 | .done(); 129 | 130 | // Add extensions 131 | auto Exts = getNamedMDAsStringSet(M, kSPIR2MD::Extensions); 132 | if (!Exts.empty()) { 133 | auto N = B.addNamedMD(kSPIRVMD::Extension); 134 | for (auto &I:Exts) 135 | N.addOp() 136 | .add(I) 137 | .done(); 138 | } 139 | if (EraseOCLMD) 140 | B.eraseNamedMD(kSPIR2MD::Extensions) 141 | .eraseNamedMD(kSPIR2MD::OptFeatures); 142 | 143 | bool HasFPContract = W.getNamedMD(kSPIR2MD::FPContract); 144 | if (EraseOCLMD) 145 | B.eraseNamedMD(kSPIR2MD::FPContract); 146 | 147 | // Add entry points 148 | auto EP = B.addNamedMD(kSPIRVMD::EntryPoint); 149 | auto EM = B.addNamedMD(kSPIRVMD::ExecutionMode); 150 | 151 | // Add execution mode 152 | NamedMDNode *KernelMDs = M->getNamedMetadata(SPIR_MD_KERNELS); 153 | if (!KernelMDs) 154 | return; 155 | 156 | for (unsigned I = 0, E = KernelMDs->getNumOperands(); I < E; ++I) { 157 | MDNode *KernelMD = KernelMDs->getOperand(I); 158 | if (KernelMD->getNumOperands() == 0) 159 | continue; 160 | Function *Kernel = mdconst::dyn_extract(KernelMD->getOperand(0)); 161 | 162 | // Workaround for OCL 2.0 producer not using SPIR_KERNEL calling convention 163 | #if SPCV_RELAX_KERNEL_CALLING_CONV 164 | Kernel->setCallingConv(CallingConv::SPIR_KERNEL); 165 | #endif 166 | 167 | MDNode *EPNode; 168 | EP.addOp() 169 | .add(spv::ExecutionModelKernel) 170 | .add(Kernel) 171 | .add(Kernel->getName()) 172 | .done(&EPNode); 173 | 174 | if (!HasFPContract) 175 | EM.addOp() 176 | .addOp(EPNode) 177 | .add(spv::ExecutionModeContractionOff) 178 | .done(); 179 | 180 | for (unsigned MI = 1, ME = KernelMD->getNumOperands(); MI < ME; ++MI) { 181 | MDNode *MD = dyn_cast(KernelMD->getOperand(MI)); 182 | if (!MD) 183 | continue; 184 | MDString *NameMD = dyn_cast(MD->getOperand(0)); 185 | if (!NameMD) 186 | continue; 187 | StringRef Name = NameMD->getString(); 188 | if (Name == kSPIR2MD::WGSizeHint) { 189 | unsigned X, Y, Z; 190 | decodeMDNode(MD, X, Y, Z); 191 | EM.addOp() 192 | .addOp(EPNode) 193 | .add(spv::ExecutionModeLocalSizeHint) 194 | .add(X).add(Y).add(Z) 195 | .done(); 196 | } else if (Name == kSPIR2MD::WGSize) { 197 | unsigned X, Y, Z; 198 | decodeMDNode(MD, X, Y, Z); 199 | EM.addOp() 200 | .addOp(EPNode) 201 | .add(spv::ExecutionModeLocalSize) 202 | .add(X).add(Y).add(Z) 203 | .done(); 204 | } else if (Name == kSPIR2MD::VecTyHint) { 205 | EM.addOp() 206 | .addOp(EPNode) 207 | .add(spv::ExecutionModeVecTypeHint) 208 | .add(transVecTypeHint(MD)) 209 | .done(); 210 | } 211 | } 212 | } 213 | } 214 | 215 | } 216 | 217 | INITIALIZE_PASS(TransOCLMD, "clmdtospv", "Transform OCL metadata to SPIR-V", 218 | false, false) 219 | 220 | ModulePass *llvm::createTransOCLMD() { 221 | return new TransOCLMD(); 222 | } 223 | -------------------------------------------------------------------------------- /libSPIRV/SPIRVDecorate.cpp: -------------------------------------------------------------------------------- 1 | //===- SPIRVDecorate.cpp -SPIR-V Decorations ---------------------*- C++ -*-===// 2 | // 3 | // The LLVM/SPIRV Translator 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a 11 | // copy of this software and associated documentation files (the "Software"), 12 | // to deal with the Software without restriction, including without limitation 13 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 | // and/or sell copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following conditions: 16 | // 17 | // Redistributions of source code must retain the above copyright notice, 18 | // this list of conditions and the following disclaimers. 19 | // Redistributions in binary form must reproduce the above copyright notice, 20 | // this list of conditions and the following disclaimers in the documentation 21 | // and/or other materials provided with the distribution. 22 | // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 | // contributors may be used to endorse or promote products derived from this 24 | // Software without specific prior written permission. 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 | // THE SOFTWARE. 32 | // 33 | //===----------------------------------------------------------------------===// 34 | /// \file 35 | /// 36 | /// This file implements SPIR-V decorations. 37 | /// 38 | //===----------------------------------------------------------------------===// 39 | 40 | #include "SPIRVDecorate.h" 41 | #include "SPIRVStream.h" 42 | #include "SPIRVValue.h" 43 | #include "SPIRVModule.h" 44 | 45 | namespace SPIRV{ 46 | template 47 | spv_ostream & 48 | operator<< (spv_ostream &O, const std::multiset& V) { 49 | for (auto &I: V) 50 | O << *I; 51 | return O; 52 | } 53 | 54 | SPIRVDecorateGeneric::SPIRVDecorateGeneric(Op OC, SPIRVWord WC, 55 | Decoration TheDec, 56 | SPIRVEntry *TheTarget) 57 | : SPIRVAnnotationGeneric(TheTarget->getModule(), WC, OC, 58 | TheTarget->getId()), 59 | Dec(TheDec), Owner(nullptr) { 60 | validate(); 61 | } 62 | 63 | SPIRVDecorateGeneric::SPIRVDecorateGeneric(Op OC, SPIRVWord WC, 64 | Decoration TheDec, 65 | SPIRVEntry *TheTarget, SPIRVWord V) 66 | : SPIRVAnnotationGeneric(TheTarget->getModule(), WC, OC, 67 | TheTarget->getId()), 68 | Dec(TheDec), Owner(nullptr) { 69 | Literals.push_back(V); 70 | validate(); 71 | } 72 | 73 | SPIRVDecorateGeneric::SPIRVDecorateGeneric(Op OC) 74 | :SPIRVAnnotationGeneric(OC), Dec(DecorationRelaxedPrecision), Owner(nullptr){ 75 | } 76 | 77 | Decoration 78 | SPIRVDecorateGeneric::getDecorateKind()const { 79 | return Dec; 80 | } 81 | 82 | SPIRVWord 83 | SPIRVDecorateGeneric::getLiteral(size_t i) const { 84 | assert(0 <= i && i <= Literals.size() && "Out of bounds"); 85 | return Literals[i]; 86 | } 87 | 88 | size_t 89 | SPIRVDecorateGeneric::getLiteralCount() const { 90 | return Literals.size(); 91 | } 92 | 93 | void 94 | SPIRVDecorate::encode(spv_ostream &O)const { 95 | SPIRVEncoder Encoder = getEncoder(O); 96 | Encoder << Target << Dec; 97 | if ( Dec == DecorationLinkageAttributes ) 98 | SPIRVDecorateLinkageAttr::encodeLiterals(Encoder, Literals); 99 | else 100 | Encoder << Literals; 101 | } 102 | 103 | void 104 | SPIRVDecorate::setWordCount(SPIRVWord Count){ 105 | WordCount = Count; 106 | Literals.resize(WordCount - FixedWC); 107 | } 108 | 109 | void 110 | SPIRVDecorate::decode(std::istream &I){ 111 | SPIRVDecoder Decoder = getDecoder(I); 112 | Decoder >> Target >> Dec; 113 | if(Dec == DecorationLinkageAttributes) 114 | SPIRVDecorateLinkageAttr::decodeLiterals(Decoder, Literals); 115 | else 116 | Decoder >> Literals; 117 | getOrCreateTarget()->addDecorate(this); 118 | } 119 | 120 | void 121 | SPIRVMemberDecorate::encode(spv_ostream &O)const { 122 | getEncoder(O) << Target << MemberNumber << Dec << Literals; 123 | } 124 | 125 | void 126 | SPIRVMemberDecorate::setWordCount(SPIRVWord Count){ 127 | WordCount = Count; 128 | Literals.resize(WordCount - FixedWC); 129 | } 130 | 131 | void 132 | SPIRVMemberDecorate::decode(std::istream &I){ 133 | getDecoder(I) >> Target >> MemberNumber >> Dec >> Literals; 134 | getOrCreateTarget()->addMemberDecorate(this); 135 | } 136 | 137 | void 138 | SPIRVDecorationGroup::encode(spv_ostream &O)const { 139 | getEncoder(O) << Id; 140 | } 141 | 142 | void 143 | SPIRVDecorationGroup::decode(std::istream &I){ 144 | getDecoder(I) >> Id; 145 | Module->addDecorationGroup(this); 146 | } 147 | 148 | void 149 | SPIRVDecorationGroup::encodeAll(spv_ostream &O) const { 150 | O << Decorations; 151 | SPIRVEntry::encodeAll(O); 152 | } 153 | 154 | void 155 | SPIRVGroupDecorateGeneric::encode(spv_ostream &O)const { 156 | getEncoder(O) << DecorationGroup << Targets; 157 | } 158 | 159 | void 160 | SPIRVGroupDecorateGeneric::decode(std::istream &I){ 161 | getDecoder(I) >> DecorationGroup >> Targets; 162 | Module->addGroupDecorateGeneric(this); 163 | } 164 | 165 | void 166 | SPIRVGroupDecorate::decorateTargets() { 167 | for(auto &I:Targets) { 168 | auto Target = getOrCreate(I); 169 | for (auto &Dec:DecorationGroup->getDecorations()) { 170 | assert(Dec->isDecorate()); 171 | Target->addDecorate(static_cast(Dec)); 172 | } 173 | } 174 | } 175 | 176 | void 177 | SPIRVGroupMemberDecorate::decorateTargets() { 178 | for(auto &I:Targets) { 179 | auto Target = getOrCreate(I); 180 | for (auto &Dec:DecorationGroup->getDecorations()) { 181 | assert(Dec->isMemberDecorate()); 182 | Target->addMemberDecorate(static_cast(Dec)); 183 | } 184 | } 185 | } 186 | 187 | bool 188 | SPIRVDecorateGeneric::Comparator::operator()(const SPIRVDecorateGeneric *A, 189 | const SPIRVDecorateGeneric *B) const { 190 | auto Action = [=](){ 191 | if (A->getOpCode() < B->getOpCode()) 192 | return true; 193 | if (A->getOpCode() > B->getOpCode()) 194 | return false; 195 | if (A->getDecorateKind() < B->getDecorateKind()) 196 | return true; 197 | if (A->getDecorateKind() > B->getDecorateKind()) 198 | return false; 199 | if (A->getLiteralCount() < B->getLiteralCount()) 200 | return true; 201 | if (A->getLiteralCount() > B->getLiteralCount()) 202 | return false; 203 | for (size_t I = 0, E = A->getLiteralCount(); I != E; ++I) { 204 | auto EA = A->getLiteral(I); 205 | auto EB = B->getLiteral(I); 206 | if (EA < EB) 207 | return true; 208 | if (EA > EB) 209 | return false; 210 | } 211 | return false; 212 | }; 213 | auto Res = Action(); 214 | return Res; 215 | } 216 | 217 | bool operator==(const SPIRVDecorateGeneric &A, const SPIRVDecorateGeneric &B) { 218 | if (A.getTargetId() != B.getTargetId()) 219 | return false; 220 | if (A.getOpCode() != B.getOpCode()) 221 | return false; 222 | if (A.getDecorateKind() != B.getDecorateKind()) 223 | return false; 224 | if (A.getLiteralCount() != B.getLiteralCount()) 225 | return false; 226 | for (size_t I = 0, E = A.getLiteralCount(); I != E; ++I) { 227 | auto EA = A.getLiteral(I); 228 | auto EB = B.getLiteral(I); 229 | if (EA != EB) 230 | return false; 231 | } 232 | return true; 233 | } 234 | } 235 | 236 | -------------------------------------------------------------------------------- /libSPIRV/SPIRVInstruction.cpp: -------------------------------------------------------------------------------- 1 | //===- SPIRVInstruction.cpp -Class to represent SPIR-V instruction - C++ -*-===// 2 | // 3 | // The LLVM/SPIRV Translator 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a 11 | // copy of this software and associated documentation files (the "Software"), 12 | // to deal with the Software without restriction, including without limitation 13 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 | // and/or sell copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following conditions: 16 | // 17 | // Redistributions of source code must retain the above copyright notice, 18 | // this list of conditions and the following disclaimers. 19 | // Redistributions in binary form must reproduce the above copyright notice, 20 | // this list of conditions and the following disclaimers in the documentation 21 | // and/or other materials provided with the distribution. 22 | // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 | // contributors may be used to endorse or promote products derived from this 24 | // Software without specific prior written permission. 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 | // THE SOFTWARE. 32 | // 33 | //===----------------------------------------------------------------------===// 34 | /// \file 35 | /// 36 | /// This file implements SPIR-V instructions. 37 | /// 38 | //===----------------------------------------------------------------------===// 39 | 40 | #include "SPIRVInstruction.h" 41 | #include "SPIRVBasicBlock.h" 42 | #include "SPIRVFunction.h" 43 | 44 | #include 45 | 46 | namespace SPIRV { 47 | 48 | // Complete constructor for instruction with type and id 49 | SPIRVInstruction::SPIRVInstruction(unsigned TheWordCount, Op TheOC, 50 | SPIRVType *TheType, SPIRVId TheId, SPIRVBasicBlock *TheBB) 51 | :SPIRVValue(TheBB->getModule(), TheWordCount, TheOC, TheType, TheId), 52 | BB(TheBB){ 53 | validate(); 54 | } 55 | 56 | SPIRVInstruction::SPIRVInstruction(unsigned TheWordCount, Op TheOC, 57 | SPIRVType *TheType, SPIRVId TheId, SPIRVBasicBlock *TheBB, SPIRVModule *TheBM) 58 | : SPIRVValue(TheBM, TheWordCount, TheOC, TheType, TheId), BB(TheBB){ 59 | validate(); 60 | } 61 | 62 | // Complete constructor for instruction with id but no type 63 | SPIRVInstruction::SPIRVInstruction(unsigned TheWordCount, Op TheOC, 64 | SPIRVId TheId, SPIRVBasicBlock *TheBB) 65 | :SPIRVValue(TheBB->getModule(), TheWordCount, TheOC, TheId), BB(TheBB){ 66 | validate(); 67 | } 68 | // Complete constructor for instruction without type and id 69 | SPIRVInstruction::SPIRVInstruction(unsigned TheWordCount, Op TheOC, 70 | SPIRVBasicBlock *TheBB) 71 | :SPIRVValue(TheBB->getModule(), TheWordCount, TheOC), BB(TheBB){ 72 | validate(); 73 | } 74 | // Complete constructor for instruction with type but no id 75 | SPIRVInstruction::SPIRVInstruction(unsigned TheWordCount, Op TheOC, 76 | SPIRVType *TheType, SPIRVBasicBlock *TheBB) 77 | :SPIRVValue(TheBB->getModule(), TheWordCount, TheOC, TheType), BB(TheBB){ 78 | validate(); 79 | } 80 | 81 | void 82 | SPIRVInstruction::setParent(SPIRVBasicBlock *TheBB) { 83 | assert(TheBB && "Invalid BB"); 84 | if (BB == TheBB) 85 | return; 86 | assert(BB == NULL && "BB cannot change parent"); 87 | BB = TheBB; 88 | } 89 | 90 | void 91 | SPIRVInstruction::setScope(SPIRVEntry *Scope) { 92 | assert(Scope && Scope->getOpCode() == OpLabel && "Invalid scope"); 93 | setParent(static_cast(Scope)); 94 | } 95 | 96 | SPIRVFunctionCall::SPIRVFunctionCall(SPIRVId TheId, SPIRVFunction *TheFunction, 97 | const std::vector &TheArgs, SPIRVBasicBlock *BB) 98 | :SPIRVFunctionCallGeneric( 99 | TheFunction->getFunctionType()->getReturnType(), 100 | TheId, TheArgs, BB), FunctionId(TheFunction->getId()){ 101 | validate(); 102 | } 103 | 104 | void 105 | SPIRVFunctionCall::validate()const { 106 | SPIRVFunctionCallGeneric::validate(); 107 | } 108 | 109 | // ToDo: Each instruction should implement this function 110 | std::vector 111 | SPIRVInstruction::getOperands() { 112 | std::vector Empty; 113 | assert(0 && "not supported"); 114 | return Empty; 115 | } 116 | 117 | std::vector 118 | SPIRVInstruction::getOperandTypes(const std::vector &Ops) { 119 | std::vector Tys; 120 | for (auto& I : Ops) { 121 | SPIRVType* Ty = nullptr; 122 | if (I->getOpCode() == OpFunction) 123 | Ty = reinterpret_cast(I)->getFunctionType(); 124 | else 125 | Ty = I->getType(); 126 | 127 | Tys.push_back(Ty); 128 | } 129 | return Tys; 130 | } 131 | 132 | std::vector 133 | SPIRVInstruction::getOperandTypes() { 134 | return getOperandTypes(getOperands()); 135 | } 136 | 137 | bool 138 | isSpecConstantOpAllowedOp(Op OC) { 139 | static SPIRVWord Table[] = 140 | { 141 | OpSConvert, 142 | OpFConvert, 143 | OpConvertFToS, 144 | OpConvertSToF, 145 | OpConvertFToU, 146 | OpConvertUToF, 147 | OpUConvert, 148 | OpConvertPtrToU, 149 | OpConvertUToPtr, 150 | OpGenericCastToPtr, 151 | OpPtrCastToGeneric, 152 | OpBitcast, 153 | OpQuantizeToF16, 154 | OpSNegate, 155 | OpNot, 156 | OpIAdd, 157 | OpISub, 158 | OpIMul, 159 | OpUDiv, 160 | OpSDiv, 161 | OpUMod, 162 | OpSRem, 163 | OpSMod, 164 | OpShiftRightLogical, 165 | OpShiftRightArithmetic, 166 | OpShiftLeftLogical, 167 | OpBitwiseOr, 168 | OpBitwiseXor, 169 | OpBitwiseAnd, 170 | OpFNegate, 171 | OpFAdd, 172 | OpFSub, 173 | OpFMul, 174 | OpFDiv, 175 | OpFRem, 176 | OpFMod, 177 | OpVectorShuffle, 178 | OpCompositeExtract, 179 | OpCompositeInsert, 180 | OpLogicalOr, 181 | OpLogicalAnd, 182 | OpLogicalNot, 183 | OpLogicalEqual, 184 | OpLogicalNotEqual, 185 | OpSelect, 186 | OpIEqual, 187 | OpULessThan, 188 | OpSLessThan, 189 | OpUGreaterThan, 190 | OpSGreaterThan, 191 | OpULessThanEqual, 192 | OpSLessThanEqual, 193 | OpUGreaterThanEqual, 194 | OpSGreaterThanEqual, 195 | OpAccessChain, 196 | OpInBoundsAccessChain, 197 | OpPtrAccessChain, 198 | OpInBoundsPtrAccessChain, 199 | }; 200 | static std::unordered_set 201 | Allow(std::begin(Table), std::end(Table)); 202 | return Allow.count(OC); 203 | } 204 | 205 | SPIRVSpecConstantOp * 206 | createSpecConstantOpInst(SPIRVInstruction *Inst) { 207 | auto OC = Inst->getOpCode(); 208 | assert (isSpecConstantOpAllowedOp(OC) && 209 | "Op code not allowed for OpSpecConstantOp"); 210 | auto Ops = Inst->getIds(Inst->getOperands()); 211 | Ops.insert(Ops.begin(), OC); 212 | return static_cast( 213 | SPIRVSpecConstantOp::create(OpSpecConstantOp, Inst->getType(), 214 | Inst->getId(), Ops, nullptr, Inst->getModule())); 215 | } 216 | 217 | SPIRVInstruction * 218 | createInstFromSpecConstantOp(SPIRVSpecConstantOp *Inst) { 219 | assert(Inst->getOpCode() == OpSpecConstantOp && 220 | "Not OpSpecConstantOp"); 221 | auto Ops = Inst->getOpWords(); 222 | auto OC = static_cast(Ops[0]); 223 | assert (isSpecConstantOpAllowedOp(OC) && 224 | "Op code not allowed for OpSpecConstantOp"); 225 | Ops.erase(Ops.begin(), Ops.begin() + 1); 226 | return SPIRVInstTemplateBase::create(OC, Inst->getType(), 227 | Inst->getId(), Ops, nullptr, Inst->getModule()); 228 | } 229 | 230 | } 231 | 232 | 233 | -------------------------------------------------------------------------------- /InstructionsOCL.td: -------------------------------------------------------------------------------- 1 | //===-- InstructionsOCL.td - SPIRV Core Instructions -------*- tablegen -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // File contains section the instructions from the OpenCL instruction set 10 | //===----------------------------------------------------------------------===// 11 | 12 | let InstructionSet = instset_OpenCL in { 13 | 14 | let InstClass = 1 in { 15 | 16 | def inst_ocl_acos : ExtInstFPUnary<0>; 17 | def inst_ocl_acosh : ExtInstFPUnary<1>; 18 | def inst_ocl_acospi : ExtInstFPUnary<2>; 19 | 20 | def inst_ocl_asin : ExtInstFPUnary<3>; 21 | def inst_ocl_asinh : ExtInstFPUnary<4>; 22 | def inst_ocl_asinpi : ExtInstFPUnary<5>; 23 | 24 | def inst_ocl_atan : ExtInstFPUnary<6>; 25 | def inst_ocl_atan2 : ExtInstFPBinary<7>; 26 | def inst_ocl_atanh : ExtInstFPUnary<8>; 27 | def inst_ocl_atanpi : ExtInstFPUnary<9>; 28 | def inst_ocl_atan2pi : ExtInstFPBinary<10>; 29 | 30 | def inst_ocl_cbrt : ExtInstFPUnary<11>; 31 | def inst_ocl_ceil : ExtInstFPUnary<12>; 32 | def inst_ocl_copysign : ExtInstFPBinary<13>; 33 | 34 | def inst_ocl_cos : ExtInstFPUnary<14>; 35 | def inst_ocl_cosh : ExtInstFPUnary<15>; 36 | def inst_ocl_cospi : ExtInstFPUnary<16>; 37 | 38 | def inst_ocl_erfc : ExtInstFPUnary<17>; 39 | def inst_ocl_erf : ExtInstFPUnary<18>; 40 | 41 | def inst_ocl_exp : ExtInstFPUnary<19>; 42 | def inst_ocl_exp2 : ExtInstFPUnary<20>; 43 | def inst_ocl_exp10 : ExtInstFPUnary<21>; 44 | def inst_ocl_expm1 : ExtInstFPUnary<22>; 45 | 46 | def inst_ocl_fabs : ExtInstFPUnary<23>; 47 | def inst_ocl_fdim : ExtInstFPBinary<24>; 48 | def inst_ocl_floor : ExtInstFPUnary<25>; 49 | def inst_ocl_floor : ExtInstFPTrinary<26>; 50 | def inst_ocl_fmax : ExtInstFPBinary<27>; 51 | def inst_ocl_fmin : ExtInstFPBinary<28>; 52 | def inst_ocl_fmod : ExtInstFPBinary<29>; 53 | 54 | def inst_ocl_fract : ExtInstFP2ArgReturn<30>; 55 | def inst_ocl_frexp : ExtInstFP2ArgReturn<31>; 56 | 57 | def inst_ocl_hypot : ExtInstFPBinary<32>; 58 | 59 | def inst_ocl_ilogb : ExtInstFPtoI32<33>; 60 | 61 | def inst_ocl_ldexp : ExtInstFPArgFPInt32<34>; 62 | 63 | def inst_ocl_lgamma : ExtInstFPUnary<35>; 64 | def inst_ocl_lgammar : ExtInstFP2ArgReturn<36>; 65 | 66 | def inst_ocl_log : ExtInstFPUnary<37>; 67 | def inst_ocl_log2 : ExtInstFPUnary<38>; 68 | def inst_ocl_log10 : ExtInstFPUnary<39>; 69 | def inst_ocl_log1p : ExtInstFPUnary<40>; 70 | def inst_ocl_logb : ExtInstFPUnary<41>; 71 | 72 | def inst_ocl_mad : ExtInstFPTrinary<42>; 73 | 74 | def inst_ocl_maxmag : ExtInstFPBinary<43>; 75 | def inst_ocl_minmag : ExtInstFPBinary<44>; 76 | 77 | def inst_ocl_modf : ExtInstFP2ArgReturn<45>; 78 | 79 | def inst_ocl_nan : ExtInstI32toFP<46>; 80 | 81 | def inst_ocl_nextafter: ExtInstFPBinary<47>; 82 | 83 | def inst_ocl_pow : ExtInstFPBinary<48>; 84 | def inst_ocl_pown : ExtInstFPArgFPInt32<49>; 85 | def inst_ocl_powr : ExtInstFPBinary<50>; 86 | 87 | def inst_ocl_remainder: ExtInstFPBinary<51>; 88 | def inst_ocl_remquo : ExtInstFP2BinaryArgReturn<52>; 89 | def inst_ocl rint : ExtInstFPtoI32<53>; 90 | 91 | def inst_ocl_rootn : ExtInstFPArgFPInt32<54>; 92 | def inst_ocl_round : ExtInstFPUnary<55>; 93 | def inst_ocl_rsqrt : ExtInstFPUnary<56>; 94 | 95 | def inst_ocl_sin : ExtInstFPUnary<57>; 96 | def inst_ocl_sincos : ExtInstFP2ArgReturn<58>; 97 | def inst_ocl_sinh : ExtInstFPUnary<59>; 98 | def inst_ocl_sinpi : ExtInstFPUnary<60>; 99 | 100 | def inst_ocl_sqrt : ExtInstFPUnary<61>; 101 | 102 | def inst_ocl_tan : ExtInstFPUnary<62>; 103 | def inst_ocl_tanh : ExtInstFPUnary<63>; 104 | def inst_ocl_tanpi : ExtInstFPUnary<64>; 105 | 106 | def inst_ocl_tgamma : ExtInstFPUnary<65>; 107 | def inst_ocl_trunc : ExtInstFPUnary<66>; 108 | 109 | //FIXME float32 only 110 | def inst_ocl_half_cos : ExtInstFPUnary<67>; 111 | def inst_ocl_half_divide: ExtInstFPBinary<68>; 112 | def inst_ocl_half_exp : ExtInstFPUnary<69>; 113 | def inst_ocl_half_exp2 : ExtInstFPUnary<70>; 114 | def inst_ocl_half_exp10: ExtInstFPUnary<71>; 115 | def inst_ocl_half_log : ExtInstFPUnary<72>; 116 | def inst_ocl_half_log2 : ExtInstFPUnary<73>; 117 | def inst_ocl_half_log10: ExtInstFPUnary<74>; 118 | def inst_ocl_half_powr : ExtInstFPBinary<75>; 119 | def inst_ocl_half_recip : ExtInstFPUnary<76>; 120 | def inst_ocl_half_rsqrt : ExtInstFPUnary<77>; 121 | def inst_ocl_half_sin : ExtInstFPUnary<78>; 122 | def inst_ocl_half_sqrt : ExtInstFPUnary<79>; 123 | def inst_ocl_half_tan : ExtInstFPUnary<80>; 124 | 125 | def inst_ocl_native_cos : ExtInstFPUnary<81>; 126 | def inst_ocl_native_divide: ExtInstFPBinary<82>; 127 | def inst_ocl_native_exp : ExtInstFPUnary<83>; 128 | def inst_ocl_native_exp2 : ExtInstFPUnary<84>; 129 | def inst_ocl_native_exp10: ExtInstFPUnary<85>; 130 | def inst_ocl_native_log : ExtInstFPUnary<86>; 131 | def inst_ocl_native_log2 : ExtInstFPUnary<87>; 132 | def inst_ocl_native_log10: ExtInstFPUnary<88>; 133 | def inst_ocl_native_powr : ExtInstFPBinary<89>; 134 | def inst_ocl_native_recip : ExtInstFPUnary<90>; 135 | def inst_ocl_native_rsqrt : ExtInstFPUnary<91>; 136 | def inst_ocl_native_sin : ExtInstFPUnary<92>; 137 | def inst_ocl_native_sqrt : ExtInstFPUnary<93>; 138 | def inst_ocl_native_tan : ExtInstFPUnary<94>; 139 | } 140 | let InstClass = 2 in { 141 | def inst_ocl_abs_s : ExtInstIntUnary<141>; 142 | def inst_ocl_absdiff_s : ExtInstIntBinary<142>; 143 | def inst_ocl_addsat_s : ExtInstIntBinary<143>; 144 | def inst_ocl_addsat_u : ExtInstIntBinary<144>; 145 | def inst_ocl_hadd_s : ExtInstIntBinary<145>; 146 | def inst_ocl_hadd_u : ExtInstIntBinary<146>; 147 | def inst_ocl_rhadd_s : ExtInstIntBinary<147>; 148 | def inst_ocl_rhadd_u : ExtInstIntBinary<148>; 149 | def inst_ocl_clamp_s : ExtInstIntBinary<149>; 150 | def inst_ocl_clamp_u : ExtInstIntBinary<150>; 151 | 152 | def inst_ocl_clz : ExtInstIntUnary<151>; 153 | def inst_ocl_ctz : ExtInstIntUnary<152>; 154 | 155 | def inst_ocl_madhi_s : ExtInstIntTrinary<153>; 156 | def inst_ocl_mad_sat_u : ExtInstIntTrinary<154>; 157 | def inst_ocl_mad_sat_s : ExtInstIntTrinary<155>; 158 | 159 | def inst_ocl_max_s : ExtInstIntBinary<156>; 160 | def inst_ocl_max_u : ExtInstIntBinary<157>; 161 | def inst_ocl_min_s : ExtInstIntBinary<158>; 162 | def inst_ocl_min_u : ExtInstIntBinary<159>; 163 | 164 | def inst_ocl_mulhi_s : ExtInstIntBinary<160>; 165 | 166 | def inst_ocl_rotate : ExtInstIntBinary<161>; 167 | 168 | def inst_ocl_subsat_s : ExtInstIntBinary<162>; 169 | def inst_ocl_subsat_u : ExtInstIntBinary<163>; 170 | 171 | // FIXME: these are int_(half_int_t,half_int_t) 172 | def inst_ocl_upsample_u : ExtInstIntBinary<164>; 173 | def inst_ocl_upsample_s : ExtInstIntBinary<165>; 174 | 175 | def inst_ocl_popcount : ExtInstIntUnary<166>; 176 | 177 | def inst_ocl_mad24_s : ExtInstIntTrinary<167>; 178 | def inst_ocl_mad24_u : ExtInstIntTrinary<168>; 179 | def inst_ocl_mul24_s : ExtInstIntBinary<169>; 180 | def inst_ocl_mul24_u : ExtInstIntBinary<170>; 181 | 182 | def inst_ocl_abs_u : ExtInstIntUnary<201>; 183 | def inst_ocl_absdiff_u : ExtInstIntBinary<202>; 184 | def inst_ocl_mulhi_u : ExtInstIntBinary<203>; 185 | def inst_ocl_madhi_u : ExtInstIntBinary<204>; 186 | } 187 | 188 | let InstClass = 3 in { 189 | def inst_ocl_fclamp : ExtInstFPTrinary<95>; 190 | def inst_ocl_degrees : ExtInstFPUnary<96>; 191 | 192 | def inst_ocl_fmax_common : ExtInstFPBinary<97>; 193 | def inst_ocl_fmin_common : ExtInstFPBinary<98>; 194 | 195 | def inst_ocl_mix : ExtInstFPTrinary<99>; 196 | def inst_ocl_radians : ExtInstFPUnary<100>; 197 | def inst_ocl_step : ExtInstFPUnary<101>; 198 | def inst_ocl_step_smooth : ExtInstFPBinary<102>; 199 | def inst_ocl_sign : ExtInstFPUnary<103>; 200 | } 201 | 202 | // FIXME: these take vector{3,4}f 203 | let InstClass = 4 in { 204 | 205 | def inst_ocl_cross : ExtInstFPBinary<104>; 206 | 207 | def inst_ocl_distance : ExtInstFPBinary<105>; 208 | def inst_ocl_length : ExtInstFPUnary<106>; 209 | def inst_ocl_normalise : ExtInstFPUnary<107>; 210 | 211 | def inst_ocl_distance_fast : ExtInstFPBinary<108>; 212 | def inst_ocl_length_fast : ExtInstFPUnary<109>; 213 | def inst_ocl_normalise_fast : ExtInstFPUnary<110>; 214 | } 215 | 216 | let InstClass = 5 in { 217 | def inst_ocl_bitselect : ExtInstAnyTrinary<186>; 218 | def inst_ocl_select : ExtInstAnyTrinary<187>; 219 | } 220 | 221 | } 222 | 223 | 224 | 225 | -------------------------------------------------------------------------------- /Operands.td: -------------------------------------------------------------------------------- 1 | //===-- Operands.td - SPIRV Operand formats ----------------*- tablegen -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // Contains "operand type" definitions for the instruction format. 10 | //===----------------------------------------------------------------------===// 11 | 12 | // Represents an operand to a SPIRVInstruction 13 | class Operand { 14 | 15 | // Depending on the value of tag 16 | // tag = 1, type = the type of the ID 17 | // tag = 2, 18 | // type = 1, Int immidiate 19 | // type = 2, String immidiate 20 | // type = 3, OpCode immidiate e.g. ExtInst 21 | // tag = 3, type = section 3.${type} of the spec values of 2-31. 22 | // union { 23 | bits<8> enum_imm_type = 0; 24 | Type type_type; 25 | // } 26 | // 0 = invalid 27 | // 1 = ID 28 | // 2 = imm 29 | // 3 = enum 30 | bit<2> tag = 0; 31 | 32 | // 0 = Type 33 | // 1 = Var 34 | // 2 = Const 35 | // 3 = Sepc Const 36 | bits<2> type_qual = 0; 37 | 38 | // 0 = None/Scalar - scalar type 39 | // 1 = Aliases - exist for this type 40 | // 2 = Pointer - a pointer to 41 | // 3 = VecScal - vector of, or scalar or 42 | // 4 = Vector - (only) vector of 43 | // 5 = Matrix 44 | // 6 = PointerVector 45 | // 7 = Array 46 | // 8 = Runtime Array 47 | // 9 = {VecScal,VecScal} 48 | bits<4> type_ext = 0; 49 | 50 | } 51 | //Invalid 52 | def oper_Invalid : Operand { 53 | let tag = 0; 54 | } 55 | // { 56 | // Enums 57 | class EnumOperand val> { 58 | let tag = 3; 59 | let type = val; 60 | } 61 | 62 | def oper_SourceLanguage : EnumOperand<2>; 63 | def oper_ExecutionModel : EnumOperand<3>; 64 | def oper_AddressingModel : EnumOperand<4>; 65 | def oper_MemoryModel : EnumOperand<5>; 66 | def oper_ExecutionMode : EnumOperand<6>; 67 | def oper_StorageClass : EnumOperand<7>; 68 | def oper_Dim : EnumOperand<8>; 69 | def oper_SamplerAddressingMode : EnumOperand<9>; 70 | def oper_SamplerFilterMode : EnumOperand<10>; 71 | def oper_ImageFormat : EnumOperand<11>; 72 | def oper_ImageChannelOrder : EnumOperand<12>; 73 | def oper_ImageChannelDataType : EnumOperand<13>; 74 | def oper_ImageOperands : EnumOperand<14>; 75 | def oper_FPFastMathMode : EnumOperand<15>; 76 | def oper_FPRoundingMode : EnumOperand<16>; 77 | def oper_LinkageType : EnumOperand<17>; 78 | def oper_AccessQualifier : EnumOperand<18>; 79 | def oper_FunctionParameterAttribute : EnumOperand<19>; 80 | def oper_Decoration : EnumOperand<20>; 81 | def oper_BuiltIn : EnumOperand<21>; 82 | def oper_SelectionControl : EnumOperand<22>; 83 | def oper_LoopControl : EnumOperand<23>; 84 | def oper_FunctionControl : EnumOperand<24>; 85 | def oper_MemorySemantics : EnumOperand<25>; 86 | def oper_MemoryAccess : EnumOperand<26>; 87 | def oper_Scope : EnumOperand<27>; 88 | def oper_GroupOperation : EnumOperand<28>; 89 | def oper_KernelEnqueueFlags : EnumOperand<29>; 90 | def oper_KernelProfilingInfo : EnumOperand<30>; 91 | def oper_Capability : EnumOperand<31>; 92 | // } 93 | // Immidiates 94 | class ImmidiateOperand val> { 95 | let tag = 2; 96 | let type = val; 97 | } 98 | def oper_ImmString : ImmidiateOperand<0>; 99 | def oper_ImmInt32 : ImmidiateOperand<1>; 100 | def oper_ImmOpCode : ImmidiateOperand<2>; 101 | 102 | class IdOperand { 103 | let tag = 1; 104 | } 105 | // Operand that is any , wildcard. 106 | // Should only really be used in debug insts. 107 | def oper_AnyId : IdOperand { let type = 0; }; 108 | 109 | class Type val> { 110 | bits<8> Val = val; 111 | } 112 | def ty_Invalid : Type<0>; 113 | def ty_Any : Type<1>; 114 | def ty_Void : Type<2>; 115 | // Fundamental types 116 | def ty_Bool : Type<3>; 117 | def ty_Int : Type<4>; 118 | def ty_Float : Type<5>; 119 | // Specialised Fundamental types 120 | def ty_Int32 : Type<6>; 121 | def ty_Float16 : Type<7>; 122 | def ty_Float32 : Type<8>; // For OpenCL's half_* functions. 123 | def ty_Sint : Type<9>; 124 | def ty_Uint : Type<10>; 125 | // Homogeneous Composite are in Operand.type_ext 126 | // Heterogeneous Composite 127 | def ty_Struct : Type<11>; 128 | def ty_Function : Type<12>; 129 | // Opaque 130 | def ty_Forward : Type<13>; // A foward declared type. 131 | def ty_Opaque : Type<14>; 132 | // Opaque Image types 133 | def ty_Image : Type<15>; 134 | def ty_Sampler : Type<16>; 135 | def ty_SampledImage : Type<17>; 136 | // Opaque Pipe types. 137 | def ty_Pipe : Type<18>; 138 | def ty_PipeStorage : Type<19>; // Spec says this is a type not a storage class. 139 | def ty_ReserveId : Type<20>; // Really an int, but carries semantic meaning 140 | // Opaque Host types. 141 | def ty_Event : Type<21>; 142 | def ty_DeviceEvent : Type<22>; 143 | def ty_Queue : Type<23>; 144 | // Opaque other 145 | def ty_NamedBarrier : Type<24>; 146 | // Pseudo types 147 | def ty_InstructionSet : Type<25>; // not to be confused with instset_* 148 | def ty_Label : Type<26>; 149 | def ty_String : Type<27>; 150 | def ty_DecorationGroup: Type<25>; 151 | // Specialised Heterogeneous Composite 152 | def ty_NDRange : TYpe<26>; 153 | 154 | // The meta type is not a pseudo or opqaue type and can have constant instances 155 | // must be able to declare Var and {Spec }Consts. 156 | multiclass TypeVarConst val> { 157 | let type = val in { 158 | def Type : IdOperand { let type_qual = 0; } 159 | def Var : IdOperand { let type_qual = 1; } 160 | def Constant : IdOperand { let type_qual = 2; } 161 | def SepcConstant : IdOperand { let type_qual = 3; } 162 | } 163 | } 164 | // The meta type is a valid type and can not have constant instances 165 | multiclass TypeVar val> { 166 | let type = val in { 167 | def Type : IdOperand { let type_qual = 0; } 168 | def Var : IdOperand { let type_qual = 1; } 169 | } 170 | } 171 | 172 | } 173 | // The meta type is a not valid type 174 | // i.e. no corresponding OpTypeFoo instructions 175 | // the "constructing" operation is OpFoo instead. 176 | multiclass Var val> { 177 | def Var : IdOperand { let type = val; let type_qual = 1; } 178 | } 179 | // There are no valid instances of this type e.g. void. 180 | multiclass Type val> { 181 | def Type : IdOperand { let type = val; let type_qual = 0; } 182 | } 183 | // Scalar / VecScal : TypeVarConst 184 | multiclass SVS_TVC { 185 | defm Scalar : TypeVarConst; 186 | defm VecScal : TypeVarConst { let type_ext = 3; } 187 | } 188 | 189 | def oper_Any : TypeVarConst; 190 | def oper_AnyPointer : TypeVar { let type_ext = 2; }; 191 | def oper_AnyVecScal : TypeVarConst { let type_ext = 1; }; 192 | def oper_AnyVector : TypeVarConst { let type_ext = 4; }; 193 | def oper_AnyPointerVecScal : TypeVarConst { let type_ext = 6; }; 194 | def oper_AnyMatrix : TypeVarConst { let type_ext = 5; }; 195 | def oper_Void : Type; 196 | def oper_VoidPointer : TypeVar { let type_ext = 2; }; 197 | // Fundamental types 198 | def oper_Bool : SVS_TVC; 199 | def oper_Int : SVS_TVC; 200 | def oper_IntPointer : TypeVar { let type_ext= 2; }; 201 | def oper_Float : SVS_TVC; 202 | def oper_FloatMatrix : TypeVarConst { let type_ext = 5; }; 203 | def oper_FloatVector : TypeVarConst { let type_ext = 4; }; 204 | // Specialised Fundamental types 205 | def oper_Int32 : TypeVarConst; 206 | def oper_Sint : SVS_TVC; 207 | def oper_SintArithExt : TypeVarConst { let type_ext = 9; }; 208 | def oper_Uint : SVS_TVC; 209 | def oper_IntArithExt : TypeVarConst { let type_ext = 9; }; 210 | def oper_Float16 : SVS_TVC; 211 | def oper_Float32 : SVS_TVC; 212 | // Heterogeneous Composite 213 | def oper_Struct : TypeVarConst; 214 | def oper_Function : TypeVar; 215 | // Opaque 216 | def oper_ForwardPointer : TypeVar { let type_ext= 2; }; 217 | def oper_Opaque : Type; 218 | // Opaque Image 219 | def oper_Image : TypeVar; 220 | def oper_Sampler : TypeVarConst; 221 | def oper_SampledImage : TypeVarConst; 222 | // Opaque Host 223 | def oper_Event : TypeVar; 224 | def oper_EventPointer : TypeVar { let type_ext= 2; }; 225 | def oper_DeviceEvent : TypeVar; 226 | def oper_DeviceEventPointer : TypeVar { let type_ext= 2; }; 227 | def oper_Queue : TypeVar; 228 | // Opaque Pipe 229 | def oper_Pipe : TypeVar; 230 | def oper_PipeStorage : TypeVar; 231 | def oper_ReserveId : TypeVar; 232 | // Opaque other 233 | def oper_NamedBarrier : TypeVar; 234 | // Pseudo 235 | def oper_String : Var; 236 | def oper_InstructionSet : Var; 237 | def oper_Label : Var; 238 | def oper_DecorationGroup : Var; 239 | // Specialised Heterogeneous Composite 240 | def oper_NDRange : TypeVarConst; 241 | -------------------------------------------------------------------------------- /libSPIRV/SPIRVOpCodeEnum.h: -------------------------------------------------------------------------------- 1 | _SPIRV_OP(Nop, 0) 2 | _SPIRV_OP(Undef, 1) 3 | _SPIRV_OP(SourceContinued, 2) 4 | _SPIRV_OP(Source, 3) 5 | _SPIRV_OP(SourceExtension, 4) 6 | _SPIRV_OP(Name, 5) 7 | _SPIRV_OP(MemberName, 6) 8 | _SPIRV_OP(String, 7) 9 | _SPIRV_OP(Line, 8) 10 | _SPIRV_OP(Extension, 10) 11 | _SPIRV_OP(ExtInstImport, 11) 12 | _SPIRV_OP(ExtInst, 12) 13 | _SPIRV_OP(MemoryModel, 14) 14 | _SPIRV_OP(EntryPoint, 15) 15 | _SPIRV_OP(ExecutionMode, 16) 16 | _SPIRV_OP(Capability, 17) 17 | _SPIRV_OP(TypeVoid, 19) 18 | _SPIRV_OP(TypeBool, 20) 19 | _SPIRV_OP(TypeInt, 21) 20 | _SPIRV_OP(TypeFloat, 22) 21 | _SPIRV_OP(TypeVector, 23) 22 | _SPIRV_OP(TypeMatrix, 24) 23 | _SPIRV_OP(TypeImage, 25) 24 | _SPIRV_OP(TypeSampler, 26) 25 | _SPIRV_OP(TypeSampledImage, 27) 26 | _SPIRV_OP(TypeArray, 28) 27 | _SPIRV_OP(TypeRuntimeArray, 29) 28 | _SPIRV_OP(TypeStruct, 30) 29 | _SPIRV_OP(TypeOpaque, 31) 30 | _SPIRV_OP(TypePointer, 32) 31 | _SPIRV_OP(TypeFunction, 33) 32 | _SPIRV_OP(TypeEvent, 34) 33 | _SPIRV_OP(TypeDeviceEvent, 35) 34 | _SPIRV_OP(TypeReserveId, 36) 35 | _SPIRV_OP(TypeQueue, 37) 36 | _SPIRV_OP(TypePipe, 38) 37 | _SPIRV_OP(TypeForwardPointer, 39) 38 | _SPIRV_OP(ConstantTrue, 41) 39 | _SPIRV_OP(ConstantFalse, 42) 40 | _SPIRV_OP(Constant, 43) 41 | _SPIRV_OP(ConstantComposite, 44) 42 | _SPIRV_OP(ConstantSampler, 45) 43 | _SPIRV_OP(ConstantNull, 46) 44 | _SPIRV_OP(SpecConstantTrue, 48) 45 | _SPIRV_OP(SpecConstantFalse, 49) 46 | _SPIRV_OP(SpecConstant, 50) 47 | _SPIRV_OP(SpecConstantComposite, 51) 48 | _SPIRV_OP(SpecConstantOp, 52) 49 | _SPIRV_OP(Function, 54) 50 | _SPIRV_OP(FunctionParameter, 55) 51 | _SPIRV_OP(FunctionEnd, 56) 52 | _SPIRV_OP(FunctionCall, 57) 53 | _SPIRV_OP(Variable, 59) 54 | _SPIRV_OP(ImageTexelPointer, 60) 55 | _SPIRV_OP(Load, 61) 56 | _SPIRV_OP(Store, 62) 57 | _SPIRV_OP(CopyMemory, 63) 58 | _SPIRV_OP(CopyMemorySized, 64) 59 | _SPIRV_OP(AccessChain, 65) 60 | _SPIRV_OP(InBoundsAccessChain, 66) 61 | _SPIRV_OP(PtrAccessChain, 67) 62 | _SPIRV_OP(ArrayLength, 68) 63 | _SPIRV_OP(GenericPtrMemSemantics, 69) 64 | _SPIRV_OP(InBoundsPtrAccessChain, 70) 65 | _SPIRV_OP(Decorate, 71) 66 | _SPIRV_OP(MemberDecorate, 72) 67 | _SPIRV_OP(DecorationGroup, 73) 68 | _SPIRV_OP(GroupDecorate, 74) 69 | _SPIRV_OP(GroupMemberDecorate, 75) 70 | _SPIRV_OP(VectorExtractDynamic, 77) 71 | _SPIRV_OP(VectorInsertDynamic, 78) 72 | _SPIRV_OP(VectorShuffle, 79) 73 | _SPIRV_OP(CompositeConstruct, 80) 74 | _SPIRV_OP(CompositeExtract, 81) 75 | _SPIRV_OP(CompositeInsert, 82) 76 | _SPIRV_OP(CopyObject, 83) 77 | _SPIRV_OP(Transpose, 84) 78 | _SPIRV_OP(SampledImage, 86) 79 | _SPIRV_OP(ImageSampleImplicitLod, 87) 80 | _SPIRV_OP(ImageSampleExplicitLod, 88) 81 | _SPIRV_OP(ImageSampleDrefImplicitLod, 89) 82 | _SPIRV_OP(ImageSampleDrefExplicitLod, 90) 83 | _SPIRV_OP(ImageSampleProjImplicitLod, 91) 84 | _SPIRV_OP(ImageSampleProjExplicitLod, 92) 85 | _SPIRV_OP(ImageSampleProjDrefImplicitLod, 93) 86 | _SPIRV_OP(ImageSampleProjDrefExplicitLod, 94) 87 | _SPIRV_OP(ImageFetch, 95) 88 | _SPIRV_OP(ImageGather, 96) 89 | _SPIRV_OP(ImageDrefGather, 97) 90 | _SPIRV_OP(ImageRead, 98) 91 | _SPIRV_OP(ImageWrite, 99) 92 | _SPIRV_OP(Image, 100) 93 | _SPIRV_OP(ImageQueryFormat, 101) 94 | _SPIRV_OP(ImageQueryOrder, 102) 95 | _SPIRV_OP(ImageQuerySizeLod, 103) 96 | _SPIRV_OP(ImageQuerySize, 104) 97 | _SPIRV_OP(ImageQueryLod, 105) 98 | _SPIRV_OP(ImageQueryLevels, 106) 99 | _SPIRV_OP(ImageQuerySamples, 107) 100 | _SPIRV_OP(ConvertFToU, 109) 101 | _SPIRV_OP(ConvertFToS, 110) 102 | _SPIRV_OP(ConvertSToF, 111) 103 | _SPIRV_OP(ConvertUToF, 112) 104 | _SPIRV_OP(UConvert, 113) 105 | _SPIRV_OP(SConvert, 114) 106 | _SPIRV_OP(FConvert, 115) 107 | _SPIRV_OP(QuantizeToF16, 116) 108 | _SPIRV_OP(ConvertPtrToU, 117) 109 | _SPIRV_OP(SatConvertSToU, 118) 110 | _SPIRV_OP(SatConvertUToS, 119) 111 | _SPIRV_OP(ConvertUToPtr, 120) 112 | _SPIRV_OP(PtrCastToGeneric, 121) 113 | _SPIRV_OP(GenericCastToPtr, 122) 114 | _SPIRV_OP(GenericCastToPtrExplicit, 123) 115 | _SPIRV_OP(Bitcast, 124) 116 | _SPIRV_OP(SNegate, 126) 117 | _SPIRV_OP(FNegate, 127) 118 | _SPIRV_OP(IAdd, 128) 119 | _SPIRV_OP(FAdd, 129) 120 | _SPIRV_OP(ISub, 130) 121 | _SPIRV_OP(FSub, 131) 122 | _SPIRV_OP(IMul, 132) 123 | _SPIRV_OP(FMul, 133) 124 | _SPIRV_OP(UDiv, 134) 125 | _SPIRV_OP(SDiv, 135) 126 | _SPIRV_OP(FDiv, 136) 127 | _SPIRV_OP(UMod, 137) 128 | _SPIRV_OP(SRem, 138) 129 | _SPIRV_OP(SMod, 139) 130 | _SPIRV_OP(FRem, 140) 131 | _SPIRV_OP(FMod, 141) 132 | _SPIRV_OP(VectorTimesScalar, 142) 133 | _SPIRV_OP(MatrixTimesScalar, 143) 134 | _SPIRV_OP(VectorTimesMatrix, 144) 135 | _SPIRV_OP(MatrixTimesVector, 145) 136 | _SPIRV_OP(MatrixTimesMatrix, 146) 137 | _SPIRV_OP(OuterProduct, 147) 138 | _SPIRV_OP(Dot, 148) 139 | _SPIRV_OP(IAddCarry, 149) 140 | _SPIRV_OP(ISubBorrow, 150) 141 | _SPIRV_OP(UMulExtended, 151) 142 | _SPIRV_OP(SMulExtended, 152) 143 | _SPIRV_OP(Any, 154) 144 | _SPIRV_OP(All, 155) 145 | _SPIRV_OP(IsNan, 156) 146 | _SPIRV_OP(IsInf, 157) 147 | _SPIRV_OP(IsFinite, 158) 148 | _SPIRV_OP(IsNormal, 159) 149 | _SPIRV_OP(SignBitSet, 160) 150 | _SPIRV_OP(LessOrGreater, 161) 151 | _SPIRV_OP(Ordered, 162) 152 | _SPIRV_OP(Unordered, 163) 153 | _SPIRV_OP(LogicalEqual, 164) 154 | _SPIRV_OP(LogicalNotEqual, 165) 155 | _SPIRV_OP(LogicalOr, 166) 156 | _SPIRV_OP(LogicalAnd, 167) 157 | _SPIRV_OP(LogicalNot, 168) 158 | _SPIRV_OP(Select, 169) 159 | _SPIRV_OP(IEqual, 170) 160 | _SPIRV_OP(INotEqual, 171) 161 | _SPIRV_OP(UGreaterThan, 172) 162 | _SPIRV_OP(SGreaterThan, 173) 163 | _SPIRV_OP(UGreaterThanEqual, 174) 164 | _SPIRV_OP(SGreaterThanEqual, 175) 165 | _SPIRV_OP(ULessThan, 176) 166 | _SPIRV_OP(SLessThan, 177) 167 | _SPIRV_OP(ULessThanEqual, 178) 168 | _SPIRV_OP(SLessThanEqual, 179) 169 | _SPIRV_OP(FOrdEqual, 180) 170 | _SPIRV_OP(FUnordEqual, 181) 171 | _SPIRV_OP(FOrdNotEqual, 182) 172 | _SPIRV_OP(FUnordNotEqual, 183) 173 | _SPIRV_OP(FOrdLessThan, 184) 174 | _SPIRV_OP(FUnordLessThan, 185) 175 | _SPIRV_OP(FOrdGreaterThan, 186) 176 | _SPIRV_OP(FUnordGreaterThan, 187) 177 | _SPIRV_OP(FOrdLessThanEqual, 188) 178 | _SPIRV_OP(FUnordLessThanEqual, 189) 179 | _SPIRV_OP(FOrdGreaterThanEqual, 190) 180 | _SPIRV_OP(FUnordGreaterThanEqual, 191) 181 | _SPIRV_OP(ShiftRightLogical, 194) 182 | _SPIRV_OP(ShiftRightArithmetic, 195) 183 | _SPIRV_OP(ShiftLeftLogical, 196) 184 | _SPIRV_OP(BitwiseOr, 197) 185 | _SPIRV_OP(BitwiseXor, 198) 186 | _SPIRV_OP(BitwiseAnd, 199) 187 | _SPIRV_OP(Not, 200) 188 | _SPIRV_OP(BitFieldInsert, 201) 189 | _SPIRV_OP(BitFieldSExtract, 202) 190 | _SPIRV_OP(BitFieldUExtract, 203) 191 | _SPIRV_OP(BitReverse, 204) 192 | _SPIRV_OP(BitCount, 205) 193 | _SPIRV_OP(DPdx, 207) 194 | _SPIRV_OP(DPdy, 208) 195 | _SPIRV_OP(Fwidth, 209) 196 | _SPIRV_OP(DPdxFine, 210) 197 | _SPIRV_OP(DPdyFine, 211) 198 | _SPIRV_OP(FwidthFine, 212) 199 | _SPIRV_OP(DPdxCoarse, 213) 200 | _SPIRV_OP(DPdyCoarse, 214) 201 | _SPIRV_OP(FwidthCoarse, 215) 202 | _SPIRV_OP(EmitVertex, 218) 203 | _SPIRV_OP(EndPrimitive, 219) 204 | _SPIRV_OP(EmitStreamVertex, 220) 205 | _SPIRV_OP(EndStreamPrimitive, 221) 206 | _SPIRV_OP(ControlBarrier, 224) 207 | _SPIRV_OP(MemoryBarrier, 225) 208 | _SPIRV_OP(AtomicLoad, 227) 209 | _SPIRV_OP(AtomicStore, 228) 210 | _SPIRV_OP(AtomicExchange, 229) 211 | _SPIRV_OP(AtomicCompareExchange, 230) 212 | _SPIRV_OP(AtomicCompareExchangeWeak, 231) 213 | _SPIRV_OP(AtomicIIncrement, 232) 214 | _SPIRV_OP(AtomicIDecrement, 233) 215 | _SPIRV_OP(AtomicIAdd, 234) 216 | _SPIRV_OP(AtomicISub, 235) 217 | _SPIRV_OP(AtomicSMin, 236) 218 | _SPIRV_OP(AtomicUMin, 237) 219 | _SPIRV_OP(AtomicSMax, 238) 220 | _SPIRV_OP(AtomicUMax, 239) 221 | _SPIRV_OP(AtomicAnd, 240) 222 | _SPIRV_OP(AtomicOr, 241) 223 | _SPIRV_OP(AtomicXor, 242) 224 | _SPIRV_OP(Phi, 245) 225 | _SPIRV_OP(LoopMerge, 246) 226 | _SPIRV_OP(SelectionMerge, 247) 227 | _SPIRV_OP(Label, 248) 228 | _SPIRV_OP(Branch, 249) 229 | _SPIRV_OP(BranchConditional, 250) 230 | _SPIRV_OP(Switch, 251) 231 | _SPIRV_OP(Kill, 252) 232 | _SPIRV_OP(Return, 253) 233 | _SPIRV_OP(ReturnValue, 254) 234 | _SPIRV_OP(Unreachable, 255) 235 | _SPIRV_OP(LifetimeStart, 256) 236 | _SPIRV_OP(LifetimeStop, 257) 237 | _SPIRV_OP(GroupAsyncCopy, 259) 238 | _SPIRV_OP(GroupWaitEvents, 260) 239 | _SPIRV_OP(GroupAll, 261) 240 | _SPIRV_OP(GroupAny, 262) 241 | _SPIRV_OP(GroupBroadcast, 263) 242 | _SPIRV_OP(GroupIAdd, 264) 243 | _SPIRV_OP(GroupFAdd, 265) 244 | _SPIRV_OP(GroupFMin, 266) 245 | _SPIRV_OP(GroupUMin, 267) 246 | _SPIRV_OP(GroupSMin, 268) 247 | _SPIRV_OP(GroupFMax, 269) 248 | _SPIRV_OP(GroupUMax, 270) 249 | _SPIRV_OP(GroupSMax, 271) 250 | _SPIRV_OP(ReadPipe, 274) 251 | _SPIRV_OP(WritePipe, 275) 252 | _SPIRV_OP(ReservedReadPipe, 276) 253 | _SPIRV_OP(ReservedWritePipe, 277) 254 | _SPIRV_OP(ReserveReadPipePackets, 278) 255 | _SPIRV_OP(ReserveWritePipePackets, 279) 256 | _SPIRV_OP(CommitReadPipe, 280) 257 | _SPIRV_OP(CommitWritePipe, 281) 258 | _SPIRV_OP(IsValidReserveId, 282) 259 | _SPIRV_OP(GetNumPipePackets, 283) 260 | _SPIRV_OP(GetMaxPipePackets, 284) 261 | _SPIRV_OP(GroupReserveReadPipePackets, 285) 262 | _SPIRV_OP(GroupReserveWritePipePackets, 286) 263 | _SPIRV_OP(GroupCommitReadPipe, 287) 264 | _SPIRV_OP(GroupCommitWritePipe, 288) 265 | _SPIRV_OP(EnqueueMarker, 291) 266 | _SPIRV_OP(EnqueueKernel, 292) 267 | _SPIRV_OP(GetKernelNDrangeSubGroupCount, 293) 268 | _SPIRV_OP(GetKernelNDrangeMaxSubGroupSize, 294) 269 | _SPIRV_OP(GetKernelWorkGroupSize, 295) 270 | _SPIRV_OP(GetKernelPreferredWorkGroupSizeMultiple, 296) 271 | _SPIRV_OP(RetainEvent, 297) 272 | _SPIRV_OP(ReleaseEvent, 298) 273 | _SPIRV_OP(CreateUserEvent, 299) 274 | _SPIRV_OP(IsValidEvent, 300) 275 | _SPIRV_OP(SetUserEventStatus, 301) 276 | _SPIRV_OP(CaptureEventProfilingInfo, 302) 277 | _SPIRV_OP(GetDefaultQueue, 303) 278 | _SPIRV_OP(BuildNDRange, 304) 279 | _SPIRV_OP(ImageSparseSampleImplicitLod, 305) 280 | _SPIRV_OP(ImageSparseSampleExplicitLod, 306) 281 | _SPIRV_OP(ImageSparseSampleDrefImplicitLod, 307) 282 | _SPIRV_OP(ImageSparseSampleDrefExplicitLod, 308) 283 | _SPIRV_OP(ImageSparseSampleProjImplicitLod, 309) 284 | _SPIRV_OP(ImageSparseSampleProjExplicitLod, 310) 285 | _SPIRV_OP(ImageSparseSampleProjDrefImplicitLod, 311) 286 | _SPIRV_OP(ImageSparseSampleProjDrefExplicitLod, 312) 287 | _SPIRV_OP(ImageSparseFetch, 313) 288 | _SPIRV_OP(ImageSparseGather, 314) 289 | _SPIRV_OP(ImageSparseDrefGather, 315) 290 | _SPIRV_OP(ImageSparseTexelsResident, 316) 291 | _SPIRV_OP(NoLine, 317) 292 | _SPIRV_OP(AtomicFlagTestAndSet, 318) 293 | _SPIRV_OP(AtomicFlagClear, 319) 294 | _SPIRV_OP(Forward, 1024) 295 | -------------------------------------------------------------------------------- /libSPIRV/SPIRVDecorate.h: -------------------------------------------------------------------------------- 1 | //===- SPIRVDecorate.h - SPIR-V Decorations ----------------------*- C++ -*-===// 2 | // 3 | // The LLVM/SPIRV Translator 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a 11 | // copy of this software and associated documentation files (the "Software"), 12 | // to deal with the Software without restriction, including without limitation 13 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 | // and/or sell copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following conditions: 16 | // 17 | // Redistributions of source code must retain the above copyright notice, 18 | // this list of conditions and the following disclaimers. 19 | // Redistributions in binary form must reproduce the above copyright notice, 20 | // this list of conditions and the following disclaimers in the documentation 21 | // and/or other materials provided with the distribution. 22 | // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 | // contributors may be used to endorse or promote products derived from this 24 | // Software without specific prior written permission. 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 | // THE SOFTWARE. 32 | // 33 | //===----------------------------------------------------------------------===// 34 | /// \file 35 | /// 36 | /// This file defines SPIR-V decorations. 37 | /// 38 | //===----------------------------------------------------------------------===// 39 | 40 | #ifndef SPIRVDECORATE_HPP_ 41 | #define SPIRVDECORATE_HPP_ 42 | 43 | #include "SPIRVEntry.h" 44 | #include "SPIRVUtil.h" 45 | #include "SPIRVStream.h" 46 | #include 47 | #include 48 | #include 49 | 50 | namespace SPIRV{ 51 | class SPIRVDecorationGroup; 52 | class SPIRVDecorateGeneric:public SPIRVAnnotationGeneric{ 53 | public: 54 | // Complete constructor for decorations without literals 55 | SPIRVDecorateGeneric(Op OC, SPIRVWord WC, Decoration TheDec, 56 | SPIRVEntry *TheTarget); 57 | // Complete constructor for decorations with one word literal 58 | SPIRVDecorateGeneric(Op OC, SPIRVWord WC, Decoration TheDec, 59 | SPIRVEntry *TheTarget, SPIRVWord V); 60 | // Incomplete constructor 61 | SPIRVDecorateGeneric(Op OC); 62 | 63 | SPIRVWord getLiteral(size_t) const; 64 | Decoration getDecorateKind() const; 65 | size_t getLiteralCount() const; 66 | /// Compare for kind and literal only. 67 | struct Comparator { 68 | bool operator()(const SPIRVDecorateGeneric *A, const SPIRVDecorateGeneric *B) const; 69 | }; 70 | /// Compare kind, literals and target. 71 | friend bool operator==(const SPIRVDecorateGeneric &A, 72 | const SPIRVDecorateGeneric &B); 73 | 74 | SPIRVDecorationGroup* getOwner() const { 75 | return Owner; 76 | } 77 | 78 | void setOwner(SPIRVDecorationGroup* owner) { 79 | Owner = owner; 80 | } 81 | 82 | SPIRVCapVec getRequiredCapability() const { 83 | return getCapability(Dec); 84 | } 85 | 86 | protected: 87 | Decoration Dec; 88 | std::vector Literals; 89 | SPIRVDecorationGroup *Owner; // Owning decorate group 90 | }; 91 | 92 | class SPIRVDecorateSet: public std::multiset { 94 | public: 95 | typedef std::multiset BaseType; 97 | iterator insert(const value_type& Dec) { 98 | auto ER = BaseType::equal_range(Dec); 99 | for (auto I = ER.first, E = ER.second; I != E; ++I) { 100 | SPIRVDBG(spvdbgs() << "[compare decorate] " << *Dec 101 | << " vs " << **I << " : "); 102 | if (**I == *Dec) 103 | return I; 104 | SPIRVDBG(spvdbgs() << " diff\n"); 105 | } 106 | SPIRVDBG(spvdbgs() << "[add decorate] " << *Dec << '\n'); 107 | return BaseType::insert(Dec); 108 | } 109 | }; 110 | 111 | class SPIRVDecorate:public SPIRVDecorateGeneric{ 112 | public: 113 | static const Op OC = OpDecorate; 114 | static const SPIRVWord FixedWC = 3; 115 | // Complete constructor for decorations without literals 116 | SPIRVDecorate(Decoration TheDec, SPIRVEntry *TheTarget) 117 | :SPIRVDecorateGeneric(OC, 3, TheDec, TheTarget){} 118 | // Complete constructor for decorations with one word literal 119 | SPIRVDecorate(Decoration TheDec, SPIRVEntry *TheTarget, SPIRVWord V) 120 | :SPIRVDecorateGeneric(OC, 4, TheDec, TheTarget, V){} 121 | // Incomplete constructor 122 | SPIRVDecorate():SPIRVDecorateGeneric(OC){} 123 | 124 | _SPIRV_DCL_ENCDEC 125 | void setWordCount(SPIRVWord); 126 | void validate()const { 127 | SPIRVDecorateGeneric::validate(); 128 | assert(WordCount == Literals.size() + FixedWC); 129 | } 130 | 131 | }; 132 | 133 | class SPIRVDecorateLinkageAttr:public SPIRVDecorate{ 134 | public: 135 | // Complete constructor for LinkageAttributes decorations 136 | SPIRVDecorateLinkageAttr(SPIRVEntry *TheTarget, 137 | const std::string &Name, SPIRVLinkageTypeKind Kind) 138 | :SPIRVDecorate(DecorationLinkageAttributes, TheTarget) { 139 | for (auto &I:getVec(Name)) 140 | Literals.push_back(I); 141 | Literals.push_back(Kind); 142 | WordCount += Literals.size(); 143 | } 144 | // Incomplete constructor 145 | SPIRVDecorateLinkageAttr():SPIRVDecorate(){} 146 | 147 | std::string getLinkageName() const { 148 | return getString(Literals.cbegin(), Literals.cend() - 1); 149 | } 150 | SPIRVLinkageTypeKind getLinkageType() const { 151 | return (SPIRVLinkageTypeKind)Literals.back(); 152 | } 153 | 154 | static void encodeLiterals(SPIRVEncoder& Encoder, 155 | const std::vector& Literals) { 156 | #ifdef _SPIRV_SUPPORT_TEXT_FMT 157 | if(SPIRVUseTextFormat) { 158 | Encoder << getString(Literals.cbegin(), Literals.cend() - 1); 159 | Encoder.OS << " "; 160 | Encoder << (SPIRVLinkageTypeKind)Literals.back(); 161 | } else 162 | #endif 163 | Encoder << Literals; 164 | } 165 | 166 | static void decodeLiterals(SPIRVDecoder& Decoder, std::vector& Literals) { 167 | #ifdef _SPIRV_SUPPORT_TEXT_FMT 168 | if(SPIRVUseTextFormat) { 169 | std::string Name; 170 | Decoder >> Name; 171 | SPIRVLinkageTypeKind Kind; 172 | Decoder >> Kind; 173 | std::copy_n(getVec(Name).begin(), Literals.size()-1, Literals.begin()); 174 | Literals.back() = Kind; 175 | } else 176 | #endif 177 | Decoder >> Literals; 178 | } 179 | }; 180 | 181 | class SPIRVMemberDecorate:public SPIRVDecorateGeneric{ 182 | public: 183 | static const Op OC = OpMemberDecorate; 184 | static const SPIRVWord FixedWC = 4; 185 | // Complete constructor for decorations without literals 186 | SPIRVMemberDecorate(Decoration TheDec, SPIRVWord Member, SPIRVEntry *TheTarget) 187 | :SPIRVDecorateGeneric(OC, 4, TheDec, TheTarget), MemberNumber(Member){} 188 | // Complete constructor for decorations with one word literal 189 | SPIRVMemberDecorate(Decoration TheDec, SPIRVWord Member, SPIRVEntry *TheTarget, 190 | SPIRVWord V) 191 | :SPIRVDecorateGeneric(OC, 5, TheDec, TheTarget, V), MemberNumber(Member){} 192 | // Incomplete constructor 193 | SPIRVMemberDecorate():SPIRVDecorateGeneric(OC), MemberNumber(SPIRVWORD_MAX){} 194 | 195 | SPIRVWord getMemberNumber() const { return MemberNumber;} 196 | std::pair getPair() const { 197 | return std::make_pair(MemberNumber, Dec); 198 | } 199 | 200 | _SPIRV_DCL_ENCDEC 201 | void setWordCount(SPIRVWord); 202 | 203 | void validate()const { 204 | SPIRVDecorateGeneric::validate(); 205 | assert(WordCount == Literals.size() + FixedWC); 206 | } 207 | protected: 208 | SPIRVWord MemberNumber; 209 | }; 210 | 211 | class SPIRVDecorationGroup:public SPIRVEntry{ 212 | public: 213 | static const Op OC = OpDecorationGroup; 214 | static const SPIRVWord WC = 2; 215 | // Complete constructor. Does not populate Decorations. 216 | SPIRVDecorationGroup(SPIRVModule *TheModule, SPIRVId TheId) 217 | :SPIRVEntry(TheModule, WC, OC, TheId){ 218 | validate(); 219 | }; 220 | // Incomplete constructor 221 | SPIRVDecorationGroup():SPIRVEntry(OC){} 222 | void encodeAll(spv_ostream &O) const; 223 | _SPIRV_DCL_ENCDEC 224 | // Move the given decorates to the decoration group 225 | void takeDecorates(SPIRVDecorateSet &Decs) { 226 | Decorations = std::move(Decs); 227 | for (auto &I:Decorations) 228 | const_cast(I)->setOwner(this); 229 | Decs.clear(); 230 | } 231 | 232 | SPIRVDecorateSet& getDecorations() { 233 | return Decorations; 234 | } 235 | 236 | protected: 237 | SPIRVDecorateSet Decorations; 238 | void validate()const { 239 | assert(OpCode == OC); 240 | assert(WordCount == WC); 241 | } 242 | }; 243 | 244 | class SPIRVGroupDecorateGeneric:public SPIRVEntryNoIdGeneric{ 245 | public: 246 | static const SPIRVWord FixedWC = 2; 247 | // Complete constructor 248 | SPIRVGroupDecorateGeneric(Op OC, SPIRVDecorationGroup *TheGroup, 249 | const std::vector &TheTargets) 250 | :SPIRVEntryNoIdGeneric(TheGroup->getModule(), FixedWC + TheTargets.size(), 251 | OC), 252 | DecorationGroup(TheGroup), Targets(TheTargets){ 253 | } 254 | // Incomplete constructor 255 | SPIRVGroupDecorateGeneric(Op OC) 256 | :SPIRVEntryNoIdGeneric(OC), DecorationGroup(nullptr){} 257 | 258 | void setWordCount(SPIRVWord WC) { 259 | SPIRVEntryNoIdGeneric::setWordCount(WC); 260 | Targets.resize(WC - FixedWC); 261 | } 262 | virtual void decorateTargets() = 0; 263 | _SPIRV_DCL_ENCDEC 264 | protected: 265 | SPIRVDecorationGroup *DecorationGroup; 266 | std::vector Targets; 267 | }; 268 | 269 | class SPIRVGroupDecorate:public SPIRVGroupDecorateGeneric{ 270 | public: 271 | static const Op OC = OpGroupDecorate; 272 | // Complete constructor 273 | SPIRVGroupDecorate(SPIRVDecorationGroup *TheGroup, 274 | const std::vector &TheTargets) 275 | :SPIRVGroupDecorateGeneric(OC, TheGroup, TheTargets){} 276 | // Incomplete constructor 277 | SPIRVGroupDecorate() 278 | :SPIRVGroupDecorateGeneric(OC){} 279 | 280 | virtual void decorateTargets(); 281 | }; 282 | 283 | class SPIRVGroupMemberDecorate:public SPIRVGroupDecorateGeneric{ 284 | public: 285 | static const Op OC = OpGroupMemberDecorate; 286 | // Complete constructor 287 | SPIRVGroupMemberDecorate(SPIRVDecorationGroup *TheGroup, 288 | const std::vector &TheTargets) 289 | :SPIRVGroupDecorateGeneric(OC, TheGroup, TheTargets){} 290 | // Incomplete constructor 291 | SPIRVGroupMemberDecorate() 292 | :SPIRVGroupDecorateGeneric(OC){} 293 | 294 | virtual void decorateTargets(); 295 | }; 296 | 297 | } 298 | 299 | 300 | #endif /* SPIRVDECORATE_HPP_ */ 301 | -------------------------------------------------------------------------------- /libSPIRV/SPIRVExtInst.h: -------------------------------------------------------------------------------- 1 | //===- SPIRVBuiltin.h - SPIR-V extended instruction --------------*- C++ -*-===// 2 | // 3 | // The LLVM/SPIRV Translator 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a 11 | // copy of this software and associated documentation files (the "Software"), 12 | // to deal with the Software without restriction, including without limitation 13 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 | // and/or sell copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following conditions: 16 | // 17 | // Redistributions of source code must retain the above copyright notice, 18 | // this list of conditions and the following disclaimers. 19 | // Redistributions in binary form must reproduce the above copyright notice, 20 | // this list of conditions and the following disclaimers in the documentation 21 | // and/or other materials provided with the distribution. 22 | // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 | // contributors may be used to endorse or promote products derived from this 24 | // Software without specific prior written permission. 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 | // THE SOFTWARE. 32 | // 33 | //===----------------------------------------------------------------------===// 34 | /// \file 35 | /// 36 | /// This file defines SPIR-V extended instructions. 37 | /// 38 | //===----------------------------------------------------------------------===// 39 | 40 | #ifndef SPIRVBUILTIN_HPP_ 41 | #define SPIRVBUILTIN_HPP_ 42 | 43 | #include "SPIRVUtil.h" 44 | #include "OpenCL.std.h" 45 | 46 | #include 47 | #include 48 | 49 | namespace SPIRV{ 50 | 51 | 52 | inline bool 53 | isOpenCLBuiltinSet (SPIRVExtInstSetKind Set) { 54 | return Set == SPIRVEIS_OpenCL; 55 | } 56 | 57 | typedef OpenCLLIB::Entrypoints OCLExtOpKind; 58 | 59 | template<> inline void 60 | SPIRVMap::init() { 61 | add(OpenCLLIB::Acos, "acos"); 62 | add(OpenCLLIB::Acosh, "acosh"); 63 | add(OpenCLLIB::Acospi, "acospi"); 64 | add(OpenCLLIB::Asin, "asin"); 65 | add(OpenCLLIB::Asinh, "asinh"); 66 | add(OpenCLLIB::Asinpi, "asinpi"); 67 | add(OpenCLLIB::Atan, "atan"); 68 | add(OpenCLLIB::Atan2, "atan2"); 69 | add(OpenCLLIB::Atanh, "atanh"); 70 | add(OpenCLLIB::Atanpi, "atanpi"); 71 | add(OpenCLLIB::Atan2pi, "atan2pi"); 72 | add(OpenCLLIB::Cbrt, "cbrt"); 73 | add(OpenCLLIB::Ceil, "ceil"); 74 | add(OpenCLLIB::Copysign, "copysign"); 75 | add(OpenCLLIB::Cos, "cos"); 76 | add(OpenCLLIB::Cosh, "cosh"); 77 | add(OpenCLLIB::Cospi, "cospi"); 78 | add(OpenCLLIB::Erfc, "erfc"); 79 | add(OpenCLLIB::Erf, "erf"); 80 | add(OpenCLLIB::Exp, "exp"); 81 | add(OpenCLLIB::Exp2, "exp2"); 82 | add(OpenCLLIB::Exp10, "exp10"); 83 | add(OpenCLLIB::Expm1, "expm1"); 84 | add(OpenCLLIB::Fabs, "fabs"); 85 | add(OpenCLLIB::Fdim, "fdim"); 86 | add(OpenCLLIB::Floor, "floor"); 87 | add(OpenCLLIB::Fma, "fma"); 88 | add(OpenCLLIB::Fmax, "fmax"); 89 | add(OpenCLLIB::Fmin, "fmin"); 90 | add(OpenCLLIB::Fmod, "fmod"); 91 | add(OpenCLLIB::Fract, "fract"); 92 | add(OpenCLLIB::Frexp, "frexp"); 93 | add(OpenCLLIB::Hypot, "hypot"); 94 | add(OpenCLLIB::Ilogb, "ilogb"); 95 | add(OpenCLLIB::Ldexp, "ldexp"); 96 | add(OpenCLLIB::Lgamma, "lgamma"); 97 | add(OpenCLLIB::Lgamma_r, "lgamma_r"); 98 | add(OpenCLLIB::Log, "log"); 99 | add(OpenCLLIB::Log2, "log2"); 100 | add(OpenCLLIB::Log10, "log10"); 101 | add(OpenCLLIB::Log1p, "log1p"); 102 | add(OpenCLLIB::Logb, "logb"); 103 | add(OpenCLLIB::Mad, "mad"); 104 | add(OpenCLLIB::Maxmag, "maxmag"); 105 | add(OpenCLLIB::Minmag, "minmag"); 106 | add(OpenCLLIB::Modf, "modf"); 107 | add(OpenCLLIB::Nan, "nan"); 108 | add(OpenCLLIB::Nextafter, "nextafter"); 109 | add(OpenCLLIB::Pow, "pow"); 110 | add(OpenCLLIB::Pown, "pown"); 111 | add(OpenCLLIB::Powr, "powr"); 112 | add(OpenCLLIB::Remainder, "remainder"); 113 | add(OpenCLLIB::Remquo, "remquo"); 114 | add(OpenCLLIB::Rint, "rint"); 115 | add(OpenCLLIB::Rootn, "rootn"); 116 | add(OpenCLLIB::Round, "round"); 117 | add(OpenCLLIB::Rsqrt, "rsqrt"); 118 | add(OpenCLLIB::Sin, "sin"); 119 | add(OpenCLLIB::Sincos, "sincos"); 120 | add(OpenCLLIB::Sinh, "sinh"); 121 | add(OpenCLLIB::Sinpi, "sinpi"); 122 | add(OpenCLLIB::Sqrt, "sqrt"); 123 | add(OpenCLLIB::Tan, "tan"); 124 | add(OpenCLLIB::Tanh, "tanh"); 125 | add(OpenCLLIB::Tanpi, "tanpi"); 126 | add(OpenCLLIB::Tgamma, "tgamma"); 127 | add(OpenCLLIB::Trunc, "trunc"); 128 | add(OpenCLLIB::Half_cos, "half_cos"); 129 | add(OpenCLLIB::Half_divide, "half_divide"); 130 | add(OpenCLLIB::Half_exp, "half_exp"); 131 | add(OpenCLLIB::Half_exp2, "half_exp2"); 132 | add(OpenCLLIB::Half_exp10, "half_exp10"); 133 | add(OpenCLLIB::Half_log, "half_log"); 134 | add(OpenCLLIB::Half_log2, "half_log2"); 135 | add(OpenCLLIB::Half_log10, "half_log10"); 136 | add(OpenCLLIB::Half_powr, "half_powr"); 137 | add(OpenCLLIB::Half_recip, "half_recip"); 138 | add(OpenCLLIB::Half_rsqrt, "half_rsqrt"); 139 | add(OpenCLLIB::Half_sin, "half_sin"); 140 | add(OpenCLLIB::Half_sqrt, "half_sqrt"); 141 | add(OpenCLLIB::Half_tan, "half_tan"); 142 | add(OpenCLLIB::Native_cos, "native_cos"); 143 | add(OpenCLLIB::Native_divide, "native_divide"); 144 | add(OpenCLLIB::Native_exp, "native_exp"); 145 | add(OpenCLLIB::Native_exp2, "native_exp2"); 146 | add(OpenCLLIB::Native_exp10, "native_exp10"); 147 | add(OpenCLLIB::Native_log, "native_log"); 148 | add(OpenCLLIB::Native_log2, "native_log2"); 149 | add(OpenCLLIB::Native_log10, "native_log10"); 150 | add(OpenCLLIB::Native_powr, "native_powr"); 151 | add(OpenCLLIB::Native_recip, "native_recip"); 152 | add(OpenCLLIB::Native_rsqrt, "native_rsqrt"); 153 | add(OpenCLLIB::Native_sin, "native_sin"); 154 | add(OpenCLLIB::Native_sqrt, "native_sqrt"); 155 | add(OpenCLLIB::Native_tan, "native_tan"); 156 | add(OpenCLLIB::FClamp, "fclamp"); 157 | add(OpenCLLIB::Degrees, "degrees"); 158 | add(OpenCLLIB::Mix, "mix"); 159 | add(OpenCLLIB::FMax_common, "fmax_common"); 160 | add(OpenCLLIB::FMin_common, "fmin_common"); 161 | add(OpenCLLIB::Radians, "radians"); 162 | add(OpenCLLIB::Step, "step"); 163 | add(OpenCLLIB::Smoothstep, "smoothstep"); 164 | add(OpenCLLIB::Sign, "sign"); 165 | add(OpenCLLIB::Cross, "cross"); 166 | add(OpenCLLIB::Distance, "distance"); 167 | add(OpenCLLIB::Length, "length"); 168 | add(OpenCLLIB::Normalize, "normalize"); 169 | add(OpenCLLIB::Fast_distance, "fast_distance"); 170 | add(OpenCLLIB::Fast_length, "fast_length"); 171 | add(OpenCLLIB::Fast_normalize, "fast_normalize"); 172 | add(OpenCLLIB::Read_imagef, "read_imagef"); 173 | add(OpenCLLIB::Read_imagei, "read_imagei"); 174 | add(OpenCLLIB::Read_imageui, "read_imageui"); 175 | add(OpenCLLIB::Read_imageh, "read_imageh"); 176 | add(OpenCLLIB::Read_imagef_samplerless, "read_imagef_samplerless"); 177 | add(OpenCLLIB::Read_imagei_samplerless, "read_imagei_samplerless"); 178 | add(OpenCLLIB::Read_imageui_samplerless, "read_imageui_samplerless"); 179 | add(OpenCLLIB::Read_imageh_samplerless, "read_imageh_samplerless"); 180 | add(OpenCLLIB::Write_imagef, "write_imagef"); 181 | add(OpenCLLIB::Write_imagei, "write_imagei"); 182 | add(OpenCLLIB::Write_imageui, "write_imageui"); 183 | add(OpenCLLIB::Write_imageh, "write_imageh"); 184 | add(OpenCLLIB::Read_imagef_mipmap_lod, "read_imagef_mipmap_lod"); 185 | add(OpenCLLIB::Read_imagei_mipmap_lod, "read_imagei_mipmap_lod"); 186 | add(OpenCLLIB::Read_imageui_mipmap_lod, "read_imageui_mipmap_lod"); 187 | add(OpenCLLIB::Read_imagef_mipmap_grad, "read_imagef_mipmap_gradient"); 188 | add(OpenCLLIB::Read_imagei_mipmap_grad, "read_imagei_mipmap_gradient"); 189 | add(OpenCLLIB::Read_imageui_mipmap_grad, "read_imageui_mipmap_gradient"); 190 | add(OpenCLLIB::Write_imagef_mipmap_lod, "write_imagef_mipmap_lod"); 191 | add(OpenCLLIB::Write_imagei_mipmap_lod, "write_imagei_mipmap_lod"); 192 | add(OpenCLLIB::Write_imageui_mipmap_lod, "write_imageui_mipmap_lod"); 193 | add(OpenCLLIB::Get_image_width, "get_image_width"); 194 | add(OpenCLLIB::Get_image_height, "get_image_height"); 195 | add(OpenCLLIB::Get_image_depth, "get_image_depth"); 196 | add(OpenCLLIB::Get_image_channel_data_type, "get_image_channel_data_type"); 197 | add(OpenCLLIB::Get_image_channel_order, "get_image_channel_order"); 198 | add(OpenCLLIB::Get_image_dim, "get_image_dim"); 199 | add(OpenCLLIB::Get_image_array_size, "get_image_array_size"); 200 | add(OpenCLLIB::Get_image_num_samples, "get_image_num_samples"); 201 | add(OpenCLLIB::Get_image_num_mip_levels, "get_image_num_mip_levels"); 202 | add(OpenCLLIB::SAbs, "s_abs"); 203 | add(OpenCLLIB::SAbs_diff, "s_abs_diff"); 204 | add(OpenCLLIB::SAdd_sat, "s_add_sat"); 205 | add(OpenCLLIB::UAdd_sat, "u_add_sat"); 206 | add(OpenCLLIB::SHadd, "s_hadd"); 207 | add(OpenCLLIB::UHadd, "u_hadd"); 208 | add(OpenCLLIB::SRhadd, "s_rhadd"); 209 | add(OpenCLLIB::URhadd, "u_rhadd"); 210 | add(OpenCLLIB::SClamp, "s_clamp"); 211 | add(OpenCLLIB::UClamp, "u_clamp"); 212 | add(OpenCLLIB::Clz, "clz"); 213 | add(OpenCLLIB::Ctz, "ctz"); 214 | add(OpenCLLIB::SMad_hi, "s_mad_hi"); 215 | add(OpenCLLIB::SMad_sat, "s_mad_sat"); 216 | add(OpenCLLIB::UMad_sat, "u_mad_sat"); 217 | add(OpenCLLIB::SMax, "s_max"); 218 | add(OpenCLLIB::SMin, "s_min"); 219 | add(OpenCLLIB::UMax, "u_max"); 220 | add(OpenCLLIB::UMin, "u_min"); 221 | add(OpenCLLIB::SMul_hi, "s_mul_hi"); 222 | add(OpenCLLIB::Rotate, "rotate"); 223 | add(OpenCLLIB::SSub_sat, "s_sub_sat"); 224 | add(OpenCLLIB::USub_sat, "u_sub_sat"); 225 | add(OpenCLLIB::U_Upsample, "u_upsample"); 226 | add(OpenCLLIB::S_Upsample, "s_upsample"); 227 | add(OpenCLLIB::Popcount, "popcount"); 228 | add(OpenCLLIB::SMad24, "s_mad24"); 229 | add(OpenCLLIB::UMad24, "u_mad24"); 230 | add(OpenCLLIB::SMul24, "s_mul24"); 231 | add(OpenCLLIB::UMul24, "u_mul24"); 232 | add(OpenCLLIB::Vloadn, "vloadn"); 233 | add(OpenCLLIB::Vstoren, "vstoren"); 234 | add(OpenCLLIB::Vload_half, "vload_half"); 235 | add(OpenCLLIB::Vload_halfn, "vload_halfn"); 236 | add(OpenCLLIB::Vstore_half, "vstore_half"); 237 | add(OpenCLLIB::Vstore_half_r, "vstore_half_r"); 238 | add(OpenCLLIB::Vstore_halfn, "vstore_halfn"); 239 | add(OpenCLLIB::Vstore_halfn_r, "vstore_halfn_r"); 240 | add(OpenCLLIB::Vloada_halfn, "vloada_halfn"); 241 | add(OpenCLLIB::Vstorea_halfn, "vstorea_halfn"); 242 | add(OpenCLLIB::Vstorea_halfn_r, "vstorea_halfn_r"); 243 | add(OpenCLLIB::Shuffle, "shuffle"); 244 | add(OpenCLLIB::Shuffle2, "shuffle2"); 245 | add(OpenCLLIB::Printf, "printf"); 246 | add(OpenCLLIB::Prefetch, "prefetch"); 247 | add(OpenCLLIB::Bitselect, "bitselect"); 248 | add(OpenCLLIB::Select, "select"); 249 | add(OpenCLLIB::UAbs, "u_abs"); 250 | add(OpenCLLIB::UAbs_diff, "u_abs_diff"); 251 | add(OpenCLLIB::UMul_hi, "u_mul_hi"); 252 | add(OpenCLLIB::UMad_hi, "u_mad_hi"); 253 | } 254 | SPIRV_DEF_NAMEMAP(OCLExtOpKind, OCLExtOpMap) 255 | 256 | inline bool 257 | isReadImage(SPIRVWord EntryPoint) { 258 | return EntryPoint >= OpenCLLIB::Read_imagef && 259 | EntryPoint <= OpenCLLIB::Read_imageui; 260 | } 261 | 262 | inline bool 263 | isWriteImage(SPIRVWord EntryPoint) { 264 | return EntryPoint >= OpenCLLIB::Write_imagef && 265 | EntryPoint <= OpenCLLIB::Write_imageui; 266 | } 267 | 268 | inline bool 269 | isReadOrWriteImage(SPIRVWord EntryPoint) { 270 | return isReadImage(EntryPoint) || isWriteImage(EntryPoint); 271 | } 272 | 273 | } 274 | 275 | #endif 276 | --------------------------------------------------------------------------------