--- /dev/null
+---
+Language: Cpp
+# BasedOnStyle: Google
+AccessModifierOffset: -1
+AlignAfterOpenBracket: true
+AlignEscapedNewlinesLeft: true
+AlignOperands: true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortIfStatementsOnASingleLine: true
+AllowShortLoopsOnASingleLine: true
+AllowShortFunctionsOnASingleLine: All
+AlwaysBreakAfterDefinitionReturnType: false
+AlwaysBreakTemplateDeclarations: true
+AlwaysBreakBeforeMultilineStrings: true
+BreakBeforeBinaryOperators: None
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+BinPackParameters: true
+BinPackArguments: true
+ColumnLimit: 80
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+ConstructorInitializerIndentWidth: 4
+DerivePointerAlignment: true
+ExperimentalAutoDetectBinPacking: false
+IndentCaseLabels: true
+IndentWrappedFunctionNames: false
+IndentFunctionDeclarationAfterType: false
+MaxEmptyLinesToKeep: 1
+KeepEmptyLinesAtTheStartOfBlocks: false
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: false
+PenaltyBreakBeforeFirstCallParameter: 1
+PenaltyBreakComment: 300
+PenaltyBreakString: 1000
+PenaltyBreakFirstLessLess: 120
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 200
+PointerAlignment: Left
+SpacesBeforeTrailingComments: 2
+Cpp11BracedListStyle: true
+Standard: Auto
+IndentWidth: 2
+TabWidth: 8
+UseTab: Never
+BreakBeforeBraces: Attach
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+SpacesInAngles: false
+SpaceInEmptyParentheses: false
+SpacesInCStyleCastParentheses: false
+SpaceAfterCStyleCast: false
+SpacesInContainerLiterals: true
+SpaceBeforeAssignmentOperators: true
+ContinuationIndentWidth: 4
+CommentPragmas: '^ IWYU pragma:'
+ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
+SpaceBeforeParens: ControlStatements
+DisableFormat: false
+...
+
--- /dev/null
+build*
+.ycm_extra_conf.py*
--- /dev/null
+# Copyright (c) 2015 The Khronos Group Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and/or associated documentation files (the
+# "Materials"), to deal in the Materials without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Materials, and to
+# permit persons to whom the Materials are furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Materials.
+#
+# MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+# KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+# SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+# https://www.khronos.org/registry/
+#
+# THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+cmake_minimum_required(VERSION 2.8)
+project(SPIRV)
+
+if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
+ add_definitions(-DSPIRV_LINUX)
+elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
+ add_definitions(-DSPIRV_WINDOWS)
+elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
+ add_definitions(-DSPIRV_MAC)
+else()
+ message(FATAL_ERROR "Your platform '${CMAKE_SYSTEM_NAME}' is not supported!")
+endif()
+
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
+if (UNIX)
+ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
+elseif(WIN32)
+ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+endif()
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+
+if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+ message(STATUS "No build type selected, default to Debug")
+ set(CMAKE_BUILD_TYPE "Debug")
+endif()
+
+if(UNIX)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-exceptions -fno-rtti")
+ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics")
+ set(SPIRV_USE_SANITIZER "" CACHE STRING
+ "Use the clang sanitizer [address|memory|thread|...]")
+ if(NOT "${SPIRV_USE_SANITIZER}" STREQUAL "")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${SPIRV_USE_SANITIZER}")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=${SPIRV_USE_SANITIZER}")
+ endif()
+ endif()
+endif()
+
+if(UNIX)
+ option(SPIRV_COLOR_TERMINAL "Enable color terminal output" ON)
+ if(${SPIRV_COLOR_TERMINAL})
+ add_definitions(-DSPV_COLOR_TERMINAL)
+ endif()
+endif()
+
+if(UNIX)
+ set(SPIRV_WARNINGS "-Wall -Wextra -Wno-missing-field-initializers")
+ option(SPIRV_WARN_EVERYTHING "Enable -Weverything for SPIRV library" OFF)
+ if(${SPIRV_WARN_EVERYTHING})
+ set(SPIRV_WARNINGS
+ "${SPIRV_WARNINGS} -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded")
+ endif()
+elseif(WIN32)
+ set(SPIRV_WARNINGS "-D_CRT_SECURE_NO_WARNINGS /wd4800")
+endif()
+
+if(UNIX)
+ option(SPIRV_WERROR "Enable error on warning" OFF)
+ if(${SPIRV_WERROR})
+ set(SPIRV_WARNINGS "${SPIRV_WARNINGS} -Werror")
+ endif()
+endif()
+
+include_directories(SYSTEM
+ ${CMAKE_CURRENT_SOURCE_DIR}/external/include)
+
+include_directories(
+ ${CMAKE_CURRENT_SOURCE_DIR}/include)
+
+set(SPIRV_SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/libspirv/libspirv.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/binary.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/diagnostic.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/opcode.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/operand.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/print.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/text.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/validate.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/binary.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/diagnostic.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/ext_inst.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/opcode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/operand.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/print.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/text.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/validate.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/validate_id.cpp)
+
+add_library(SPIRV ${SPIRV_SOURCES})
+target_link_libraries(SPIRV ${SPIRV_LIBS})
+set_target_properties(SPIRV PROPERTIES COMPILE_FLAGS ${SPIRV_WARNINGS})
+
+add_executable(spirv-as
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/libspirv/libspirv.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/tools/as/as.cpp)
+set_target_properties(spirv-as PROPERTIES COMPILE_FLAGS ${SPIRV_WARNINGS})
+target_link_libraries(spirv-as SPIRV)
+
+add_executable(spirv-dis
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/libspirv/libspirv.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/tools/dis/dis.cpp)
+set_target_properties(spirv-dis PROPERTIES COMPILE_FLAGS ${SPIRV_WARNINGS})
+target_link_libraries(spirv-dis SPIRV)
+
+add_executable(spirv-val
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/libspirv/libspirv.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/tools/val/val.cpp)
+set_target_properties(spirv-val PROPERTIES COMPILE_FLAGS ${SPIRV_WARNINGS})
+target_link_libraries(spirv-val SPIRV)
+
+set(GTEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/googletest)
+if(EXISTS ${GTEST_DIR})
+ if(WIN32)
+ option(gtest_force_shared_crt
+ "Use shared (DLL) run-time lib even when Google Test is built as static lib."
+ ON)
+ endif()
+
+ message(STATUS "Found googletest, building tests.")
+
+ include_directories(SYSTEM
+ ${CMAKE_CURRENT_SOURCE_DIR}/external/googletest
+ ${CMAKE_CURRENT_SOURCE_DIR}/external/googletest/include)
+
+ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/external/googletest)
+
+ add_executable(UnitSPIRV
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/UnitSPIRV.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/BinaryEndianness.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/FixWord.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/BinaryHeaderGet.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/BinaryToText.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/NamedId.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/OpcodeTableGet.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/OpcodeIsVariable.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/OpcodeRequiresCapabilities.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/OpcodeMake.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/OpcodeSplit.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/OperandTableGet.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/TextAdvance.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/TextWordGet.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/TextToBinary.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/TextDestroy.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/DiagnosticPrint.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/Validate.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/ValidateID.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/main.cpp)
+ target_link_libraries(UnitSPIRV SPIRV gtest)
+else()
+ message(STATUS "Did not find googletest, tests will not be built."
+ "To enable tests place googletest in '<spirv-dir>/external/googletest'.")
+endif()
+
+set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/install)
+install(TARGETS SPIRV spirv-as spirv-dis spirv-val
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib
+ ARCHIVE DESTINATION lib)
+
+install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/libspirv/libspirv.h
+ DESTINATION include/libspirv/)
--- /dev/null
+/*
+** Copyright (c) 2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and/or associated documentation files (the "Materials"),
+** to deal in the Materials without restriction, including without limitation
+** the rights to use, copy, modify, merge, publish, distribute, sublicense,
+** and/or sell copies of the Materials, and to permit persons to whom the
+** Materials are furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Materials.
+**
+** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
+** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
+** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
+** IN THE MATERIALS.
+*/
+
+//
+// Author: John Kessenich, LunarG
+//
+
+namespace GLSL_STD_450 {
+
+enum Entrypoints {
+ Round = 0,
+ RoundEven = 1,
+ Trunc = 2,
+ Abs = 3,
+ Sign = 4,
+ Floor = 5,
+ Ceil = 6,
+ Fract = 7,
+
+ Radians = 8,
+ Degrees = 9,
+ Sin = 10,
+ Cos = 11,
+ Tan = 12,
+ Asin = 13,
+ Acos = 14,
+ Atan = 15,
+ Sinh = 16,
+ Cosh = 17,
+ Tanh = 18,
+ Asinh = 19,
+ Acosh = 20,
+ Atanh = 21,
+ Atan2 = 22,
+
+ Pow = 23,
+ Exp = 24,
+ Log = 25,
+ Exp2 = 26,
+ Log2 = 27,
+ Sqrt = 28,
+ InverseSqrt = 29,
+
+ Determinant = 30,
+ MatrixInverse = 31,
+
+ Modf = 32, // second argument needs the OpVariable = , not an OpLoad
+ Min = 33,
+ Max = 34,
+ Clamp = 35,
+ Mix = 36,
+ Step = 37,
+ SmoothStep = 38,
+
+ FloatBitsToInt = 39,
+ FloatBitsToUint = 40,
+ IntBitsToFloat = 41,
+ UintBitsToFloat = 42,
+
+ Fma = 43,
+ Frexp = 44,
+ Ldexp = 45,
+
+ PackSnorm4x8 = 46,
+ PackUnorm4x8 = 47,
+ PackSnorm2x16 = 48,
+ PackUnorm2x16 = 49,
+ PackHalf2x16 = 50,
+ PackDouble2x32 = 51,
+ UnpackSnorm2x16 = 52,
+ UnpackUnorm2x16 = 53,
+ UnpackHalf2x16 = 54,
+ UnpackSnorm4x8 = 55,
+ UnpackUnorm4x8 = 56,
+ UnpackDouble2x32 = 57,
+
+ Length = 58,
+ Distance = 59,
+ Cross = 60,
+ Normalize = 61,
+ Ftransform = 62,
+ FaceForward = 63,
+ Reflect = 64,
+ Refract = 65,
+
+ UaddCarry = 66,
+ UsubBorrow = 67,
+ UmulExtended = 68,
+ ImulExtended = 69,
+ BitfieldExtract = 70,
+ BitfieldInsert = 71,
+ BitfieldReverse = 72,
+ BitCount = 73,
+ FindLSB = 74,
+ FindMSB = 75,
+
+ InterpolateAtCentroid = 76,
+ InterpolateAtSample = 77,
+ InterpolateAtOffset = 78,
+
+ Count
+};
+
+inline void GetDebugNames(const char** names)
+{
+ for (int i = 0; i < Count; ++i)
+ names[i] = "Unknown";
+
+ names[Round] = "round";
+ names[RoundEven] = "roundEven";
+ names[Trunc] = "trunc";
+ names[Abs] = "abs";
+ names[Sign] = "sign";
+ names[Floor] = "floor";
+ names[Ceil] = "ceil";
+ names[Fract] = "fract";
+ names[Radians] = "radians";
+ names[Degrees] = "degrees";
+ names[Sin] = "sin";
+ names[Cos] = "cos";
+ names[Tan] = "tan";
+ names[Asin] = "asin";
+ names[Acos] = "acos";
+ names[Atan] = "atan";
+ names[Sinh] = "sinh";
+ names[Cosh] = "cosh";
+ names[Tanh] = "tanh";
+ names[Asinh] = "asinh";
+ names[Acosh] = "acosh";
+ names[Atanh] = "atanh";
+ names[Atan2] = "atan2";
+ names[Pow] = "pow";
+ names[Exp] = "exp";
+ names[Log] = "log";
+ names[Exp2] = "exp2";
+ names[Log2] = "log2";
+ names[Sqrt] = "sqrt";
+ names[InverseSqrt] = "inversesqrt";
+ names[Determinant] = "determinant";
+ names[MatrixInverse] = "inverse";
+ names[Modf] = "modf";
+ names[Min] = "min";
+ names[Max] = "max";
+ names[Clamp] = "clamp";
+ names[Mix] = "mix";
+ names[Step] = "step";
+ names[SmoothStep] = "smoothstep";
+ names[FloatBitsToInt] = "floatBitsToInt";
+ names[FloatBitsToUint] = "floatBitsToUint";
+ names[IntBitsToFloat] = "intBitsToFloat";
+ names[UintBitsToFloat] = "uintBitsToFloat";
+ names[Fma] = "fma";
+ names[Frexp] = "frexp";
+ names[Ldexp] = "ldexp";
+ names[PackSnorm4x8] = "packSnorm4x8";
+ names[PackUnorm4x8] = "packUnorm4x8";
+ names[PackSnorm2x16] = "packSnorm2x16";
+ names[PackUnorm2x16] = "packUnorm2x16";
+ names[PackHalf2x16] = "packHalf2x16";
+ names[PackDouble2x32] = "packDouble2x32";
+ names[UnpackSnorm2x16] = "unpackSnorm2x16";
+ names[UnpackUnorm2x16] = "unpackUnorm2x16";
+ names[UnpackHalf2x16] = "unpackHalf2x16";
+ names[UnpackSnorm4x8] = "unpackSnorm4x8";
+ names[UnpackUnorm4x8] = "unpackUnorm4x8";
+ names[UnpackDouble2x32] = "unpackDouble2x32";
+ names[Length] = "length";
+ names[Distance] = "distance";
+ names[Cross] = "cross";
+ names[Normalize] = "normalize";
+ names[Ftransform] = "ftransform";
+ names[FaceForward] = "faceforward";
+ names[Reflect] = "reflect";
+ names[Refract] = "refract";
+ names[UaddCarry] = "uaddCarry";
+ names[UsubBorrow] = "usubBorrow";
+ names[UmulExtended] = "umulExtended";
+ names[ImulExtended] = "imulExtended";
+ names[BitfieldExtract] = "bitfieldExtract";
+ names[BitfieldInsert] = "bitfieldInsert";
+ names[BitfieldReverse] = "bitfieldReverse";
+ names[BitCount] = "bitCount";
+ names[FindLSB] = "findLSB";
+ names[FindMSB] = "findMSB";
+ names[InterpolateAtCentroid] = "interpolateAtCentroid";
+ names[InterpolateAtSample] = "interpolateAtSample";
+ names[InterpolateAtOffset] = "interpolateAtOffset";
+}
+
+}; // end namespace GLSL_STD_450
--- /dev/null
+/*
+** Copyright (c) 2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and/or associated documentation files (the "Materials"),
+** to deal in the Materials without restriction, including without limitation
+** the rights to use, copy, modify, merge, publish, distribute, sublicense,
+** and/or sell copies of the Materials, and to permit persons to whom the
+** Materials are furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Materials.
+**
+** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
+** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
+** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
+** IN THE MATERIALS.
+*/
+
+//
+// Author: Boaz Ouriel, Intel
+//
+
+namespace OpenCLLIB {
+
+enum Entrypoints {
+
+ // math functions
+ Acos = 0,
+ Acosh = 1,
+ Acospi = 2,
+ Asin = 3,
+ Asinh = 4,
+ Asinpi = 5,
+ Atan = 6,
+ Atan2 = 7,
+ Atanh = 8,
+ Atanpi = 9,
+ Atan2pi = 10,
+ Cbrt = 11,
+ Ceil = 12,
+ Copysign = 13,
+ Cos = 14,
+ Cosh = 15,
+ Cospi = 16,
+ Erfc = 17,
+ Erf = 18,
+ Exp = 19,
+ Exp2 = 20,
+ Exp10 = 21,
+ Expm1 = 22,
+ Fabs = 23,
+ Fdim = 24,
+ Floor = 25,
+ Fma = 26,
+ Fmax = 27,
+ Fmin = 28,
+ Fmod = 29,
+ Fract = 30,
+ Frexp = 31,
+ Hypot = 32,
+ Ilogb = 33,
+ Ldexp = 34,
+ Lgamma = 35,
+ Lgamma_r = 36,
+ Log = 37,
+ Log2 = 38,
+ Log10 = 39,
+ Log1p = 40,
+ Logb = 41,
+ Mad = 42,
+ Maxmag = 43,
+ Minmag = 44,
+ Modf = 45,
+ Nan = 46,
+ Nextafter = 47,
+ Pow = 48,
+ Pown = 49,
+ Powr = 50,
+ Remainder = 51,
+ Remquo = 52,
+ Rint = 53,
+ Rootn = 54,
+ Round = 55,
+ Rsqrt = 56,
+ Sin = 57,
+ Sincos = 58,
+ Sinh = 59,
+ Sinpi = 60,
+ Sqrt = 61,
+ Tan = 62,
+ Tanh = 63,
+ Tanpi = 64,
+ Tgamma = 65,
+ Trunc = 66,
+ Half_cos = 67,
+ Half_divide = 68,
+ Half_exp = 69,
+ Half_exp2 = 70,
+ Half_exp10 = 71,
+ Half_log = 72,
+ Half_log2 = 73,
+ Half_log10 = 74,
+ Half_powr = 75,
+ Half_recip = 76,
+ Half_rsqrt = 77,
+ Half_sin = 78,
+ Half_sqrt = 79,
+ Half_tan = 80,
+ Native_cos = 81,
+ Native_divide = 82,
+ Native_exp = 83,
+ Native_exp2 = 84,
+ Native_exp10 = 85,
+ Native_log = 86,
+ Native_log2 = 87,
+ Native_log10 = 88,
+ Native_powr = 89,
+ Native_recip = 90,
+ Native_rsqrt = 91,
+ Native_sin = 92,
+ Native_sqrt = 93,
+ Native_tan = 94,
+
+ // Common
+ FClamp = 95,
+ Degrees = 96,
+ FMax_common = 97,
+ FMin_common = 98,
+ Mix = 99,
+ Radians = 100,
+ Step = 101,
+ Smoothstep = 102,
+ Sign = 103,
+
+ // Geometrics
+ Cross = 104,
+ Distance = 105,
+ Length = 106,
+ Normalize = 107,
+ Fast_distance = 108,
+ Fast_length = 109,
+ Fast_normalize = 110,
+
+ // Images
+ Read_imagef = 111,
+ Read_imagei = 112,
+ Read_imageui = 113,
+ Read_imageh = 114,
+
+ Read_imagef_samplerless = 115,
+ Read_imagei_samplerless = 116,
+ Read_imageui_samplerless = 117,
+ Read_imageh_samplerless = 118,
+
+ Write_imagef = 119,
+ Write_imagei = 120,
+ Write_imageui = 121,
+ Write_imageh = 122,
+ Read_imagef_mipmap_lod = 123,
+ Read_imagei_mipmap_lod = 124,
+ Read_imageui_mipmap_lod = 125,
+ Read_imagef_mipmap_grad = 126,
+ Read_imagei_mipmap_grad = 127,
+ Read_imageui_mipmap_grad = 128,
+ Write_imagef_mipmap_lod = 129,
+ Write_imagei_mipmap_lod = 130,
+ Write_imageui_mipmap_lod = 131,
+ Get_image_width = 132,
+ Get_image_height = 133,
+ Get_image_depth = 134,
+ Get_image_channel_data_type = 135,
+ Get_image_channel_order = 136,
+ Get_image_dim = 137,
+ Get_image_array_size = 138,
+ Get_image_num_samples = 139,
+ Get_image_num_mip_levels = 140,
+
+ // Integers
+ SAbs = 141,
+ SAbs_diff = 142,
+ SAdd_sat = 143,
+ UAdd_sat = 144,
+ SHadd = 145,
+ UHadd = 146,
+ SRhadd = 147,
+ URhadd = 148,
+ SClamp = 149,
+ UClamp = 150,
+ Clz = 151,
+ Ctz = 152,
+ SMad_hi = 153,
+ UMad_sat = 154,
+ SMad_sat = 155,
+ SMax = 156,
+ UMax = 157,
+ SMin = 158,
+ UMin = 159,
+ SMul_hi = 160,
+ Rotate = 161,
+ SSub_sat = 162,
+ USub_sat = 163,
+ U_Upsample = 164,
+ S_Upsample = 165,
+ Popcount = 166,
+ SMad24 = 167,
+ UMad24 = 168,
+ SMul24 = 169,
+ UMul24 = 170,
+
+ // Vector Loads/Stores
+ Vloadn = 171,
+ Vstoren = 172,
+ Vload_half = 173,
+ Vload_halfn = 174,
+ Vstore_half = 175,
+ Vstore_half_r = 176,
+ Vstore_halfn = 177,
+ Vstore_halfn_r = 178,
+ Vloada_halfn = 179,
+ Vstorea_halfn = 180,
+ Vstorea_halfn_r = 181,
+
+ // Vector Misc
+ Shuffle = 182,
+ Shuffle2 = 183,
+
+ //
+ Printf = 184,
+ Prefetch = 185,
+
+ // Relationals
+ Bitselect = 186,
+ Select = 187,
+
+ // pipes
+ Read_pipe = 188,
+ Write_pipe = 189,
+ Reserve_read_pipe = 190,
+ Reserve_write_pipe = 191,
+ Commit_read_pipe = 192,
+ Commit_write_pipe = 193,
+ Is_valid_reserve_id = 194,
+ Work_group_reserve_read_pipe = 195,
+ Work_group_reserve_write_pipe = 196,
+ Work_group_commit_read_pipe = 197,
+ Work_group_commit_write_pipe = 198,
+ Get_pipe_num_packets = 199,
+ Get_pipe_max_packets = 200,
+
+ // more integers
+ UAbs = 201,
+ UAbs_diff = 202,
+ UMul_hi = 203,
+ UMad_hi = 204,
+};
+
+enum ImageChannelOrder {
+ R_ChannelOrder = 0x10B0,
+ A_ChannelOrder = 0x10B1,
+ RG_ChannelOrder = 0x10B2,
+ RA_ChannelOrder = 0x10B3,
+ RGB_ChannelOrder = 0x10B4,
+ RGBA_ChannelOrder = 0x10B5,
+ BGRA_ChannelOrder = 0x10B6,
+ ARGB_ChannelOrder = 0x10B7,
+ INTENSITY_ChannelOrder = 0x10B8,
+ LUMINANCE_ChannelOrder = 0x10B9,
+ Rx_ChannelOrder = 0x10BA,
+ RGx_ChannelOrder = 0x10BB,
+ RGBx_ChannelOrder = 0x10BC,
+ DEPTH_ChannelOrder = 0x10BD,
+ DEPTH_STENCIL_ChannelOrder = 0x10BE,
+ sRGB_ChannelOrder = 0x10BF,
+ sRGBx_ChannelOrder = 0x10C0,
+ sRGBA_ChannelOrder = 0x10C1,
+ sBGRA_ChannelOrder = 0x10C2,
+};
+
+enum ImageChannelType {
+ SNORM_INT8_ChannelType = 0x10D0,
+ SNORM_INT16_ChannelType = 0x10D1,
+ UNORM_INT8_ChannelType = 0x10D2,
+ UNORM_INT16_ChannelType = 0x10D3,
+ UNORM_SHORT_565_ChannelType = 0x10D4,
+ UNORM_SHORT_555_ChannelType = 0x10D5,
+ UNORM_INT_101010_ChannelType = 0x10D6,
+ SIGNED_INT8_ChannelType = 0x10D7,
+ SIGNED_INT16_ChannelType = 0x10D8,
+ SIGNED_INT32_ChannelType = 0x10D9,
+ UNSIGNED_INT8_ChannelType = 0x10DA,
+ UNSIGNED_INT16_ChannelType = 0x10DB,
+ UNSIGNED_INT32_ChannelType = 0x10DC,
+ HALF_FLOAT_ChannelType = 0x10DD,
+ FLOAT_ChannelType = 0x10DE,
+ UNORM_INT24_ChannelType = 0x10DF,
+};
+
+}; // end namespace OpenCL20
+
--- /dev/null
+/*
+** Copyright (c) 2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and/or associated documentation files (the "Materials"),
+** to deal in the Materials without restriction, including without limitation
+** the rights to use, copy, modify, merge, publish, distribute, sublicense,
+** and/or sell copies of the Materials, and to permit persons to whom the
+** Materials are furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Materials.
+**
+** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
+** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
+** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
+** IN THE MATERIALS.
+*/
+
+/*
+** This header is automatically generated by the same tool that creates
+** the Binary Section of the SPIR-V specification.
+*/
+
+/*
+** Specification revision 30.
+** Enumeration tokens for SPIR-V, in three styles: C, C++, generic.
+** - C++ will have the tokens in the "spv" name space, with no prefix.
+** - C will have tokens with as "Spv" prefix.
+**
+** Some tokens act like mask values, which can be OR'd together,
+** while others are mutually exclusive. The mask-like ones have
+** "Mask" in their name, and a parallel enum that has the shift
+** amount (1 << x) for each corresponding enumerant.
+*/
+
+#ifndef spirv_H
+#define spirv_H
+
+#ifdef __cplusplus
+
+namespace spv {
+
+static const int MagicNumber = 0x07230203;
+static const int Version = 99;
+
+typedef unsigned int Id;
+
+static const unsigned int OpCodeMask = 0xFFFF;
+static const unsigned int WordCountShift = 16;
+
+enum SourceLanguage {
+ SourceLanguageUnknown = 0,
+ SourceLanguageESSL = 1,
+ SourceLanguageGLSL = 2,
+ SourceLanguageOpenCL = 3,
+};
+
+enum ExecutionModel {
+ ExecutionModelVertex = 0,
+ ExecutionModelTessellationControl = 1,
+ ExecutionModelTessellationEvaluation = 2,
+ ExecutionModelGeometry = 3,
+ ExecutionModelFragment = 4,
+ ExecutionModelGLCompute = 5,
+ ExecutionModelKernel = 6,
+};
+
+enum AddressingModel {
+ AddressingModelLogical = 0,
+ AddressingModelPhysical32 = 1,
+ AddressingModelPhysical64 = 2,
+};
+
+enum MemoryModel {
+ MemoryModelSimple = 0,
+ MemoryModelGLSL450 = 1,
+ MemoryModelOpenCL12 = 2,
+ MemoryModelOpenCL20 = 3,
+ MemoryModelOpenCL21 = 4,
+};
+
+enum ExecutionMode {
+ ExecutionModeInvocations = 0,
+ ExecutionModeSpacingEqual = 1,
+ ExecutionModeSpacingFractionalEven = 2,
+ ExecutionModeSpacingFractionalOdd = 3,
+ ExecutionModeVertexOrderCw = 4,
+ ExecutionModeVertexOrderCcw = 5,
+ ExecutionModePixelCenterInteger = 6,
+ ExecutionModeOriginUpperLeft = 7,
+ ExecutionModeEarlyFragmentTests = 8,
+ ExecutionModePointMode = 9,
+ ExecutionModeXfb = 10,
+ ExecutionModeDepthReplacing = 11,
+ ExecutionModeDepthAny = 12,
+ ExecutionModeDepthGreater = 13,
+ ExecutionModeDepthLess = 14,
+ ExecutionModeDepthUnchanged = 15,
+ ExecutionModeLocalSize = 16,
+ ExecutionModeLocalSizeHint = 17,
+ ExecutionModeInputPoints = 18,
+ ExecutionModeInputLines = 19,
+ ExecutionModeInputLinesAdjacency = 20,
+ ExecutionModeInputTriangles = 21,
+ ExecutionModeInputTrianglesAdjacency = 22,
+ ExecutionModeInputQuads = 23,
+ ExecutionModeInputIsolines = 24,
+ ExecutionModeOutputVertices = 25,
+ ExecutionModeOutputPoints = 26,
+ ExecutionModeOutputLineStrip = 27,
+ ExecutionModeOutputTriangleStrip = 28,
+ ExecutionModeVecTypeHint = 29,
+ ExecutionModeContractionOff = 30,
+ ExecutionModeOriginLowerLeft = 31,
+};
+
+enum StorageClass {
+ StorageClassUniformConstant = 0,
+ StorageClassInput = 1,
+ StorageClassUniform = 2,
+ StorageClassOutput = 3,
+ StorageClassWorkgroupLocal = 4,
+ StorageClassWorkgroupGlobal = 5,
+ StorageClassPrivateGlobal = 6,
+ StorageClassFunction = 7,
+ StorageClassGeneric = 8,
+ StorageClassAtomicCounter = 10,
+};
+
+enum Dim {
+ Dim1D = 0,
+ Dim2D = 1,
+ Dim3D = 2,
+ DimCube = 3,
+ DimRect = 4,
+ DimBuffer = 5,
+};
+
+enum SamplerAddressingMode {
+ SamplerAddressingModeNone = 0,
+ SamplerAddressingModeClampToEdge = 1,
+ SamplerAddressingModeClamp = 2,
+ SamplerAddressingModeRepeat = 3,
+ SamplerAddressingModeRepeatMirrored = 4,
+};
+
+enum SamplerFilterMode {
+ SamplerFilterModeNearest = 0,
+ SamplerFilterModeLinear = 1,
+};
+
+enum FPFastMathModeShift {
+ FPFastMathModeNotNaNShift = 0,
+ FPFastMathModeNotInfShift = 1,
+ FPFastMathModeNSZShift = 2,
+ FPFastMathModeAllowRecipShift = 3,
+ FPFastMathModeFastShift = 4,
+};
+
+enum FPFastMathModeMask {
+ FPFastMathModeMaskNone = 0,
+ FPFastMathModeNotNaNMask = 0x00000001,
+ FPFastMathModeNotInfMask = 0x00000002,
+ FPFastMathModeNSZMask = 0x00000004,
+ FPFastMathModeAllowRecipMask = 0x00000008,
+ FPFastMathModeFastMask = 0x00000010,
+};
+
+enum FPRoundingMode {
+ FPRoundingModeRTE = 0,
+ FPRoundingModeRTZ = 1,
+ FPRoundingModeRTP = 2,
+ FPRoundingModeRTN = 3,
+};
+
+enum LinkageType {
+ LinkageTypeExport = 0,
+ LinkageTypeImport = 1,
+};
+
+enum AccessQualifier {
+ AccessQualifierReadOnly = 0,
+ AccessQualifierWriteOnly = 1,
+ AccessQualifierReadWrite = 2,
+};
+
+enum FunctionParameterAttribute {
+ FunctionParameterAttributeZext = 0,
+ FunctionParameterAttributeSext = 1,
+ FunctionParameterAttributeByVal = 2,
+ FunctionParameterAttributeSret = 3,
+ FunctionParameterAttributeNoAlias = 4,
+ FunctionParameterAttributeNoCapture = 5,
+ FunctionParameterAttributeSVM = 6,
+ FunctionParameterAttributeNoWrite = 7,
+ FunctionParameterAttributeNoReadWrite = 8,
+};
+
+enum Decoration {
+ DecorationPrecisionLow = 0,
+ DecorationPrecisionMedium = 1,
+ DecorationPrecisionHigh = 2,
+ DecorationBlock = 3,
+ DecorationBufferBlock = 4,
+ DecorationRowMajor = 5,
+ DecorationColMajor = 6,
+ DecorationGLSLShared = 7,
+ DecorationGLSLStd140 = 8,
+ DecorationGLSLStd430 = 9,
+ DecorationGLSLPacked = 10,
+ DecorationSmooth = 11,
+ DecorationNoperspective = 12,
+ DecorationFlat = 13,
+ DecorationPatch = 14,
+ DecorationCentroid = 15,
+ DecorationSample = 16,
+ DecorationInvariant = 17,
+ DecorationRestrict = 18,
+ DecorationAliased = 19,
+ DecorationVolatile = 20,
+ DecorationConstant = 21,
+ DecorationCoherent = 22,
+ DecorationNonwritable = 23,
+ DecorationNonreadable = 24,
+ DecorationUniform = 25,
+ DecorationNoStaticUse = 26,
+ DecorationCPacked = 27,
+ DecorationSaturatedConversion = 28,
+ DecorationStream = 29,
+ DecorationLocation = 30,
+ DecorationComponent = 31,
+ DecorationIndex = 32,
+ DecorationBinding = 33,
+ DecorationDescriptorSet = 34,
+ DecorationOffset = 35,
+ DecorationAlignment = 36,
+ DecorationXfbBuffer = 37,
+ DecorationStride = 38,
+ DecorationBuiltIn = 39,
+ DecorationFuncParamAttr = 40,
+ DecorationFPRoundingMode = 41,
+ DecorationFPFastMathMode = 42,
+ DecorationLinkageAttributes = 43,
+ DecorationSpecId = 44,
+};
+
+enum BuiltIn {
+ BuiltInPosition = 0,
+ BuiltInPointSize = 1,
+ BuiltInClipVertex = 2,
+ BuiltInClipDistance = 3,
+ BuiltInCullDistance = 4,
+ BuiltInVertexId = 5,
+ BuiltInInstanceId = 6,
+ BuiltInPrimitiveId = 7,
+ BuiltInInvocationId = 8,
+ BuiltInLayer = 9,
+ BuiltInViewportIndex = 10,
+ BuiltInTessLevelOuter = 11,
+ BuiltInTessLevelInner = 12,
+ BuiltInTessCoord = 13,
+ BuiltInPatchVertices = 14,
+ BuiltInFragCoord = 15,
+ BuiltInPointCoord = 16,
+ BuiltInFrontFacing = 17,
+ BuiltInSampleId = 18,
+ BuiltInSamplePosition = 19,
+ BuiltInSampleMask = 20,
+ BuiltInFragColor = 21,
+ BuiltInFragDepth = 22,
+ BuiltInHelperInvocation = 23,
+ BuiltInNumWorkgroups = 24,
+ BuiltInWorkgroupSize = 25,
+ BuiltInWorkgroupId = 26,
+ BuiltInLocalInvocationId = 27,
+ BuiltInGlobalInvocationId = 28,
+ BuiltInLocalInvocationIndex = 29,
+ BuiltInWorkDim = 30,
+ BuiltInGlobalSize = 31,
+ BuiltInEnqueuedWorkgroupSize = 32,
+ BuiltInGlobalOffset = 33,
+ BuiltInGlobalLinearId = 34,
+ BuiltInWorkgroupLinearId = 35,
+ BuiltInSubgroupSize = 36,
+ BuiltInSubgroupMaxSize = 37,
+ BuiltInNumSubgroups = 38,
+ BuiltInNumEnqueuedSubgroups = 39,
+ BuiltInSubgroupId = 40,
+ BuiltInSubgroupLocalInvocationId = 41,
+};
+
+enum SelectionControlShift {
+ SelectionControlFlattenShift = 0,
+ SelectionControlDontFlattenShift = 1,
+};
+
+enum SelectionControlMask {
+ SelectionControlMaskNone = 0,
+ SelectionControlFlattenMask = 0x00000001,
+ SelectionControlDontFlattenMask = 0x00000002,
+};
+
+enum LoopControlShift {
+ LoopControlUnrollShift = 0,
+ LoopControlDontUnrollShift = 1,
+};
+
+enum LoopControlMask {
+ LoopControlMaskNone = 0,
+ LoopControlUnrollMask = 0x00000001,
+ LoopControlDontUnrollMask = 0x00000002,
+};
+
+enum FunctionControlShift {
+ FunctionControlInlineShift = 0,
+ FunctionControlDontInlineShift = 1,
+ FunctionControlPureShift = 2,
+ FunctionControlConstShift = 3,
+};
+
+enum FunctionControlMask {
+ FunctionControlMaskNone = 0,
+ FunctionControlInlineMask = 0x00000001,
+ FunctionControlDontInlineMask = 0x00000002,
+ FunctionControlPureMask = 0x00000004,
+ FunctionControlConstMask = 0x00000008,
+};
+
+enum MemorySemanticsShift {
+ MemorySemanticsRelaxedShift = 0,
+ MemorySemanticsSequentiallyConsistentShift = 1,
+ MemorySemanticsAcquireShift = 2,
+ MemorySemanticsReleaseShift = 3,
+ MemorySemanticsUniformMemoryShift = 4,
+ MemorySemanticsSubgroupMemoryShift = 5,
+ MemorySemanticsWorkgroupLocalMemoryShift = 6,
+ MemorySemanticsWorkgroupGlobalMemoryShift = 7,
+ MemorySemanticsAtomicCounterMemoryShift = 8,
+ MemorySemanticsImageMemoryShift = 9,
+};
+
+enum MemorySemanticsMask {
+ MemorySemanticsMaskNone = 0,
+ MemorySemanticsRelaxedMask = 0x00000001,
+ MemorySemanticsSequentiallyConsistentMask = 0x00000002,
+ MemorySemanticsAcquireMask = 0x00000004,
+ MemorySemanticsReleaseMask = 0x00000008,
+ MemorySemanticsUniformMemoryMask = 0x00000010,
+ MemorySemanticsSubgroupMemoryMask = 0x00000020,
+ MemorySemanticsWorkgroupLocalMemoryMask = 0x00000040,
+ MemorySemanticsWorkgroupGlobalMemoryMask = 0x00000080,
+ MemorySemanticsAtomicCounterMemoryMask = 0x00000100,
+ MemorySemanticsImageMemoryMask = 0x00000200,
+};
+
+enum MemoryAccessShift {
+ MemoryAccessVolatileShift = 0,
+ MemoryAccessAlignedShift = 1,
+};
+
+enum MemoryAccessMask {
+ MemoryAccessMaskNone = 0,
+ MemoryAccessVolatileMask = 0x00000001,
+ MemoryAccessAlignedMask = 0x00000002,
+};
+
+enum Scope {
+ ScopeCrossDevice = 0,
+ ScopeDevice = 1,
+ ScopeWorkgroup = 2,
+ ScopeSubgroup = 3,
+ ScopeInvocation = 4,
+};
+
+enum GroupOperation {
+ GroupOperationReduce = 0,
+ GroupOperationInclusiveScan = 1,
+ GroupOperationExclusiveScan = 2,
+};
+
+enum KernelEnqueueFlags {
+ KernelEnqueueFlagsNoWait = 0,
+ KernelEnqueueFlagsWaitKernel = 1,
+ KernelEnqueueFlagsWaitWorkGroup = 2,
+};
+
+enum KernelProfilingInfoShift {
+ KernelProfilingInfoCmdExecTimeShift = 0,
+};
+
+enum KernelProfilingInfoMask {
+ KernelProfilingInfoMaskNone = 0,
+ KernelProfilingInfoCmdExecTimeMask = 0x00000001,
+};
+
+enum Capability {
+ CapabilityMatrix = 0,
+ CapabilityShader = 1,
+ CapabilityGeometry = 2,
+ CapabilityTessellation = 3,
+ CapabilityAddresses = 4,
+ CapabilityLinkage = 5,
+ CapabilityKernel = 6,
+ CapabilityVector16 = 7,
+ CapabilityFloat16Buffer = 8,
+ CapabilityFloat16 = 9,
+ CapabilityFloat64 = 10,
+ CapabilityInt64 = 11,
+ CapabilityInt64Atomics = 12,
+ CapabilityImageBasic = 13,
+ CapabilityImageReadWrite = 14,
+ CapabilityImageMipmap = 15,
+ CapabilityImageSRGBWrite = 16,
+ CapabilityPipes = 17,
+ CapabilityGroups = 18,
+ CapabilityDeviceEnqueue = 19,
+};
+
+enum Op {
+ OpNop = 0,
+ OpSource = 1,
+ OpSourceExtension = 2,
+ OpExtension = 3,
+ OpExtInstImport = 4,
+ OpMemoryModel = 5,
+ OpEntryPoint = 6,
+ OpExecutionMode = 7,
+ OpTypeVoid = 8,
+ OpTypeBool = 9,
+ OpTypeInt = 10,
+ OpTypeFloat = 11,
+ OpTypeVector = 12,
+ OpTypeMatrix = 13,
+ OpTypeSampler = 14,
+ OpTypeFilter = 15,
+ OpTypeArray = 16,
+ OpTypeRuntimeArray = 17,
+ OpTypeStruct = 18,
+ OpTypeOpaque = 19,
+ OpTypePointer = 20,
+ OpTypeFunction = 21,
+ OpTypeEvent = 22,
+ OpTypeDeviceEvent = 23,
+ OpTypeReserveId = 24,
+ OpTypeQueue = 25,
+ OpTypePipe = 26,
+ OpConstantTrue = 27,
+ OpConstantFalse = 28,
+ OpConstant = 29,
+ OpConstantComposite = 30,
+ OpConstantSampler = 31,
+ OpConstantNull = 32,
+ OpSpecConstantTrue = 34,
+ OpSpecConstantFalse = 35,
+ OpSpecConstant = 36,
+ OpSpecConstantComposite = 37,
+ OpVariable = 38,
+ OpVariableArray = 39,
+ OpFunction = 40,
+ OpFunctionParameter = 41,
+ OpFunctionEnd = 42,
+ OpFunctionCall = 43,
+ OpExtInst = 44,
+ OpUndef = 45,
+ OpLoad = 46,
+ OpStore = 47,
+ OpPhi = 48,
+ OpDecorationGroup = 49,
+ OpDecorate = 50,
+ OpMemberDecorate = 51,
+ OpGroupDecorate = 52,
+ OpGroupMemberDecorate = 53,
+ OpName = 54,
+ OpMemberName = 55,
+ OpString = 56,
+ OpLine = 57,
+ OpVectorExtractDynamic = 58,
+ OpVectorInsertDynamic = 59,
+ OpVectorShuffle = 60,
+ OpCompositeConstruct = 61,
+ OpCompositeExtract = 62,
+ OpCompositeInsert = 63,
+ OpCopyObject = 64,
+ OpCopyMemory = 65,
+ OpCopyMemorySized = 66,
+ OpSampler = 67,
+ OpTextureSample = 68,
+ OpTextureSampleDref = 69,
+ OpTextureSampleLod = 70,
+ OpTextureSampleProj = 71,
+ OpTextureSampleGrad = 72,
+ OpTextureSampleOffset = 73,
+ OpTextureSampleProjLod = 74,
+ OpTextureSampleProjGrad = 75,
+ OpTextureSampleLodOffset = 76,
+ OpTextureSampleProjOffset = 77,
+ OpTextureSampleGradOffset = 78,
+ OpTextureSampleProjLodOffset = 79,
+ OpTextureSampleProjGradOffset = 80,
+ OpTextureFetchTexelLod = 81,
+ OpTextureFetchTexelOffset = 82,
+ OpTextureFetchSample = 83,
+ OpTextureFetchTexel = 84,
+ OpTextureGather = 85,
+ OpTextureGatherOffset = 86,
+ OpTextureGatherOffsets = 87,
+ OpTextureQuerySizeLod = 88,
+ OpTextureQuerySize = 89,
+ OpTextureQueryLod = 90,
+ OpTextureQueryLevels = 91,
+ OpTextureQuerySamples = 92,
+ OpAccessChain = 93,
+ OpInBoundsAccessChain = 94,
+ OpSNegate = 95,
+ OpFNegate = 96,
+ OpNot = 97,
+ OpAny = 98,
+ OpAll = 99,
+ OpConvertFToU = 100,
+ OpConvertFToS = 101,
+ OpConvertSToF = 102,
+ OpConvertUToF = 103,
+ OpUConvert = 104,
+ OpSConvert = 105,
+ OpFConvert = 106,
+ OpConvertPtrToU = 107,
+ OpConvertUToPtr = 108,
+ OpPtrCastToGeneric = 109,
+ OpGenericCastToPtr = 110,
+ OpBitcast = 111,
+ OpTranspose = 112,
+ OpIsNan = 113,
+ OpIsInf = 114,
+ OpIsFinite = 115,
+ OpIsNormal = 116,
+ OpSignBitSet = 117,
+ OpLessOrGreater = 118,
+ OpOrdered = 119,
+ OpUnordered = 120,
+ OpArrayLength = 121,
+ OpIAdd = 122,
+ OpFAdd = 123,
+ OpISub = 124,
+ OpFSub = 125,
+ OpIMul = 126,
+ OpFMul = 127,
+ OpUDiv = 128,
+ OpSDiv = 129,
+ OpFDiv = 130,
+ OpUMod = 131,
+ OpSRem = 132,
+ OpSMod = 133,
+ OpFRem = 134,
+ OpFMod = 135,
+ OpVectorTimesScalar = 136,
+ OpMatrixTimesScalar = 137,
+ OpVectorTimesMatrix = 138,
+ OpMatrixTimesVector = 139,
+ OpMatrixTimesMatrix = 140,
+ OpOuterProduct = 141,
+ OpDot = 142,
+ OpShiftRightLogical = 143,
+ OpShiftRightArithmetic = 144,
+ OpShiftLeftLogical = 145,
+ OpLogicalOr = 146,
+ OpLogicalXor = 147,
+ OpLogicalAnd = 148,
+ OpBitwiseOr = 149,
+ OpBitwiseXor = 150,
+ OpBitwiseAnd = 151,
+ OpSelect = 152,
+ OpIEqual = 153,
+ OpFOrdEqual = 154,
+ OpFUnordEqual = 155,
+ OpINotEqual = 156,
+ OpFOrdNotEqual = 157,
+ OpFUnordNotEqual = 158,
+ OpULessThan = 159,
+ OpSLessThan = 160,
+ OpFOrdLessThan = 161,
+ OpFUnordLessThan = 162,
+ OpUGreaterThan = 163,
+ OpSGreaterThan = 164,
+ OpFOrdGreaterThan = 165,
+ OpFUnordGreaterThan = 166,
+ OpULessThanEqual = 167,
+ OpSLessThanEqual = 168,
+ OpFOrdLessThanEqual = 169,
+ OpFUnordLessThanEqual = 170,
+ OpUGreaterThanEqual = 171,
+ OpSGreaterThanEqual = 172,
+ OpFOrdGreaterThanEqual = 173,
+ OpFUnordGreaterThanEqual = 174,
+ OpDPdx = 175,
+ OpDPdy = 176,
+ OpFwidth = 177,
+ OpDPdxFine = 178,
+ OpDPdyFine = 179,
+ OpFwidthFine = 180,
+ OpDPdxCoarse = 181,
+ OpDPdyCoarse = 182,
+ OpFwidthCoarse = 183,
+ OpEmitVertex = 184,
+ OpEndPrimitive = 185,
+ OpEmitStreamVertex = 186,
+ OpEndStreamPrimitive = 187,
+ OpControlBarrier = 188,
+ OpMemoryBarrier = 189,
+ OpImagePointer = 190,
+ OpAtomicInit = 191,
+ OpAtomicLoad = 192,
+ OpAtomicStore = 193,
+ OpAtomicExchange = 194,
+ OpAtomicCompareExchange = 195,
+ OpAtomicCompareExchangeWeak = 196,
+ OpAtomicIIncrement = 197,
+ OpAtomicIDecrement = 198,
+ OpAtomicIAdd = 199,
+ OpAtomicISub = 200,
+ OpAtomicUMin = 201,
+ OpAtomicUMax = 202,
+ OpAtomicAnd = 203,
+ OpAtomicOr = 204,
+ OpAtomicXor = 205,
+ OpLoopMerge = 206,
+ OpSelectionMerge = 207,
+ OpLabel = 208,
+ OpBranch = 209,
+ OpBranchConditional = 210,
+ OpSwitch = 211,
+ OpKill = 212,
+ OpReturn = 213,
+ OpReturnValue = 214,
+ OpUnreachable = 215,
+ OpLifetimeStart = 216,
+ OpLifetimeStop = 217,
+ OpCompileFlag = 218,
+ OpAsyncGroupCopy = 219,
+ OpWaitGroupEvents = 220,
+ OpGroupAll = 221,
+ OpGroupAny = 222,
+ OpGroupBroadcast = 223,
+ OpGroupIAdd = 224,
+ OpGroupFAdd = 225,
+ OpGroupFMin = 226,
+ OpGroupUMin = 227,
+ OpGroupSMin = 228,
+ OpGroupFMax = 229,
+ OpGroupUMax = 230,
+ OpGroupSMax = 231,
+ OpGenericCastToPtrExplicit = 232,
+ OpGenericPtrMemSemantics = 233,
+ OpReadPipe = 234,
+ OpWritePipe = 235,
+ OpReservedReadPipe = 236,
+ OpReservedWritePipe = 237,
+ OpReserveReadPipePackets = 238,
+ OpReserveWritePipePackets = 239,
+ OpCommitReadPipe = 240,
+ OpCommitWritePipe = 241,
+ OpIsValidReserveId = 242,
+ OpGetNumPipePackets = 243,
+ OpGetMaxPipePackets = 244,
+ OpGroupReserveReadPipePackets = 245,
+ OpGroupReserveWritePipePackets = 246,
+ OpGroupCommitReadPipe = 247,
+ OpGroupCommitWritePipe = 248,
+ OpEnqueueMarker = 249,
+ OpEnqueueKernel = 250,
+ OpGetKernelNDrangeSubGroupCount = 251,
+ OpGetKernelNDrangeMaxSubGroupSize = 252,
+ OpGetKernelWorkGroupSize = 253,
+ OpGetKernelPreferredWorkGroupSizeMultiple = 254,
+ OpRetainEvent = 255,
+ OpReleaseEvent = 256,
+ OpCreateUserEvent = 257,
+ OpIsValidEvent = 258,
+ OpSetUserEventStatus = 259,
+ OpCaptureEventProfilingInfo = 260,
+ OpGetDefaultQueue = 261,
+ OpBuildNDRange = 262,
+ OpSatConvertSToU = 263,
+ OpSatConvertUToS = 264,
+ OpAtomicIMin = 265,
+ OpAtomicIMax = 266,
+ OpSpecConstantOp = 267,
+ OpCapability = 268,
+};
+
+}; // end namespace spv
+
+#endif // #ifdef __cplusplus
+
+
+#ifndef __cplusplus
+
+static const int SpvMagicNumber = 0x07230203;
+static const int SpvVersion = 99;
+
+typedef unsigned int SpvId;
+
+static const unsigned int SpvOpCodeMask = 0xFFFF;
+static const unsigned int SpvWordCountShift = 16;
+
+typedef enum SpvSourceLanguage_ {
+ SpvSourceLanguageUnknown = 0,
+ SpvSourceLanguageESSL = 1,
+ SpvSourceLanguageGLSL = 2,
+ SpvSourceLanguageOpenCL = 3,
+} SpvSourceLanguage;
+
+typedef enum SpvExecutionModel_ {
+ SpvExecutionModelVertex = 0,
+ SpvExecutionModelTessellationControl = 1,
+ SpvExecutionModelTessellationEvaluation = 2,
+ SpvExecutionModelGeometry = 3,
+ SpvExecutionModelFragment = 4,
+ SpvExecutionModelGLCompute = 5,
+ SpvExecutionModelKernel = 6,
+} SpvExecutionModel;
+
+typedef enum SpvAddressingModel_ {
+ SpvAddressingModelLogical = 0,
+ SpvAddressingModelPhysical32 = 1,
+ SpvAddressingModelPhysical64 = 2,
+} SpvAddressingModel;
+
+typedef enum SpvMemoryModel_ {
+ SpvMemoryModelSimple = 0,
+ SpvMemoryModelGLSL450 = 1,
+ SpvMemoryModelOpenCL12 = 2,
+ SpvMemoryModelOpenCL20 = 3,
+ SpvMemoryModelOpenCL21 = 4,
+} SpvMemoryModel;
+
+typedef enum SpvExecutionMode_ {
+ SpvExecutionModeInvocations = 0,
+ SpvExecutionModeSpacingEqual = 1,
+ SpvExecutionModeSpacingFractionalEven = 2,
+ SpvExecutionModeSpacingFractionalOdd = 3,
+ SpvExecutionModeVertexOrderCw = 4,
+ SpvExecutionModeVertexOrderCcw = 5,
+ SpvExecutionModePixelCenterInteger = 6,
+ SpvExecutionModeOriginUpperLeft = 7,
+ SpvExecutionModeEarlyFragmentTests = 8,
+ SpvExecutionModePointMode = 9,
+ SpvExecutionModeXfb = 10,
+ SpvExecutionModeDepthReplacing = 11,
+ SpvExecutionModeDepthAny = 12,
+ SpvExecutionModeDepthGreater = 13,
+ SpvExecutionModeDepthLess = 14,
+ SpvExecutionModeDepthUnchanged = 15,
+ SpvExecutionModeLocalSize = 16,
+ SpvExecutionModeLocalSizeHint = 17,
+ SpvExecutionModeInputPoints = 18,
+ SpvExecutionModeInputLines = 19,
+ SpvExecutionModeInputLinesAdjacency = 20,
+ SpvExecutionModeInputTriangles = 21,
+ SpvExecutionModeInputTrianglesAdjacency = 22,
+ SpvExecutionModeInputQuads = 23,
+ SpvExecutionModeInputIsolines = 24,
+ SpvExecutionModeOutputVertices = 25,
+ SpvExecutionModeOutputPoints = 26,
+ SpvExecutionModeOutputLineStrip = 27,
+ SpvExecutionModeOutputTriangleStrip = 28,
+ SpvExecutionModeVecTypeHint = 29,
+ SpvExecutionModeContractionOff = 30,
+ SpvExecutionModeOriginLowerLeft = 31,
+} SpvExecutionMode;
+
+typedef enum SpvStorageClass_ {
+ SpvStorageClassUniformConstant = 0,
+ SpvStorageClassInput = 1,
+ SpvStorageClassUniform = 2,
+ SpvStorageClassOutput = 3,
+ SpvStorageClassWorkgroupLocal = 4,
+ SpvStorageClassWorkgroupGlobal = 5,
+ SpvStorageClassPrivateGlobal = 6,
+ SpvStorageClassFunction = 7,
+ SpvStorageClassGeneric = 8,
+ SpvStorageClassAtomicCounter = 10,
+} SpvStorageClass;
+
+typedef enum SpvDim_ {
+ SpvDim1D = 0,
+ SpvDim2D = 1,
+ SpvDim3D = 2,
+ SpvDimCube = 3,
+ SpvDimRect = 4,
+ SpvDimBuffer = 5,
+} SpvDim;
+
+typedef enum SpvSamplerAddressingMode_ {
+ SpvSamplerAddressingModeNone = 0,
+ SpvSamplerAddressingModeClampToEdge = 1,
+ SpvSamplerAddressingModeClamp = 2,
+ SpvSamplerAddressingModeRepeat = 3,
+ SpvSamplerAddressingModeRepeatMirrored = 4,
+} SpvSamplerAddressingMode;
+
+typedef enum SpvSamplerFilterMode_ {
+ SpvSamplerFilterModeNearest = 0,
+ SpvSamplerFilterModeLinear = 1,
+} SpvSamplerFilterMode;
+
+typedef enum SpvFPFastMathModeShift_ {
+ SpvFPFastMathModeNotNaNShift = 0,
+ SpvFPFastMathModeNotInfShift = 1,
+ SpvFPFastMathModeNSZShift = 2,
+ SpvFPFastMathModeAllowRecipShift = 3,
+ SpvFPFastMathModeFastShift = 4,
+} SpvFPFastMathModeShift;
+
+typedef enum SpvFPFastMathModeMask_ {
+ SpvFPFastMathModeMaskNone = 0,
+ SpvFPFastMathModeNotNaNMask = 0x00000001,
+ SpvFPFastMathModeNotInfMask = 0x00000002,
+ SpvFPFastMathModeNSZMask = 0x00000004,
+ SpvFPFastMathModeAllowRecipMask = 0x00000008,
+ SpvFPFastMathModeFastMask = 0x00000010,
+} SpvFPFastMathModeMask;
+
+typedef enum SpvFPRoundingMode_ {
+ SpvFPRoundingModeRTE = 0,
+ SpvFPRoundingModeRTZ = 1,
+ SpvFPRoundingModeRTP = 2,
+ SpvFPRoundingModeRTN = 3,
+} SpvFPRoundingMode;
+
+typedef enum SpvLinkageType_ {
+ SpvLinkageTypeExport = 0,
+ SpvLinkageTypeImport = 1,
+} SpvLinkageType;
+
+typedef enum SpvAccessQualifier_ {
+ SpvAccessQualifierReadOnly = 0,
+ SpvAccessQualifierWriteOnly = 1,
+ SpvAccessQualifierReadWrite = 2,
+} SpvAccessQualifier;
+
+typedef enum SpvFunctionParameterAttribute_ {
+ SpvFunctionParameterAttributeZext = 0,
+ SpvFunctionParameterAttributeSext = 1,
+ SpvFunctionParameterAttributeByVal = 2,
+ SpvFunctionParameterAttributeSret = 3,
+ SpvFunctionParameterAttributeNoAlias = 4,
+ SpvFunctionParameterAttributeNoCapture = 5,
+ SpvFunctionParameterAttributeSVM = 6,
+ SpvFunctionParameterAttributeNoWrite = 7,
+ SpvFunctionParameterAttributeNoReadWrite = 8,
+} SpvFunctionParameterAttribute;
+
+typedef enum SpvDecoration_ {
+ SpvDecorationPrecisionLow = 0,
+ SpvDecorationPrecisionMedium = 1,
+ SpvDecorationPrecisionHigh = 2,
+ SpvDecorationBlock = 3,
+ SpvDecorationBufferBlock = 4,
+ SpvDecorationRowMajor = 5,
+ SpvDecorationColMajor = 6,
+ SpvDecorationGLSLShared = 7,
+ SpvDecorationGLSLStd140 = 8,
+ SpvDecorationGLSLStd430 = 9,
+ SpvDecorationGLSLPacked = 10,
+ SpvDecorationSmooth = 11,
+ SpvDecorationNoperspective = 12,
+ SpvDecorationFlat = 13,
+ SpvDecorationPatch = 14,
+ SpvDecorationCentroid = 15,
+ SpvDecorationSample = 16,
+ SpvDecorationInvariant = 17,
+ SpvDecorationRestrict = 18,
+ SpvDecorationAliased = 19,
+ SpvDecorationVolatile = 20,
+ SpvDecorationConstant = 21,
+ SpvDecorationCoherent = 22,
+ SpvDecorationNonwritable = 23,
+ SpvDecorationNonreadable = 24,
+ SpvDecorationUniform = 25,
+ SpvDecorationNoStaticUse = 26,
+ SpvDecorationCPacked = 27,
+ SpvDecorationSaturatedConversion = 28,
+ SpvDecorationStream = 29,
+ SpvDecorationLocation = 30,
+ SpvDecorationComponent = 31,
+ SpvDecorationIndex = 32,
+ SpvDecorationBinding = 33,
+ SpvDecorationDescriptorSet = 34,
+ SpvDecorationOffset = 35,
+ SpvDecorationAlignment = 36,
+ SpvDecorationXfbBuffer = 37,
+ SpvDecorationStride = 38,
+ SpvDecorationBuiltIn = 39,
+ SpvDecorationFuncParamAttr = 40,
+ SpvDecorationFPRoundingMode = 41,
+ SpvDecorationFPFastMathMode = 42,
+ SpvDecorationLinkageAttributes = 43,
+ SpvDecorationSpecId = 44,
+} SpvDecoration;
+
+typedef enum SpvBuiltIn_ {
+ SpvBuiltInPosition = 0,
+ SpvBuiltInPointSize = 1,
+ SpvBuiltInClipVertex = 2,
+ SpvBuiltInClipDistance = 3,
+ SpvBuiltInCullDistance = 4,
+ SpvBuiltInVertexId = 5,
+ SpvBuiltInInstanceId = 6,
+ SpvBuiltInPrimitiveId = 7,
+ SpvBuiltInInvocationId = 8,
+ SpvBuiltInLayer = 9,
+ SpvBuiltInViewportIndex = 10,
+ SpvBuiltInTessLevelOuter = 11,
+ SpvBuiltInTessLevelInner = 12,
+ SpvBuiltInTessCoord = 13,
+ SpvBuiltInPatchVertices = 14,
+ SpvBuiltInFragCoord = 15,
+ SpvBuiltInPointCoord = 16,
+ SpvBuiltInFrontFacing = 17,
+ SpvBuiltInSampleId = 18,
+ SpvBuiltInSamplePosition = 19,
+ SpvBuiltInSampleMask = 20,
+ SpvBuiltInFragColor = 21,
+ SpvBuiltInFragDepth = 22,
+ SpvBuiltInHelperInvocation = 23,
+ SpvBuiltInNumWorkgroups = 24,
+ SpvBuiltInWorkgroupSize = 25,
+ SpvBuiltInWorkgroupId = 26,
+ SpvBuiltInLocalInvocationId = 27,
+ SpvBuiltInGlobalInvocationId = 28,
+ SpvBuiltInLocalInvocationIndex = 29,
+ SpvBuiltInWorkDim = 30,
+ SpvBuiltInGlobalSize = 31,
+ SpvBuiltInEnqueuedWorkgroupSize = 32,
+ SpvBuiltInGlobalOffset = 33,
+ SpvBuiltInGlobalLinearId = 34,
+ SpvBuiltInWorkgroupLinearId = 35,
+ SpvBuiltInSubgroupSize = 36,
+ SpvBuiltInSubgroupMaxSize = 37,
+ SpvBuiltInNumSubgroups = 38,
+ SpvBuiltInNumEnqueuedSubgroups = 39,
+ SpvBuiltInSubgroupId = 40,
+ SpvBuiltInSubgroupLocalInvocationId = 41,
+} SpvBuiltIn;
+
+typedef enum SpvSelectionControlShift_ {
+ SpvSelectionControlFlattenShift = 0,
+ SpvSelectionControlDontFlattenShift = 1,
+} SpvSelectionControlShift;
+
+typedef enum SpvSelectionControlMask_ {
+ SpvSelectionControlMaskNone = 0,
+ SpvSelectionControlFlattenMask = 0x00000001,
+ SpvSelectionControlDontFlattenMask = 0x00000002,
+} SpvSelectionControlMask;
+
+typedef enum SpvLoopControlShift_ {
+ SpvLoopControlUnrollShift = 0,
+ SpvLoopControlDontUnrollShift = 1,
+} SpvLoopControlShift;
+
+typedef enum SpvLoopControlMask_ {
+ SpvLoopControlMaskNone = 0,
+ SpvLoopControlUnrollMask = 0x00000001,
+ SpvLoopControlDontUnrollMask = 0x00000002,
+} SpvLoopControlMask;
+
+typedef enum SpvFunctionControlShift_ {
+ SpvFunctionControlInlineShift = 0,
+ SpvFunctionControlDontInlineShift = 1,
+ SpvFunctionControlPureShift = 2,
+ SpvFunctionControlConstShift = 3,
+} SpvFunctionControlShift;
+
+typedef enum SpvFunctionControlMask_ {
+ SpvFunctionControlMaskNone = 0,
+ SpvFunctionControlInlineMask = 0x00000001,
+ SpvFunctionControlDontInlineMask = 0x00000002,
+ SpvFunctionControlPureMask = 0x00000004,
+ SpvFunctionControlConstMask = 0x00000008,
+} SpvFunctionControlMask;
+
+typedef enum SpvMemorySemanticsShift_ {
+ SpvMemorySemanticsRelaxedShift = 0,
+ SpvMemorySemanticsSequentiallyConsistentShift = 1,
+ SpvMemorySemanticsAcquireShift = 2,
+ SpvMemorySemanticsReleaseShift = 3,
+ SpvMemorySemanticsUniformMemoryShift = 4,
+ SpvMemorySemanticsSubgroupMemoryShift = 5,
+ SpvMemorySemanticsWorkgroupLocalMemoryShift = 6,
+ SpvMemorySemanticsWorkgroupGlobalMemoryShift = 7,
+ SpvMemorySemanticsAtomicCounterMemoryShift = 8,
+ SpvMemorySemanticsImageMemoryShift = 9,
+} SpvMemorySemanticsShift;
+
+typedef enum SpvMemorySemanticsMask_ {
+ SpvMemorySemanticsMaskNone = 0,
+ SpvMemorySemanticsRelaxedMask = 0x00000001,
+ SpvMemorySemanticsSequentiallyConsistentMask = 0x00000002,
+ SpvMemorySemanticsAcquireMask = 0x00000004,
+ SpvMemorySemanticsReleaseMask = 0x00000008,
+ SpvMemorySemanticsUniformMemoryMask = 0x00000010,
+ SpvMemorySemanticsSubgroupMemoryMask = 0x00000020,
+ SpvMemorySemanticsWorkgroupLocalMemoryMask = 0x00000040,
+ SpvMemorySemanticsWorkgroupGlobalMemoryMask = 0x00000080,
+ SpvMemorySemanticsAtomicCounterMemoryMask = 0x00000100,
+ SpvMemorySemanticsImageMemoryMask = 0x00000200,
+} SpvMemorySemanticsMask;
+
+typedef enum SpvMemoryAccessShift_ {
+ SpvMemoryAccessVolatileShift = 0,
+ SpvMemoryAccessAlignedShift = 1,
+} SpvMemoryAccessShift;
+
+typedef enum SpvMemoryAccessMask_ {
+ SpvMemoryAccessMaskNone = 0,
+ SpvMemoryAccessVolatileMask = 0x00000001,
+ SpvMemoryAccessAlignedMask = 0x00000002,
+} SpvMemoryAccessMask;
+
+typedef enum SpvScope_ {
+ SpvScopeCrossDevice = 0,
+ SpvScopeDevice = 1,
+ SpvScopeWorkgroup = 2,
+ SpvScopeSubgroup = 3,
+ SpvScopeInvocation = 4,
+} SpvScope;
+
+typedef enum SpvGroupOperation_ {
+ SpvGroupOperationReduce = 0,
+ SpvGroupOperationInclusiveScan = 1,
+ SpvGroupOperationExclusiveScan = 2,
+} SpvGroupOperation;
+
+typedef enum SpvKernelEnqueueFlags_ {
+ SpvKernelEnqueueFlagsNoWait = 0,
+ SpvKernelEnqueueFlagsWaitKernel = 1,
+ SpvKernelEnqueueFlagsWaitWorkGroup = 2,
+} SpvKernelEnqueueFlags;
+
+typedef enum SpvKernelProfilingInfoShift_ {
+ SpvKernelProfilingInfoCmdExecTimeShift = 0,
+} SpvKernelProfilingInfoShift;
+
+typedef enum SpvKernelProfilingInfoMask_ {
+ SpvKernelProfilingInfoMaskNone = 0,
+ SpvKernelProfilingInfoCmdExecTimeMask = 0x00000001,
+} SpvKernelProfilingInfoMask;
+
+typedef enum SpvCapability_ {
+ SpvCapabilityMatrix = 0,
+ SpvCapabilityShader = 1,
+ SpvCapabilityGeometry = 2,
+ SpvCapabilityTessellation = 3,
+ SpvCapabilityAddresses = 4,
+ SpvCapabilityLinkage = 5,
+ SpvCapabilityKernel = 6,
+ SpvCapabilityVector16 = 7,
+ SpvCapabilityFloat16Buffer = 8,
+ SpvCapabilityFloat16 = 9,
+ SpvCapabilityFloat64 = 10,
+ SpvCapabilityInt64 = 11,
+ SpvCapabilityInt64Atomics = 12,
+ SpvCapabilityImageBasic = 13,
+ SpvCapabilityImageReadWrite = 14,
+ SpvCapabilityImageMipmap = 15,
+ SpvCapabilityImageSRGBWrite = 16,
+ SpvCapabilityPipes = 17,
+ SpvCapabilityGroups = 18,
+ SpvCapabilityDeviceEnqueue = 19,
+} SpvCapability;
+
+typedef enum SpvOp_ {
+ SpvOpNop = 0,
+ SpvOpSource = 1,
+ SpvOpSourceExtension = 2,
+ SpvOpExtension = 3,
+ SpvOpExtInstImport = 4,
+ SpvOpMemoryModel = 5,
+ SpvOpEntryPoint = 6,
+ SpvOpExecutionMode = 7,
+ SpvOpTypeVoid = 8,
+ SpvOpTypeBool = 9,
+ SpvOpTypeInt = 10,
+ SpvOpTypeFloat = 11,
+ SpvOpTypeVector = 12,
+ SpvOpTypeMatrix = 13,
+ SpvOpTypeSampler = 14,
+ SpvOpTypeFilter = 15,
+ SpvOpTypeArray = 16,
+ SpvOpTypeRuntimeArray = 17,
+ SpvOpTypeStruct = 18,
+ SpvOpTypeOpaque = 19,
+ SpvOpTypePointer = 20,
+ SpvOpTypeFunction = 21,
+ SpvOpTypeEvent = 22,
+ SpvOpTypeDeviceEvent = 23,
+ SpvOpTypeReserveId = 24,
+ SpvOpTypeQueue = 25,
+ SpvOpTypePipe = 26,
+ SpvOpConstantTrue = 27,
+ SpvOpConstantFalse = 28,
+ SpvOpConstant = 29,
+ SpvOpConstantComposite = 30,
+ SpvOpConstantSampler = 31,
+ SpvOpConstantNull = 32,
+ SpvOpSpecConstantTrue = 34,
+ SpvOpSpecConstantFalse = 35,
+ SpvOpSpecConstant = 36,
+ SpvOpSpecConstantComposite = 37,
+ SpvOpVariable = 38,
+ SpvOpVariableArray = 39,
+ SpvOpFunction = 40,
+ SpvOpFunctionParameter = 41,
+ SpvOpFunctionEnd = 42,
+ SpvOpFunctionCall = 43,
+ SpvOpExtInst = 44,
+ SpvOpUndef = 45,
+ SpvOpLoad = 46,
+ SpvOpStore = 47,
+ SpvOpPhi = 48,
+ SpvOpDecorationGroup = 49,
+ SpvOpDecorate = 50,
+ SpvOpMemberDecorate = 51,
+ SpvOpGroupDecorate = 52,
+ SpvOpGroupMemberDecorate = 53,
+ SpvOpName = 54,
+ SpvOpMemberName = 55,
+ SpvOpString = 56,
+ SpvOpLine = 57,
+ SpvOpVectorExtractDynamic = 58,
+ SpvOpVectorInsertDynamic = 59,
+ SpvOpVectorShuffle = 60,
+ SpvOpCompositeConstruct = 61,
+ SpvOpCompositeExtract = 62,
+ SpvOpCompositeInsert = 63,
+ SpvOpCopyObject = 64,
+ SpvOpCopyMemory = 65,
+ SpvOpCopyMemorySized = 66,
+ SpvOpSampler = 67,
+ SpvOpTextureSample = 68,
+ SpvOpTextureSampleDref = 69,
+ SpvOpTextureSampleLod = 70,
+ SpvOpTextureSampleProj = 71,
+ SpvOpTextureSampleGrad = 72,
+ SpvOpTextureSampleOffset = 73,
+ SpvOpTextureSampleProjLod = 74,
+ SpvOpTextureSampleProjGrad = 75,
+ SpvOpTextureSampleLodOffset = 76,
+ SpvOpTextureSampleProjOffset = 77,
+ SpvOpTextureSampleGradOffset = 78,
+ SpvOpTextureSampleProjLodOffset = 79,
+ SpvOpTextureSampleProjGradOffset = 80,
+ SpvOpTextureFetchTexelLod = 81,
+ SpvOpTextureFetchTexelOffset = 82,
+ SpvOpTextureFetchSample = 83,
+ SpvOpTextureFetchTexel = 84,
+ SpvOpTextureGather = 85,
+ SpvOpTextureGatherOffset = 86,
+ SpvOpTextureGatherOffsets = 87,
+ SpvOpTextureQuerySizeLod = 88,
+ SpvOpTextureQuerySize = 89,
+ SpvOpTextureQueryLod = 90,
+ SpvOpTextureQueryLevels = 91,
+ SpvOpTextureQuerySamples = 92,
+ SpvOpAccessChain = 93,
+ SpvOpInBoundsAccessChain = 94,
+ SpvOpSNegate = 95,
+ SpvOpFNegate = 96,
+ SpvOpNot = 97,
+ SpvOpAny = 98,
+ SpvOpAll = 99,
+ SpvOpConvertFToU = 100,
+ SpvOpConvertFToS = 101,
+ SpvOpConvertSToF = 102,
+ SpvOpConvertUToF = 103,
+ SpvOpUConvert = 104,
+ SpvOpSConvert = 105,
+ SpvOpFConvert = 106,
+ SpvOpConvertPtrToU = 107,
+ SpvOpConvertUToPtr = 108,
+ SpvOpPtrCastToGeneric = 109,
+ SpvOpGenericCastToPtr = 110,
+ SpvOpBitcast = 111,
+ SpvOpTranspose = 112,
+ SpvOpIsNan = 113,
+ SpvOpIsInf = 114,
+ SpvOpIsFinite = 115,
+ SpvOpIsNormal = 116,
+ SpvOpSignBitSet = 117,
+ SpvOpLessOrGreater = 118,
+ SpvOpOrdered = 119,
+ SpvOpUnordered = 120,
+ SpvOpArrayLength = 121,
+ SpvOpIAdd = 122,
+ SpvOpFAdd = 123,
+ SpvOpISub = 124,
+ SpvOpFSub = 125,
+ SpvOpIMul = 126,
+ SpvOpFMul = 127,
+ SpvOpUDiv = 128,
+ SpvOpSDiv = 129,
+ SpvOpFDiv = 130,
+ SpvOpUMod = 131,
+ SpvOpSRem = 132,
+ SpvOpSMod = 133,
+ SpvOpFRem = 134,
+ SpvOpFMod = 135,
+ SpvOpVectorTimesScalar = 136,
+ SpvOpMatrixTimesScalar = 137,
+ SpvOpVectorTimesMatrix = 138,
+ SpvOpMatrixTimesVector = 139,
+ SpvOpMatrixTimesMatrix = 140,
+ SpvOpOuterProduct = 141,
+ SpvOpDot = 142,
+ SpvOpShiftRightLogical = 143,
+ SpvOpShiftRightArithmetic = 144,
+ SpvOpShiftLeftLogical = 145,
+ SpvOpLogicalOr = 146,
+ SpvOpLogicalXor = 147,
+ SpvOpLogicalAnd = 148,
+ SpvOpBitwiseOr = 149,
+ SpvOpBitwiseXor = 150,
+ SpvOpBitwiseAnd = 151,
+ SpvOpSelect = 152,
+ SpvOpIEqual = 153,
+ SpvOpFOrdEqual = 154,
+ SpvOpFUnordEqual = 155,
+ SpvOpINotEqual = 156,
+ SpvOpFOrdNotEqual = 157,
+ SpvOpFUnordNotEqual = 158,
+ SpvOpULessThan = 159,
+ SpvOpSLessThan = 160,
+ SpvOpFOrdLessThan = 161,
+ SpvOpFUnordLessThan = 162,
+ SpvOpUGreaterThan = 163,
+ SpvOpSGreaterThan = 164,
+ SpvOpFOrdGreaterThan = 165,
+ SpvOpFUnordGreaterThan = 166,
+ SpvOpULessThanEqual = 167,
+ SpvOpSLessThanEqual = 168,
+ SpvOpFOrdLessThanEqual = 169,
+ SpvOpFUnordLessThanEqual = 170,
+ SpvOpUGreaterThanEqual = 171,
+ SpvOpSGreaterThanEqual = 172,
+ SpvOpFOrdGreaterThanEqual = 173,
+ SpvOpFUnordGreaterThanEqual = 174,
+ SpvOpDPdx = 175,
+ SpvOpDPdy = 176,
+ SpvOpFwidth = 177,
+ SpvOpDPdxFine = 178,
+ SpvOpDPdyFine = 179,
+ SpvOpFwidthFine = 180,
+ SpvOpDPdxCoarse = 181,
+ SpvOpDPdyCoarse = 182,
+ SpvOpFwidthCoarse = 183,
+ SpvOpEmitVertex = 184,
+ SpvOpEndPrimitive = 185,
+ SpvOpEmitStreamVertex = 186,
+ SpvOpEndStreamPrimitive = 187,
+ SpvOpControlBarrier = 188,
+ SpvOpMemoryBarrier = 189,
+ SpvOpImagePointer = 190,
+ SpvOpAtomicInit = 191,
+ SpvOpAtomicLoad = 192,
+ SpvOpAtomicStore = 193,
+ SpvOpAtomicExchange = 194,
+ SpvOpAtomicCompareExchange = 195,
+ SpvOpAtomicCompareExchangeWeak = 196,
+ SpvOpAtomicIIncrement = 197,
+ SpvOpAtomicIDecrement = 198,
+ SpvOpAtomicIAdd = 199,
+ SpvOpAtomicISub = 200,
+ SpvOpAtomicUMin = 201,
+ SpvOpAtomicUMax = 202,
+ SpvOpAtomicAnd = 203,
+ SpvOpAtomicOr = 204,
+ SpvOpAtomicXor = 205,
+ SpvOpLoopMerge = 206,
+ SpvOpSelectionMerge = 207,
+ SpvOpLabel = 208,
+ SpvOpBranch = 209,
+ SpvOpBranchConditional = 210,
+ SpvOpSwitch = 211,
+ SpvOpKill = 212,
+ SpvOpReturn = 213,
+ SpvOpReturnValue = 214,
+ SpvOpUnreachable = 215,
+ SpvOpLifetimeStart = 216,
+ SpvOpLifetimeStop = 217,
+ SpvOpCompileFlag = 218,
+ SpvOpAsyncGroupCopy = 219,
+ SpvOpWaitGroupEvents = 220,
+ SpvOpGroupAll = 221,
+ SpvOpGroupAny = 222,
+ SpvOpGroupBroadcast = 223,
+ SpvOpGroupIAdd = 224,
+ SpvOpGroupFAdd = 225,
+ SpvOpGroupFMin = 226,
+ SpvOpGroupUMin = 227,
+ SpvOpGroupSMin = 228,
+ SpvOpGroupFMax = 229,
+ SpvOpGroupUMax = 230,
+ SpvOpGroupSMax = 231,
+ SpvOpGenericCastToPtrExplicit = 232,
+ SpvOpGenericPtrMemSemantics = 233,
+ SpvOpReadPipe = 234,
+ SpvOpWritePipe = 235,
+ SpvOpReservedReadPipe = 236,
+ SpvOpReservedWritePipe = 237,
+ SpvOpReserveReadPipePackets = 238,
+ SpvOpReserveWritePipePackets = 239,
+ SpvOpCommitReadPipe = 240,
+ SpvOpCommitWritePipe = 241,
+ SpvOpIsValidReserveId = 242,
+ SpvOpGetNumPipePackets = 243,
+ SpvOpGetMaxPipePackets = 244,
+ SpvOpGroupReserveReadPipePackets = 245,
+ SpvOpGroupReserveWritePipePackets = 246,
+ SpvOpGroupCommitReadPipe = 247,
+ SpvOpGroupCommitWritePipe = 248,
+ SpvOpEnqueueMarker = 249,
+ SpvOpEnqueueKernel = 250,
+ SpvOpGetKernelNDrangeSubGroupCount = 251,
+ SpvOpGetKernelNDrangeMaxSubGroupSize = 252,
+ SpvOpGetKernelWorkGroupSize = 253,
+ SpvOpGetKernelPreferredWorkGroupSizeMultiple = 254,
+ SpvOpRetainEvent = 255,
+ SpvOpReleaseEvent = 256,
+ SpvOpCreateUserEvent = 257,
+ SpvOpIsValidEvent = 258,
+ SpvOpSetUserEventStatus = 259,
+ SpvOpCaptureEventProfilingInfo = 260,
+ SpvOpGetDefaultQueue = 261,
+ SpvOpBuildNDRange = 262,
+ SpvOpSatConvertSToU = 263,
+ SpvOpSatConvertUToS = 264,
+ SpvOpAtomicIMin = 265,
+ SpvOpAtomicIMax = 266,
+ SpvOpSpecConstantOp = 267,
+ SpvOpCapability = 268,
+} SpvOp;
+
+#endif // #ifndef __cplusplus
+
+#endif // #ifndef spirv_H
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#ifndef _CODEPLAY_SPIRV_SPIRV_H_
+#define _CODEPLAY_SPIRV_SPIRV_H_
+
+#include <headers/spirv.h>
+#include <headers/GLSL450Lib.h>
+#include <headers/OpenCLLib.h>
+
+#ifdef __cplusplus
+using namespace spv;
+extern "C" {
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+// Magic numbers
+
+#define SPV_MAGIC_NUMBER 0x07230203
+#define SPV_VERSION_NUMBER 99u
+
+// Header indices
+
+#define SPV_INDEX_MAGIC_NUMBER 0u
+#define SPV_INDEX_VERSION_NUMBER 1u
+#define SPV_INDEX_GENERATOR_NUMBER 2u
+#define SPV_INDEX_BOUND 3u
+#define SPV_INDEX_SCHEMA 4u
+#define SPV_INDEX_INSTRUCTION 5u
+
+// Universal limits
+
+// NOTE: These are set to the minimum maximum values
+#define SPV_LIMIT_LITERAL_NAME_MAX 0x00000400
+#define SPV_LIMIT_LITERAL_STRING_MAX 0x00010000
+#define SPV_LIMIT_INSTRUCTION_WORD_COUNT_MAX 0x00000108
+#define SPV_LIMIT_RESULT_ID_BOUND 0x00400000
+#define SPV_LIMIT_CONTROL_FLOW_NEST_DEPTH 0x00000400
+#define SPV_LIMIT_GLOBAL_VARIABLES_MAX 0x00010000
+#define SPV_LIMIT_LOCAL_VARIABLES_MAX 0x00080000
+// TODO: Decorations per target ID max, depends on decoration table size
+#define SPV_LIMIT_EXECUTION_MODE_PER_ENTRY_POINT_MAX 0x00000100
+#define SPV_LIMIT_INDICIES_MAX_ACCESS_CHAIN_COMPOSITE_MAX 0x00000100
+#define SPV_LIMIT_FUNCTION_PARAMETERS_PER_FUNCTION_DECL 0x00000100
+#define SPV_LIMIT_FUNCTION_CALL_ARGUMENTS_MAX 0x00000100
+#define SPV_LIMIT_EXT_FUNCTION_CALL_ARGUMENTS_MAX 0x00000100
+#define SPV_LIMIT_SWITCH_LITERAL_LABEL_PAIRS_MAX 0x00004000
+#define SPV_LIMIT_STRUCT_MEMBERS_MAX 0x0000400
+#define SPV_LIMIT_STRUCT_NESTING_DEPTH_MAX 0x00000100
+
+// Helpers
+
+#define spvCheck(condition, action) \
+ if (condition) { \
+ action; \
+ }
+
+#define spvCheckReturn(expression) \
+ { \
+ spv_result_t error = (expression); \
+ if (error) { \
+ return error; \
+ } \
+ }
+
+#define spvIsInBitfield(value, bitfield) (value == (value & bitfield))
+
+#define SPV_BIT(shift) 1 << shift
+
+#define SPV_FORCE_16_BIT_ENUM(name) _##name = 0x7fff
+#define SPV_FORCE_32_BIT_ENUM(name) _##name = 0x7fffffff
+
+// Enumerations
+
+typedef enum spv_generator_t {
+ SPV_GENERATOR_KHRONOS = 0,
+ SPV_GENERATOR_VALVE = 1,
+ SPV_GENERATOR_LUNARG = 2,
+ SPV_GENERATOR_CODEPLAY = 3,
+ SPV_FORCE_32_BIT_ENUM(spv_generator_t)
+} spv_generator_t;
+
+typedef enum spv_result_t {
+ SPV_SUCCESS = 0,
+ SPV_UNSUPPORTED = 1,
+ SPV_END_OF_STREAM = 2,
+ SPV_WARNING = 3,
+ SPV_ERROR_INTERNAL = -1,
+ SPV_ERROR_OUT_OF_MEMORY = -2,
+ SPV_ERROR_INVALID_POINTER = -3,
+ SPV_ERROR_INVALID_BINARY = -4,
+ SPV_ERROR_INVALID_TEXT = -5,
+ SPV_ERROR_INVALID_TABLE = -6,
+ SPV_ERROR_INVALID_VALUE = -7,
+ SPV_ERROR_INVALID_DIAGNOSTIC = -8,
+ SPV_ERROR_INVALID_LOOKUP = -9,
+ SPV_ERROR_INVALID_ID = -10,
+ SPV_FORCE_32_BIT_ENUM(spv_result_t)
+} spv_result_t;
+
+typedef enum spv_endianness_t {
+ SPV_ENDIANNESS_LITTLE,
+ SPV_ENDIANNESS_BIG,
+ SPV_FORCE_32_BIT_ENUM(spv_endianness_t)
+} spv_endianness_t;
+
+typedef enum spv_opcode_flags_t {
+ SPV_OPCODE_FLAGS_NONE = 0,
+ SPV_OPCODE_FLAGS_VARIABLE = 1,
+ SPV_OPCODE_FLAGS_CAPABILITIES = 2,
+ SPV_FORCE_32_BIT_ENUM(spv_opcode_flags_t)
+} spv_opcode_flags_t;
+
+typedef enum spv_operand_type_t {
+ SPV_OPERAND_TYPE_NONE,
+ SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_LITERAL,
+ SPV_OPERAND_TYPE_LITERAL_NUMBER,
+ SPV_OPERAND_TYPE_LITERAL_STRING,
+ SPV_OPERAND_TYPE_SOURCE_LANGUAGE,
+ SPV_OPERAND_TYPE_EXECUTION_MODEL,
+ SPV_OPERAND_TYPE_ADDRESSING_MODEL,
+ SPV_OPERAND_TYPE_MEMORY_MODEL,
+ SPV_OPERAND_TYPE_EXECUTION_MODE,
+ SPV_OPERAND_TYPE_STORAGE_CLASS,
+ SPV_OPERAND_TYPE_DIMENSIONALITY,
+ SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE,
+ SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE,
+ SPV_OPERAND_TYPE_FP_FAST_MATH_MODE,
+ SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
+ SPV_OPERAND_TYPE_LINKAGE_TYPE,
+ SPV_OPERAND_TYPE_ACCESS_QUALIFIER,
+ SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
+ SPV_OPERAND_TYPE_DECORATION,
+ SPV_OPERAND_TYPE_BUILT_IN,
+ SPV_OPERAND_TYPE_SELECTION_CONTROL,
+ SPV_OPERAND_TYPE_LOOP_CONTROL,
+ SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+ SPV_OPERAND_TYPE_MEMORY_SEMANTICS,
+ SPV_OPERAND_TYPE_MEMORY_ACCESS,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE,
+ SPV_OPERAND_TYPE_GROUP_OPERATION,
+ SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS,
+ SPV_OPERAND_TYPE_KERENL_PROFILING_INFO,
+ SPV_OPERAND_TYPE_CAPABILITY,
+
+ SPV_OPERAND_TYPE_ELLIPSIS, // NOTE: Unspecified variable operands
+ SPV_FORCE_32_BIT_ENUM(spv_operand_type_t)
+} spv_operand_type_t;
+
+typedef enum spv_ext_inst_type_t {
+ SPV_EXT_INST_TYPE_NONE,
+ SPV_EXT_INST_TYPE_GLSL_STD_450,
+ SPV_EXT_INST_TYPE_OPENCL_STD_12,
+ SPV_EXT_INST_TYPE_OPENCL_STD_20,
+ SPV_EXT_INST_TYPE_OPENCL_STD_21,
+
+ SPV_FORCE_32_BIT_ENUM(spv_ext_inst_type_t)
+} spv_ext_inst_type_t;
+
+typedef enum spv_binary_to_text_options_t {
+ SPV_BINARY_TO_TEXT_OPTION_NONE = SPV_BIT(0),
+ SPV_BINARY_TO_TEXT_OPTION_PRINT = SPV_BIT(1),
+ SPV_BINARY_TO_TEXT_OPTION_COLOR = SPV_BIT(2),
+ SPV_FORCE_32_BIT_ENUM(spv_binary_to_text_options_t)
+} spv_binary_to_text_options_t;
+
+typedef enum spv_validate_options_t {
+ SPV_VALIDATE_BASIC_BIT = SPV_BIT(0),
+ SPV_VALIDATE_LAYOUT_BIT = SPV_BIT(1),
+ SPV_VALIDATE_ID_BIT = SPV_BIT(2),
+ SPV_VALIDATE_RULES_BIT = SPV_BIT(3),
+ SPV_VALIDATE_ALL = SPV_VALIDATE_BASIC_BIT | SPV_VALIDATE_LAYOUT_BIT |
+ SPV_VALIDATE_ID_BIT | SPV_VALIDATE_RULES_BIT,
+ SPV_FORCE_32_BIT_ENUM(spv_validation_options_t)
+} spv_validate_options_t;
+
+// Structures
+
+typedef struct spv_header_t {
+ uint32_t magic;
+ uint32_t version;
+ uint32_t generator;
+ uint32_t bound;
+ uint32_t schema; // NOTE: Reserved
+ const uint32_t *instructions; // NOTE: Unfixed pointer to instruciton stream
+} spv_header_t;
+
+typedef struct spv_opcode_desc_t {
+ const char *name;
+ const uint16_t wordCount;
+ const Op opcode;
+ const uint32_t flags; // Bitfield of spv_opcode_flags_t
+ const uint32_t capabilities; // spv_language_capabilities_t
+ const spv_operand_type_t operandTypes[16]; // TODO: Smaller/larger?
+} spv_opcode_desc_t;
+
+typedef struct spv_opcode_table_t {
+ const uint32_t count;
+ const spv_opcode_desc_t *entries;
+} spv_opcode_table_t;
+
+typedef struct spv_operand_desc_t {
+ const char *name;
+ const uint32_t value;
+ const uint32_t flags; // Bitfield of spv_opcode_flags_t
+ const uint32_t capabilities; // spv_language_capabilities_t
+ const spv_operand_type_t operandTypes[16]; // TODO: Smaller/larger?
+} spv_operand_desc_t;
+
+typedef struct spv_operand_desc_group_t {
+ const spv_operand_type_t type;
+ const uint32_t count;
+ const spv_operand_desc_t *entries;
+} spv_operand_desc_group_t;
+
+typedef struct spv_operand_table_t {
+ const uint32_t count;
+ const spv_operand_desc_group_t *types;
+} spv_operand_table_t;
+
+typedef struct spv_ext_inst_desc_t {
+ const char *name;
+ const uint32_t ext_inst;
+ const spv_operand_type_t operandTypes[16]; // TODO: Smaller/larger?
+} spv_ext_inst_desc_t;
+
+typedef struct spv_ext_inst_group_t {
+ const spv_ext_inst_type_t type;
+ const uint32_t count;
+ const spv_ext_inst_desc_t *entries;
+} spv_ext_inst_group_t;
+
+typedef struct spv_ext_inst_table_t {
+ const uint32_t count;
+ const spv_ext_inst_group_t *groups;
+} spv_ext_inst_table_t;
+
+typedef struct spv_binary_t {
+ uint32_t *code;
+ uint64_t wordCount;
+} spv_binary_t;
+
+typedef struct spv_text_t {
+ const char *str;
+ uint64_t length;
+} spv_text_t;
+
+typedef struct spv_instruction_t {
+ uint16_t wordCount;
+ Op opcode;
+ spv_ext_inst_type_t extInstType;
+ uint32_t words[SPV_LIMIT_INSTRUCTION_WORD_COUNT_MAX];
+} spv_instruction_t;
+
+typedef struct spv_position_t {
+ uint64_t line;
+ uint64_t column;
+ uint64_t index;
+} spv_position_t;
+
+typedef struct spv_diagnostic_t {
+ spv_position_t position;
+ char *error;
+} spv_diagnostic_t;
+
+// Type Definitions
+
+typedef const spv_opcode_desc_t *spv_opcode_desc;
+typedef const spv_opcode_table_t *spv_opcode_table;
+typedef const spv_operand_desc_t *spv_operand_desc;
+typedef const spv_operand_table_t *spv_operand_table;
+typedef const spv_ext_inst_desc_t *spv_ext_inst_desc;
+typedef const spv_ext_inst_table_t *spv_ext_inst_table;
+typedef spv_binary_t *spv_binary;
+typedef spv_text_t *spv_text;
+typedef spv_position_t *spv_position;
+typedef spv_diagnostic_t *spv_diagnostic;
+
+// Platform API
+
+// Opcode API
+
+/// @brief Populate the Opcode table
+///
+/// @param[out] pOpcodeTable table to be populated
+///
+/// @return result code
+spv_result_t spvOpcodeTableGet(spv_opcode_table *pOpcodeTable);
+
+/// @brief Populate the operand table
+///
+/// @param[in] pOperandTable table to be populated
+///
+/// @return result code
+spv_result_t spvOperandTableGet(spv_operand_table *pOperandTable);
+
+/// @brief Populate the extended instruction table
+///
+/// @param pTable table to be populated
+///
+/// @return result code
+spv_result_t spvExtInstTableGet(spv_ext_inst_table *pTable);
+
+// Text API
+
+/// @brief Entry point to covert text form to binary form
+///
+/// @param[in] text input text
+/// @param[in] opcodeTable of specified Opcodes
+/// @param[in] operandTable of specified operands
+/// @param[in] extInstTable of specified extended instructions
+/// @param[out] pBinary the binary module
+/// @param[out] pDiagnostic contains diagnostic on failure
+///
+/// @return result code
+spv_result_t spvTextToBinary(const spv_text text,
+ const spv_opcode_table opcodeTable,
+ const spv_operand_table operandTable,
+ const spv_ext_inst_table extInstTable,
+ spv_binary *pBinary, spv_diagnostic *pDiagnostic);
+
+/// @brief Free an allocated text stream
+///
+/// @param text the text object to be destored
+void spvTextDestroy(spv_text text);
+
+// Binary API
+
+/// @brief Entry point to convert binary to text form
+///
+/// @param[in] binary the input binary stream
+/// @param[in] options bitfield of spv_binary_to_text_options_t values
+/// @param[in] opcodeTable table of specified Opcodes
+/// @param[in] operandTable table of specified operands
+/// @param[in] extInstTable of specified extended instructions
+/// @param[out] pText the textual form
+/// @param[out] pDiagnostic contains diagnostic on failure
+///
+/// @return result code
+spv_result_t spvBinaryToText(const spv_binary binary, const uint32_t options,
+ const spv_opcode_table opcodeTable,
+ const spv_operand_table operandTable,
+ const spv_ext_inst_table extInstTable,
+ spv_text *pText, spv_diagnostic *pDiagnostic);
+
+/// @brief Free a binary stream from memory
+///
+/// @param binary stream to destroy
+void spvBinaryDestroy(spv_binary binary);
+
+// Validation API
+
+/// @brief Validate a SPIR-V binary for correctness
+///
+/// @param[in] binary the input binary stream
+/// @param[in] opcodeTable table of specified Opcodes
+/// @param[in] operandTable table of specified operands
+/// @param[in] extInstTable of specified extended instructions
+/// @param[in] options bitfield of spv_validation_options_t
+/// @param[out] pDiagnostic contains diagnostic on failure
+///
+/// @return result code
+spv_result_t spvValidate(const spv_binary binary,
+ const spv_opcode_table opcodeTable,
+ const spv_operand_table operandTable,
+ const spv_ext_inst_table extInstTable,
+ const uint32_t options, spv_diagnostic *pDiagnostic);
+
+// Diagnostic API
+
+/// @brief Create a diagnostic object
+///
+/// @param position position in the text or binary stream
+/// @param message error message to display, is copied
+///
+/// @return the diagnostic object
+spv_diagnostic spvDiagnosticCreate(const spv_position position,
+ const char *message);
+
+/// @brief Destroy a diagnostic object
+///
+/// @param diagnostic object to destory
+void spvDiagnosticDestroy(spv_diagnostic diagnostic);
+
+/// @brief Print the diagnostic to stderr
+///
+/// @param[in] diagnostic to print
+///
+/// @return result code
+spv_result_t spvDiagnosticPrint(const spv_diagnostic diagnostic);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+Copyright (c) 2015 The Khronos Group Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and/or associated documentation files (the
+"Materials"), to deal in the Materials without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Materials, and to
+permit persons to whom the Materials are furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Materials.
+
+MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+ https://www.khronos.org/registry/
+
+THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
--- /dev/null
+# SPIR-V Tools
+
+## Overview
+
+The project includes an assembler, disassembler, and validator for SPIR-V, all
+based on a common static library. The library contains all of the implementation
+details and is used in the standalone tools whilst also enabling integration
+into other code bases directly.
+
+Currently, the assembler and disassembler only support the core SPIR-V
+specification (i.e. nothing Vulkan or OpenCL-specific) and the validator is a
+work in progress. See the Future Work section for more information.
+
+## Build
+
+The project uses CMake to generate platform-specific build configurations. To
+generate these build files issue the following commands.
+
+```
+mkdir <spirv-dir>/build
+cd <spirv-dir>/build
+cmake [-G<platform-generator>] ..
+```
+
+Once the build files have been generated, build using your preferred
+development environment.
+
+### CMake Options
+
+* `SPIRV_USE_SANITIZER=<sanitizer>` - on UNIX platforms with an appropriate
+ version of `clang` this option enables the use of the sanitizers documented
+ [here](http://clang.llvm.org/docs/UsersManual.html#controlling-code-generation),
+ this should only be used with a debug build, disabled by default
+* `SPIRV_COLOR_TERMINAL=ON` - enables color console output, enabled by default
+* `SPIRV_WARN_EVERYTHING=OFF` - on UNIX platforms enable the `-Weverything`
+ compiler front end option, disabled by default
+* `SPIRV_WERROR=OFF` - on UNIX platforms enable the `-Werror` compiler front end
+ option, disabled by default
+
+## Library
+
+### Usage
+
+In order to use the library from an application, the include path should point to
+`<spirv-dir>/include`, which will enable the application to include the header
+`<spirv-dir>/include/libspirv/libspirv.h` then linking against the static
+library in `<spirv-build-dir>/bin/libSPIRV.a` or
+`<spirv-build-dir>/bin/SPIRV.lib`. The intention is for this to be a C API,
+however currently it relies on the generated header `spirv.h` meaning this is
+currently a C++ API.
+
+* `SPIRV` - the static library CMake target outputs `<spirv-dir>/lib/libSPIRV.a`
+ on Linux/Mac or `<spirv-dir>/lib/SPIRV.lib` on Windows.
+
+#### Entry Points
+
+There are three main entry points into the library.
+
+* `spvTextToBinary` implements the assembler functionality.
+* `spvBinaryToText` implements the disassembler functionality.
+* `spvValidate` implements the validator functionality.
+
+### Source
+
+In addition to the interface header `<spirv-dir>/include/libspirv/libspirv.h`
+the implementation source files reside in `<spirv-dir>/source/*`.
+
+## Tools
+
+### Assembler
+
+The standalone assembler is the binary called `spirv-as` and is located in
+`<spirv-build-dir>/bin/spirv-as`. The functionality of the assembler is
+implemented by the `spvTextToBinary` library function.
+
+The assembler operates on the textual form.
+
+* `spirv-as` - the standalone assembler
+ * `<spirv-dir>/bin/spirv-as`
+
+#### Options
+
+* `-o <filename>` is used to specify the output file, otherwise this is set to
+ `out.spv`.
+
+#### Format
+
+The assembly attempts to adhere to the binary form as closely as possible using
+text names from that specification. Here is an example.
+
+```
+OpCapability Shader
+OpMemoryModel Logical Simple
+OpEntryPoint GLCompute $3 "main"
+OpExecutionMode $3 LocalSize 64 64 1
+OpTypeVoid %1
+OpTypeFunction %2 $1
+OpFunction $1 %3 None $2
+OpLabel %4
+OpReturn
+OpFunctionEnd
+```
+
+Each line encapsulates one and only one instruction, or an OpCode and all of its
+operands. OpCodes use the names provided in section 3.28 Instructions of the
+SPIR-V specification, immediate values such as Addressing Model, Memory Model,
+etc. use the names provided in sections 3.2 Source Language through 3.27
+Capability of the SPIR-V specification. Literals strings are enclosed in quotes
+`"<string>"` while literal numbers have no special formatting.
+
+##### ID Definitions & Usage
+
+An ID definition pertains to the `Result <id>` of an OpCode, and ID usage is any
+input to an OpCode. To differentiate between definitions and uses, all ID
+definitions are prefixed with `%` and take the form `%<id>`, meanwhile all ID
+uses are prefixed with `$` and take the form `$<id>`. See the above example to
+see this in action.
+
+##### Named IDs
+
+The assembler also supports named IDs, or virtual IDs, which greatly improves
+the readability of the assembly. The same ID definition and usage prefixes
+apply. Names must begin with an character in the range `[a-z|A-Z]`. The
+following example will result in identical SPIR-V binary as the example above.
+
+```
+OpCapability Shader
+OpMemoryModel Logical Simple
+OpEntryPoint GLCompute $main "main"
+OpExecutionMode $main LocalSize 64 64 1
+OpTypeVoid %void
+OpTypeFunction %fnMain $void
+OpFunction $void %main None $fnMain
+OpLabel %lbMain
+OpReturn
+OpFunctionEnd
+```
+
+##### Arbitrary Integers
+
+When writing tests it can be useful to emit an invalid 32 bit word into the
+binary stream at arbitrary positions within the assembly. To specify an
+arbitrary word into the stream the prefix `!` is used, this takes the form
+`!<integer>`. Here is an example.
+
+```
+OpCapability !0x0000FF000
+```
+
+### Disassembler
+
+The standalone disassembler is the binary called `spirv-dis` and is located in
+`<spirv-build-dir>/bin/spirv-dis`. The functionality of the disassembler is
+implemented by the `spvBinaryToText` library function.
+
+The disassembler operates on the binary form.
+
+* `spirv-dis` - the standalone disassembler
+ * `<spirv-dir>/bin/spirv-dis`
+
+#### Options
+
+* `-o <filename>` is used to specify the output file, otherwise this is set to
+ `out.spvasm`.
+* `-p` prints the assembly to the console on stdout, this includes colored
+ output on Linux, Windows, and Mac.
+
+### Validator
+
+The standalone validator is the binary called `spirv-val` and is located in
+`<spirv-build-dir>/bin/spirv-val`. The functionality of the validator is
+implemented by the `spvValidate` library function.
+
+The validator operates on the binary form.
+
+* `spirv-val` - the standalone validator
+ * `<spirv-dir>/bin/spirv-val`
+
+#### Options
+
+* `-basic` performs basic stream validation, currently not implemented.
+* `-layout` performs logical layout validation as described in section 2.16
+ Validation Rules, currently not implemented.
+* `-id` performs ID validation according to the instruction rules in sections
+ 3.28.1 through 3.28.22, enabled but is a work in progress.
+* `-capability` performs capability validation and or reporting, currently not
+ implemented.
+
+## Tests
+
+The project contains a number of tests, implemented in the `UnitSPIRV`
+executable, used to drive the development and correctness of the tools, these
+use the [googletest](https://code.google.com/p/googletest/) framework. The
+[googletest](https://code.google.com/p/googletest/) source is not provided with
+this project, to enable the tests place the
+[googletest](https://code.google.com/p/googletest/) source in the
+`<spirv-dir>/external/googletest` directory, rerun CMake if you have already
+done so previously, CMake will detect the existence of
+`<spirv-dir>/external/googletest` then build as normal.
+
+## Future Work
+
+* Support extension libraries in `spirv-as`, `spirv-dis`, and `spirv-val`.
+* Complete implementation of ID validation rules in `spirv-val`.
+* Implement section 2.16 Validation Rules in `spirv-val`.
+* Implement Capability validation and or report in `spirv-val`.
+* Improve assembly output from `spirv-dis`.
+* Improve diagnostic reports.
+
+## Known Issues
+
+* Improve literal parsing in the assembler, currently only decimal integers and
+ floating-point numbers are supported as literal operands and the parser is not
+ contextually aware of the desired width of the operand.
+
+## Licence
+
+Copyright (c) 2015 The Khronos Group Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and/or associated documentation files (the
+"Materials"), to deal in the Materials without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Materials, and to
+permit persons to whom the Materials are furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Materials.
+
+MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+ https://www.khronos.org/registry/
+
+THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include <libspirv/libspirv.h>
+#include "binary.h"
+#include "diagnostic.h"
+#include "ext_inst.h"
+#include "opcode.h"
+#include "operand.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include <sstream>
+
+// Binary API
+
+enum {
+ I32_ENDIAN_LITTLE = 0x03020100ul,
+ I32_ENDIAN_BIG = 0x00010203ul,
+};
+
+static const union {
+ unsigned char bytes[4];
+ uint32_t value;
+} o32_host_order = {{0, 1, 2, 3}};
+
+#define I32_ENDIAN_HOST (o32_host_order.value)
+
+spv_result_t spvBinaryEndianness(const spv_binary binary,
+ spv_endianness_t *pEndian) {
+ spvCheck(!binary->code || !binary->wordCount,
+ return SPV_ERROR_INVALID_BINARY);
+ spvCheck(!pEndian, return SPV_ERROR_INVALID_POINTER);
+
+ uint8_t bytes[4];
+ memcpy(bytes, binary->code, sizeof(uint32_t));
+
+ if (0x03 == bytes[0] && 0x02 == bytes[1] && 0x23 == bytes[2] &&
+ 0x07 == bytes[3]) {
+ *pEndian = SPV_ENDIANNESS_LITTLE;
+ return SPV_SUCCESS;
+ }
+
+ if (0x07 == bytes[0] && 0x23 == bytes[1] && 0x02 == bytes[2] &&
+ 0x03 == bytes[3]) {
+ *pEndian = SPV_ENDIANNESS_BIG;
+ return SPV_SUCCESS;
+ }
+
+ return SPV_ERROR_INVALID_BINARY;
+}
+
+uint32_t spvFixWord(const uint32_t word, const spv_endianness_t endian) {
+ if ((SPV_ENDIANNESS_LITTLE == endian && I32_ENDIAN_HOST == I32_ENDIAN_BIG) ||
+ (SPV_ENDIANNESS_BIG == endian && I32_ENDIAN_HOST == I32_ENDIAN_LITTLE)) {
+ return (word & 0x000000ff) << 24 | (word & 0x0000ff00) << 8 |
+ (word & 0x00ff0000) >> 8 | (word & 0xff000000) >> 24;
+ }
+
+ return word;
+}
+
+spv_result_t spvBinaryHeaderGet(const spv_binary binary,
+ const spv_endianness_t endian,
+ spv_header_t *pHeader) {
+ spvCheck(!binary->code || !binary->wordCount,
+ return SPV_ERROR_INVALID_BINARY);
+ spvCheck(!pHeader, return SPV_ERROR_INVALID_POINTER);
+
+ // TODO: Validation checking?
+ pHeader->magic = spvFixWord(binary->code[SPV_INDEX_MAGIC_NUMBER], endian);
+ pHeader->version = spvFixWord(binary->code[SPV_INDEX_VERSION_NUMBER], endian);
+ pHeader->generator =
+ spvFixWord(binary->code[SPV_INDEX_GENERATOR_NUMBER], endian);
+ pHeader->bound = spvFixWord(binary->code[SPV_INDEX_BOUND], endian);
+ pHeader->schema = spvFixWord(binary->code[SPV_INDEX_SCHEMA], endian);
+ pHeader->instructions = &binary->code[SPV_INDEX_INSTRUCTION];
+
+ return SPV_SUCCESS;
+}
+
+spv_result_t spvBinaryHeaderSet(spv_binary_t *binary, const uint32_t bound) {
+ spvCheck(!binary, return SPV_ERROR_INVALID_BINARY);
+ spvCheck(!binary->code || !binary->wordCount,
+ return SPV_ERROR_INVALID_BINARY);
+
+ binary->code[SPV_INDEX_MAGIC_NUMBER] = SPV_MAGIC_NUMBER;
+ binary->code[SPV_INDEX_VERSION_NUMBER] = SPV_VERSION_NUMBER;
+ binary->code[SPV_INDEX_GENERATOR_NUMBER] = SPV_GENERATOR_CODEPLAY;
+ binary->code[SPV_INDEX_BOUND] = bound;
+ binary->code[SPV_INDEX_SCHEMA] = 0; // NOTE: Reserved
+
+ return SPV_SUCCESS;
+}
+
+spv_result_t spvBinaryEncodeU32(const uint32_t value, spv_instruction_t *pInst,
+ const spv_position position,
+ spv_diagnostic *pDiagnostic) {
+ spvCheck(pInst->wordCount + 1 > SPV_LIMIT_INSTRUCTION_WORD_COUNT_MAX,
+ DIAGNOSTIC << "Instruction word count '"
+ << SPV_LIMIT_INSTRUCTION_WORD_COUNT_MAX << "' exceeded.";
+ return SPV_ERROR_INVALID_TEXT);
+
+ pInst->words[pInst->wordCount++] = (uint32_t)value;
+ return SPV_SUCCESS;
+}
+
+spv_result_t spvBinaryEncodeU64(const uint64_t value, spv_instruction_t *pInst,
+ const spv_position position,
+ spv_diagnostic *pDiagnostic) {
+ spvCheck(pInst->wordCount + 2 > SPV_LIMIT_INSTRUCTION_WORD_COUNT_MAX,
+ DIAGNOSTIC << "Instruction word count '"
+ << SPV_LIMIT_INSTRUCTION_WORD_COUNT_MAX << "' exceeded.";
+ return SPV_ERROR_INVALID_TEXT);
+
+ uint32_t low = (uint32_t)(0x00000000ffffffff & value);
+ uint32_t high = (uint32_t)((0xffffffff00000000 & value) >> 32);
+ pInst->words[pInst->wordCount++] = low;
+ pInst->words[pInst->wordCount++] = high;
+ return SPV_SUCCESS;
+}
+
+spv_result_t spvBinaryEncodeString(const char *str, spv_instruction_t *pInst,
+ const spv_position position,
+ spv_diagnostic *pDiagnostic) {
+ size_t length = strlen(str);
+ size_t wordCount = (length / 4) + 1;
+ spvCheck((sizeof(uint32_t) * pInst->wordCount) + length >
+ sizeof(uint32_t) * SPV_LIMIT_INSTRUCTION_WORD_COUNT_MAX,
+ DIAGNOSTIC << "Instruction word count '"
+ << SPV_LIMIT_INSTRUCTION_WORD_COUNT_MAX << "'exceeded.";
+ return SPV_ERROR_INVALID_TEXT);
+
+ char *dest = (char *)&pInst->words[pInst->wordCount];
+ strncpy(dest, str, length);
+ pInst->wordCount += (uint16_t)wordCount;
+
+ return SPV_SUCCESS;
+}
+
+spv_operand_type_t spvBinaryOperandInfo(const uint32_t word,
+ const uint16_t operandIndex,
+ const spv_opcode_desc opcodeEntry,
+ const spv_operand_table operandTable,
+ spv_operand_desc *pOperandEntry) {
+ spv_operand_type_t type;
+ if (operandIndex < opcodeEntry->wordCount) {
+ // NOTE: Do operand table lookup to set operandEntry if successful
+ uint16_t index = operandIndex - 1;
+ type = opcodeEntry->operandTypes[index];
+ spv_operand_desc entry = nullptr;
+ if (!spvOperandTableValueLookup(operandTable, type, word, &entry)) {
+ if (SPV_OPERAND_TYPE_NONE != entry->operandTypes[0]) {
+ *pOperandEntry = entry;
+ }
+ }
+ } else if (*pOperandEntry) {
+ // NOTE: Use specified operand entry operand type for this word
+ uint16_t index = operandIndex - opcodeEntry->wordCount;
+ type = (*pOperandEntry)->operandTypes[index];
+ } else if (OpSwitch == opcodeEntry->opcode) {
+ // NOTE: OpSwitch is a special case which expects a list of paired extra
+ // operands
+ assert(0 &&
+ "This case is previously untested, remove this assert and ensure it "
+ "is behaving correctly!");
+ uint16_t lastIndex = opcodeEntry->wordCount - 1;
+ uint16_t index = lastIndex + ((operandIndex - lastIndex) % 2);
+ type = opcodeEntry->operandTypes[index];
+ } else {
+ // NOTE: Default to last operand type in opcode entry
+ uint16_t index = opcodeEntry->wordCount - 1;
+ type = opcodeEntry->operandTypes[index];
+ }
+ return type;
+}
+
+spv_result_t spvBinaryDecodeOperand(
+ const Op opcode, const spv_operand_type_t type, const uint32_t *words,
+ const spv_endianness_t endian, const uint32_t options,
+ const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
+ spv_ext_inst_type_t *pExtInstType, out_stream &stream,
+ spv_position position, spv_diagnostic *pDiagnostic) {
+ spvCheck(!words || !position, return SPV_ERROR_INVALID_POINTER);
+ spvCheck(!pDiagnostic, return SPV_ERROR_INVALID_DIAGNOSTIC);
+
+ bool print = spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_PRINT, options);
+ bool color =
+ print && spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_COLOR, options);
+
+ uint64_t index = 0;
+ switch (type) {
+ case SPV_OPERAND_TYPE_ID: {
+ stream.get() << ((color) ? clr::yellow() : "");
+ stream.get() << "$" << spvFixWord(words[index], endian);
+ stream.get() << ((color) ? clr::reset() : "");
+ index++;
+ position->index++;
+ } break;
+ case SPV_OPERAND_TYPE_RESULT_ID: {
+ stream.get() << (color ? clr::blue() : "");
+ stream.get() << "%" << spvFixWord(words[index], endian);
+ stream.get() << (color ? clr::reset() : "");
+ index++;
+ position->index++;
+ } break;
+ case SPV_OPERAND_TYPE_LITERAL: {
+ // TODO: Need to support multiple word literals
+ stream.get() << (color ? clr::red() : "");
+ stream.get() << spvFixWord(words[index], endian);
+ stream.get() << (color ? clr::reset() : "");
+ index++;
+ position->index++;
+ } break;
+ case SPV_OPERAND_TYPE_LITERAL_NUMBER: {
+ // NOTE: Special case for extended instruction use
+ if (OpExtInst == opcode) {
+ spv_ext_inst_desc extInst;
+ spvCheck(spvExtInstTableValueLookup(extInstTable, *pExtInstType,
+ words[0], &extInst),
+ DIAGNOSTIC << "Invalid extended instruction '" << words[0]
+ << "'.";
+ return SPV_ERROR_INVALID_BINARY);
+ }
+
+ stream.get() << (color ? clr::red() : "");
+ stream.get() << spvFixWord(words[index], endian);
+ stream.get() << (color ? clr::reset() : "");
+ index++;
+ position->index++;
+ } break;
+ case SPV_OPERAND_TYPE_LITERAL_STRING: {
+ const char *string = (const char *)&words[index];
+ uint64_t stringOperandCount = (strlen(string) / 4) + 1;
+
+ // NOTE: Special case for extended instruction import
+ if (OpExtInstImport == opcode) {
+ *pExtInstType = spvExtInstImportTypeGet(string);
+ spvCheck(SPV_EXT_INST_TYPE_NONE == *pExtInstType,
+ DIAGNOSTIC << "Invalid extended instruction import'" << string
+ << "'.";
+ return SPV_ERROR_INVALID_BINARY);
+ }
+
+ stream.get() << "\"";
+ stream.get() << (color ? clr::green() : "");
+ stream.get() << string;
+ stream.get() << (color ? clr::reset() : "");
+ stream.get() << "\"";
+ index += stringOperandCount;
+ position->index += stringOperandCount;
+ } break;
+ case SPV_OPERAND_TYPE_CAPABILITY:
+ case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
+ case SPV_OPERAND_TYPE_EXECUTION_MODEL:
+ case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
+ case SPV_OPERAND_TYPE_MEMORY_MODEL:
+ case SPV_OPERAND_TYPE_EXECUTION_MODE:
+ case SPV_OPERAND_TYPE_STORAGE_CLASS:
+ case SPV_OPERAND_TYPE_DIMENSIONALITY:
+ case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE:
+ case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
+ case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
+ case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
+ case SPV_OPERAND_TYPE_LINKAGE_TYPE:
+ case SPV_OPERAND_TYPE_ACCESS_QUALIFIER:
+ case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE:
+ case SPV_OPERAND_TYPE_DECORATION:
+ case SPV_OPERAND_TYPE_BUILT_IN:
+ case SPV_OPERAND_TYPE_SELECTION_CONTROL:
+ case SPV_OPERAND_TYPE_LOOP_CONTROL:
+ case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
+ case SPV_OPERAND_TYPE_MEMORY_SEMANTICS:
+ case SPV_OPERAND_TYPE_MEMORY_ACCESS:
+ case SPV_OPERAND_TYPE_EXECUTION_SCOPE:
+ case SPV_OPERAND_TYPE_GROUP_OPERATION:
+ case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
+ case SPV_OPERAND_TYPE_KERENL_PROFILING_INFO: {
+ spv_operand_desc entry;
+ spvCheck(
+ spvOperandTableValueLookup(operandTable, type,
+ spvFixWord(words[index], endian), &entry),
+ DIAGNOSTIC << "Invalid " << spvOperandTypeStr(type) << " operand '"
+ << words[index] << "'.";
+ return SPV_ERROR_INVALID_TEXT);
+ stream.get() << entry->name;
+ index++;
+ position->index++;
+ } break;
+ default: {
+ DIAGNOSTIC << "Invalid binary operand '" << type << "'";
+ return SPV_ERROR_INVALID_BINARY;
+ }
+ }
+
+ return SPV_SUCCESS;
+}
+
+spv_result_t spvBinaryDecodeOpcode(
+ spv_instruction_t *pInst, const spv_endianness_t endian,
+ const uint32_t options, const spv_opcode_table opcodeTable,
+ const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
+ out_stream &stream, spv_position position, spv_diagnostic *pDiagnostic) {
+ spvCheck(!pInst || !position, return SPV_ERROR_INVALID_POINTER);
+ spvCheck(!opcodeTable || !operandTable || !extInstTable,
+ return SPV_ERROR_INVALID_TABLE);
+ spvCheck(!pDiagnostic, return SPV_ERROR_INVALID_DIAGNOSTIC);
+
+ uint16_t wordCount;
+ Op opcode;
+ spvOpcodeSplit(spvFixWord(pInst->words[0], endian), &wordCount, &opcode);
+
+ spv_opcode_desc opcodeEntry;
+ spvCheck(spvOpcodeTableValueLookup(opcodeTable, opcode, &opcodeEntry),
+ DIAGNOSTIC << "Invalid Opcode '" << opcode << "'.";
+ return SPV_ERROR_INVALID_BINARY);
+
+ spvCheck(opcodeEntry->wordCount > wordCount,
+ DIAGNOSTIC << "Invalid instruction word count '" << wordCount
+ << "', expected at least '" << opcodeEntry->wordCount
+ << "'.";
+ return SPV_ERROR_INVALID_BINARY);
+
+ stream.get() << "Op" << opcodeEntry->name;
+
+ position->index++;
+
+ spv_operand_desc operandEntry = nullptr;
+ for (uint16_t index = 1; index < wordCount; ++index) {
+ const uint32_t word = spvFixWord(pInst->words[index], endian);
+ const uint64_t currentPosIndex = position->index;
+
+ stream.get() << " ";
+ spv_operand_type_t type = spvBinaryOperandInfo(word, index, opcodeEntry,
+ operandTable, &operandEntry);
+ spvCheck(spvBinaryDecodeOperand(
+ opcodeEntry->opcode, type, pInst->words + index, endian,
+ options, operandTable, extInstTable, &pInst->extInstType,
+ stream, position, pDiagnostic),
+ return SPV_ERROR_INVALID_BINARY);
+ index += (uint16_t)(position->index - currentPosIndex - 1);
+ }
+
+ return SPV_SUCCESS;
+}
+
+spv_result_t spvBinaryToText(const spv_binary binary, const uint32_t options,
+ const spv_opcode_table opcodeTable,
+ const spv_operand_table operandTable,
+ const spv_ext_inst_table extInstTable,
+ spv_text *pText, spv_diagnostic *pDiagnostic) {
+ spvCheck(!binary->code || !binary->wordCount,
+ return SPV_ERROR_INVALID_BINARY);
+ spvCheck(!opcodeTable || !operandTable || !extInstTable,
+ return SPV_ERROR_INVALID_TABLE);
+ spvCheck(pText && spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_PRINT, options),
+ return SPV_ERROR_INVALID_POINTER);
+ spvCheck(!pText && !spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_PRINT, options),
+ return SPV_ERROR_INVALID_POINTER);
+ spvCheck(!pDiagnostic, return SPV_ERROR_INVALID_DIAGNOSTIC);
+
+ spv_endianness_t endian;
+ spv_position_t position = {};
+ spvCheck(spvBinaryEndianness(binary, &endian),
+ DIAGNOSTIC << "Invalid SPIR-V magic number '" << std::hex
+ << binary->code[0] << "'.";
+ return SPV_ERROR_INVALID_BINARY);
+
+ spv_header_t header;
+ spvCheck(spvBinaryHeaderGet(binary, endian, &header),
+ DIAGNOSTIC << "Invalid SPIR-V header.";
+ return SPV_ERROR_INVALID_BINARY);
+
+ bool print = spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_PRINT, options);
+ bool color =
+ print && spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_COLOR, options);
+
+ std::stringstream sstream;
+ out_stream stream(sstream);
+ if (print) {
+ stream = out_stream();
+ }
+
+ if (color) {
+ stream.get() << clr::grey();
+ }
+ stream.get() << "; SPIR-V\n"
+ << "; Version: " << header.version << "\n"
+ << "; Generator: " << spvGeneratorStr(header.generator) << "\n"
+ << "; Bound: " << header.bound << "\n"
+ << "; Schema: " << header.schema << "\n";
+ if (color) {
+ stream.get() << clr::reset();
+ }
+
+ const uint32_t *words = binary->code;
+ position.index = SPV_INDEX_INSTRUCTION;
+ spv_ext_inst_type_t extInstType = SPV_EXT_INST_TYPE_NONE;
+ while (position.index < binary->wordCount) {
+ uint64_t index = position.index;
+ uint16_t wordCount;
+ Op opcode;
+ spvOpcodeSplit(spvFixWord(words[position.index], endian), &wordCount,
+ &opcode);
+
+ spv_instruction_t inst = {};
+ inst.extInstType = extInstType;
+ spvInstructionCopy(&words[position.index], opcode, wordCount, endian,
+ &inst);
+
+ spvCheck(
+ spvBinaryDecodeOpcode(&inst, endian, options, opcodeTable, operandTable,
+ extInstTable, stream, &position, pDiagnostic),
+ return SPV_ERROR_INVALID_BINARY);
+ extInstType = inst.extInstType;
+
+ spvCheck((index + wordCount) != position.index,
+ DIAGNOSTIC << "Invalid word count.";
+ return SPV_ERROR_INVALID_BINARY);
+
+ stream.get() << "\n";
+ }
+
+ if (!print) {
+ size_t length = sstream.str().size();
+ char *str = new char[length + 1];
+ spvCheck(!str, return SPV_ERROR_OUT_OF_MEMORY);
+ strncpy(str, sstream.str().c_str(), length + 1);
+ spv_text text = new spv_text_t();
+ spvCheck(!text, return SPV_ERROR_OUT_OF_MEMORY);
+ text->str = str;
+ text->length = length;
+ *pText = text;
+ }
+
+ return SPV_SUCCESS;
+}
+
+void spvBinaryDestroy(spv_binary binary) {
+ spvCheck(!binary, return );
+ if (binary->code) {
+ delete[] binary->code;
+ }
+ delete binary;
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#ifndef _LIBSPIRV_UTIL_BINARY_H_
+#define _LIBSPIRV_UTIL_BINARY_H_
+
+#include <libspirv/libspirv.h>
+#include "print.h"
+
+// Functions
+
+/// @brief Fix the endianness of a word
+///
+/// @param[in] word whos endianness should be fixed
+/// @param[in] endian the desired endianness
+///
+/// @return word with host endianness correction
+uint32_t spvFixWord(const uint32_t word, const spv_endianness_t endian);
+
+/// @brief Determine the endianness of the SPV binary
+///
+/// Gets the endianness of the SPV source. Returns SPV_ENDIANNESS_UNKNOWN if
+/// the
+/// SPV magic number is invalid, otherwise the determined endianness.
+///
+/// @param[in] binary the binary module
+/// @param[out] pEndian return the endianness of the SPV module
+///
+/// @return result code
+spv_result_t spvBinaryEndianness(const spv_binary binary,
+ spv_endianness_t *pEndian);
+
+/// @brief Grab the header from the SPV module
+///
+/// @param[in] binary the binary module
+/// @param[in] endian the endianness of the module
+/// @param[out] pHeader the returned header
+///
+/// @return result code
+spv_result_t spvBinaryHeaderGet(const spv_binary binary,
+ const spv_endianness_t endian,
+ spv_header_t *pHeader);
+
+/// @brief Populate a binary stream with this generators header
+///
+/// @param[in,out] binary the binary stream
+/// @param[in] bound the upper ID bound
+///
+/// @return result code
+spv_result_t spvBinaryHeaderSet(spv_binary binary, const uint32_t bound);
+
+/// @brief Append a single word into a binary stream
+///
+/// @param[in] value the word to encode
+/// @param[in] pInst the stream to append to
+/// @param[in,out] position position in the binary
+/// @param[out] pDiagnostic contains diagnostic on failure
+///
+/// @return result code
+spv_result_t spvBinaryEncodeU32(const uint32_t value, spv_instruction_t *pInst,
+ const spv_position position,
+ spv_diagnostic *pDiagnostic);
+
+/// @brief Append two related words into the binary stream
+///
+/// @param[in] value the two words to encode
+/// @param[in] pInst the stream to append to
+/// @param[in,out] position position in the binary
+/// @param[out] pDiagnostic contains diagnostic on failure
+///
+/// @return result code
+spv_result_t spvBinaryEncodeU64(const uint64_t value, spv_instruction_t *pInst,
+ const spv_position position,
+ spv_diagnostic *pDiagnostic);
+
+/// @brief Append a string literal in the binary stream
+///
+/// @param[in] str the string to encode
+/// @param[in] pInst the stream to append to
+/// @param[in,out] position position in the binary
+/// @param[out] pDiagnostic contains diagnostic on failure
+///
+/// @return result code
+spv_result_t spvBinaryEncodeString(const char *str, spv_instruction_t *pInst,
+ const spv_position position,
+ spv_diagnostic *pDiagnostic);
+
+/// @brief Determine the type of the desired operand
+///
+/// @param[in] word the operand value
+/// @param[in] index the word index in the instruction
+/// @param[in] opcodeEntry table of specified Opcodes
+/// @param[in] operandTable table of specified operands
+/// @param[in,out] pOperandEntry the entry in the operand table
+///
+/// @return type returned
+spv_operand_type_t spvBinaryOperandInfo(const uint32_t word,
+ const uint16_t index,
+ const spv_opcode_desc opcodeEntry,
+ const spv_operand_table operandTable,
+ spv_operand_desc *pOperandEntry);
+
+/// @brief Translate a binary operand to the textual form
+///
+/// @param[in] opcode of the current instruction
+/// @param[in] type type of the operand to decode
+/// @param[in] words the binary stream of words
+/// @param[in] endian the endianness of the stream
+/// @param[in] options bitfield of spv_binary_to_text_options_t values
+/// @param[in] operandTable table of specified operands
+/// @param[in,out] pExtInstType type of extended instruction library
+/// @param[in,out] stream the text output stream
+/// @param[in,out] position position in the binary stream
+/// @param[out] pDiag return diagnostic on error
+///
+/// @return result code
+spv_result_t spvBinaryDecodeOperand(
+ const Op opcode, const spv_operand_type_t type, const uint32_t *words,
+ const spv_endianness_t endian, const uint32_t options,
+ const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
+ spv_ext_inst_type_t *pExtInstType, out_stream &stream,
+ spv_position position, spv_diagnostic *pDiag);
+
+/// @brief Translate binary Opcode stream to textual form
+///
+/// @param[in] pInst the Opcode instruction stream
+/// @param[in] endian the endianness of the stream
+/// @param[in] options bitfield of spv_binary_to_text_options_t values
+/// @param[in] opcodeTable table of specified Opcodes
+/// @param[in] operandTable table of specified operands
+/// @param[out] stream output text stream
+/// @param[in,out] position position in the stream
+/// @param[out] pDiag return diagnostic on error
+///
+/// @return result code
+spv_result_t spvBinaryDecodeOpcode(
+ spv_instruction_t *pInst, const spv_endianness_t endian,
+ const uint32_t options, const spv_opcode_table opcodeTable,
+ const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
+ out_stream &stream, spv_position position, spv_diagnostic *pDiag);
+
+#endif
+
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include <libspirv/libspirv.h>
+#include "diagnostic.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include <iostream>
+
+// Diagnostic API
+
+spv_diagnostic spvDiagnosticCreate(const spv_position position,
+ const char *message) {
+ spv_diagnostic diagnostic = new spv_diagnostic_t;
+ spvCheck(!diagnostic, return nullptr);
+ size_t length = strlen(message) + 1;
+ diagnostic->error = new char[length];
+ spvCheck(!diagnostic->error, delete diagnostic; return nullptr);
+ diagnostic->position = *position;
+ memset(diagnostic->error, 0, length);
+ strncpy(diagnostic->error, message, length);
+ return diagnostic;
+}
+
+void spvDiagnosticDestroy(spv_diagnostic diagnostic) {
+ spvCheck(!diagnostic, return );
+ if (diagnostic->error) {
+ delete[] diagnostic->error;
+ }
+ delete diagnostic;
+}
+
+spv_result_t spvDiagnosticPrint(const spv_diagnostic diagnostic) {
+ spvCheck(!diagnostic, return SPV_ERROR_INVALID_DIAGNOSTIC);
+
+ // TODO: Check that the logic choosing between a text or binary diagnostic is
+ // corrent.
+ if ((diagnostic->position.line || diagnostic->position.column) &&
+ diagnostic->position.index) {
+ // NOTE: This is a text position
+ // NOTE: add 1 to the line as editors start at line 1, we are counting new
+ // line characters to start at line 0
+ std::cerr << "error: " << diagnostic->position.line + 1 << ": "
+ << diagnostic->position.column + 1 << ": " << diagnostic->error
+ << "\n";
+ return SPV_SUCCESS;
+ } else if (!diagnostic->position.line && !diagnostic->position.column &&
+ diagnostic->position.index) {
+ // NOTE: This is a binary position
+ std::cerr << "error: " << diagnostic->position.index << ": "
+ << diagnostic->error << "\n";
+ return SPV_SUCCESS;
+ }
+
+ return SPV_ERROR_INVALID_VALUE;
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#ifndef _LIBSPIRV_UTIL_DIAGNOSTIC_H_
+#define _LIBSPIRV_UTIL_DIAGNOSTIC_H_
+
+#include <libspirv/libspirv.h>
+
+#include <sstream>
+
+#include <iostream>
+
+class diagnostic_helper {
+ public:
+ diagnostic_helper(spv_position_t &position, spv_diagnostic *pDiagnostic)
+ : position(&position), pDiagnostic(pDiagnostic) {}
+
+ diagnostic_helper(spv_position position, spv_diagnostic *pDiagnostic)
+ : position(position), pDiagnostic(pDiagnostic) {}
+
+ ~diagnostic_helper() {
+ *pDiagnostic = spvDiagnosticCreate(position, stream.str().c_str());
+ }
+
+ std::stringstream stream;
+
+ private:
+ spv_position position;
+ spv_diagnostic *pDiagnostic;
+};
+
+#define DIAGNOSTIC \
+ diagnostic_helper helper(position, pDiagnostic); \
+ helper.stream
+
+#endif
--- /dev/null
+#include <libspirv/libspirv.h>
+
+#include <string.h>
+
+static const spv_ext_inst_desc_t glslStd450Entries[] = {
+ {
+ "round", GLSL_STD_450::Round, {SPV_OPERAND_TYPE_ID},
+ },
+ // TODO: Add remaining GLSL.std.450 instructions
+};
+
+static const spv_ext_inst_desc_t openclStd12Entries[] = {
+ {"placeholder", 0, {}},
+ // TODO: Add remaining OpenCL.std.12 instructions
+};
+
+static const spv_ext_inst_desc_t openclStd20Entries[] = {
+ {"placeholder", 0, {}},
+ // TODO: Add remaining OpenCL.std.20 instructions
+};
+
+static const spv_ext_inst_desc_t openclStd21Entries[] = {
+ {"placeholder", 0, {}},
+ // TODO: Add remaining OpenCL.std.21 instructions
+};
+
+spv_result_t spvExtInstTableGet(spv_ext_inst_table *pExtInstTable) {
+ spvCheck(!pExtInstTable, return SPV_ERROR_INVALID_POINTER);
+
+ static const spv_ext_inst_group_t groups[] = {
+ {SPV_EXT_INST_TYPE_GLSL_STD_450,
+ sizeof(glslStd450Entries) / sizeof(spv_ext_inst_desc_t),
+ glslStd450Entries},
+ {SPV_EXT_INST_TYPE_OPENCL_STD_12,
+ sizeof(openclStd12Entries) / sizeof(spv_ext_inst_desc_t),
+ openclStd12Entries},
+ {SPV_EXT_INST_TYPE_OPENCL_STD_20,
+ sizeof(openclStd20Entries) / sizeof(spv_ext_inst_desc_t),
+ openclStd20Entries},
+ {SPV_EXT_INST_TYPE_OPENCL_STD_21,
+ sizeof(openclStd21Entries) / sizeof(spv_ext_inst_desc_t),
+ openclStd21Entries},
+ };
+
+ static const spv_ext_inst_table_t table = {
+ sizeof(groups) / sizeof(spv_ext_inst_group_t), groups};
+
+ *pExtInstTable = &table;
+
+ return SPV_SUCCESS;
+}
+
+spv_ext_inst_type_t spvExtInstImportTypeGet(const char *name) {
+ if (!strcmp("GLSL.std.450", name)) {
+ return SPV_EXT_INST_TYPE_GLSL_STD_450;
+ }
+ if (!strcmp("OpenCL.std.12", name)) {
+ return SPV_EXT_INST_TYPE_OPENCL_STD_12;
+ }
+ if (!strcmp("OpenCL.std.20", name)) {
+ return SPV_EXT_INST_TYPE_OPENCL_STD_20;
+ }
+ if (!strcmp("OpenCL.std.21", name)) {
+ return SPV_EXT_INST_TYPE_OPENCL_STD_21;
+ }
+ return SPV_EXT_INST_TYPE_NONE;
+}
+
+spv_result_t spvExtInstTableNameLookup(const spv_ext_inst_table table,
+ const spv_ext_inst_type_t type,
+ const char *name,
+ spv_ext_inst_desc *pEntry) {
+ spvCheck(!table, return SPV_ERROR_INVALID_TABLE);
+ spvCheck(!pEntry, return SPV_ERROR_INVALID_POINTER);
+
+ for (uint32_t groupIndex = 0; groupIndex < table->count; groupIndex++) {
+ auto &group = table->groups[groupIndex];
+ if (type == group.type) {
+ for (uint32_t index = 0; index < group.count; index++) {
+ auto &entry = group.entries[index];
+ if (!strcmp(name, entry.name)) {
+ *pEntry = &table->groups[groupIndex].entries[index];
+ return SPV_SUCCESS;
+ }
+ }
+ }
+ }
+
+ return SPV_ERROR_INVALID_LOOKUP;
+}
+
+spv_result_t spvExtInstTableValueLookup(const spv_ext_inst_table table,
+ const spv_ext_inst_type_t type,
+ const uint32_t value,
+ spv_ext_inst_desc *pEntry) {
+ spvCheck(!table, return SPV_ERROR_INVALID_TABLE);
+ spvCheck(!pEntry, return SPV_ERROR_INVALID_POINTER);
+
+ for (uint32_t groupIndex = 0; groupIndex < table->count; groupIndex++) {
+ auto &group = table->groups[groupIndex];
+ if (type == group.type) {
+ for (uint32_t index = 0; index < group.count; index++) {
+ auto &entry = group.entries[index];
+ if (value == entry.ext_inst) {
+ *pEntry = &table->groups[groupIndex].entries[index];
+ return SPV_SUCCESS;
+ }
+ }
+ }
+ }
+
+ return SPV_ERROR_INVALID_LOOKUP;
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#ifndef _CODEPLAY_SPIRV_EXT_INST_H_
+#define _CODEPLAY_SPIRV_EXT_INST_H_
+
+#include <libspirv/libspirv.h>
+
+/// @brief Get the type from the extended instruction library string
+///
+/// @param name of the library
+///
+/// @return type of the extended instruction library
+spv_ext_inst_type_t spvExtInstImportTypeGet(const char *name);
+
+/// @brief Find the extented instruction with value in the table
+///
+/// @param table to lookup
+/// @param type of the extended instruction import
+/// @param name of the extended instruction to find
+/// @param pEntry return the extended instruction entry
+///
+/// @return result code
+spv_result_t spvExtInstTableNameLookup(const spv_ext_inst_table table,
+ const spv_ext_inst_type_t type,
+ const char *name,
+ spv_ext_inst_desc *pEntry);
+
+/// @brief Find the extented instruction with value in the table
+///
+/// @param table to lookup
+/// @param type of the extended instruction import
+/// @param value of the extended instruction to find
+/// @param pEntry return the extended instruction entry
+///
+/// @return result code
+spv_result_t spvExtInstTableValueLookup(const spv_ext_inst_table table,
+ const spv_ext_inst_type_t type,
+ const uint32_t value,
+ spv_ext_inst_desc *pEntry);
+
+#endif
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include <libspirv/libspirv.h>
+#include "binary.h"
+#include "opcode.h"
+
+#include <assert.h>
+#include <string.h>
+
+// Opcode API
+
+const char *spvGeneratorStr(uint32_t generator) {
+ switch (generator) {
+ case SPV_GENERATOR_KHRONOS:
+ return "Khronos";
+ case SPV_GENERATOR_VALVE:
+ return "Valve";
+ case SPV_GENERATOR_LUNARG:
+ return "LunarG";
+ case SPV_GENERATOR_CODEPLAY:
+ return "Codeplay Software Ltd.";
+ default:
+ return "Unknown";
+ }
+}
+
+uint32_t spvOpcodeMake(uint16_t wordCount, Op opcode) {
+ return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
+}
+
+void spvOpcodeSplit(const uint32_t word, uint16_t *pWordCount, Op *pOpcode) {
+ if (pWordCount) {
+ *pWordCount = (uint16_t)((0xffff0000 & word) >> 16);
+ }
+ if (pOpcode) {
+ *pOpcode = (Op)(0x0000ffff & word);
+ }
+}
+
+static const spv_opcode_desc_t opcodeTableEntries[] = {
+ {"Nop", 1, OpNop, SPV_OPCODE_FLAGS_NONE, 0, {}},
+ {"Undef",
+ 3,
+ OpUndef,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}},
+ {
+ "Source",
+ 3,
+ OpSource,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_SOURCE_LANGUAGE, SPV_OPERAND_TYPE_LITERAL_NUMBER},
+ },
+ {"SourceExtension",
+ 1,
+ OpSourceExtension,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_LITERAL_STRING}},
+ {"Name",
+ 2,
+ OpName,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_STRING}},
+ {"MemberName",
+ 3,
+ OpMemberName,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_NUMBER,
+ SPV_OPERAND_TYPE_LITERAL_STRING}},
+ {"String",
+ 2,
+ OpString,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_LITERAL_STRING}},
+ {"Line",
+ 5,
+ OpLine,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_NUMBER,
+ SPV_OPERAND_TYPE_LITERAL_NUMBER}},
+ {"DecorationGroup",
+ 2,
+ OpDecorationGroup,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_RESULT_ID}},
+ {"Decorate",
+ 3,
+ OpDecorate,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DECORATION,
+ SPV_OPERAND_TYPE_LITERAL, SPV_OPERAND_TYPE_LITERAL,
+ SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"MemberDecorate",
+ 4,
+ OpMemberDecorate,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_NUMBER,
+ SPV_OPERAND_TYPE_DECORATION, SPV_OPERAND_TYPE_LITERAL,
+ SPV_OPERAND_TYPE_LITERAL, SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"GroupDecorate",
+ 2,
+ OpGroupDecorate,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"GroupMemberDecorate",
+ 2,
+ OpGroupMemberDecorate,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"Extension",
+ 1,
+ OpExtension,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_LITERAL_STRING}},
+ {"ExtInstImport",
+ 2,
+ OpExtInstImport,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_LITERAL_STRING}},
+ {"ExtInst",
+ 5,
+ OpExtInst,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"MemoryModel",
+ 3,
+ OpMemoryModel,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ADDRESSING_MODEL, SPV_OPERAND_TYPE_MEMORY_MODEL}},
+ {"EntryPoint",
+ 3,
+ OpEntryPoint,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_EXECUTION_MODEL, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_LITERAL_STRING}},
+ {"ExecutionMode",
+ 3,
+ OpExecutionMode,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_EXECUTION_MODE,
+ SPV_OPERAND_TYPE_LITERAL, SPV_OPERAND_TYPE_LITERAL,
+ SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"CompileFlag",
+ 1,
+ OpCompileFlag,
+ SPV_OPCODE_FLAGS_VARIABLE | SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_LITERAL_STRING}},
+ {"Capability",
+ 2,
+ OpCapability,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_CAPABILITY}},
+ {"TypeVoid",
+ 2,
+ OpTypeVoid,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_RESULT_ID}},
+ {"TypeBool",
+ 2,
+ OpTypeBool,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_RESULT_ID}},
+ {"TypeInt",
+ 4,
+ OpTypeInt,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_LITERAL_NUMBER,
+ SPV_OPERAND_TYPE_LITERAL_NUMBER}},
+ {"TypeFloat",
+ 3,
+ OpTypeFloat,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_LITERAL_NUMBER}},
+ {"TypeVector",
+ 4,
+ OpTypeVector,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_LITERAL_NUMBER}},
+ {"TypeMatrix",
+ 4,
+ OpTypeMatrix,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityMatrix,
+ {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_LITERAL_NUMBER}},
+ {"TypeSampler",
+ 8,
+ OpTypeSampler,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {
+ SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_DIMENSIONALITY, SPV_OPERAND_TYPE_LITERAL_NUMBER,
+ SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_LITERAL_NUMBER,
+ SPV_OPERAND_TYPE_LITERAL_NUMBER,
+ SPV_OPERAND_TYPE_ID // TODO: See Khronos bug 13755
+ }},
+ {"TypeFilter",
+ 2,
+ OpTypeFilter,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_RESULT_ID}},
+ {"TypeArray",
+ 4,
+ OpTypeArray,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"TypeRuntimeArray",
+ 3,
+ OpTypeRuntimeArray,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"TypeStruct",
+ 2,
+ OpTypeStruct,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"TypeOpaque",
+ 2,
+ OpTypeOpaque,
+ SPV_OPCODE_FLAGS_VARIABLE | SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_LITERAL_STRING}},
+ {"TypePointer",
+ 4,
+ OpTypePointer,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_STORAGE_CLASS,
+ SPV_OPERAND_TYPE_ID}},
+ {"TypeFunction",
+ 3,
+ OpTypeFunction,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"TypeEvent",
+ 2,
+ OpTypeEvent,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_RESULT_ID}},
+ {"TypeDeviceEvent",
+ 2,
+ OpTypeDeviceEvent,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_RESULT_ID}},
+ {"TypeReserveId",
+ 2,
+ OpTypeReserveId,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_RESULT_ID}},
+ {"TypeQueue",
+ 2,
+ OpTypeQueue,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_RESULT_ID}},
+ {"TypePipe",
+ 4,
+ OpTypePipe,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityPipes,
+ {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ACCESS_QUALIFIER}},
+ {"ConstantTrue",
+ 3,
+ OpConstantTrue,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}},
+ {"ConstantFalse",
+ 3,
+ OpConstantFalse,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}},
+ {"Constant",
+ 3,
+ OpConstant,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_LITERAL,
+ SPV_OPERAND_TYPE_LITERAL, SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"ConstantComposite",
+ 3,
+ OpConstantComposite,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"ConstantSampler",
+ 6,
+ OpConstantSampler,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE, SPV_OPERAND_TYPE_LITERAL_NUMBER,
+ SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE}},
+ {"ConstantNull",
+ 3,
+ OpConstantNull,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}},
+ {"SpecConstantTrue",
+ 3,
+ OpSpecConstantTrue,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}},
+ {"SpecConstantFalse",
+ 3,
+ OpSpecConstantFalse,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}},
+ {"SpecConstant",
+ 3,
+ OpSpecConstant,
+ SPV_OPCODE_FLAGS_VARIABLE | SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_LITERAL,
+ SPV_OPERAND_TYPE_LITERAL, SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"SpecConstantComposite",
+ 3,
+ OpSpecConstantComposite,
+ SPV_OPCODE_FLAGS_VARIABLE | SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ELLIPSIS}},
+ {
+ "SpecConstantOp",
+ 4,
+ OpSpecConstantOp,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ELLIPSIS},
+
+ },
+ {"Variable",
+ 4,
+ OpVariable,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_STORAGE_CLASS, SPV_OPERAND_TYPE_ID}},
+ {"VariableArray",
+ 5,
+ OpVariableArray,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityAddresses,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_STORAGE_CLASS, SPV_OPERAND_TYPE_ID}},
+ {"Load",
+ 4,
+ OpLoad,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_MEMORY_ACCESS, SPV_OPERAND_TYPE_MEMORY_ACCESS,
+ SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"Store",
+ 3,
+ OpStore,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_MEMORY_ACCESS,
+ SPV_OPERAND_TYPE_MEMORY_ACCESS, SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"CopyMemory",
+ 3,
+ OpCopyMemory,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_MEMORY_ACCESS,
+ SPV_OPERAND_TYPE_MEMORY_ACCESS, SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"CopyMemorySized",
+ 4,
+ OpCopyMemorySized,
+ SPV_OPCODE_FLAGS_VARIABLE | SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityAddresses,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_MEMORY_ACCESS, SPV_OPERAND_TYPE_MEMORY_ACCESS,
+ SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"AccessChain",
+ 4,
+ OpAccessChain,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"InBoundsAccessChain",
+ 4,
+ OpInBoundsAccessChain,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"ArrayLength",
+ 5,
+ OpArrayLength,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_LITERAL_NUMBER}},
+ {"ImagePointer",
+ 6,
+ OpImagePointer,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"GenericPtrMemSemantics",
+ 4,
+ OpGenericPtrMemSemantics,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"Function",
+ 5,
+ OpFunction,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_FUNCTION_CONTROL, SPV_OPERAND_TYPE_ID}},
+ {"FunctionParameter",
+ 3,
+ OpFunctionParameter,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}},
+ {"FunctionEnd", 1, OpFunctionEnd, SPV_OPCODE_FLAGS_NONE, 0, {}},
+ {"FunctionCall",
+ 4,
+ OpFunctionCall,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"Sampler",
+ 5,
+ OpSampler,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"TextureSample",
+ 5,
+ OpTextureSample,
+ SPV_OPCODE_FLAGS_VARIABLE | SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"TextureSampleDref",
+ 6,
+ OpTextureSampleDref,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"TextureSampleLod",
+ 6,
+ OpTextureSampleLod,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"TextureSampleProj",
+ 5,
+ OpTextureSampleProj,
+ SPV_OPCODE_FLAGS_VARIABLE | SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"TextureSampleGrad",
+ 7,
+ OpTextureSampleGrad,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"TextureSampleOffset",
+ 6,
+ OpTextureSampleOffset,
+ SPV_OPCODE_FLAGS_VARIABLE | SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"TextureSampleProjLod",
+ 6,
+ OpTextureSampleProjLod,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"TextureSampleProjGrad",
+ 7,
+ OpTextureSampleProjGrad,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"TextureSampleLodOffset",
+ 7,
+ OpTextureSampleLodOffset,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"TextureSampleProjOffset",
+ 6,
+ OpTextureSampleProjOffset,
+ SPV_OPCODE_FLAGS_VARIABLE | SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"TextureSampleGradOffset",
+ 8,
+ OpTextureSampleGradOffset,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"TextureSampleProjLodOffset",
+ 7,
+ OpTextureSampleProjLodOffset,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"TextureSampleProjGradOffset",
+ 8,
+ OpTextureSampleProjGradOffset,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"TextureFetchTexel",
+ 6,
+ OpTextureFetchTexel,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"TextureFetchTexelOffset",
+ 6,
+ OpTextureFetchTexelOffset,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"TextureFetchSample",
+ 6,
+ OpTextureFetchSample,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"TextureFetchTexel",
+ 5,
+ OpTextureFetchTexel,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"TextureGather",
+ 6,
+ OpTextureGather,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"TextureGatherOffset",
+ 7,
+ OpTextureGatherOffset,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"TextureGatherOffsets",
+ 7,
+ OpTextureGatherOffsets,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"TextureQuerySizeLod",
+ 5,
+ OpTextureQuerySizeLod,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"TextureQuerySize",
+ 4,
+ OpTextureQuerySize,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"TextureQueryLod",
+ 5,
+ OpTextureQueryLod,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"TextureQueryLevels",
+ 4,
+ OpTextureQueryLevels,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"TextureQuerySamples",
+ 4,
+ OpTextureQuerySamples,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"ConvertFToU",
+ 4,
+ OpConvertFToU,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"ConvertFToS",
+ 4,
+ OpConvertFToS,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"ConvertSToF",
+ 4,
+ OpConvertSToF,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"ConvertUToF",
+ 4,
+ OpConvertUToF,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"UConvert",
+ 4,
+ OpUConvert,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"SConvert",
+ 4,
+ OpSConvert,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"FConvert",
+ 4,
+ OpFConvert,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"ConvertPtrToU",
+ 4,
+ OpConvertPtrToU,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityAddresses,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"ConvertUToPtr",
+ 4,
+ OpConvertUToPtr,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityAddresses,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"PtrCastToGeneric",
+ 4,
+ OpPtrCastToGeneric,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"GenericCastToPtr",
+ 4,
+ OpGenericCastToPtr,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"Bitcast",
+ 4,
+ OpBitcast,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"GenericCastToPtrExplicit",
+ 5,
+ OpGenericCastToPtrExplicit,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_STORAGE_CLASS}},
+ {"SatConvertSToU",
+ 4,
+ OpSatConvertSToU,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"SatConvertUToS",
+ 4,
+ OpSatConvertUToS,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"VectorExtractDynamic",
+ 5,
+ OpVectorExtractDynamic,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"VectorInsertDynamic",
+ 6,
+ OpVectorInsertDynamic,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"VectorShuffle",
+ 5,
+ OpVectorShuffle,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL, SPV_OPERAND_TYPE_LITERAL,
+ SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"CompositeConstruct",
+ 3,
+ OpCompositeConstruct,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"CompositeExtract",
+ 4,
+ OpCompositeExtract,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_LITERAL, SPV_OPERAND_TYPE_LITERAL,
+ SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"CompositeInsert",
+ 5,
+ OpCompositeInsert,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL, SPV_OPERAND_TYPE_LITERAL,
+ SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"CopyObject",
+ 4,
+ OpCopyObject,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"Transpose",
+ 4,
+ OpTranspose,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityMatrix,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"SNegate",
+ 4,
+ OpSNegate,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"FNegate",
+ 4,
+ OpFNegate,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"Not",
+ 4,
+ OpNot,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"IAdd",
+ 5,
+ OpIAdd,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"FAdd",
+ 5,
+ OpFAdd,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"ISub",
+ 5,
+ OpISub,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"FSub",
+ 5,
+ OpFSub,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"IMul",
+ 5,
+ OpIMul,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"FMul",
+ 5,
+ OpFMul,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"UDiv",
+ 5,
+ OpUDiv,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"SDiv",
+ 5,
+ OpSDiv,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"FDiv",
+ 5,
+ OpFDiv,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"UMod",
+ 5,
+ OpUMod,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"SRem",
+ 5,
+ OpSRem,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"SMod",
+ 5,
+ OpSMod,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"FRem",
+ 5,
+ OpFRem,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"FMod",
+ 5,
+ OpFMod,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"VectorTimesScalar",
+ 5,
+ OpVectorTimesScalar,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"MatrixTimesScalar",
+ 5,
+ OpMatrixTimesScalar,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityMatrix,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"VectorTimesMatrix",
+ 5,
+ OpVectorTimesMatrix,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityMatrix,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"MatrixTimesVector",
+ 5,
+ OpMatrixTimesVector,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityMatrix,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"MatrixTimesMatrix",
+ 5,
+ OpMatrixTimesMatrix,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityMatrix,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"OuterProduct",
+ 5,
+ OpOuterProduct,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityMatrix,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"Dot",
+ 5,
+ OpDot,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"ShiftRightLogical",
+ 5,
+ OpShiftRightLogical,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"ShiftRightArithmetic",
+ 5,
+ OpShiftRightArithmetic,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"ShiftLeftLogical",
+ 5,
+ OpShiftLeftLogical,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"BitwiseOr",
+ 5,
+ OpBitwiseOr,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"BitwiseXor",
+ 5,
+ OpBitwiseXor,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"BitwiseAnd",
+ 5,
+ OpBitwiseAnd,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"Any",
+ 4,
+ OpAny,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"All",
+ 4,
+ OpAll,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"IsNan",
+ 4,
+ OpIsNan,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"IsInf",
+ 4,
+ OpIsInf,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"IsFinite",
+ 4,
+ OpIsFinite,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"IsNormal",
+ 4,
+ OpIsNormal,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"SignBitSet",
+ 4,
+ OpSignBitSet,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"LessOrGreater",
+ 5,
+ OpLessOrGreater,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"Ordered",
+ 5,
+ OpOrdered,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"Unordered",
+ 5,
+ OpUnordered,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"LogicalOr",
+ 5,
+ OpLogicalOr,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"LogicalXor",
+ 5,
+ OpLogicalXor,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"LogicalAnd",
+ 5,
+ OpLogicalAnd,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"Select",
+ 6,
+ OpSelect,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"IEqual",
+ 5,
+ OpIEqual,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"FOrdEqual",
+ 5,
+ OpFOrdEqual,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"FUnordEqual",
+ 5,
+ OpFUnordEqual,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"INotEqual",
+ 5,
+ OpINotEqual,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"FOrdNotEqual",
+ 5,
+ OpFOrdNotEqual,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"FUnordNotEqual",
+ 5,
+ OpFUnordNotEqual,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"ULessThan",
+ 5,
+ OpULessThan,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"SLessThan",
+ 5,
+ OpSLessThan,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"FOrdLessThan",
+ 5,
+ OpFOrdLessThan,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"FUnordLessThan",
+ 5,
+ OpFUnordLessThan,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"UGreaterThan",
+ 5,
+ OpUGreaterThan,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"SGreaterThan",
+ 5,
+ OpSGreaterThan,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"FOrdGreaterThan",
+ 5,
+ OpFOrdGreaterThan,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"FUnordGreaterThan",
+ 5,
+ OpFUnordGreaterThan,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"ULessThanEqual",
+ 5,
+ OpULessThanEqual,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"SLessThanEqual",
+ 5,
+ OpSLessThanEqual,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"FOrdLessThanEqual",
+ 5,
+ OpFOrdLessThanEqual,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"FUnordLessThanEqual",
+ 5,
+ OpFUnordLessThanEqual,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"UGreaterThanEqual",
+ 5,
+ OpUGreaterThanEqual,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"SGreaterThanEqual",
+ 5,
+ OpSGreaterThanEqual,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"FOrdGreaterThanEqual",
+ 5,
+ OpFOrdGreaterThanEqual,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"FUnordGreaterThanEqual",
+ 5,
+ OpFUnordGreaterThanEqual,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"DPdx",
+ 4,
+ OpDPdx,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"DPdy",
+ 4,
+ OpDPdy,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {
+ "Fwidth",
+ 4,
+ OpFwidth,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID},
+ },
+ {"DPdxFine",
+ 4,
+ OpDPdxFine,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"DPdyFine",
+ 4,
+ OpDPdyFine,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {
+ "FwidthFine",
+ 4,
+ OpFwidthFine,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID},
+ },
+ {"DPdxCoarse",
+ 4,
+ OpDPdxCoarse,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"DPdyCoarse",
+ 4,
+ OpDPdyCoarse,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {
+ "FwidthCoarse",
+ 4,
+ OpFwidthCoarse,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID},
+ },
+ {"Phi",
+ 3,
+ OpPhi,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"LoopMerge",
+ 3,
+ OpLoopMerge,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LOOP_CONTROL}},
+ {"SelectionMerge",
+ 3,
+ OpSelectionMerge,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SELECTION_CONTROL}},
+ {"Label",
+ 2,
+ OpLabel,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_RESULT_ID}},
+ {"Branch", 2, OpBranch, SPV_OPCODE_FLAGS_NONE, 0, {SPV_OPERAND_TYPE_ID}},
+ {"BranchConditional",
+ 4,
+ OpBranchConditional,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_LITERAL, SPV_OPERAND_TYPE_LITERAL,
+ SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"Switch",
+ 3,
+ OpSwitch,
+ SPV_OPCODE_FLAGS_VARIABLE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_LITERAL, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL,
+ SPV_OPERAND_TYPE_ID}},
+ {"Kill", 1, OpKill, SPV_OPCODE_FLAGS_CAPABILITIES, CapabilityShader, {}},
+ {"Return", 1, OpReturn, SPV_OPCODE_FLAGS_NONE, 0, {}},
+ {"ReturnValue",
+ 2,
+ OpReturnValue,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID}},
+ {"Unreachable",
+ 1,
+ OpUnreachable,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {}},
+ {"LifetimeStart",
+ 3,
+ OpLifetimeStart,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_NUMBER}},
+ {"LifetimeStop",
+ 3,
+ OpLifetimeStop,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_NUMBER}},
+ {"AtomicInit",
+ 3,
+ OpAtomicInit,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"AtomicLoad",
+ 6,
+ OpAtomicLoad,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_MEMORY_SEMANTICS}},
+ {"AtomicStore",
+ 5,
+ OpAtomicStore,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_EXECUTION_SCOPE,
+ SPV_OPERAND_TYPE_MEMORY_SEMANTICS, SPV_OPERAND_TYPE_ID}},
+ {"AtomicExchange",
+ 7,
+ OpAtomicExchange,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_MEMORY_SEMANTICS,
+ SPV_OPERAND_TYPE_ID}},
+ {"AtomicCompareExchange",
+ 8,
+ OpAtomicCompareExchange,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_MEMORY_SEMANTICS,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"AtomicCompareExchangeWeak",
+ 8,
+ OpAtomicCompareExchangeWeak,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_MEMORY_SEMANTICS,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"AtomicIIncrement",
+ 6,
+ OpAtomicIIncrement,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_MEMORY_SEMANTICS}},
+ {"AtomicIDecrement",
+ 6,
+ OpAtomicIDecrement,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_MEMORY_SEMANTICS}},
+ {"AtomicIAdd",
+ 7,
+ OpAtomicIAdd,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_MEMORY_SEMANTICS,
+ SPV_OPERAND_TYPE_ID}},
+ {"AtomicISub",
+ 7,
+ OpAtomicISub,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_MEMORY_SEMANTICS,
+ SPV_OPERAND_TYPE_ID}},
+ {"AtomicUMin",
+ 7,
+ OpAtomicUMin,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_MEMORY_SEMANTICS,
+ SPV_OPERAND_TYPE_ID}},
+ {"AtomicUMax",
+ 7,
+ OpAtomicUMax,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_MEMORY_SEMANTICS,
+ SPV_OPERAND_TYPE_ID}},
+ {"AtomicAnd",
+ 7,
+ OpAtomicAnd,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_MEMORY_SEMANTICS,
+ SPV_OPERAND_TYPE_ID}},
+ {"AtomicOr",
+ 7,
+ OpAtomicOr,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_MEMORY_SEMANTICS,
+ SPV_OPERAND_TYPE_ID}},
+ {"AtomicXor",
+ 7,
+ OpAtomicXor,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_MEMORY_SEMANTICS,
+ SPV_OPERAND_TYPE_ID}},
+ {"AtomicIMin",
+ 7,
+ OpAtomicIMin,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_MEMORY_SEMANTICS,
+ SPV_OPERAND_TYPE_ID}},
+ {"AtomicIMax",
+ 7,
+ OpAtomicIMax,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_MEMORY_SEMANTICS,
+ SPV_OPERAND_TYPE_ID}},
+ {"EmitVertex",
+ 1,
+ OpEmitVertex,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGeometry,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_STRING}},
+ {"EndPrimitive",
+ 1,
+ OpEndPrimitive,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGeometry,
+ {}},
+ {"EmitStreamVertex",
+ 2,
+ OpEmitStreamVertex,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGeometry,
+ {SPV_OPERAND_TYPE_ID}},
+ {"EndStreamPrimitive",
+ 2,
+ OpEndStreamPrimitive,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGeometry,
+ {SPV_OPERAND_TYPE_ID}},
+ {"ControlBarrier",
+ 2,
+ OpControlBarrier,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_EXECUTION_SCOPE}},
+ {"MemoryBarrier",
+ 3,
+ OpMemoryBarrier,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_MEMORY_SEMANTICS}},
+ {"AsyncGroupCopy",
+ 9,
+ OpAsyncGroupCopy,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"WaitGroupEvents",
+ 6,
+ OpWaitGroupEvents,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"GroupAll",
+ 5,
+ OpGroupAll,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGroups,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_ID}},
+ {"GroupAny",
+ 5,
+ OpGroupAny,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGroups,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_ID}},
+ {"GroupBroadcast",
+ 6,
+ OpGroupBroadcast,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGroups,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"GroupIAdd",
+ 6,
+ OpGroupIAdd,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGroups,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_GROUP_OPERATION,
+ SPV_OPERAND_TYPE_ID}},
+ {"GroupFAdd",
+ 6,
+ OpGroupFAdd,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGroups,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_GROUP_OPERATION,
+ SPV_OPERAND_TYPE_ID}},
+ {"GroupFMin",
+ 6,
+ OpGroupFMin,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGroups,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_GROUP_OPERATION,
+ SPV_OPERAND_TYPE_ID}},
+ {"GroupUMin",
+ 6,
+ OpGroupUMin,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGroups,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_GROUP_OPERATION,
+ SPV_OPERAND_TYPE_ID}},
+ {"GroupSMin",
+ 6,
+ OpGroupSMin,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGroups,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_GROUP_OPERATION,
+ SPV_OPERAND_TYPE_ID}},
+ {"GroupFMax",
+ 6,
+ OpGroupFMax,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGroups,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_GROUP_OPERATION,
+ SPV_OPERAND_TYPE_ID}},
+ {"GroupUMax",
+ 6,
+ OpGroupUMax,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGroups,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_GROUP_OPERATION,
+ SPV_OPERAND_TYPE_ID}},
+ {"GroupSMax",
+ 6,
+ OpGroupSMax,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGroups,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_GROUP_OPERATION,
+ SPV_OPERAND_TYPE_ID}},
+ {"EnqueueMarker",
+ 7,
+ OpEnqueueMarker,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityDeviceEnqueue,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"EnqueueKernel",
+ 13,
+ OpEnqueueKernel,
+ SPV_OPCODE_FLAGS_VARIABLE | SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityDeviceEnqueue,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ELLIPSIS}},
+ {"GetKernelNDrangeSubGroupCount",
+ 5,
+ OpGetKernelNDrangeSubGroupCount,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityDeviceEnqueue,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"GetKernelNDrangeMaxSubGroupSize",
+ 5,
+ OpGetKernelNDrangeMaxSubGroupSize,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityDeviceEnqueue,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"GetKernelWorkGroupSize",
+ 4,
+ OpGetKernelWorkGroupSize,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityDeviceEnqueue,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"GetKernelPreferredWorkGroupSizeMultiple",
+ 4,
+ OpGetKernelPreferredWorkGroupSizeMultiple,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityDeviceEnqueue,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"RetainEvent",
+ 2,
+ OpRetainEvent,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityDeviceEnqueue,
+ {SPV_OPERAND_TYPE_ID}},
+ {"ReleaseEvent",
+ 2,
+ OpRetainEvent,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityDeviceEnqueue,
+ {SPV_OPERAND_TYPE_ID}},
+ {"CreateUserEvent",
+ 3,
+ OpCreateUserEvent,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityDeviceEnqueue,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}},
+ {"IsValidEvent",
+ 4,
+ OpIsValidEvent,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityDeviceEnqueue,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"SetUserEventStatus",
+ 3,
+ OpSetUserEventStatus,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityDeviceEnqueue,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"CapabilitytureEventProfilingInfo",
+ 4,
+ OpCaptureEventProfilingInfo,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityDeviceEnqueue,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_KERENL_PROFILING_INFO,
+ SPV_OPERAND_TYPE_ID}},
+ {"GetDefaultQueue",
+ 3,
+ OpGetDefaultQueue,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityDeviceEnqueue,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}},
+ {"BuildNDRange",
+ 6,
+ OpBuildNDRange,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityDeviceEnqueue,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"ReadPipe",
+ 5,
+ OpReadPipe,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityPipes,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"WritePipe",
+ 5,
+ OpWritePipe,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityPipes,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"ReservedReadPipe",
+ 7,
+ OpReservedReadPipe,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityPipes,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"ReservedWritePipe",
+ 7,
+ OpReservedWritePipe,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityPipes,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"ReserveReadPipePackets",
+ 5,
+ OpReserveReadPipePackets,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityPipes,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"ReserveWritePipePackets",
+ 5,
+ OpReserveWritePipePackets,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityPipes,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"CommitReadPipe",
+ 3,
+ OpCommitReadPipe,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityPipes,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"CommitWritePipe",
+ 3,
+ OpCommitWritePipe,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityPipes,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}},
+ {"IsValidReserveId",
+ 4,
+ OpIsValidReserveId,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityPipes,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"GetNumPipePackets",
+ 4,
+ OpGetNumPipePackets,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityPipes,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"GetMaxPipePackets",
+ 4,
+ OpGetMaxPipePackets,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityPipes,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}},
+ {"GroupReserveReadPipePackets",
+ 6,
+ OpGroupReserveReadPipePackets,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityPipes,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"GroupReserveWritePipePackets",
+ 6,
+ OpGroupReserveWritePipePackets,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityPipes,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID,
+ SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"GroupCommitReadPipe",
+ 4,
+ OpGroupCommitReadPipe,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityPipes,
+ {SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}},
+ {"GroupCommitWritePipe",
+ 4,
+ OpGroupCommitWritePipe,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityPipes,
+ {SPV_OPERAND_TYPE_EXECUTION_SCOPE, SPV_OPERAND_TYPE_ID,
+ SPV_OPERAND_TYPE_ID}}};
+
+spv_result_t spvOpcodeTableGet(spv_opcode_table *pInstTable) {
+ spvCheck(!pInstTable, return SPV_ERROR_INVALID_POINTER);
+
+ static const spv_opcode_table_t table = {
+ sizeof(opcodeTableEntries) / sizeof(spv_opcode_desc_t),
+ opcodeTableEntries};
+
+ *pInstTable = &table;
+
+ return SPV_SUCCESS;
+}
+
+spv_result_t spvOpcodeTableNameLookup(const spv_opcode_table table,
+ const char *name,
+ spv_opcode_desc *pEntry) {
+ spvCheck(!name || !pEntry, return SPV_ERROR_INVALID_POINTER);
+ spvCheck(!table, return SPV_ERROR_INVALID_TABLE);
+
+ // TODO: This lookup of the Opcode table is suboptimal! Binary sort would be
+ // preferable but the table requires sorting on the Opcode name, but it's
+ // static
+ // const initialized and matches the order of the spec.
+ const size_t nameLength = strlen(name);
+ for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
+ if (nameLength == strlen(table->entries[opcodeIndex].name) &&
+ !strncmp(name, table->entries[opcodeIndex].name, nameLength)) {
+ // NOTE: Found out Opcode!
+ *pEntry = &table->entries[opcodeIndex];
+ return SPV_SUCCESS;
+ }
+ }
+
+ return SPV_ERROR_INVALID_LOOKUP;
+}
+
+spv_result_t spvOpcodeTableValueLookup(const spv_opcode_table table,
+ const Op opcode,
+ spv_opcode_desc *pEntry) {
+ spvCheck(!table, return SPV_ERROR_INVALID_TABLE);
+ spvCheck(!pEntry, return SPV_ERROR_INVALID_POINTER);
+
+ // TODO: As above this lookup is not optimal.
+ for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
+ if (opcode == table->entries[opcodeIndex].opcode) {
+ // NOTE: Found the Opcode!
+ *pEntry = &table->entries[opcodeIndex];
+ return SPV_SUCCESS;
+ }
+ }
+
+ return SPV_ERROR_INVALID_LOOKUP;
+}
+
+int32_t spvOpcodeIsVariable(spv_opcode_desc entry) {
+ return SPV_OPCODE_FLAGS_VARIABLE ==
+ (SPV_OPCODE_FLAGS_VARIABLE & entry->flags);
+}
+
+int32_t spvOpcodeRequiresCapabilities(spv_opcode_desc entry) {
+ return SPV_OPCODE_FLAGS_CAPABILITIES ==
+ (SPV_OPCODE_FLAGS_CAPABILITIES & entry->flags);
+}
+
+void spvInstructionCopy(const uint32_t *words, const Op opcode,
+ const uint16_t wordCount, const spv_endianness_t endian,
+ spv_instruction_t *pInst) {
+ pInst->opcode = opcode;
+ pInst->wordCount = wordCount;
+ for (uint16_t wordIndex = 0; wordIndex < wordCount; ++wordIndex) {
+ pInst->words[wordIndex] = spvFixWord(words[wordIndex], endian);
+ if (!wordIndex) {
+ uint16_t thisWordCount;
+ Op thisOpcode;
+ spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
+ assert(opcode == thisOpcode && wordCount == thisWordCount &&
+ "Endianness failed!");
+ }
+ }
+}
+
+const char *spvOpcodeString(const Op opcode) {
+#define CASE(OPCODE) \
+ case OPCODE: \
+ return #OPCODE;
+ switch (opcode) {
+ CASE(OpNop)
+ CASE(OpSource)
+ CASE(OpSourceExtension)
+ CASE(OpExtension)
+ CASE(OpExtInstImport)
+ CASE(OpMemoryModel)
+ CASE(OpEntryPoint)
+ CASE(OpExecutionMode)
+ CASE(OpTypeVoid)
+ CASE(OpTypeBool)
+ CASE(OpTypeInt)
+ CASE(OpTypeFloat)
+ CASE(OpTypeVector)
+ CASE(OpTypeMatrix)
+ CASE(OpTypeSampler)
+ CASE(OpTypeFilter)
+ CASE(OpTypeArray)
+ CASE(OpTypeRuntimeArray)
+ CASE(OpTypeStruct)
+ CASE(OpTypeOpaque)
+ CASE(OpTypePointer)
+ CASE(OpTypeFunction)
+ CASE(OpTypeEvent)
+ CASE(OpTypeDeviceEvent)
+ CASE(OpTypeReserveId)
+ CASE(OpTypeQueue)
+ CASE(OpTypePipe)
+ CASE(OpConstantTrue)
+ CASE(OpConstantFalse)
+ CASE(OpConstant)
+ CASE(OpConstantComposite)
+ CASE(OpConstantSampler)
+ CASE(OpConstantNull)
+ CASE(OpSpecConstantTrue)
+ CASE(OpSpecConstantFalse)
+ CASE(OpSpecConstant)
+ CASE(OpSpecConstantComposite)
+ CASE(OpVariable)
+ CASE(OpVariableArray)
+ CASE(OpFunction)
+ CASE(OpFunctionParameter)
+ CASE(OpFunctionEnd)
+ CASE(OpFunctionCall)
+ CASE(OpExtInst)
+ CASE(OpUndef)
+ CASE(OpLoad)
+ CASE(OpStore)
+ CASE(OpPhi)
+ CASE(OpDecorationGroup)
+ CASE(OpDecorate)
+ CASE(OpMemberDecorate)
+ CASE(OpGroupDecorate)
+ CASE(OpGroupMemberDecorate)
+ CASE(OpName)
+ CASE(OpMemberName)
+ CASE(OpString)
+ CASE(OpLine)
+ CASE(OpVectorExtractDynamic)
+ CASE(OpVectorInsertDynamic)
+ CASE(OpVectorShuffle)
+ CASE(OpCompositeConstruct)
+ CASE(OpCompositeExtract)
+ CASE(OpCompositeInsert)
+ CASE(OpCopyObject)
+ CASE(OpCopyMemory)
+ CASE(OpCopyMemorySized)
+ CASE(OpSampler)
+ CASE(OpTextureSample)
+ CASE(OpTextureSampleDref)
+ CASE(OpTextureSampleLod)
+ CASE(OpTextureSampleProj)
+ CASE(OpTextureSampleGrad)
+ CASE(OpTextureSampleOffset)
+ CASE(OpTextureSampleProjLod)
+ CASE(OpTextureSampleProjGrad)
+ CASE(OpTextureSampleLodOffset)
+ CASE(OpTextureSampleProjOffset)
+ CASE(OpTextureSampleGradOffset)
+ CASE(OpTextureSampleProjLodOffset)
+ CASE(OpTextureSampleProjGradOffset)
+ CASE(OpTextureFetchTexelOffset)
+ CASE(OpTextureFetchSample)
+ CASE(OpTextureFetchTexel)
+ CASE(OpTextureGather)
+ CASE(OpTextureGatherOffset)
+ CASE(OpTextureGatherOffsets)
+ CASE(OpTextureQuerySizeLod)
+ CASE(OpTextureQuerySize)
+ CASE(OpTextureQueryLod)
+ CASE(OpTextureQueryLevels)
+ CASE(OpTextureQuerySamples)
+ CASE(OpAccessChain)
+ CASE(OpInBoundsAccessChain)
+ CASE(OpSNegate)
+ CASE(OpFNegate)
+ CASE(OpNot)
+ CASE(OpAny)
+ CASE(OpAll)
+ CASE(OpConvertFToU)
+ CASE(OpConvertFToS)
+ CASE(OpConvertSToF)
+ CASE(OpConvertUToF)
+ CASE(OpUConvert)
+ CASE(OpSConvert)
+ CASE(OpFConvert)
+ CASE(OpConvertPtrToU)
+ CASE(OpConvertUToPtr)
+ CASE(OpPtrCastToGeneric)
+ CASE(OpGenericCastToPtr)
+ CASE(OpBitcast)
+ CASE(OpTranspose)
+ CASE(OpIsNan)
+ CASE(OpIsInf)
+ CASE(OpIsFinite)
+ CASE(OpIsNormal)
+ CASE(OpSignBitSet)
+ CASE(OpLessOrGreater)
+ CASE(OpOrdered)
+ CASE(OpUnordered)
+ CASE(OpArrayLength)
+ CASE(OpIAdd)
+ CASE(OpFAdd)
+ CASE(OpISub)
+ CASE(OpFSub)
+ CASE(OpIMul)
+ CASE(OpFMul)
+ CASE(OpUDiv)
+ CASE(OpSDiv)
+ CASE(OpFDiv)
+ CASE(OpUMod)
+ CASE(OpSRem)
+ CASE(OpSMod)
+ CASE(OpFRem)
+ CASE(OpFMod)
+ CASE(OpVectorTimesScalar)
+ CASE(OpMatrixTimesScalar)
+ CASE(OpVectorTimesMatrix)
+ CASE(OpMatrixTimesVector)
+ CASE(OpMatrixTimesMatrix)
+ CASE(OpOuterProduct)
+ CASE(OpDot)
+ CASE(OpShiftRightLogical)
+ CASE(OpShiftRightArithmetic)
+ CASE(OpShiftLeftLogical)
+ CASE(OpLogicalOr)
+ CASE(OpLogicalXor)
+ CASE(OpLogicalAnd)
+ CASE(OpBitwiseOr)
+ CASE(OpBitwiseXor)
+ CASE(OpBitwiseAnd)
+ CASE(OpSelect)
+ CASE(OpIEqual)
+ CASE(OpFOrdEqual)
+ CASE(OpFUnordEqual)
+ CASE(OpINotEqual)
+ CASE(OpFOrdNotEqual)
+ CASE(OpFUnordNotEqual)
+ CASE(OpULessThan)
+ CASE(OpSLessThan)
+ CASE(OpFOrdLessThan)
+ CASE(OpFUnordLessThan)
+ CASE(OpUGreaterThan)
+ CASE(OpSGreaterThan)
+ CASE(OpFOrdGreaterThan)
+ CASE(OpFUnordGreaterThan)
+ CASE(OpULessThanEqual)
+ CASE(OpSLessThanEqual)
+ CASE(OpFOrdLessThanEqual)
+ CASE(OpFUnordLessThanEqual)
+ CASE(OpUGreaterThanEqual)
+ CASE(OpSGreaterThanEqual)
+ CASE(OpFOrdGreaterThanEqual)
+ CASE(OpFUnordGreaterThanEqual)
+ CASE(OpDPdx)
+ CASE(OpDPdy)
+ CASE(OpFwidth)
+ CASE(OpDPdxFine)
+ CASE(OpDPdyFine)
+ CASE(OpFwidthFine)
+ CASE(OpDPdxCoarse)
+ CASE(OpDPdyCoarse)
+ CASE(OpFwidthCoarse)
+ CASE(OpEmitVertex)
+ CASE(OpEndPrimitive)
+ CASE(OpEmitStreamVertex)
+ CASE(OpEndStreamPrimitive)
+ CASE(OpControlBarrier)
+ CASE(OpMemoryBarrier)
+ CASE(OpImagePointer)
+ CASE(OpAtomicInit)
+ CASE(OpAtomicLoad)
+ CASE(OpAtomicStore)
+ CASE(OpAtomicExchange)
+ CASE(OpAtomicCompareExchange)
+ CASE(OpAtomicCompareExchangeWeak)
+ CASE(OpAtomicIIncrement)
+ CASE(OpAtomicIDecrement)
+ CASE(OpAtomicIAdd)
+ CASE(OpAtomicISub)
+ CASE(OpAtomicUMin)
+ CASE(OpAtomicUMax)
+ CASE(OpAtomicAnd)
+ CASE(OpAtomicOr)
+ CASE(OpAtomicXor)
+ CASE(OpLoopMerge)
+ CASE(OpSelectionMerge)
+ CASE(OpLabel)
+ CASE(OpBranch)
+ CASE(OpBranchConditional)
+ CASE(OpSwitch)
+ CASE(OpKill)
+ CASE(OpReturn)
+ CASE(OpReturnValue)
+ CASE(OpUnreachable)
+ CASE(OpLifetimeStart)
+ CASE(OpLifetimeStop)
+ CASE(OpCompileFlag)
+ CASE(OpAsyncGroupCopy)
+ CASE(OpWaitGroupEvents)
+ CASE(OpGroupAll)
+ CASE(OpGroupAny)
+ CASE(OpGroupBroadcast)
+ CASE(OpGroupIAdd)
+ CASE(OpGroupFAdd)
+ CASE(OpGroupFMin)
+ CASE(OpGroupUMin)
+ CASE(OpGroupSMin)
+ CASE(OpGroupFMax)
+ CASE(OpGroupUMax)
+ CASE(OpGroupSMax)
+ CASE(OpGenericCastToPtrExplicit)
+ CASE(OpGenericPtrMemSemantics)
+ CASE(OpReadPipe)
+ CASE(OpWritePipe)
+ CASE(OpReservedReadPipe)
+ CASE(OpReservedWritePipe)
+ CASE(OpReserveReadPipePackets)
+ CASE(OpReserveWritePipePackets)
+ CASE(OpCommitReadPipe)
+ CASE(OpCommitWritePipe)
+ CASE(OpIsValidReserveId)
+ CASE(OpGetNumPipePackets)
+ CASE(OpGetMaxPipePackets)
+ CASE(OpGroupReserveReadPipePackets)
+ CASE(OpGroupReserveWritePipePackets)
+ CASE(OpGroupCommitReadPipe)
+ CASE(OpGroupCommitWritePipe)
+ CASE(OpEnqueueMarker)
+ CASE(OpEnqueueKernel)
+ CASE(OpGetKernelNDrangeSubGroupCount)
+ CASE(OpGetKernelNDrangeMaxSubGroupSize)
+ CASE(OpGetKernelWorkGroupSize)
+ CASE(OpGetKernelPreferredWorkGroupSizeMultiple)
+ CASE(OpRetainEvent)
+ CASE(OpReleaseEvent)
+ CASE(OpCreateUserEvent)
+ CASE(OpIsValidEvent)
+ CASE(OpSetUserEventStatus)
+ CASE(OpCaptureEventProfilingInfo)
+ CASE(OpGetDefaultQueue)
+ CASE(OpBuildNDRange)
+ default:
+ assert(0 && "Unreachable!");
+ }
+#undef CASE
+ return "unknown";
+}
+
+int32_t spvOpcodeIsType(const Op opcode) {
+ switch (opcode) {
+ case OpTypeVoid:
+ case OpTypeBool:
+ case OpTypeInt:
+ case OpTypeFloat:
+ case OpTypeVector:
+ case OpTypeMatrix:
+ case OpTypeSampler:
+ case OpTypeFilter:
+ case OpTypeArray:
+ case OpTypeRuntimeArray:
+ case OpTypeStruct:
+ case OpTypeOpaque:
+ case OpTypePointer:
+ case OpTypeFunction:
+ case OpTypeEvent:
+ case OpTypeDeviceEvent:
+ case OpTypeReserveId:
+ case OpTypeQueue:
+ case OpTypePipe:
+ return true;
+ default:
+ return false;
+ }
+}
+
+int32_t spvOpcodeIsScalarType(const Op opcode) {
+ switch (opcode) {
+ case OpTypeInt:
+ case OpTypeFloat:
+ return true;
+ default:
+ return false;
+ }
+}
+
+int32_t spvOpcodeIsConstant(const Op opcode) {
+ switch (opcode) {
+ case OpConstantTrue:
+ case OpConstantFalse:
+ case OpConstant:
+ case OpConstantComposite:
+ case OpConstantSampler:
+ // case OpConstantNull:
+ case OpConstantNull:
+ case OpSpecConstantTrue:
+ case OpSpecConstantFalse:
+ case OpSpecConstant:
+ case OpSpecConstantComposite:
+ // case OpSpecConstantOp:
+ return true;
+ default:
+ return false;
+ }
+}
+
+int32_t spvOpcodeIsComposite(const Op opcode) {
+ switch (opcode) {
+ case OpTypeVector:
+ case OpTypeMatrix:
+ case OpTypeArray:
+ case OpTypeStruct:
+ return true;
+ default:
+ return false;
+ }
+}
+
+int32_t spvOpcodeAreTypesEqual(const spv_instruction_t *pTypeInst0,
+ const spv_instruction_t *pTypeInst1) {
+ spvCheck(pTypeInst0->opcode != pTypeInst1->opcode, return false);
+ spvCheck(pTypeInst0->words[1] != pTypeInst1->words[1], return false);
+ return true;
+}
+
+int32_t spvOpcodeIsPointer(const Op opcode) {
+ switch (opcode) {
+ case OpVariable:
+ case OpVariableArray:
+ case OpAccessChain:
+ case OpInBoundsAccessChain:
+ // TODO: case OpImagePointer:
+ case OpFunctionParameter:
+ return true;
+ default:
+ return false;
+ }
+}
+
+int32_t spvOpcodeIsObject(const Op opcode) {
+ switch (opcode) {
+ case OpConstantTrue:
+ case OpConstantFalse:
+ case OpConstant:
+ case OpConstantComposite:
+ // TODO: case OpConstantSampler:
+ case OpConstantNull:
+ case OpSpecConstantTrue:
+ case OpSpecConstantFalse:
+ case OpSpecConstant:
+ case OpSpecConstantComposite:
+ // TODO: case OpSpecConstantOp:
+ case OpVariable:
+ case OpVariableArray:
+ case OpAccessChain:
+ case OpInBoundsAccessChain:
+ case OpConvertFToU:
+ case OpConvertFToS:
+ case OpConvertSToF:
+ case OpConvertUToF:
+ case OpUConvert:
+ case OpSConvert:
+ case OpFConvert:
+ case OpConvertPtrToU:
+ // TODO: case OpConvertUToPtr:
+ case OpPtrCastToGeneric:
+ // TODO: case OpGenericCastToPtr:
+ case OpBitcast:
+ // TODO: case OpGenericCastToPtrExplicit:
+ case OpSatConvertSToU:
+ case OpSatConvertUToS:
+ case OpVectorExtractDynamic:
+ case OpCompositeConstruct:
+ case OpCompositeExtract:
+ case OpCopyObject:
+ case OpTranspose:
+ case OpSNegate:
+ case OpFNegate:
+ case OpNot:
+ case OpIAdd:
+ case OpFAdd:
+ case OpISub:
+ case OpFSub:
+ case OpIMul:
+ case OpFMul:
+ case OpUDiv:
+ case OpSDiv:
+ case OpFDiv:
+ case OpUMod:
+ case OpSRem:
+ case OpSMod:
+ case OpVectorTimesScalar:
+ case OpMatrixTimesScalar:
+ case OpVectorTimesMatrix:
+ case OpMatrixTimesVector:
+ case OpMatrixTimesMatrix:
+ case OpOuterProduct:
+ case OpDot:
+ case OpShiftRightLogical:
+ case OpShiftRightArithmetic:
+ case OpShiftLeftLogical:
+ case OpBitwiseOr:
+ case OpBitwiseXor:
+ case OpBitwiseAnd:
+ case OpAny:
+ case OpAll:
+ case OpIsNan:
+ case OpIsInf:
+ case OpIsFinite:
+ case OpIsNormal:
+ case OpSignBitSet:
+ case OpLessOrGreater:
+ case OpOrdered:
+ case OpUnordered:
+ case OpLogicalOr:
+ case OpLogicalXor:
+ case OpLogicalAnd:
+ case OpSelect:
+ case OpIEqual:
+ case OpFOrdEqual:
+ case OpFUnordEqual:
+ case OpINotEqual:
+ case OpFOrdNotEqual:
+ case OpFUnordNotEqual:
+ case OpULessThan:
+ case OpSLessThan:
+ case OpFOrdLessThan:
+ case OpFUnordLessThan:
+ case OpUGreaterThan:
+ case OpSGreaterThan:
+ case OpFOrdGreaterThan:
+ case OpFUnordGreaterThan:
+ case OpULessThanEqual:
+ case OpSLessThanEqual:
+ case OpFOrdLessThanEqual:
+ case OpFUnordLessThanEqual:
+ case OpUGreaterThanEqual:
+ case OpSGreaterThanEqual:
+ case OpFOrdGreaterThanEqual:
+ case OpFUnordGreaterThanEqual:
+ case OpDPdx:
+ case OpDPdy:
+ case OpFwidth:
+ case OpDPdxFine:
+ case OpDPdyFine:
+ case OpFwidthFine:
+ case OpDPdxCoarse:
+ case OpDPdyCoarse:
+ case OpFwidthCoarse:
+ case OpReturnValue:
+ return true;
+ default:
+ return false;
+ }
+}
+
+int32_t spvOpcodeIsBasicTypeNullable(Op opcode) {
+ switch (opcode) {
+ case OpTypeBool:
+ case OpTypeInt:
+ case OpTypeFloat:
+ case OpTypePointer:
+ case OpTypeEvent:
+ case OpTypeDeviceEvent:
+ case OpTypeReserveId:
+ case OpTypeQueue:
+ return true;
+ default:
+ return false;
+ }
+}
+
+int32_t spvInstructionIsInBasicBlock(const spv_instruction_t *pFirstInst,
+ const spv_instruction_t *pInst) {
+ while (pFirstInst != pInst) {
+ spvCheck(OpFunction == pInst->opcode, break);
+ pInst--;
+ }
+ spvCheck(OpFunction != pInst->opcode, return false);
+ return true;
+}
+
+int32_t spvOpcodeIsValue(Op opcode) {
+ spvCheck(spvOpcodeIsPointer(opcode), return true);
+ spvCheck(spvOpcodeIsConstant(opcode), return true);
+ switch (opcode) {
+ case OpLoad:
+ // TODO: Other Opcode's resulting in a value
+ return true;
+ default:
+ return false;
+ }
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#ifndef _LIBSPIRV_UTIL_OPCODE_H_
+#define _LIBSPIRV_UTIL_OPCODE_H_
+
+#include <libspirv/libspirv.h>
+
+// Functions
+
+/// @brief Get the name of the SPIR-V generator
+///
+/// @param[in] generator Khronos SPIR-V generator ID
+///
+/// @return string name
+const char *spvGeneratorStr(uint32_t generator);
+
+/// @brief Combine word count and Opcode enumerant in single word
+///
+/// @param[in] wordCount Opcode consumes
+/// @param[in] opcode enumerant value
+///
+/// @return Opcode word
+uint32_t spvOpcodeMake(uint16_t wordCount, Op opcode);
+
+/// @brief Split the binary opcode into its constituent parts
+///
+/// @param[in] word binary opcode to split
+/// @param[out] wordCount the returned number of words (optional)
+/// @param[out] opcode the returned opcode enumerant (optional)
+void spvOpcodeSplit(const uint32_t word, uint16_t *wordCount, Op *opcode);
+
+/// @brief Find the named Opcode in the table
+///
+/// @param[in] table to lookup
+/// @param[in] name name of Opcode to find
+/// @param[out] pEntry returned Opcode table entry
+///
+/// @return result code
+spv_result_t spvOpcodeTableNameLookup(const spv_opcode_table table,
+ const char *name, spv_opcode_desc *pEntry);
+
+/// @brief Find the opcode ID in the table
+///
+/// @param[out] table to lookup
+/// @param[in] opcode value of Opcode to fine
+/// @param[out] pEntry return Opcode table entry
+///
+/// @return result code
+spv_result_t spvOpcodeTableValueLookup(const spv_opcode_table table,
+ const Op opcode, spv_opcode_desc *pEntry);
+
+/// @brief Determine if the Opcode has variable word count
+///
+/// This function does not check if @a entry is valid.
+///
+/// @param[in] entry the Opcode entry
+///
+/// @return zero if false, non-zero otherwise
+int32_t spvOpcodeIsVariable(spv_opcode_desc entry);
+
+/// @brief Determine if the Opcode has capaspvity requirements
+///
+/// This function does not check if @a entry is valid.
+///
+/// @param[in] entry the Opcode entry
+///
+/// @return zero if false, non-zero otherwise
+int32_t spvOpcodeRequiresCapabilities(spv_opcode_desc entry);
+
+/// @brief Copy an instructions word and fix the endianness
+///
+/// @param[in] words the input instruction stream
+/// @param[in] opcode the instructions Opcode
+/// @param[in] wordCount the number of words to copy
+/// @param[in] endian the endianness of the stream
+/// @param[out] pInst the returned instruction
+void spvInstructionCopy(const uint32_t *words, const Op opcode,
+ const uint16_t wordCount, const spv_endianness_t endian,
+ spv_instruction_t *pInst);
+
+/// @brief Get the string of an OpCode
+///
+/// @param[in] opcode the opcode
+///
+/// @return the opcode string
+const char *spvOpcodeString(const Op opcode);
+
+/// @brief Determine if the Opcode is a type
+///
+/// @param[in] opcode the opcode
+///
+/// @return zero if false, non-zero otherwise
+int32_t spvOpcodeIsType(const Op opcode);
+
+/// @brief Determine if the OpCode is a scalar type
+///
+/// @param[in] opcode the opcode
+///
+/// @return zero if false, non-zero otherwise
+int32_t spvOpcodeIsScalarType(const Op opcode);
+
+/// @brief Determine if the Opcode is a constant
+///
+/// @param[in] opcode the opcode
+///
+/// @return zero if false, non-zero otherwise
+int32_t spvOpcodeIsConstant(const Op opcode);
+
+/// @brief Determine if the Opcode is a composite type
+///
+/// @param[in] opcode the opcode
+///
+/// @return zero if false, non-zero otherwise
+int32_t spvOpcodeIsComposite(const Op opcode);
+
+/// @brief Deep comparison of type declaration instructions
+///
+/// @param[in] pTypeInst0 type definition zero
+/// @param[in] pTypeInst1 type definition one
+///
+/// @return zero if false, non-zero otherwise
+int32_t spvOpcodeAreTypesEqual(const spv_instruction_t *pTypeInst0,
+ const spv_instruction_t *pTypeInst1);
+
+/// @brief Determine if the Opcode results in a pointer
+///
+/// @param[in] opcode the opcode
+///
+/// @return zero if false, non-zero otherwise
+int32_t spvOpcodeIsPointer(const Op opcode);
+
+/// @brief Determine if the Opcode results in a instantation of a non-void type
+///
+/// @param[in] opcode the opcode
+///
+/// @return zero if false, non-zero otherwise
+int32_t spvOpcodeIsObject(const Op opcode);
+
+/// @brief Determine if the scalar type Opcode is nullable
+///
+/// @param[in] opcode the opcode
+///
+/// @return zero if false, non-zero otherwise
+int32_t spvOpcodeIsBasicTypeNullable(Op opcode);
+
+/// @brief Determine if instruction is in a basic block
+///
+/// @param[in] pFirstInst first instruction in the stream
+/// @param[in] pInst current instruction
+///
+/// @return zero if false, non-zero otherwise
+int32_t spvInstructionIsInBasicBlock(const spv_instruction_t *pFirstInst,
+ const spv_instruction_t *pInst);
+
+/// @brief Determine if the Opcode contains a value
+///
+/// @param[in] opcode the opcode
+///
+/// @return zero if false, non-zero otherwise
+int32_t spvOpcodeIsValue(Op opcode);
+
+#endif
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "operand.h"
+
+#include <assert.h>
+#include <string.h>
+
+static const spv_operand_desc_t sourceLanguageEntries[] = {
+ {"Unknown",
+ SourceLanguageUnknown,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"ESSL",
+ SourceLanguageESSL,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"GLSL",
+ SourceLanguageGLSL,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"OpenCL",
+ SourceLanguageOpenCL,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_t executionModelEntries[] = {
+ {"Vertex",
+ ExecutionModelVertex,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"TessellationControl",
+ ExecutionModelTessellationControl,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityTessellation,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"TessellationEvaluation",
+ ExecutionModelTessellationEvaluation,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityTessellation,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Geometry",
+ ExecutionModelGeometry,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGeometry,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Fragment",
+ ExecutionModelFragment,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"GLCompute",
+ ExecutionModelGLCompute,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Kernel",
+ ExecutionModelKernel,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_t addressingModelEntries[] = {
+ {"Logical",
+ AddressingModelLogical,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Physical32",
+ AddressingModelPhysical32,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityAddresses,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Physical64",
+ AddressingModelPhysical64,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityAddresses,
+ {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_t memoryModelEntries[] = {
+ {"Simple",
+ MemoryModelSimple,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"GLSL450",
+ MemoryModelGLSL450,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"OpenCL1.2",
+ MemoryModelOpenCL12,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"OpenCL2.0",
+ MemoryModelOpenCL20,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"OpenCL2.1",
+ MemoryModelOpenCL21,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_t executionModeEntries[] = {
+ {"Invocations",
+ ExecutionModeInvocations,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGeometry,
+ {SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
+ {"SpacingEqual",
+ ExecutionModeSpacingEqual,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityTessellation,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"SpacingFractionalEven",
+ ExecutionModeSpacingFractionalEven,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityTessellation,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"SpacingFractionalOdd",
+ ExecutionModeSpacingFractionalOdd,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityTessellation,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"VertexOrderCw",
+ ExecutionModeVertexOrderCw,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityTessellation,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"VertexOrderCcw",
+ ExecutionModeVertexOrderCcw,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityTessellation,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"PixelCenterInteger",
+ ExecutionModePixelCenterInteger,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"OriginUpperLeft",
+ ExecutionModeOriginUpperLeft,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"EarlyFragmentTests",
+ ExecutionModeEarlyFragmentTests,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"PointMode",
+ ExecutionModePointMode,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityTessellation,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Xfb",
+ ExecutionModeXfb,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"DepthReplacing",
+ ExecutionModeDepthReplacing,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"DepthAny",
+ ExecutionModeDepthAny,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"DepthGreater",
+ ExecutionModeDepthGreater,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"DepthLess",
+ ExecutionModeDepthLess,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"DepthUnchanged",
+ ExecutionModeDepthUnchanged,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"LocalSize",
+ ExecutionModeLocalSize,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_LITERAL_NUMBER,
+ SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
+ {"LocalSizeHint",
+ ExecutionModeLocalSizeHint,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_LITERAL_NUMBER,
+ SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
+ {"InputPoints",
+ ExecutionModeInputPoints,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGeometry,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"InputLines",
+ ExecutionModeInputLines,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGeometry,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"InputLinesAdjacency",
+ ExecutionModeInputLinesAdjacency,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGeometry,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"InputTriangles",
+ ExecutionModeInputTriangles,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGeometry | CapabilityTessellation,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"InputTrianglesAdjacency",
+ ExecutionModeInputTrianglesAdjacency,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGeometry,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"InputQuads",
+ ExecutionModeInputQuads,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityTessellation,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"InputIsolines",
+ ExecutionModeInputIsolines,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityTessellation,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"OutputVertices",
+ ExecutionModeOutputVertices,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGeometry | CapabilityTessellation,
+ {SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
+ {"OutputPoints",
+ ExecutionModeOutputPoints,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGeometry,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"OutputLineStrip",
+ ExecutionModeOutputLineStrip,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGeometry,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"OutputTriangleStrip",
+ ExecutionModeOutputTriangleStrip,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGeometry,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"VecTypeHint",
+ ExecutionModeVecTypeHint,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
+ {"ContractionOff",
+ ExecutionModeContractionOff,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {
+ "OriginLowerLeft",
+ ExecutionModeOriginLowerLeft,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE},
+ },
+};
+
+static const spv_operand_desc_t storageClassEntries[] = {
+ {"UniformConstant",
+ StorageClassUniformConstant,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Input",
+ StorageClassInput,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Uniform",
+ StorageClassUniform,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Output",
+ StorageClassOutput,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"WorkgroupLocal",
+ StorageClassWorkgroupLocal,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"WorkgroupGlobal",
+ StorageClassWorkgroupGlobal,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"PrivateGlobal",
+ StorageClassPrivateGlobal,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Function",
+ StorageClassFunction,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Generic",
+ StorageClassGeneric,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"AtomicCounter",
+ StorageClassAtomicCounter,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_t dimensionalityEntries[] = {
+ {"1D", Dim1D, SPV_OPCODE_FLAGS_NONE, 0, {SPV_OPERAND_TYPE_NONE}},
+ {"2D", Dim2D, SPV_OPCODE_FLAGS_NONE, 0, {SPV_OPERAND_TYPE_NONE}},
+ {"3D", Dim3D, SPV_OPCODE_FLAGS_NONE, 0, {SPV_OPERAND_TYPE_NONE}},
+ {"Cube",
+ DimCube,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Rect",
+ DimRect,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Buffer", DimBuffer, SPV_OPCODE_FLAGS_NONE, 0, {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_t samplerAddressingModeEntries[] = {
+ {"None",
+ SamplerAddressingModeNone,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"ClampToEdge",
+ SamplerAddressingModeClampToEdge,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Clamp",
+ SamplerAddressingModeClamp,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Repeat",
+ SamplerAddressingModeRepeat,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"RepeatMirrored",
+ SamplerAddressingModeRepeatMirrored,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_t samplerFilterModeEntries[] = {
+ {"Nearest",
+ SamplerFilterModeNearest,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Linear",
+ SamplerFilterModeLinear,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_t fpFastMathModeEntries[] = {
+ {"None",
+ FPFastMathModeMaskNone,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"NotNaN",
+ FPFastMathModeNotNaNMask,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"NotInf",
+ FPFastMathModeNotInfMask,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"NSZ",
+ FPFastMathModeNSZMask,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"AllowRecip",
+ FPFastMathModeAllowRecipMask,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Fast",
+ FPFastMathModeFastMask,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_t fpRoundingModeEntries[] = {
+ {"RTE",
+ FPRoundingModeRTE,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"RTZ",
+ FPRoundingModeRTZ,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"RTP",
+ FPRoundingModeRTP,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"RTN",
+ FPRoundingModeRTN,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_t linkageTypeEntries[] = {
+ {"Export",
+ LinkageTypeExport,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityLinkage,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Import",
+ LinkageTypeImport,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityLinkage,
+ {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_t accessQualifierEntries[] = {
+ {"ReadOnly",
+ AccessQualifierReadOnly,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"WriteOnly",
+ AccessQualifierWriteOnly,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"ReadWrite",
+ AccessQualifierReadWrite,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_t functionParameterAttributeEntries[] = {
+ {"Zext",
+ FunctionParameterAttributeZext,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Sext",
+ FunctionParameterAttributeSext,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"ByVal",
+ FunctionParameterAttributeByVal,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Sret",
+ FunctionParameterAttributeSret,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"NoAlias",
+ FunctionParameterAttributeNoAlias,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"NoCapabilityture",
+ FunctionParameterAttributeNoCapture,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"SVM",
+ FunctionParameterAttributeSVM,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"NoWrite",
+ FunctionParameterAttributeNoWrite,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"NoReadWrite",
+ FunctionParameterAttributeNoReadWrite,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_t decorationEntries[] = {
+ {"PrecisionLow",
+ DecorationPrecisionLow,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"PrecisionMedium",
+ DecorationPrecisionMedium,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"PrecisionHigh",
+ DecorationPrecisionHigh,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Block",
+ DecorationBlock,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"BufferBlock",
+ DecorationBufferBlock,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"RowMajor",
+ DecorationRowMajor,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityMatrix,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"ColMajor",
+ DecorationColMajor,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityMatrix,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"GLSLShared",
+ DecorationGLSLShared,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"GLSLStd140",
+ DecorationGLSLStd140,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"GLSLStd430",
+ DecorationGLSLStd430,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"GLSLPacked",
+ DecorationGLSLPacked,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Smooth",
+ DecorationSmooth,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Noperspective",
+ DecorationNoperspective,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Flat",
+ DecorationFlat,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Patch",
+ DecorationPatch,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityTessellation,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Centroid",
+ DecorationCentroid,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Sample",
+ DecorationSample,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Invariant",
+ DecorationInvariant,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Restrict",
+ DecorationRestrict,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Aliased",
+ DecorationAliased,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Volatile",
+ DecorationVolatile,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Constant",
+ DecorationConstant,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Coherent",
+ DecorationCoherent,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Nonwritable",
+ DecorationNonwritable,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Nonreadable",
+ DecorationNonreadable,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Uniform",
+ DecorationUniform,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"NoStaticUse",
+ DecorationNoStaticUse,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"CPacked",
+ DecorationCPacked,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"FPSaturatedConversion",
+ DecorationSaturatedConversion,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Stream",
+ DecorationStream,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGeometry,
+ {SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
+ {"Location",
+ DecorationLocation,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
+ {"Component",
+ DecorationComponent,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
+ {"Index",
+ DecorationIndex,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
+ {"Binding",
+ DecorationBinding,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
+ {"DescriptorSet",
+ DecorationDescriptorSet,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
+ {"Offset",
+ DecorationOffset,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
+ {"Alignment",
+ DecorationAlignment,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
+ {"XfbBuffer",
+ DecorationXfbBuffer,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
+ {"Stride",
+ DecorationStride,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
+ {"BuiltIn",
+ DecorationBuiltIn,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_BUILT_IN, SPV_OPERAND_TYPE_NONE}},
+ {"FuncParamAttr",
+ DecorationFuncParamAttr,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE, SPV_OPERAND_TYPE_NONE}},
+ {"FPRoundingMode",
+ DecorationFPRoundingMode,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_NONE}},
+ {"FPFastMathMode",
+ DecorationFPRoundingMode,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_FP_FAST_MATH_MODE, SPV_OPERAND_TYPE_NONE}},
+ {"LinkageAttributes",
+ DecorationLinkageAttributes,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityLinkage,
+ {SPV_OPERAND_TYPE_LINKAGE_TYPE, SPV_OPERAND_TYPE_NONE}},
+ {
+ "SpecId",
+ DecorationSpecId,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_LITERAL_NUMBER},
+ },
+};
+
+static const spv_operand_desc_t builtInEntries[] = {
+ {"Position",
+ BuiltInPosition,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"PointSize",
+ BuiltInPointSize,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"ClipVertex",
+ BuiltInClipVertex,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"ClipDistance",
+ BuiltInClipDistance,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"CullDistance",
+ BuiltInCullDistance,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"VertexId",
+ BuiltInVertexId,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"InstanceId",
+ BuiltInInstanceId,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"PrimitiveId",
+ BuiltInPrimitiveId,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGeometry | CapabilityTessellation,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"InvocationId",
+ BuiltInInvocationId,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGeometry | CapabilityTessellation,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Layer",
+ BuiltInLayer,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGeometry,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"ViewportIndex",
+ BuiltInViewportIndex,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityGeometry,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"TessLevelOuter",
+ BuiltInTessLevelOuter,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityTessellation,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"TessLevelInner",
+ BuiltInTessLevelInner,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityTessellation,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"TessCoord",
+ BuiltInTessCoord,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityTessellation,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"PatchVertices",
+ BuiltInPatchVertices,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityTessellation,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"FragCoord",
+ BuiltInFragCoord,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"PointCoord",
+ BuiltInPointCoord,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"FrontFacing",
+ BuiltInFrontFacing,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"SampleId",
+ BuiltInSampleId,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"SamplePosition",
+ BuiltInSamplePosition,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"SampleMask",
+ BuiltInSampleMask,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"FragColor",
+ BuiltInFragColor,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"FragDepth",
+ BuiltInFragDepth,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"HelperInvocation",
+ BuiltInHelperInvocation,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"NumWorkgroups",
+ BuiltInNumWorkgroups,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"WorkgroupSize",
+ BuiltInWorkgroupSize,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"WorkgroupId",
+ BuiltInWorkgroupId,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"LocalInvocationId",
+ BuiltInLocalInvocationId,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"GlobalInvocationId",
+ BuiltInGlobalInvocationId,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"LocalInvocationIndex",
+ BuiltInLocalInvocationId,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"WorkDim",
+ BuiltInWorkDim,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"GlobalSize",
+ BuiltInGlobalSize,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"EnqueuedWorkgroupSize",
+ BuiltInEnqueuedWorkgroupSize,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"GlobalOffset",
+ BuiltInGlobalOffset,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"GlobalLinearId",
+ BuiltInGlobalLinearId,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"WorkgroupLinearId",
+ BuiltInWorkgroupLinearId,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"SubgroupSize",
+ BuiltInSubgroupSize,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"SubgroupMaxSize",
+ BuiltInSubgroupMaxSize,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"NumSubgroups",
+ BuiltInNumSubgroups,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"NumEnqueuedSubgroups",
+ BuiltInNumEnqueuedSubgroups,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"SubgroupId",
+ BuiltInSampleId,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"SubgroupLocalInvocationId",
+ BuiltInSubgroupLocalInvocationId,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_t selectionControlEntries[] = {
+ {"None",
+ SelectionControlMaskNone,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Flatten",
+ SelectionControlFlattenMask,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"DontFlatten",
+ SelectionControlDontFlattenMask,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_t loopControlEntries[] = {
+ {"None",
+ LoopControlMaskNone,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Unroll",
+ LoopControlUnrollMask,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"DontUnroll",
+ LoopControlDontUnrollMask,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_t functionControlEntries[] = {
+ {"None",
+ FunctionControlMaskNone,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"InLine",
+ FunctionControlInlineMask,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"DontInline",
+ FunctionControlDontInlineMask,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Pure",
+ FunctionControlPureMask,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Const",
+ FunctionControlConstMask,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_t memorySemanticsEntries[] = {
+ {"None",
+ MemorySemanticsMaskNone,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Relaxed",
+ MemorySemanticsRelaxedMask,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"SequentiallyConsistent",
+ MemorySemanticsSequentiallyConsistentMask,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Acquire",
+ MemorySemanticsAcquireMask,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Release",
+ MemorySemanticsReleaseMask,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"UniformMemory",
+ MemorySemanticsUniformMemoryMask,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"SubgroupMemory",
+ MemorySemanticsSubgroupMemoryMask,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"WorkgroupLocalMemory",
+ MemorySemanticsWorkgroupLocalMemoryMask,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"WorkgroupGlobalMemory",
+ MemorySemanticsWorkgroupGlobalMemoryMask,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"AtomicCounterMemory",
+ MemorySemanticsAtomicCounterMemoryMask,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {
+ "ImageMemory",
+ MemorySemanticsImageMemoryMask,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE},
+ },
+};
+
+static const spv_operand_desc_t memoryAccessEntries[] = {
+ {"None",
+ MemoryAccessMaskNone,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Volatile",
+ MemoryAccessVolatileMask,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {
+ "Aligned",
+ MemoryAccessAlignedMask,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE},
+ },
+};
+
+static const spv_operand_desc_t scopeEntries[] = {
+ {"CrossDevice",
+ ScopeCrossDevice,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Device", ScopeDevice, SPV_OPCODE_FLAGS_NONE, 0, {SPV_OPERAND_TYPE_NONE}},
+ {"Workgroup",
+ ScopeWorkgroup,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Subgroup",
+ ScopeSubgroup,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {
+ "Invocation",
+ ScopeInvocation,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE},
+ },
+};
+
+static const spv_operand_desc_t groupOperationEntries[] = {
+ {"Reduce",
+ GroupOperationReduce,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"InclusiveScan",
+ GroupOperationInclusiveScan,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"ExclusiveScan",
+ GroupOperationExclusiveScan,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_t kernelKernelEnqueueFlagssEntries[] = {
+ {"NoWait",
+ KernelEnqueueFlagsNoWait,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"WaitKernel",
+ KernelEnqueueFlagsWaitKernel,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"WaitWorkGroup",
+ KernelEnqueueFlagsWaitWorkGroup,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_t kernelProfilingInfoEntries[] = {
+ {"None",
+ KernelProfilingInfoMaskNone,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"CmdExecTime",
+ KernelProfilingInfoCmdExecTimeMask,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityKernel,
+ {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_t capabilityInfoEntries[] = {
+ {"Matrix",
+ CapabilityMatrix,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Shader",
+ CapabilityShader,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityMatrix,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Geometry",
+ CapabilityGeometry,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Tessellation",
+ CapabilityTessellation,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ CapabilityShader,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Addresses",
+ CapabilityAddresses,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Linkage",
+ CapabilityLinkage,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Kernel",
+ CapabilityKernel,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Vector16",
+ CapabilityVector16,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Float16Buffer",
+ CapabilityFloat16Buffer,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Float16",
+ CapabilityFloat16,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Float64",
+ CapabilityFloat64,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Int64",
+ CapabilityInt64,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Int64Atomics",
+ CapabilityInt64Atomics,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"ImageBasic",
+ CapabilityImageBasic,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"ImageReadWrite",
+ CapabilityImageReadWrite,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"ImageSRGBWrite",
+ CapabilityImageSRGBWrite,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Pipes",
+ CapabilityPipes,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"Groups",
+ CapabilityGroups,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+ {"DeviceEnqueue",
+ CapabilityDeviceEnqueue,
+ SPV_OPCODE_FLAGS_NONE,
+ 0,
+ {SPV_OPERAND_TYPE_NONE}},
+};
+
+static const spv_operand_desc_group_t opcodeEntryTypes[] = {
+ {SPV_OPERAND_TYPE_SOURCE_LANGUAGE,
+ sizeof(sourceLanguageEntries) / sizeof(spv_operand_desc_t),
+ sourceLanguageEntries},
+ {SPV_OPERAND_TYPE_EXECUTION_MODEL,
+ sizeof(executionModelEntries) / sizeof(spv_operand_desc_t),
+ executionModelEntries},
+ {SPV_OPERAND_TYPE_ADDRESSING_MODEL,
+ sizeof(addressingModelEntries) / sizeof(spv_operand_desc_t),
+ addressingModelEntries},
+ {SPV_OPERAND_TYPE_MEMORY_MODEL,
+ sizeof(memoryModelEntries) / sizeof(spv_operand_desc_t),
+ memoryModelEntries},
+ {SPV_OPERAND_TYPE_EXECUTION_MODE,
+ sizeof(executionModeEntries) / sizeof(spv_operand_desc_t),
+ executionModeEntries},
+ {SPV_OPERAND_TYPE_STORAGE_CLASS,
+ sizeof(storageClassEntries) / sizeof(spv_operand_desc_t),
+ storageClassEntries},
+ {SPV_OPERAND_TYPE_DIMENSIONALITY,
+ sizeof(dimensionalityEntries) / sizeof(spv_operand_desc_t),
+ dimensionalityEntries},
+ {SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE,
+ sizeof(samplerAddressingModeEntries) / sizeof(spv_operand_desc_t),
+ samplerAddressingModeEntries},
+ {SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE,
+ sizeof(samplerFilterModeEntries) / sizeof(spv_operand_desc_t),
+ samplerFilterModeEntries},
+ {SPV_OPERAND_TYPE_FP_FAST_MATH_MODE,
+ sizeof(fpFastMathModeEntries) / sizeof(spv_operand_desc_t),
+ fpFastMathModeEntries},
+ {SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
+ sizeof(fpRoundingModeEntries) / sizeof(spv_operand_desc_t),
+ fpRoundingModeEntries},
+ {SPV_OPERAND_TYPE_LINKAGE_TYPE,
+ sizeof(linkageTypeEntries) / sizeof(spv_operand_desc_t),
+ linkageTypeEntries},
+ {SPV_OPERAND_TYPE_ACCESS_QUALIFIER,
+ sizeof(accessQualifierEntries) / sizeof(spv_operand_desc_t),
+ accessQualifierEntries},
+ {SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
+ sizeof(functionParameterAttributeEntries) / sizeof(spv_operand_desc_t),
+ functionParameterAttributeEntries},
+ {SPV_OPERAND_TYPE_DECORATION,
+ sizeof(decorationEntries) / sizeof(spv_operand_desc_t), decorationEntries},
+ {SPV_OPERAND_TYPE_BUILT_IN,
+ sizeof(builtInEntries) / sizeof(spv_operand_desc_t), builtInEntries},
+ {SPV_OPERAND_TYPE_SELECTION_CONTROL,
+ sizeof(selectionControlEntries) / sizeof(spv_operand_desc_t),
+ selectionControlEntries},
+ {SPV_OPERAND_TYPE_LOOP_CONTROL,
+ sizeof(loopControlEntries) / sizeof(spv_operand_desc_t),
+ loopControlEntries},
+ {SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+ sizeof(functionControlEntries) / sizeof(spv_operand_desc_t),
+ functionControlEntries},
+ {SPV_OPERAND_TYPE_MEMORY_SEMANTICS,
+ sizeof(memorySemanticsEntries) / sizeof(spv_operand_desc_t),
+ memorySemanticsEntries},
+ {SPV_OPERAND_TYPE_MEMORY_ACCESS,
+ sizeof(memoryAccessEntries) / sizeof(spv_operand_desc_t),
+ memoryAccessEntries},
+ {SPV_OPERAND_TYPE_EXECUTION_SCOPE,
+ sizeof(scopeEntries) / sizeof(spv_operand_desc_t), scopeEntries},
+ {SPV_OPERAND_TYPE_GROUP_OPERATION,
+ sizeof(groupOperationEntries) / sizeof(spv_operand_desc_t),
+ groupOperationEntries},
+ {SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS,
+ sizeof(kernelKernelEnqueueFlagssEntries) / sizeof(spv_operand_desc_t),
+ kernelKernelEnqueueFlagssEntries},
+ {SPV_OPERAND_TYPE_KERENL_PROFILING_INFO,
+ sizeof(kernelProfilingInfoEntries) / sizeof(spv_operand_desc_t),
+ kernelProfilingInfoEntries},
+ {SPV_OPERAND_TYPE_CAPABILITY,
+ sizeof(capabilityInfoEntries) / sizeof(spv_operand_desc_t),
+ capabilityInfoEntries},
+};
+
+spv_result_t spvOperandTableGet(spv_operand_table *pOperandTable) {
+ spvCheck(!pOperandTable, return SPV_ERROR_INVALID_POINTER);
+
+ static const spv_operand_table_t table = {
+ sizeof(opcodeEntryTypes) / sizeof(spv_operand_desc_group_t),
+ opcodeEntryTypes};
+
+ *pOperandTable = &table;
+
+ return SPV_SUCCESS;
+}
+
+spv_result_t spvOperandTableNameLookup(const spv_operand_table table,
+ const spv_operand_type_t type,
+ const char *name,
+ spv_operand_desc *pEntry) {
+ spvCheck(!table, return SPV_ERROR_INVALID_TABLE);
+ spvCheck(!name || !pEntry, return SPV_ERROR_INVALID_POINTER);
+
+ const uint64_t nameLength = strlen(name);
+ for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) {
+ if (type == table->types[typeIndex].type) {
+ for (uint64_t operandIndex = 0;
+ operandIndex < table->types[typeIndex].count; ++operandIndex) {
+ if (nameLength ==
+ strlen(table->types[typeIndex].entries[operandIndex].name) &&
+ !strncmp(table->types[typeIndex].entries[operandIndex].name, name,
+ strlen(name))) {
+ *pEntry = &table->types[typeIndex].entries[operandIndex];
+ return SPV_SUCCESS;
+ }
+ }
+ }
+ }
+
+ return SPV_ERROR_INVALID_LOOKUP;
+}
+
+spv_result_t spvOperandTableValueLookup(const spv_operand_table table,
+ const spv_operand_type_t type,
+ const uint32_t value,
+ spv_operand_desc *pEntry) {
+ spvCheck(!table, return SPV_ERROR_INVALID_TABLE);
+ spvCheck(!pEntry, return SPV_ERROR_INVALID_POINTER);
+
+ for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) {
+ if (type == table->types[typeIndex].type) {
+ for (uint64_t operandIndex = 0;
+ operandIndex < table->types[typeIndex].count; ++operandIndex) {
+ if (value == table->types[typeIndex].entries[operandIndex].value) {
+ *pEntry = &table->types[typeIndex].entries[operandIndex];
+ return SPV_SUCCESS;
+ }
+ }
+ }
+ }
+
+ return SPV_ERROR_INVALID_LOOKUP;
+}
+
+const char *spvOperandTypeStr(spv_operand_type_t type) {
+ switch (type) {
+ case SPV_OPERAND_TYPE_ID:
+ return "id";
+ case SPV_OPERAND_TYPE_RESULT_ID:
+ return "result ID";
+ case SPV_OPERAND_TYPE_LITERAL:
+ return "literal";
+ case SPV_OPERAND_TYPE_LITERAL_NUMBER:
+ return "literal number";
+ case SPV_OPERAND_TYPE_LITERAL_STRING:
+ return "literal string";
+ case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
+ return "source langauge";
+ case SPV_OPERAND_TYPE_EXECUTION_MODEL:
+ return "execution model";
+ case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
+ return "addressing model";
+ case SPV_OPERAND_TYPE_MEMORY_MODEL:
+ return "memory model";
+ case SPV_OPERAND_TYPE_EXECUTION_MODE:
+ return "execution mode";
+ case SPV_OPERAND_TYPE_STORAGE_CLASS:
+ return "storage class";
+ case SPV_OPERAND_TYPE_DIMENSIONALITY:
+ return "dimensionality";
+ case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE:
+ return "addressing mode";
+ case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
+ return "sampler filter mode";
+ case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
+ return "floating pointer fast math mode";
+ case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
+ return "floating point rounding mode";
+ case SPV_OPERAND_TYPE_LINKAGE_TYPE:
+ return "linkage type";
+ case SPV_OPERAND_TYPE_ACCESS_QUALIFIER:
+ return "access qualifier";
+ case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE:
+ return "function parameter attribute";
+ case SPV_OPERAND_TYPE_DECORATION:
+ return "decoration";
+ case SPV_OPERAND_TYPE_BUILT_IN:
+ return "built in";
+ case SPV_OPERAND_TYPE_SELECTION_CONTROL:
+ return "selection control";
+ case SPV_OPERAND_TYPE_LOOP_CONTROL:
+ return "loop control";
+ case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
+ return "function control";
+ case SPV_OPERAND_TYPE_MEMORY_SEMANTICS:
+ return "memory semantics";
+ case SPV_OPERAND_TYPE_MEMORY_ACCESS:
+ return "memory access";
+ case SPV_OPERAND_TYPE_EXECUTION_SCOPE:
+ return "execution scope";
+ case SPV_OPERAND_TYPE_GROUP_OPERATION:
+ return "group operation";
+ case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
+ return "kernel enqeue flags";
+ case SPV_OPERAND_TYPE_KERENL_PROFILING_INFO:
+ return "kernel profiling info";
+ case SPV_OPERAND_TYPE_CAPABILITY:
+ return "capability";
+ default:
+ assert(0 && "Unhandled operand type!");
+ break;
+ }
+ return "unknown";
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#ifndef _CODEPLAY_SPIRV_OPERAND_H_
+#define _CODEPLAY_SPIRV_OPERAND_H_
+
+#include <libspirv/libspirv.h>
+
+/// @brief Find the named operand in the table
+///
+/// @param[in] table to lookup
+/// @param[in] type the operand group's type
+/// @param[in] name of the operand to find
+/// @param[out] pEntry returned operand table entry
+///
+/// @return result code
+spv_result_t spvOperandTableNameLookup(const spv_operand_table table,
+ const spv_operand_type_t type,
+ const char *name,
+ spv_operand_desc *pEntry);
+
+/// @brief Find the operand with value in the table
+///
+/// @param[in] table to lookup
+/// @param[in] type the operand group's type
+/// @param[in] value of the operand to find
+/// @param[out] pEntry return operand table entry
+///
+/// @return result code
+spv_result_t spvOperandTableValueLookup(const spv_operand_table table,
+ const spv_operand_type_t type,
+ const uint32_t value,
+ spv_operand_desc *pEntry);
+
+/// @brief Get the name string of the operand type
+///
+/// @param type the type of the operand
+///
+/// @return the string name of the operand
+const char *spvOperandTypeStr(spv_operand_type_t type);
+
+#endif
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "print.h"
+
+#if defined(SPIRV_LINUX) || defined(SPIRV_MAC)
+clr::reset::operator const char *() { return "\e[0m"; }
+
+clr::grey::operator const char *() { return "\e[1;30m"; }
+
+clr::red::operator const char *() { return "\e[31m"; }
+
+clr::green::operator const char *() { return "\e[32m"; }
+
+clr::yellow::operator const char *() { return "\e[33m"; }
+
+clr::blue::operator const char *() { return "\e[34m"; }
+#elif defined(SPIRV_WINDOWS)
+#include <Windows.h>
+
+clr::reset::operator const char *() {
+ const DWORD color = 0Xf;
+ HANDLE hConsole;
+ hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleTextAttribute(hConsole, color);
+ hConsole = GetStdHandle(STD_ERROR_HANDLE);
+ SetConsoleTextAttribute(hConsole, color);
+ return "";
+}
+
+clr::grey::operator const char *() {
+ const DWORD color = 0x8;
+ HANDLE hConsole;
+ hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleTextAttribute(hConsole, color);
+ hConsole = GetStdHandle(STD_ERROR_HANDLE);
+ SetConsoleTextAttribute(hConsole, color);
+ return "";
+}
+
+clr::red::operator const char *() {
+ const DWORD color = 0x4;
+ HANDLE hConsole;
+ hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleTextAttribute(hConsole, color);
+ hConsole = GetStdHandle(STD_ERROR_HANDLE);
+ SetConsoleTextAttribute(hConsole, color);
+ return "";
+}
+
+clr::green::operator const char *() {
+ const DWORD color = 0x2;
+ HANDLE hConsole;
+ hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleTextAttribute(hConsole, color);
+ hConsole = GetStdHandle(STD_ERROR_HANDLE);
+ SetConsoleTextAttribute(hConsole, color);
+ return "";
+}
+
+clr::yellow::operator const char *() {
+ const DWORD color = 0x6;
+ HANDLE hConsole;
+ hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleTextAttribute(hConsole, color);
+ hConsole = GetStdHandle(STD_ERROR_HANDLE);
+ SetConsoleTextAttribute(hConsole, color);
+ return "";
+}
+
+clr::blue::operator const char *() {
+ const DWORD color = 0x1;
+ HANDLE hConsole;
+ hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleTextAttribute(hConsole, color);
+ hConsole = GetStdHandle(STD_ERROR_HANDLE);
+ SetConsoleTextAttribute(hConsole, color);
+ return "";
+}
+#endif
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#ifndef _LIBSPIRV_PRINT_H_
+#define _LIBSPIRV_PRINT_H_
+
+#include <iostream>
+#include <sstream>
+
+/// @brief Wrapper for out stream selection
+class out_stream {
+ public:
+ out_stream() : pStream(nullptr) {}
+ out_stream(std::stringstream &stream) : pStream(&stream) {}
+
+ std::ostream &get() {
+ if (pStream) {
+ return *pStream;
+ }
+ return std::cout;
+ }
+
+ private:
+ std::stringstream *pStream;
+};
+
+namespace clr {
+/// @brief Reset console color
+struct reset {
+ operator const char *();
+};
+/// @brief Set console color to grey
+struct grey {
+ operator const char *();
+};
+/// @brief Set console color to red
+struct red {
+ operator const char *();
+};
+/// @brief Set console color to green
+struct green {
+ operator const char *();
+};
+/// @brief Set console color to yellow
+struct yellow {
+ operator const char *();
+};
+/// @brief Set console color to blue
+struct blue {
+ operator const char *();
+};
+}
+
+#endif
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include <libspirv/libspirv.h>
+#include "binary.h"
+#include "diagnostic.h"
+#include "ext_inst.h"
+#include "opcode.h"
+#include "operand.h"
+#include "text.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <string>
+#include <vector>
+#include <unordered_map>
+
+// Structures
+
+struct spv_named_id_table_t {
+ std::unordered_map<std::string, uint32_t> namedIds;
+};
+
+// Text API
+
+std::string getWord(const char *str) {
+ size_t index = 0;
+ while (true) {
+ switch (str[index]) {
+ case '\0':
+ case '\t':
+ case '\n':
+ case ' ':
+ break;
+ default:
+ index++;
+ }
+ }
+ return std::string(str, str + index);
+}
+
+spv_named_id_table spvNamedIdTableCreate() {
+ return new spv_named_id_table_t();
+}
+
+void spvNamedIdTableDestory(spv_named_id_table table) { delete table; }
+
+uint32_t spvNamedIdAssignOrGet(spv_named_id_table table, const char *textValue,
+ uint32_t *pBound) {
+ if (table->namedIds.end() == table->namedIds.find(textValue)) {
+ table->namedIds[textValue] = *pBound;
+ }
+ return table->namedIds[textValue];
+}
+
+int32_t spvTextIsNamedId(const char *textValue) {
+ // TODO: Strengthen the parsing of textValue to only include allow names that
+ // match: ([a-z]|[A-Z])(_|[a-z]|[A-Z]|[0-9])*
+ switch (textValue[0]) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return false;
+ default:
+ break;
+ }
+ return true;
+}
+
+spv_result_t spvTextAdvanceLine(const spv_text text, spv_position position) {
+ while (true) {
+ switch (text->str[position->index]) {
+ case '\0':
+ return SPV_END_OF_STREAM;
+ case '\n':
+ position->column = 0;
+ position->line++;
+ position->index++;
+ return SPV_SUCCESS;
+ default:
+ position->line++;
+ position->index++;
+ break;
+ }
+ }
+}
+
+spv_result_t spvTextAdvance(const spv_text text, spv_position position) {
+ // NOTE: Consume white space, otherwise don't advance.
+ switch (text->str[position->index]) {
+ case '\0':
+ return SPV_END_OF_STREAM;
+ case ';':
+ return spvTextAdvanceLine(text, position);
+ case ' ':
+ case '\t':
+ position->column++;
+ position->index++;
+ return spvTextAdvance(text, position);
+ case '\n':
+ position->column = 0;
+ position->line++;
+ position->index++;
+ return spvTextAdvance(text, position);
+ default:
+ break;
+ }
+
+ return SPV_SUCCESS;
+}
+
+spv_result_t spvTextWordGet(const spv_text text,
+ const spv_position startPosition, std::string &word,
+ spv_position endPosition) {
+ spvCheck(!text->str || !text->length, return SPV_ERROR_INVALID_TEXT);
+ spvCheck(!startPosition || !endPosition, return SPV_ERROR_INVALID_POINTER);
+
+ *endPosition = *startPosition;
+
+ // NOTE: Assumes first character is not white space!
+ while (true) {
+ switch (text->str[endPosition->index]) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\0': { // NOTE: End of word found!
+ word.assign(text->str + startPosition->index,
+ (size_t)(endPosition->index - startPosition->index));
+ return SPV_SUCCESS;
+ }
+ default:
+ break;
+ }
+
+ endPosition->column++;
+ endPosition->index++;
+ }
+}
+
+spv_result_t spvTextStringGet(const spv_text text,
+ const spv_position startPosition,
+ std::string &string, spv_position endPosition) {
+ spvCheck(!text->str || !text->length, return SPV_ERROR_INVALID_TEXT);
+ spvCheck(!startPosition || !endPosition, return SPV_ERROR_INVALID_POINTER);
+
+ spvCheck('"' != text->str[startPosition->index],
+ return SPV_ERROR_INVALID_TEXT);
+
+ *endPosition = *startPosition;
+
+ // NOTE: Assumes first character is not white space
+ while (true) {
+ endPosition->column++;
+ endPosition->index++;
+
+ switch (text->str[endPosition->index]) {
+ case '"': {
+ endPosition->column++;
+ endPosition->index++;
+
+ string.assign(text->str + startPosition->index,
+ (size_t)(endPosition->index - startPosition->index));
+
+ return SPV_SUCCESS;
+ }
+ case '\n':
+ case '\0':
+ return SPV_ERROR_INVALID_TEXT;
+ default:
+ break;
+ }
+ }
+}
+
+spv_result_t spvTextToUInt32(const char *textValue, uint32_t *pValue) {
+ char *endPtr = nullptr;
+ *pValue = strtoul(textValue, &endPtr, 0);
+ if (0 == *pValue && textValue == endPtr) {
+ return SPV_ERROR_INVALID_TEXT;
+ }
+ return SPV_SUCCESS;
+}
+
+spv_result_t spvTextToLiteral(const char *textValue, spv_literal_t *pLiteral) {
+ bool isSigned = false;
+ bool isFloat = false;
+ bool isString = false;
+
+ if ('-' == textValue[0]) {
+ isSigned = true;
+ }
+
+ for (uint64_t index = 0; index < strlen(textValue); ++index) {
+ switch (textValue[index]) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ break;
+ case '.':
+ isFloat = true;
+ break;
+ default:
+ isString = true;
+ break;
+ }
+ }
+
+ if (isString) {
+ pLiteral->type = SPV_LITERAL_TYPE_STRING;
+ strncpy(pLiteral->value.str, textValue, strlen(textValue));
+ } else if (isFloat) {
+ double d = strtod(textValue, nullptr);
+ float f = (float)d;
+ if (d == (double)f) {
+ pLiteral->type = SPV_LITERAL_TYPE_FLOAT_32;
+ pLiteral->value.f = f;
+ } else {
+ pLiteral->type = SPV_LITERAL_TYPE_FLOAT_64;
+ pLiteral->value.d = d;
+ }
+ } else if (isSigned) {
+ int64_t i64 = strtoll(textValue, nullptr, 10);
+ int32_t i32 = (int32_t)i64;
+ if (i64 == (int64_t)i32) {
+ pLiteral->type = SPV_LITERAL_TYPE_INT_32;
+ pLiteral->value.i32 = i32;
+ } else {
+ pLiteral->type = SPV_LITERAL_TYPE_INT_64;
+ pLiteral->value.i64 = i64;
+ }
+ } else {
+ uint64_t u64 = strtoull(textValue, nullptr, 10);
+ uint32_t u32 = (uint32_t)u64;
+ if (u64 == (uint64_t)u32) {
+ pLiteral->type = SPV_LITERAL_TYPE_UINT_32;
+ pLiteral->value.u32 = u32;
+ } else {
+ pLiteral->type = SPV_LITERAL_TYPE_UINT_64;
+ pLiteral->value.u64 = u64;
+ }
+ }
+
+ return SPV_SUCCESS;
+}
+
+spv_result_t spvTextEncodeOperand(
+ const spv_operand_type_t type, const char *textValue,
+ const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
+ spv_named_id_table namedIdTable, spv_instruction_t *pInst,
+ const spv_operand_type_t **ppExtraOperands, uint32_t *pBound,
+ const spv_position position, spv_diagnostic *pDiagnostic) {
+ // NOTE: Handle immediate int in the stream
+ if ('!' == textValue[0]) {
+ const char *begin = textValue + 1;
+ char *end = nullptr;
+ uint32_t immediateInt = strtoul(begin, &end, 0);
+ size_t size = strlen(textValue);
+ size_t length = (end - begin);
+ spvCheck(size - 1 != length, DIAGNOSTIC << "Invalid immediate integer '"
+ << textValue << "'.";
+ return SPV_ERROR_INVALID_TEXT);
+ position->column += size;
+ position->index += size;
+ pInst->words[pInst->wordCount] = immediateInt;
+ pInst->wordCount += 1;
+ return SPV_SUCCESS;
+ }
+
+ switch (type) {
+ case SPV_OPERAND_TYPE_ID: {
+ if ('$' == textValue[0]) {
+ textValue++;
+ }
+ // TODO: Force all ID's to be prefixed with '$'.
+ uint32_t id = 0;
+ if (spvTextIsNamedId(textValue)) {
+ id = spvNamedIdAssignOrGet(namedIdTable, textValue, pBound);
+ } else {
+ spvCheck(spvTextToUInt32(textValue, &id),
+ DIAGNOSTIC << "Invalid ID '" << textValue << "'.";
+ return SPV_ERROR_INVALID_TEXT);
+ }
+ pInst->words[pInst->wordCount++] = id;
+ if (*pBound <= id) {
+ *pBound = id + 1;
+ }
+ } break;
+ case SPV_OPERAND_TYPE_RESULT_ID: {
+ if ('%' == textValue[0]) {
+ textValue++;
+ }
+ // TODO: Force all Result ID's to be prefixed with '%'.
+ uint32_t id = 0;
+ if (spvTextIsNamedId(textValue)) {
+ id = spvNamedIdAssignOrGet(namedIdTable, textValue, pBound);
+ } else {
+ spvCheck(spvTextToUInt32(textValue, &id),
+ DIAGNOSTIC << "Invalid result ID '" << textValue << "'.";
+ return SPV_ERROR_INVALID_TEXT);
+ }
+ pInst->words[pInst->wordCount++] = id;
+ if (*pBound <= id) {
+ *pBound = id + 1;
+ }
+ } break;
+ case SPV_OPERAND_TYPE_LITERAL_NUMBER: {
+ // NOTE: Special case for extension instruction lookup
+ if (OpExtInst == pInst->opcode) {
+ spv_ext_inst_desc extInst;
+ spvCheck(spvExtInstTableNameLookup(extInstTable, pInst->extInstType,
+ textValue, &extInst),
+ DIAGNOSTIC << "Invalid extended instruction name '"
+ << textValue << "'.";
+ return SPV_ERROR_INVALID_TEXT);
+ pInst->words[pInst->wordCount++] = extInst->ext_inst;
+ *ppExtraOperands = extInst->operandTypes;
+ return SPV_SUCCESS;
+ }
+
+ // TODO: Literal numbers can be any number up to 64 bits wide. This
+ // includes integers and floating point numbers.
+ spvCheck(spvTextToUInt32(textValue, &pInst->words[pInst->wordCount++]),
+ DIAGNOSTIC << "Invalid literal number '" << textValue << "'.";
+ return SPV_ERROR_INVALID_TEXT);
+ } break;
+ case SPV_OPERAND_TYPE_LITERAL: {
+ spv_literal_t literal = {};
+ spvCheck(spvTextToLiteral(textValue, &literal),
+ DIAGNOSTIC << "Invalid literal '" << textValue << "'.";
+ return SPV_ERROR_INVALID_TEXT);
+ switch (literal.type) {
+ case SPV_LITERAL_TYPE_INT_32:
+ spvCheck(spvBinaryEncodeU32((uint32_t)literal.value.i32, pInst,
+ position, pDiagnostic),
+ return SPV_ERROR_INVALID_TEXT);
+ break;
+ case SPV_LITERAL_TYPE_INT_64: {
+ spvCheck(spvBinaryEncodeU64((uint64_t)literal.value.i64, pInst,
+ position, pDiagnostic),
+ return SPV_ERROR_INVALID_TEXT);
+ } break;
+ case SPV_LITERAL_TYPE_UINT_32: {
+ spvCheck(spvBinaryEncodeU32(literal.value.u32, pInst, position,
+ pDiagnostic),
+ return SPV_ERROR_INVALID_TEXT);
+ } break;
+ case SPV_LITERAL_TYPE_UINT_64: {
+ spvCheck(spvBinaryEncodeU64((uint64_t)literal.value.u64, pInst,
+ position, pDiagnostic),
+ return SPV_ERROR_INVALID_TEXT);
+ } break;
+ case SPV_LITERAL_TYPE_FLOAT_32: {
+ spvCheck(spvBinaryEncodeU32((uint32_t)literal.value.f, pInst,
+ position, pDiagnostic),
+ return SPV_ERROR_INVALID_TEXT);
+ } break;
+ case SPV_LITERAL_TYPE_FLOAT_64: {
+ spvCheck(spvBinaryEncodeU64((uint64_t)literal.value.d, pInst,
+ position, pDiagnostic),
+ return SPV_ERROR_INVALID_TEXT);
+ } break;
+ case SPV_LITERAL_TYPE_STRING: {
+ spvCheck(spvBinaryEncodeString(literal.value.str, pInst, position,
+ pDiagnostic),
+ return SPV_ERROR_INVALID_TEXT);
+ } break;
+ default:
+ DIAGNOSTIC << "Invalid literal '" << textValue << "'";
+ return SPV_ERROR_INVALID_TEXT;
+ }
+ } break;
+ case SPV_OPERAND_TYPE_LITERAL_STRING: {
+ size_t len = strlen(textValue);
+ spvCheck('"' != textValue[0] && '"' != textValue[len - 1],
+ DIAGNOSTIC << "Invalid literal string '" << textValue
+ << "', expected quotes.";
+ return SPV_ERROR_INVALID_TEXT);
+ // NOTE: Strip quotes
+ std::string text(textValue + 1, len - 2);
+
+ // NOTE: Special case for extended instruction library import
+ if (OpExtInstImport == pInst->opcode) {
+ pInst->extInstType = spvExtInstImportTypeGet(text.c_str());
+ }
+
+ spvCheck(
+ spvBinaryEncodeString(text.c_str(), pInst, position, pDiagnostic),
+ return SPV_ERROR_INVALID_TEXT);
+ } break;
+ default: {
+ // NOTE: All non literal operands are handled here using the operand
+ // table.
+ spv_operand_desc entry;
+ spvCheck(spvOperandTableNameLookup(operandTable, type, textValue, &entry),
+ DIAGNOSTIC << "Invalid " << spvOperandTypeStr(type) << " '"
+ << textValue << "'.";
+ return SPV_ERROR_INVALID_TEXT;);
+ spvCheck(spvBinaryEncodeU32(entry->value, pInst, position, pDiagnostic),
+ DIAGNOSTIC << "Invalid " << spvOperandTypeStr(type) << " '"
+ << textValue << "'.";
+ return SPV_ERROR_INVALID_TEXT;);
+ if (ppExtraOperands && entry->operandTypes[0] != SPV_OPERAND_TYPE_NONE) {
+ *ppExtraOperands = entry->operandTypes;
+ }
+ } break;
+ }
+ return SPV_SUCCESS;
+}
+
+spv_result_t spvTextEncodeOpcode(
+ const spv_text text, const spv_opcode_table opcodeTable,
+ const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
+ spv_named_id_table namedIdTable, uint32_t *pBound, spv_instruction_t *pInst,
+ spv_position position, spv_diagnostic *pDiagnostic) {
+ std::string opcodeName;
+ spv_position_t nextPosition = {};
+ spvCheck(spvTextWordGet(text, position, opcodeName, &nextPosition),
+ return SPV_ERROR_INTERNAL);
+
+ bool immediate = false;
+ spvCheck('!' == text->str[position->index], immediate = true);
+ if (!immediate) {
+ spvCheck('O' != opcodeName[0] || 'p' != opcodeName[1],
+ DIAGNOSTIC << "Invalid Opcode prefix '" << opcodeName << "'.";
+ return SPV_ERROR_INVALID_TEXT);
+ }
+
+ // NOTE: Handle insertion of an immediate integer into the binary stream
+ if (immediate) {
+ const char *begin = opcodeName.data() + 1;
+ char *end = nullptr;
+ uint32_t immediateInt = strtoul(begin, &end, 0);
+ size_t size = opcodeName.size() - 1;
+ spvCheck(size != (size_t)(end - begin),
+ DIAGNOSTIC << "Invalid immediate integer '" << opcodeName << "'.";
+ return SPV_ERROR_INVALID_TEXT);
+ position->column += opcodeName.size();
+ position->index += opcodeName.size();
+ pInst->words[0] = immediateInt;
+ pInst->wordCount = 1;
+ return SPV_SUCCESS;
+ }
+
+ // NOTE: The table contains Opcode names without the "Op" prefix.
+ const char *pInstName = opcodeName.data() + 2;
+
+ spv_opcode_desc opcodeEntry;
+ spv_result_t error =
+ spvOpcodeTableNameLookup(opcodeTable, pInstName, &opcodeEntry);
+ spvCheck(error, DIAGNOSTIC << "Invalid Opcode name '"
+ << getWord(text->str + position->index) << "'";
+ return error);
+ pInst->opcode = opcodeEntry->opcode;
+ *position = nextPosition;
+ pInst->wordCount++;
+
+ // NOTE: Process the fixed size operands
+ const spv_operand_type_t *extraOperandTypes = nullptr;
+ for (int32_t operandIndex = 0; operandIndex < (opcodeEntry->wordCount - 1);
+ ++operandIndex) {
+ spvCheck(spvTextAdvance(text, position),
+ DIAGNOSTIC << "Expected operand, found end of stream.";
+ return SPV_ERROR_INVALID_TEXT);
+
+ std::string operandValue;
+ error = spvTextWordGet(text, position, operandValue, &nextPosition);
+ spvCheck(error, return error);
+
+ error = spvTextEncodeOperand(
+ opcodeEntry->operandTypes[operandIndex], operandValue.c_str(),
+ operandTable, extInstTable, namedIdTable, pInst, &extraOperandTypes,
+ pBound, position, pDiagnostic);
+ spvCheck(error, return error);
+
+ *position = nextPosition;
+ }
+
+ if (spvOpcodeIsVariable(opcodeEntry)) {
+ if (!extraOperandTypes) {
+ // NOTE: Handle variable length not defined by an immediate previously
+ // encountered in the Opcode.
+ spv_operand_type_t type =
+ opcodeEntry->operandTypes[opcodeEntry->wordCount - 1];
+
+ while (!spvTextAdvance(text, position)) {
+ std::string textValue;
+ spvTextWordGet(text, position, textValue, &nextPosition);
+
+ // NOTE: Check if the next text word is an Opcode
+ if ('O' == textValue[0] && 'p' == textValue[1]) {
+ // NOTE: This is the end of the current instruction stream and we
+ // break out of this loop
+ break;
+ } else {
+ if (SPV_OPERAND_TYPE_LITERAL_STRING == type) {
+ spvCheck(spvTextAdvance(text, position),
+ DIAGNOSTIC << "Invalid string, found end of stream.";
+ return SPV_ERROR_INVALID_TEXT);
+
+ std::string string;
+ spvCheck(spvTextStringGet(text, position, string, &nextPosition),
+ DIAGNOSTIC << "Invalid string, new line or end of stream.";
+ return SPV_ERROR_INVALID_TEXT);
+ spvCheck(
+ spvTextEncodeOperand(type, string.c_str(), operandTable,
+ extInstTable, namedIdTable, pInst, nullptr,
+ pBound, position, pDiagnostic),
+ return SPV_ERROR_INVALID_TEXT);
+ } else {
+ spvCheck(
+ spvTextEncodeOperand(type, textValue.c_str(), operandTable,
+ extInstTable, namedIdTable, pInst, nullptr,
+ pBound, position, pDiagnostic),
+ return SPV_ERROR_INVALID_TEXT);
+ }
+ *position = nextPosition;
+ }
+ }
+ } else {
+ // NOTE: Process the variable size operands defined by an immediate
+ // previously encountered in the Opcode.
+ uint64_t extraOperandsIndex = 0;
+ while (extraOperandTypes[extraOperandsIndex]) {
+ spvCheck(spvTextAdvance(text, position),
+ DIAGNOSTIC << "Expected operand, found end of stream.";
+ return SPV_ERROR_INVALID_TEXT);
+
+ std::string operandValue;
+ error = spvTextWordGet(text, position, operandValue, &nextPosition);
+
+ error = spvTextEncodeOperand(extraOperandTypes[extraOperandsIndex],
+ operandValue.c_str(), operandTable,
+ extInstTable, namedIdTable, pInst, nullptr,
+ pBound, position, pDiagnostic);
+ spvCheck(error, return error);
+
+ *position = nextPosition;
+
+ extraOperandsIndex++;
+ }
+ }
+ }
+
+ pInst->words[0] = spvOpcodeMake(pInst->wordCount, opcodeEntry->opcode);
+
+ return SPV_SUCCESS;
+}
+
+spv_result_t spvTextToBinary(const spv_text text,
+ const spv_opcode_table opcodeTable,
+ const spv_operand_table operandTable,
+ const spv_ext_inst_table extInstTable,
+ spv_binary *pBinary, spv_diagnostic *pDiagnostic) {
+ spv_position_t position = {};
+ spvCheck(!text->str || !text->length, DIAGNOSTIC << "Text stream is empty.";
+ return SPV_ERROR_INVALID_TEXT);
+ spvCheck(!opcodeTable || !operandTable || !extInstTable,
+ return SPV_ERROR_INVALID_TABLE);
+ spvCheck(!pBinary, return SPV_ERROR_INVALID_POINTER);
+ spvCheck(!pDiagnostic, return SPV_ERROR_INVALID_DIAGNOSTIC);
+
+ // NOTE: Ensure diagnostic is zero initialised
+ *pDiagnostic = {};
+
+ uint32_t bound = 1;
+
+ std::vector<spv_instruction_t> instructions;
+
+ spvCheck(spvTextAdvance(text, &position), DIAGNOSTIC
+ << "Text stream is empty.";
+ return SPV_ERROR_INVALID_TEXT);
+
+ spv_named_id_table namedIdTable = spvNamedIdTableCreate();
+ spvCheck(!namedIdTable, return SPV_ERROR_OUT_OF_MEMORY);
+
+ spv_ext_inst_type_t extInstType = SPV_EXT_INST_TYPE_NONE;
+ while (text->length > position.index) {
+ spv_instruction_t inst = {};
+ inst.extInstType = extInstType;
+
+ spvCheck(spvTextEncodeOpcode(text, opcodeTable, operandTable, extInstTable,
+ namedIdTable, &bound, &inst, &position,
+ pDiagnostic),
+ spvNamedIdTableDestory(namedIdTable);
+ return SPV_ERROR_INVALID_TEXT);
+ extInstType = inst.extInstType;
+
+ instructions.push_back(inst);
+
+ spvCheck(spvTextAdvance(text, &position), break);
+ }
+
+ spvNamedIdTableDestory(namedIdTable);
+
+ size_t totalSize = SPV_INDEX_INSTRUCTION;
+ for (auto &inst : instructions) {
+ totalSize += inst.wordCount;
+ }
+
+ uint32_t *data = new uint32_t[totalSize];
+ spvCheck(!data, return SPV_ERROR_OUT_OF_MEMORY);
+ uint64_t currentIndex = SPV_INDEX_INSTRUCTION;
+ for (auto &inst : instructions) {
+ memcpy(data + currentIndex, inst.words, sizeof(uint32_t) * inst.wordCount);
+ currentIndex += inst.wordCount;
+ }
+
+ spv_binary binary = new spv_binary_t();
+ spvCheck(!binary, delete[] data; return SPV_ERROR_OUT_OF_MEMORY);
+ binary->code = data;
+ binary->wordCount = totalSize;
+
+ spv_result_t error = spvBinaryHeaderSet(binary, bound);
+ spvCheck(error, spvBinaryDestroy(binary); return error);
+
+ *pBinary = binary;
+
+ return SPV_SUCCESS;
+}
+
+void spvTextDestroy(spv_text text) {
+ spvCheck(!text, return );
+ if (text->str) {
+ delete[] text->str;
+ }
+ delete text;
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#ifndef _LIBSPIRV_UTIL_TEXT_H_
+#define _LIBSPIRV_UTIL_TEXT_H_
+
+#include <libspirv/libspirv.h>
+
+#include <string>
+
+// Structures
+
+typedef enum spv_literal_type_t {
+ SPV_LITERAL_TYPE_INT_32,
+ SPV_LITERAL_TYPE_INT_64,
+ SPV_LITERAL_TYPE_UINT_32,
+ SPV_LITERAL_TYPE_UINT_64,
+ SPV_LITERAL_TYPE_FLOAT_32,
+ SPV_LITERAL_TYPE_FLOAT_64,
+ SPV_LITERAL_TYPE_STRING,
+ SPV_FORCE_32_BIT_ENUM(spv_literal_type_t)
+} spv_literal_type_t;
+
+typedef struct spv_literal_t {
+ spv_literal_type_t type;
+ union value_t {
+ int32_t i32;
+ int64_t i64;
+ uint32_t u32;
+ uint64_t u64;
+ float f;
+ double d;
+ char str[SPV_LIMIT_LITERAL_STRING_MAX];
+ } value;
+} spv_literal_t;
+
+struct spv_named_id_table_t;
+
+// Types
+
+typedef spv_named_id_table_t *spv_named_id_table;
+
+// Functions
+
+/// @brief Advance text to the start of the next line
+///
+/// @param[in] text to be parsed
+/// @param[in,out] pPosition position text has been advanced to
+///
+/// @return result code
+spv_result_t spvTextAdvanceLine(const spv_text text, spv_position_t *pPosition);
+
+/// @brief Advance text to first non white space character
+///
+/// If a null terminator is found during the text advance SPV_END_OF_STREAM is
+/// returned, SPV_SUCCESS otherwise. No error checking is performed on the
+/// parameters, its the users responsispvity to ensure these are non null.
+///
+/// @param[in] text to be parsed
+/// @param[in,out] pPosition position text has been advanced to
+///
+/// @return result code
+spv_result_t spvTextAdvance(const spv_text text, spv_position_t *pPosition);
+
+/// @brief Fetch the next word from the text stream
+///
+/// @param[in] text stream to read from
+/// @param[in] startPosition current position in text stream
+/// @param[out] word returned word
+/// @param[out] endPosition one past the end of the returned word
+///
+/// @return result code
+spv_result_t spvTextWordGet(const spv_text text,
+ const spv_position startPosition, std::string &word,
+ spv_position endPosition);
+
+/// @brief Fetch a string, including quotes, from the text stream
+///
+/// @param[in] text stream to read from
+/// @param[in] startPosition current position in text stream
+/// @param[out] string returned string
+/// @param[out] endPosition one past the end of the return string
+///
+/// @return result code
+spv_result_t spvTextStringGet(const spv_text text,
+ const spv_position startPosition,
+ std::string &string, spv_position endPosition);
+
+/// @brief Convert the input text to a unsigned 32 bit integer
+///
+/// @param[in] textValue input text to parse
+/// @param[out] pValue the returned integer
+///
+/// @return result code
+spv_result_t spvTextToUInt32(const char *textValue, uint32_t *pValue);
+
+/// @brief Convert the input text to one of the number types
+///
+/// @param[in] textValue input text to parse
+/// @param[out] pLiteral the returned literal number
+///
+/// @return result code
+spv_result_t spvTextToLiteral(const char *textValue, spv_literal_t *pLiteral);
+
+/// @brief Create a named ID table
+///
+/// @return named ID table
+spv_named_id_table spvNamedIdTableCreate();
+
+/// @brief Free a named ID table
+///
+/// @param table named ID table
+void spvNamedIdTableDestory(spv_named_id_table table);
+
+/// @brief Lookup or assign a named ID
+///
+/// @param table named ID table
+/// @param textValue name value
+/// @param pBound upper ID bound, used for assigning new ID's
+///
+/// @return the new ID assossiated with the named ID
+uint32_t spvNamedIdAssignOrGet(spv_named_id_table table, const char *textValue,
+ uint32_t *pBound);
+
+/// @brief Determine if a name has an assossiated ID
+///
+/// @param textValue name value
+///
+/// @return zero on failure, non-zero otherwise
+int32_t spvTextIsNamedId(const char *textValue);
+
+/// @brief Translate an Opcode operand to binary form
+///
+/// @param[in] type of the operand
+/// @param[in] textValue word of text to be parsed
+/// @param[in] operandTable operand lookup table
+/// @param[in,out] namedIdTable table of named ID's
+/// @param[out] pInst return binary Opcode
+/// @param[out] ppExtraOperands list of extra variable operands, if any
+/// @param[in,out] pBound current highest defined ID value
+/// @param[in] pPosition used in diagnostic on error
+/// @param[out] pDiagnostic populated on error
+///
+/// @return result code
+spv_result_t spvTextEncodeOperand(
+ const spv_operand_type_t type, const char *textValue,
+ const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
+ spv_named_id_table namedIdTable, spv_instruction_t *pInst,
+ const spv_operand_type_t **ppExtraOperands, uint32_t *pBound,
+ const spv_position_t *pPosition, spv_diagnostic *pDiagnostic);
+
+/// @brief Translate single Opcode and operands to binary form
+///
+/// @param[in] text stream to translate
+/// @param[in] opcodeTable Opcode lookup table
+/// @param[in] operandTable operand lookup table
+/// @param[in,out] namedIdTable table of named ID's
+/// @param[in,out] pBound current highest defined ID value
+/// @param[out] pInst returned binary Opcode
+/// @param[in,out] pPosition in the text stream
+/// @param[out] pDiagnostic populated on failure
+///
+/// @return result code
+spv_result_t spvTextEncodeOpcode(
+ const spv_text text, const spv_opcode_table opcodeTable,
+ const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
+ spv_named_id_table namedIdTable, uint32_t *pBound, spv_instruction_t *pInst,
+ spv_position_t *pPosition, spv_diagnostic *pDiagnostic);
+
+#endif
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include <libspirv/libspirv.h>
+#include "binary.h"
+#include "diagnostic.h"
+#include "opcode.h"
+#include "operand.h"
+#include "validate.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <vector>
+
+spv_result_t spvValidateOperandsString(const uint32_t *words,
+ const uint16_t wordCount,
+ spv_position position,
+ spv_diagnostic *pDiagnostic) {
+ const char *str = (const char *)words;
+ uint64_t strWordCount = strlen(str) / sizeof(uint32_t) + 1;
+ spvCheck(strWordCount < wordCount, DIAGNOSTIC << "Instruction word count is "
+ "too short, string extends "
+ "past end of instruction.";
+ return SPV_WARNING);
+ return SPV_SUCCESS;
+}
+
+spv_result_t spvValidateOperandsLiteral(const uint32_t *words,
+ const uint32_t length,
+ const uint16_t maxLength,
+ spv_position position,
+ spv_diagnostic *pDiagnostic) {
+ // NOTE: A literal could either be a number consuming up to 2 words or a
+ // null terminated string.
+ (void)words;
+ (void)length;
+ (void)maxLength;
+ (void)position;
+ (void)pDiagnostic;
+ return SPV_UNSUPPORTED;
+}
+
+spv_result_t spvValidateOperandValue(const spv_operand_type_t type,
+ const uint32_t word,
+ const spv_operand_table operandTable,
+ spv_position position,
+ spv_diagnostic *pDiagnostic) {
+ switch (type) {
+ case SPV_OPERAND_TYPE_ID:
+ case SPV_OPERAND_TYPE_RESULT_ID: {
+ // NOTE: ID's are validated in SPV_VALIDATION_LEVEL_1, this is
+ // SPV_VALIDATION_LEVEL_0
+ } break;
+ case SPV_OPERAND_TYPE_LITERAL_NUMBER: {
+ // NOTE: Implicitly valid as they are encoded as 32 bit value
+ } break;
+ case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
+ case SPV_OPERAND_TYPE_EXECUTION_MODEL:
+ case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
+ case SPV_OPERAND_TYPE_MEMORY_MODEL:
+ case SPV_OPERAND_TYPE_EXECUTION_MODE:
+ case SPV_OPERAND_TYPE_STORAGE_CLASS:
+ case SPV_OPERAND_TYPE_DIMENSIONALITY:
+ case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE:
+ case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
+ case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
+ case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
+ case SPV_OPERAND_TYPE_LINKAGE_TYPE:
+ case SPV_OPERAND_TYPE_ACCESS_QUALIFIER:
+ case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE:
+ case SPV_OPERAND_TYPE_DECORATION:
+ case SPV_OPERAND_TYPE_BUILT_IN:
+ case SPV_OPERAND_TYPE_SELECTION_CONTROL:
+ case SPV_OPERAND_TYPE_LOOP_CONTROL:
+ case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
+ case SPV_OPERAND_TYPE_MEMORY_SEMANTICS:
+ case SPV_OPERAND_TYPE_MEMORY_ACCESS:
+ case SPV_OPERAND_TYPE_EXECUTION_SCOPE:
+ case SPV_OPERAND_TYPE_GROUP_OPERATION:
+ case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
+ case SPV_OPERAND_TYPE_KERENL_PROFILING_INFO: {
+ spv_operand_desc operandEntry = nullptr;
+ spv_result_t error =
+ spvOperandTableValueLookup(operandTable, type, word, &operandEntry);
+ spvCheck(error, DIAGNOSTIC << "Invalid '" << spvOperandTypeStr(type)
+ << "' operand '" << word << "'.";
+ return error);
+ } break;
+ default:
+ assert(0 && "Invalid operand types should already have been caught!");
+ }
+ return SPV_SUCCESS;
+}
+
+spv_result_t spvValidateBasic(const spv_instruction_t *pInsts,
+ const uint64_t instCount,
+ const spv_opcode_table opcodeTable,
+ const spv_operand_table operandTable,
+ spv_position position,
+ spv_diagnostic *pDiagnostic) {
+ for (uint64_t instIndex = 0; instIndex < instCount; ++instIndex) {
+ const uint32_t *words = pInsts[instIndex].words;
+ uint16_t wordCount;
+ Op opcode;
+ spvOpcodeSplit(words[0], &wordCount, &opcode);
+
+ spv_opcode_desc opcodeEntry = nullptr;
+ spvCheck(spvOpcodeTableValueLookup(opcodeTable, opcode, &opcodeEntry),
+ DIAGNOSTIC << "Invalid Opcode '" << opcode << "'.";
+ return SPV_ERROR_INVALID_BINARY);
+ position->index++;
+
+ spvCheck(opcodeEntry->wordCount > wordCount,
+ DIAGNOSTIC << "Instruction word count '" << wordCount
+ << "' is not small, expected at least '"
+ << opcodeEntry->wordCount << "'.";
+ return SPV_ERROR_INVALID_BINARY);
+
+ spv_operand_desc operandEntry = nullptr;
+ for (uint16_t index = 1; index < pInsts[instIndex].wordCount;
+ ++index, position->index++) {
+ const uint32_t word = words[index];
+ spv_operand_type_t type = spvBinaryOperandInfo(
+ word, index, opcodeEntry, operandTable, &operandEntry);
+ if (SPV_OPERAND_TYPE_LITERAL_STRING == type) {
+ spvCheckReturn(spvValidateOperandsString(
+ words + index, wordCount - index, position, pDiagnostic));
+ // NOTE: String literals are always at the end of Opcodes
+ break;
+ } else if (SPV_OPERAND_TYPE_LITERAL == type) {
+ spvCheckReturn(spvValidateOperandsLiteral(
+ words + index, wordCount - index, 2, position, pDiagnostic));
+ } else {
+ spvCheckReturn(spvValidateOperandValue(type, word, operandTable,
+ position, pDiagnostic));
+ }
+ }
+ }
+
+ return SPV_SUCCESS;
+}
+
+spv_result_t spvValidateIDs(const spv_instruction_t *pInsts,
+ const uint64_t count, const uint32_t bound,
+ const spv_opcode_table opcodeTable,
+ const spv_operand_table operandTable,
+ const spv_ext_inst_table extInstTable,
+ spv_position position,
+ spv_diagnostic *pDiagnostic) {
+ std::vector<spv_id_info_t> idUses;
+ std::vector<spv_id_info_t> idDefs;
+
+ for (uint64_t instIndex = 0; instIndex < count; ++instIndex) {
+ const uint32_t *words = pInsts[instIndex].words;
+ Op opcode;
+ spvOpcodeSplit(words[0], nullptr, &opcode);
+
+ spv_opcode_desc opcodeEntry = nullptr;
+ spvCheck(spvOpcodeTableValueLookup(opcodeTable, opcode, &opcodeEntry),
+ DIAGNOSTIC << "Invalid Opcode '" << opcode << "'.";
+ return SPV_ERROR_INVALID_BINARY);
+
+ spv_operand_desc operandEntry = nullptr;
+ position->index++; // NOTE: Account for Opcode word
+ for (uint16_t index = 1; index < pInsts[instIndex].wordCount;
+ ++index, position->index++) {
+ const uint32_t word = words[index];
+
+ spv_operand_type_t type = spvBinaryOperandInfo(
+ word, index, opcodeEntry, operandTable, &operandEntry);
+
+ if (SPV_OPERAND_TYPE_RESULT_ID == type || SPV_OPERAND_TYPE_ID == type) {
+ spvCheck(0 == word, DIAGNOSTIC << "Invalid ID of '0' is not allowed.";
+ return SPV_ERROR_INVALID_ID);
+ spvCheck(bound < word, DIAGNOSTIC << "Invalid ID '" << word
+ << "' exceeds the bound '" << bound
+ << "'.";
+ return SPV_ERROR_INVALID_ID);
+ }
+
+ if (SPV_OPERAND_TYPE_RESULT_ID == type) {
+ idDefs.push_back(
+ {word, opcodeEntry->opcode, &pInsts[instIndex], *position});
+ }
+
+ if (SPV_OPERAND_TYPE_ID == type) {
+ idUses.push_back({word, opcodeEntry->opcode, nullptr, *position});
+ }
+ }
+ }
+
+ // NOTE: Error on redefined ID
+ for (size_t outerIndex = 0; outerIndex < idDefs.size(); ++outerIndex) {
+ for (size_t innerIndex = 0; innerIndex < idDefs.size(); ++innerIndex) {
+ if (outerIndex == innerIndex) {
+ continue;
+ }
+ if (idDefs[outerIndex].id == idDefs[innerIndex].id) {
+ DIAGNOSTIC << "Multiply defined ID '" << idDefs[outerIndex].id << "'.";
+ return SPV_ERROR_INVALID_ID;
+ }
+ }
+ }
+
+ // NOTE: Validate ID usage, including use of undefined ID's
+ position->index = SPV_INDEX_INSTRUCTION;
+ spvCheck(spvValidateInstructionIDs(pInsts, count, idUses.data(),
+ idUses.size(), idDefs.data(),
+ idDefs.size(), opcodeTable, operandTable,
+ extInstTable, position, pDiagnostic),
+ return SPV_ERROR_INVALID_ID);
+
+ return SPV_SUCCESS;
+}
+
+spv_result_t spvValidate(const spv_binary binary,
+ const spv_opcode_table opcodeTable,
+ const spv_operand_table operandTable,
+ const spv_ext_inst_table extInstTable,
+ const uint32_t options, spv_diagnostic *pDiagnostic) {
+ spvCheck(!opcodeTable || !operandTable, return SPV_ERROR_INVALID_TABLE);
+ spvCheck(!pDiagnostic, return SPV_ERROR_INVALID_DIAGNOSTIC);
+
+ spv_endianness_t endian;
+ spv_position_t position = {};
+ spvCheck(spvBinaryEndianness(binary, &endian),
+ DIAGNOSTIC << "Invalid SPIR-V magic number.";
+ return SPV_ERROR_INVALID_BINARY);
+
+ spv_header_t header;
+ spvCheck(spvBinaryHeaderGet(binary, endian, &header),
+ DIAGNOSTIC << "Invalid SPIR-V header.";
+ return SPV_ERROR_INVALID_BINARY);
+
+ // NOTE: Copy each instruction for easier processing
+ std::vector<spv_instruction_t> instructions;
+ uint64_t index = SPV_INDEX_INSTRUCTION;
+ while (index < binary->wordCount) {
+ uint16_t wordCount;
+ Op opcode;
+ spvOpcodeSplit(spvFixWord(binary->code[index], endian), &wordCount,
+ &opcode);
+ spv_instruction_t inst;
+ spvInstructionCopy(&binary->code[index], opcode, wordCount, endian, &inst);
+ instructions.push_back(inst);
+ index += wordCount;
+ }
+
+ if (spvIsInBitfield(SPV_VALIDATE_BASIC_BIT, options)) {
+ position.index = SPV_INDEX_INSTRUCTION;
+ // TODO: Imcomplete implementation
+ spvCheckReturn(spvValidateBasic(instructions.data(), instructions.size(),
+ opcodeTable, operandTable, &position,
+ pDiagnostic));
+ }
+
+ if (spvIsInBitfield(SPV_VALIDATE_LAYOUT_BIT, options)) {
+ position.index = SPV_INDEX_INSTRUCTION;
+ // TODO: spvBinaryValidateLayout
+ }
+
+ if (spvIsInBitfield(SPV_VALIDATE_ID_BIT, options)) {
+ position.index = SPV_INDEX_INSTRUCTION;
+ spvCheckReturn(spvValidateIDs(instructions.data(), instructions.size(),
+ header.bound, opcodeTable, operandTable,
+ extInstTable, &position, pDiagnostic));
+ }
+
+ if (spvIsInBitfield(SPV_VALIDATE_RULES_BIT, options)) {
+ position.index = SPV_INDEX_INSTRUCTION;
+ // TODO: Specified validation rules...
+ }
+
+ return SPV_SUCCESS;
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#ifndef _LIBSPIRV_UTIL_VALIDATE_H_
+#define _LIBSPIRV_UTIL_VALIDATE_H_
+
+#include <libspirv/libspirv.h>
+
+// Structures
+
+typedef struct spv_id_info_t {
+ uint32_t id;
+ Op opcode;
+ const spv_instruction_t *inst;
+ spv_position_t position;
+} spv_id_info_t;
+
+// Functions
+
+/// @brief Validate the ID usage of the instruction stream
+///
+/// @param[in] pInsts stream of instructions
+/// @param[in] instCount number of instructions
+/// @param[in] pIdUses stream of ID uses
+/// @param[in] idUsesCount number of ID uses
+/// @param[in] pIdDefs stream of ID uses
+/// @param[in] idDefsCount number of ID uses
+/// @param[in] opcodeTable table of specified Opcodes
+/// @param[in] operandTable table of specified operands
+/// @param[in,out] position current position in the stream
+/// @param[out] pDiag contains diagnostic on failure
+///
+/// @return result code
+spv_result_t spvValidateInstructionIDs(
+ const spv_instruction_t *pInsts, const uint64_t instCount,
+ const spv_id_info_t *pIdUses, const uint64_t idUsesCount,
+ const spv_id_info_t *pIdDefs, const uint64_t idDefsCount,
+ const spv_opcode_table opcodeTable, const spv_operand_table operandTable,
+ const spv_ext_inst_table extInstTable, spv_position position,
+ spv_diagnostic *pDiag);
+
+/// @brief Validate the ID's within a SPIR-V binary
+///
+/// @param[in] pInstructions array of instructions
+/// @param[in] count number of elements in instruction array
+/// @param[in] bound the binary header
+/// @param[in] opcodeTable table of specified Opcodes
+/// @param[in] operandTable table of specified operands
+/// @param[in,out] position current word in the binary
+/// @param[out] pDiagnostic contains diagnostic on failure
+///
+/// @return result code
+spv_result_t spvValidateIDs(const spv_instruction_t *pInstructions,
+ const uint64_t count, const uint32_t bound,
+ const spv_opcode_table opcodeTable,
+ const spv_operand_table operandTable,
+ const spv_ext_inst_table extInstTable,
+ spv_position position, spv_diagnostic *pDiagnostic);
+
+#endif
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include <libspirv/libspirv.h>
+#include "diagnostic.h"
+#include "opcode.h"
+#include "validate.h"
+
+#include <assert.h>
+
+#include <iostream>
+#include <unordered_map>
+#include <vector>
+
+namespace {
+class idUsage {
+ public:
+ idUsage(const spv_opcode_table opcodeTable,
+ const spv_operand_table operandTable,
+ const spv_ext_inst_table extInstTable, const spv_id_info_t *pIdUses,
+ const uint64_t idUsesCount, const spv_id_info_t *pIdDefs,
+ const uint64_t idDefsCount, const spv_instruction_t *pInsts,
+ const uint64_t instCount, spv_position position,
+ spv_diagnostic *pDiagnostic)
+ : opcodeTable(opcodeTable),
+ operandTable(operandTable),
+ extInstTable(extInstTable),
+ firstInst(pInsts),
+ instCount(instCount),
+ position(position),
+ pDiagnostic(pDiagnostic) {
+ for (uint64_t idUsesIndex = 0; idUsesIndex < idUsesCount; ++idUsesIndex) {
+ idUses[pIdUses[idUsesIndex].id].push_back(pIdUses[idUsesIndex]);
+ }
+ for (uint64_t idDefsIndex = 0; idDefsIndex < idDefsCount; ++idDefsIndex) {
+ idDefs[pIdDefs[idDefsIndex].id] = pIdDefs[idDefsIndex];
+ }
+ }
+
+ bool isValid(const spv_instruction_t *inst);
+
+ template <Op>
+ bool isValid(const spv_instruction_t *inst, const spv_opcode_desc);
+
+ std::unordered_map<uint32_t, spv_id_info_t>::iterator find(
+ const uint32_t &id) {
+ return idDefs.find(id);
+ }
+ std::unordered_map<uint32_t, spv_id_info_t>::const_iterator find(
+ const uint32_t &id) const {
+ return idDefs.find(id);
+ }
+
+ bool found(std::unordered_map<uint32_t, spv_id_info_t>::iterator item) {
+ return idDefs.end() != item;
+ }
+ bool found(std::unordered_map<uint32_t, spv_id_info_t>::const_iterator item) {
+ return idDefs.end() != item;
+ }
+
+ std::unordered_map<uint32_t, std::vector<spv_id_info_t>>::iterator findUses(
+ const uint32_t &id) {
+ return idUses.find(id);
+ }
+ std::unordered_map<uint32_t, std::vector<spv_id_info_t>>::const_iterator
+ findUses(const uint32_t &id) const {
+ return idUses.find(id);
+ }
+
+ bool foundUses(
+ std::unordered_map<uint32_t, std::vector<spv_id_info_t>>::iterator item) {
+ return idUses.end() != item;
+ }
+ bool foundUses(std::unordered_map<
+ uint32_t, std::vector<spv_id_info_t>>::const_iterator item) {
+ return idUses.end() != item;
+ }
+
+ private:
+ const spv_opcode_table opcodeTable;
+ const spv_operand_table operandTable;
+ const spv_ext_inst_table extInstTable;
+ const spv_instruction_t *const firstInst;
+ const uint64_t instCount;
+ spv_position position;
+ spv_diagnostic *pDiagnostic;
+ std::unordered_map<uint32_t, std::vector<spv_id_info_t>> idUses;
+ std::unordered_map<uint32_t, spv_id_info_t> idDefs;
+};
+
+#define DIAG(INDEX) \
+ position->index += INDEX; \
+ DIAGNOSTIC
+
+#if 0
+template <>
+bool idUsage::isValid<OpUndef>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ assert(0 && "Unimplemented!");
+ return false;
+}
+#endif
+
+template <>
+bool idUsage::isValid<OpName>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto targetIndex = 1;
+ auto target = find(inst->words[targetIndex]);
+ spvCheck(!found(target), DIAG(targetIndex) << "OpName Target <id> '"
+ << inst->words[targetIndex]
+ << "' is not defined.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpMemberName>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto typeIndex = 1;
+ auto type = find(inst->words[typeIndex]);
+ spvCheck(!found(type), DIAG(typeIndex) << "OpMemberName Type <id> '"
+ << inst->words[typeIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(OpTypeStruct != type->second.opcode,
+ DIAG(typeIndex) << "OpMemberName Type <id> '"
+ << inst->words[typeIndex]
+ << "' is not a struct type.";
+ return false);
+ auto memberIndex = 2;
+ auto member = inst->words[memberIndex];
+ auto memberCount = (uint32_t)(type->second.inst->wordCount - 2);
+ spvCheck(memberCount <= member, DIAG(memberIndex)
+ << "OpMemberName Member <id> '"
+ << inst->words[memberIndex]
+ << "' index is larger than Type <id> '"
+ << type->second.id << "'s member count.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpLine>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto targetIndex = 1;
+ auto target = find(inst->words[targetIndex]);
+ spvCheck(!found(target), DIAG(targetIndex) << "OpLine Target <id> '"
+ << inst->words[targetIndex]
+ << "' is not defined.";
+ return false);
+ auto fileIndex = 2;
+ auto file = find(inst->words[fileIndex]);
+ spvCheck(!found(file), DIAG(fileIndex) << "OpLine Target <id> '"
+ << inst->words[fileIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(OpString != file->second.opcode,
+ DIAG(fileIndex) << "OpLine Target <id> '" << inst->words[fileIndex]
+ << "' is not an OpString.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpDecorate>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto targetIndex = 1;
+ auto target = find(inst->words[targetIndex]);
+ spvCheck(!found(target), DIAG(targetIndex) << "OpDecorate Target <id> '"
+ << inst->words[targetIndex]
+ << "' is not defined.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpMemberDecorate>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto structTypeIndex = 1;
+ auto structType = find(inst->words[structTypeIndex]);
+ spvCheck(!found(structType), DIAG(structTypeIndex)
+ << "OpMemberDecorate Structure type <id> '"
+ << inst->words[structTypeIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(OpTypeStruct != structType->second.inst->opcode,
+ DIAG(structTypeIndex) << "OpMemberDecorate Structure type <id> '"
+ << inst->words[structTypeIndex]
+ << "' is not a struct type.";
+ return false);
+ auto memberIndex = 2;
+ auto member = inst->words[memberIndex];
+ auto memberCount = (uint32_t)(structType->second.inst->wordCount - 2);
+ spvCheck(memberCount < member, DIAG(memberIndex)
+ << "OpMemberDecorate Structure type <id> '"
+ << inst->words[memberIndex]
+ << "' member count is less than Member";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpGroupDecorate>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto decorationGroupIndex = 1;
+ auto decorationGroup = find(inst->words[decorationGroupIndex]);
+ spvCheck(!found(decorationGroup),
+ DIAG(decorationGroupIndex)
+ << "OpGroupDecorate Decoration group <id> '"
+ << inst->words[decorationGroupIndex] << "' is not defined.";
+ return false);
+ spvCheck(OpDecorationGroup != decorationGroup->second.opcode,
+ DIAG(decorationGroupIndex)
+ << "OpGroupDecorate Decoration group <id> '"
+ << inst->words[decorationGroupIndex]
+ << "' is not a decoration group.";
+ return false);
+ for (uint64_t targetIndex = 2; targetIndex < inst->wordCount; ++targetIndex) {
+ auto target = find(inst->words[targetIndex]);
+ spvCheck(!found(target), DIAG(targetIndex)
+ << "OpGroupDecorate Target <id> '"
+ << inst->words[targetIndex]
+ << "' is not defined.";
+ return false);
+ }
+ return true;
+}
+
+#if 0
+template <>
+bool idUsage::isValid<OpGroupMemberDecorate>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpExtInst>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+template <>
+bool idUsage::isValid<OpEntryPoint>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto entryPointIndex = 2;
+ auto entryPoint = find(inst->words[entryPointIndex]);
+ spvCheck(!found(entryPoint), DIAG(entryPointIndex)
+ << "OpEntryPoint Entry Point <id> '"
+ << inst->words[entryPointIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(OpFunction != entryPoint->second.opcode,
+ DIAG(entryPointIndex) << "OpEntryPoint Entry Point <id> '"
+ << inst->words[entryPointIndex]
+ << "' is not a function.";
+ return false);
+ // TODO: Check the entry point signature is void main(void), may be subject
+ // to change
+ auto entryPointType = find(entryPoint->second.inst->words[4]);
+ spvCheck(!found(entryPointType), assert(0 && "Unreachable!"));
+ spvCheck(3 != entryPointType->second.inst->wordCount,
+ DIAG(entryPointIndex) << "OpEntryPoint Entry Point <id> '"
+ << inst->words[entryPointIndex]
+ << "'s function parameter count is not zero.";
+ return false);
+ auto returnType = find(entryPoint->second.inst->words[1]);
+ spvCheck(!found(returnType), assert(0 && "Unreachable!"));
+ spvCheck(OpTypeVoid != returnType->second.opcode,
+ DIAG(entryPointIndex) << "OpEntryPoint Entry Point <id> '"
+ << inst->words[entryPointIndex]
+ << "'s function return type is not void.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpExecutionMode>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto entryPointIndex = 1;
+ auto entryPoint = find(inst->words[entryPointIndex]);
+ spvCheck(!found(entryPoint), DIAG(entryPointIndex)
+ << "OpExecutionMode Entry Point <id> '"
+ << inst->words[entryPointIndex]
+ << "' is not defined.";
+ return false);
+ auto entryPointUses = findUses(inst->words[entryPointIndex]);
+ spvCheck(!foundUses(entryPointUses), assert(0 && "Unreachable!"));
+ bool foundEntryPointUse = false;
+ for (auto use : entryPointUses->second) {
+ if (OpEntryPoint == use.opcode) {
+ foundEntryPointUse = true;
+ }
+ }
+ spvCheck(!foundEntryPointUse, DIAG(entryPointIndex)
+ << "OpExecutionMode Entry Point <id> '"
+ << inst->words[entryPointIndex]
+ << "' is not the Entry Point "
+ "operand of an OpEntryPoint.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpTypeVector>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto componentIndex = 2;
+ auto componentType = find(inst->words[componentIndex]);
+ spvCheck(!found(componentType), DIAG(componentIndex)
+ << "OpTypeVector Component Type <id> '"
+ << inst->words[componentIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(!spvOpcodeIsScalarType(componentType->second.opcode),
+ DIAG(componentIndex) << "OpTypeVector Component Type <id> '"
+ << inst->words[componentIndex]
+ << "' is not a scalar type.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpTypeMatrix>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto columnTypeIndex = 2;
+ auto columnType = find(inst->words[columnTypeIndex]);
+ spvCheck(!found(columnType), DIAG(columnTypeIndex)
+ << "OpTypeMatrix Column Type <id> '"
+ << inst->words[columnTypeIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(OpTypeVector != columnType->second.opcode,
+ DIAG(columnTypeIndex) << "OpTypeMatrix Column Type <id> '"
+ << inst->words[columnTypeIndex]
+ << "' is not a vector.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpTypeSampler>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto sampledTypeIndex = 2;
+ auto sampledType = find(inst->words[sampledTypeIndex]);
+ spvCheck(!found(sampledType), DIAG(sampledTypeIndex)
+ << "OpTypeSampler Sampled Type <id> '"
+ << inst->words[sampledTypeIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(!spvOpcodeIsScalarType(sampledType->second.opcode),
+ DIAG(sampledTypeIndex) << "OpTypeSampler Sampled Type <id> '"
+ << inst->words[sampledTypeIndex]
+ << "' is not a scalar type.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpTypeArray>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto elementTypeIndex = 2;
+ auto elementType = find(inst->words[elementTypeIndex]);
+ spvCheck(!found(elementType), DIAG(elementTypeIndex)
+ << "OpTypeArray Element Type <id> '"
+ << inst->words[elementTypeIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(!spvOpcodeIsType(elementType->second.opcode),
+ DIAG(elementTypeIndex) << "OpTypeArray Element Type <id> '"
+ << inst->words[elementTypeIndex]
+ << "' is not a type.";
+ return false);
+ auto lengthIndex = 3;
+ auto length = find(inst->words[lengthIndex]);
+ spvCheck(!found(length), DIAG(lengthIndex) << "OpTypeArray Length <id> '"
+ << inst->words[lengthIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(OpConstant != length->second.opcode &&
+ OpSpecConstant != length->second.opcode,
+ DIAG(lengthIndex) << "OpTypeArray Length <id> '"
+ << inst->words[lengthIndex]
+ << "' is not a scalar constant type.";
+ return false);
+
+ // NOTE: Check the initialiser value of the constant
+ auto constInst = length->second.inst;
+ auto constResultTypeIndex = 1;
+ auto constResultType = find(constInst->words[constResultTypeIndex]);
+ spvCheck(!found(constResultType), DIAG(lengthIndex)
+ << "OpTypeArray Length <id> '"
+ << inst->words[constResultTypeIndex]
+ << "' result type is not defined.";
+ return false);
+ spvCheck(OpTypeInt != constResultType->second.opcode,
+ DIAG(lengthIndex) << "OpTypeArray Length <id> '"
+ << inst->words[lengthIndex]
+ << "' is not a constant integer type.";
+ return false);
+ if (4 == constInst->wordCount) {
+ spvCheck(1 > constInst->words[3], DIAG(lengthIndex)
+ << "OpTypeArray Length <id> '"
+ << inst->words[lengthIndex]
+ << "' value must be at least 1.";
+ return false);
+ } else if (5 == constInst->wordCount) {
+ uint64_t value =
+ constInst->words[3] | ((uint64_t)constInst->words[4]) << 32;
+ bool signedness = constResultType->second.inst->words[3];
+ if (signedness) {
+ spvCheck(1 > (int64_t)value, DIAG(lengthIndex)
+ << "OpTypeArray Length <id> '"
+ << inst->words[lengthIndex]
+ << "' value must be at least 1.";
+ return false);
+ } else {
+ spvCheck(1 > value, DIAG(lengthIndex) << "OpTypeArray Length <id> '"
+ << inst->words[lengthIndex]
+ << "' value must be at least 1.";
+ return false);
+ }
+ }
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpTypeRuntimeArray>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto elementTypeIndex = 2;
+ auto elementType = find(inst->words[elementTypeIndex]);
+ spvCheck(!found(elementType), DIAG(elementTypeIndex)
+ << "OpTypeRuntimeArray Element Type <id> '"
+ << inst->words[elementTypeIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(!spvOpcodeIsType(elementType->second.opcode),
+ DIAG(elementTypeIndex) << "OpTypeRuntimeArray Element Type <id> '"
+ << inst->words[elementTypeIndex]
+ << "' is not a type.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpTypeStruct>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ for (uint64_t memberTypeIndex = 2; memberTypeIndex < inst->wordCount;
+ ++memberTypeIndex) {
+ auto memberType = find(inst->words[memberTypeIndex]);
+ spvCheck(!found(memberType), DIAG(memberTypeIndex)
+ << "OpTypeStruct Member Type <id> '"
+ << inst->words[memberTypeIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(!spvOpcodeIsType(memberType->second.opcode),
+ DIAG(memberTypeIndex) << "OpTypeStruct Member Type <id> '"
+ << inst->words[memberTypeIndex]
+ << "' is not a type.";
+ return false);
+ }
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpTypePointer>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto typeIndex = 3;
+ auto type = find(inst->words[typeIndex]);
+ spvCheck(!found(type), DIAG(typeIndex) << "OpTypePointer Type <id> '"
+ << inst->words[typeIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(!spvOpcodeIsType(type->second.opcode),
+ DIAG(typeIndex) << "OpTypePointer Type <id> '"
+ << inst->words[typeIndex] << "' is not a type.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpTypeFunction>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto returnTypeIndex = 2;
+ auto returnType = find(inst->words[returnTypeIndex]);
+ spvCheck(!found(returnType), DIAG(returnTypeIndex)
+ << "OpTypeFunction Return Type <id> '"
+ << inst->words[returnTypeIndex]
+ << "' is not defined";
+ return false);
+ spvCheck(!spvOpcodeIsType(returnType->second.opcode),
+ DIAG(returnTypeIndex) << "OpTypeFunction Return Type <id> '"
+ << inst->words[returnTypeIndex]
+ << "' is not a type.";
+ return false);
+ for (uint64_t paramTypeIndex = 3; paramTypeIndex < inst->wordCount;
+ ++paramTypeIndex) {
+ auto paramType = find(inst->words[paramTypeIndex]);
+ spvCheck(!found(paramType), DIAG(paramTypeIndex)
+ << "OpTypeFunction Parameter Type <id> '"
+ << inst->words[paramTypeIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(!spvOpcodeIsType(paramType->second.opcode),
+ DIAG(paramTypeIndex) << "OpTypeFunction Parameter Type <id> '"
+ << inst->words[paramTypeIndex]
+ << "' is not a type.";
+ return false);
+ }
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpTypePipe>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto typeIndex = 2;
+ auto type = find(inst->words[typeIndex]);
+ spvCheck(!found(type), DIAG(typeIndex) << "OpTypePipe Type <id> '"
+ << inst->words[typeIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(!spvOpcodeIsType(type->second.opcode),
+ DIAG(typeIndex) << "OpTypePipe Type <id> '" << inst->words[typeIndex]
+ << "' is not a type.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpConstantTrue>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto resultTypeIndex = 1;
+ auto resultType = find(inst->words[resultTypeIndex]);
+ spvCheck(!found(resultType), DIAG(resultTypeIndex)
+ << "OpConstantTrue Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(OpTypeBool != resultType->second.opcode,
+ DIAG(resultTypeIndex) << "OpConstantTrue Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not a boolean type.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpConstantFalse>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto resultTypeIndex = 1;
+ auto resultType = find(inst->words[resultTypeIndex]);
+ spvCheck(!found(resultType), DIAG(resultTypeIndex)
+ << "OpConstantFalse Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(OpTypeBool != resultType->second.opcode,
+ DIAG(resultTypeIndex) << "OpConstantFalse Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not a boolean type.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpConstant>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto resultTypeIndex = 1;
+ auto resultType = find(inst->words[resultTypeIndex]);
+ spvCheck(!found(resultType), DIAG(resultTypeIndex)
+ << "OpConstant Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(!spvOpcodeIsScalarType(resultType->second.opcode),
+ DIAG(resultTypeIndex)
+ << "OpConstant Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not a scalar integer or floating point type.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpConstantComposite>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto resultTypeIndex = 1;
+ auto resultType = find(inst->words[resultTypeIndex]);
+ spvCheck(!found(resultType), DIAG(resultTypeIndex)
+ << "OpConstantComposite Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(!spvOpcodeIsComposite(resultType->second.opcode),
+ DIAG(resultTypeIndex) << "OpConstantComposite Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not a composite type.";
+ return false);
+
+ uint32_t constituentCount = inst->wordCount - 3;
+ switch (resultType->second.opcode) {
+ case OpTypeVector: {
+ auto componentCount = resultType->second.inst->words[3];
+ spvCheck(
+ componentCount != constituentCount,
+ // TODO: Output ID's on diagnostic
+ DIAG(inst->wordCount - 1)
+ << "OpConstantComposite Constituent <id> count does not match "
+ "Result Type <id> '" << resultType->second.id
+ << "'s vector component count.";
+ return false);
+ auto componentType = find(resultType->second.inst->words[2]);
+ spvCheck(!found(componentType), assert(0 && "Unreachable!"));
+ for (uint64_t constituentIndex = 3; constituentIndex < inst->wordCount;
+ constituentIndex++) {
+ auto constituent = find(inst->words[constituentIndex]);
+ spvCheck(!found(constituent), assert(0 && "Unreachable!"));
+ spvCheck(!spvOpcodeIsConstant(constituent->second.opcode),
+ DIAG(constituentIndex)
+ << "OpConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex] << "' is not a constant.";
+ return false);
+ auto constituentResultType = find(constituent->second.inst->words[1]);
+ spvCheck(!found(constituentResultType), assert(0 && "Unreachable!"));
+ spvCheck(componentType->second.opcode !=
+ constituentResultType->second.opcode,
+ DIAG(constituentIndex)
+ << "OpConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex]
+ << "'s type does not match Result Type <id> '"
+ << resultType->second.id << "'s vector element type.";
+ return false);
+ }
+ } break;
+ case OpTypeMatrix: {
+ auto columnCount = resultType->second.inst->words[3];
+ spvCheck(
+ columnCount != constituentCount,
+ // TODO: Output ID's on diagnostic
+ DIAG(inst->wordCount - 1)
+ << "OpConstantComposite Constituent <id> count does not match "
+ "Result Type <id> '" << resultType->second.id
+ << "'s matrix column count.";
+ return false);
+
+ auto columnType = find(resultType->second.inst->words[2]);
+ spvCheck(!found(columnType), assert(0 && "Unreachable!"));
+ auto componentCount = columnType->second.inst->words[3];
+ auto componentType = find(columnType->second.inst->words[2]);
+ spvCheck(!found(componentType), assert(0 && "Unreachable!"));
+
+ for (uint64_t constituentIndex = 3; constituentIndex < inst->wordCount;
+ constituentIndex++) {
+ auto constituent = find(inst->words[constituentIndex]);
+ spvCheck(!found(constituent),
+ DIAG(constituentIndex)
+ << "OpConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex] << "' is not defined.";
+ return false);
+ spvCheck(OpConstantComposite != constituent->second.opcode,
+ DIAG(constituentIndex)
+ << "OpConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex]
+ << "' is not a constant composite.";
+ return false);
+ auto vector = find(constituent->second.inst->words[1]);
+ spvCheck(!found(vector), assert(0 && "Unreachable!"));
+ spvCheck(columnType->second.opcode != vector->second.opcode,
+ DIAG(constituentIndex)
+ << "OpConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex]
+ << "' type does not match Result Type <id> '"
+ << resultType->second.id << "'s matrix column type.";
+ return false);
+ auto vectorComponentType = find(vector->second.inst->words[2]);
+ spvCheck(!found(vectorComponentType), assert(0 && "Unreachable!"));
+ spvCheck(!spvOpcodeAreTypesEqual(componentType->second.inst,
+ vectorComponentType->second.inst),
+ DIAG(constituentIndex)
+ << "OpConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex]
+ << "' component type does not match Result Type <id> '"
+ << resultType->second.id
+ << "'s matrix column component type.";
+ return false);
+ spvCheck(
+ componentCount != vector->second.inst->words[3],
+ DIAG(constituentIndex)
+ << "OpConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex]
+ << "' vector component count does not match Result Type <id> '"
+ << resultType->second.id << "'s vector component count.";
+ return false);
+ }
+ } break;
+ case OpTypeArray: {
+ auto elementType = find(resultType->second.inst->words[2]);
+ spvCheck(!found(elementType), assert(0 && "Unreachable!"));
+ auto length = find(resultType->second.inst->words[3]);
+ spvCheck(!found(length), assert(0 && "Unreachable!"));
+ spvCheck(length->second.inst->words[3] != constituentCount,
+ DIAG(inst->wordCount - 1)
+ << "OpConstantComposite Constituent count does not match "
+ "Result Type <id> '" << resultType->second.id
+ << "'s array length.";
+ return false);
+ for (uint64_t constituentIndex = 3; constituentIndex < inst->wordCount;
+ constituentIndex++) {
+ auto constituent = find(inst->words[constituentIndex]);
+ spvCheck(!found(constituent),
+ DIAG(constituentIndex)
+ << "OpConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex] << "' is not defined.";
+ return false);
+ spvCheck(!spvOpcodeIsConstant(constituent->second.opcode),
+ DIAG(constituentIndex)
+ << "OpConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex] << "' is not a constant.";
+ return false);
+ auto constituentType = find(constituent->second.inst->words[1]);
+ spvCheck(!found(constituentType), assert(0 && "Unreachable!"));
+ spvCheck(!spvOpcodeAreTypesEqual(elementType->second.inst,
+ constituentType->second.inst),
+ DIAG(constituentIndex)
+ << "OpConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex]
+ << "'s type does not match Result Type <id> '"
+ << resultType->second.id << "'s array element type.";
+ return false);
+ }
+ } break;
+ case OpTypeStruct: {
+ uint32_t memberCount = resultType->second.inst->wordCount - 2;
+ spvCheck(memberCount != constituentCount,
+ DIAG(resultTypeIndex)
+ << "OpConstantComposite Constituent <id> '"
+ << inst->words[resultTypeIndex]
+ << "' count does not match Result Type <id> '"
+ << resultType->second.id << "'s struct member count.";
+ return false);
+ for (uint32_t constituentIndex = 3, memberIndex = 2;
+ constituentIndex < inst->wordCount;
+ constituentIndex++, memberIndex++) {
+ auto constituent = find(inst->words[constituentIndex]);
+ spvCheck(!found(constituent),
+ DIAG(constituentIndex)
+ << "OpConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex] << "' is not define.";
+ return false);
+ spvCheck(!spvOpcodeIsConstant(constituent->second.opcode),
+ DIAG(constituentIndex)
+ << "OpConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex] << "' is not a constant.";
+ return false);
+ auto constituentType = find(constituent->second.inst->words[1]);
+ spvCheck(!found(constituentType), assert(0 && "Unreachable!"));
+
+ auto memberType = find(resultType->second.inst->words[memberIndex]);
+ spvCheck(!found(memberType), assert(0 && "Unreachable!"));
+ spvCheck(!spvOpcodeAreTypesEqual(memberType->second.inst,
+ constituentType->second.inst),
+ DIAG(constituentIndex)
+ << "OpConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex]
+ << "' type does not match the Result Type <id> '"
+ << resultType->second.id << "'s member type.";
+ return false);
+ }
+ } break;
+ default: { assert(0 && "Unreachable!"); } break;
+ }
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpConstantSampler>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto resultTypeIndex = 1;
+ auto resultType = find(inst->words[resultTypeIndex]);
+ spvCheck(!found(resultType), DIAG(resultTypeIndex)
+ << "OpConstantSampler Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(OpTypeSampler != resultType->second.opcode,
+ DIAG(resultTypeIndex) << "OpConstantSampler Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not a sampler type.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpConstantNull>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto resultTypeIndex = 1;
+ auto resultType = find(inst->words[resultTypeIndex]);
+ spvCheck(!found(resultType), DIAG(resultTypeIndex)
+ << "OpConstantNull Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not defined.";
+ return false);
+ switch (resultType->second.inst->opcode) {
+ default: {
+ spvCheck(!spvOpcodeIsBasicTypeNullable(resultType->second.inst->opcode),
+ DIAG(resultTypeIndex) << "OpConstantNull Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' can not be null.";
+ return false);
+ } break;
+ case OpTypeVector: {
+ auto type = find(resultType->second.inst->words[2]);
+ spvCheck(!found(type), assert(0 && "Unreachable!"));
+ spvCheck(!spvOpcodeIsBasicTypeNullable(type->second.inst->opcode),
+ DIAG(resultTypeIndex)
+ << "OpConstantNull Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "'s vector component type can not be null.";
+ return false);
+ } break;
+ case OpTypeArray: {
+ auto type = find(resultType->second.inst->words[2]);
+ spvCheck(!found(type), assert(0 && "Unreachable!"));
+ spvCheck(!spvOpcodeIsBasicTypeNullable(type->second.inst->opcode),
+ DIAG(resultTypeIndex)
+ << "OpConstantNull Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "'s array element type can not be null.";
+ return false);
+ } break;
+ case OpTypeMatrix: {
+ auto columnType = find(resultType->second.inst->words[2]);
+ spvCheck(!found(columnType), assert(0 && "Unreachable!"));
+ auto type = find(columnType->second.inst->words[2]);
+ spvCheck(!found(type), assert(0 && "Unreachable!"));
+ spvCheck(!spvOpcodeIsBasicTypeNullable(type->second.inst->opcode),
+ DIAG(resultTypeIndex)
+ << "OpConstantNull Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "'s matrix component type cna not be null.";
+ return false);
+ } break;
+ case OpTypeStruct: {
+ for (uint64_t elementIndex = 2;
+ elementIndex < resultType->second.inst->wordCount; ++elementIndex) {
+ auto element = find(resultType->second.inst->words[elementIndex]);
+ spvCheck(!found(element), assert(0 && "Unreachable!"));
+ spvCheck(!spvOpcodeIsBasicTypeNullable(element->second.inst->opcode),
+ DIAG(resultTypeIndex)
+ << "OpConstantNull Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "'s struct element type can not be null.";
+ return false);
+ }
+ } break;
+ }
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpSpecConstantTrue>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto resultTypeIndex = 1;
+ auto resultType = find(inst->words[resultTypeIndex]);
+ spvCheck(!found(resultType), DIAG(resultTypeIndex)
+ << "OpSpecConstantTrue Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(OpTypeBool != resultType->second.opcode,
+ DIAG(resultTypeIndex) << "OpSpecConstantTrue Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not a boolean type.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpSpecConstantFalse>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto resultTypeIndex = 1;
+ auto resultType = find(inst->words[resultTypeIndex]);
+ spvCheck(!found(resultType), DIAG(resultTypeIndex)
+ << "OpSpecConstantFalse Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(OpTypeBool != resultType->second.opcode,
+ DIAG(resultTypeIndex) << "OpSpecConstantFalse Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not a boolean type.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpSpecConstant>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto resultTypeIndex = 1;
+ auto resultType = find(inst->words[resultTypeIndex]);
+ spvCheck(!found(resultType), DIAG(resultTypeIndex)
+ << "OpSpecConstant Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(!spvOpcodeIsScalarType(resultType->second.opcode),
+ DIAG(resultTypeIndex) << "OpSpecConstant Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not a scalar type.";
+ return false);
+ return true;
+}
+
+#if 0
+template <>
+bool idUsage::isValid<OpSpecConstantComposite>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpSpecConstantOp>(const spv_instruction_t *inst) {}
+#endif
+
+template <>
+bool idUsage::isValid<OpVariable>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {
+ auto resultTypeIndex = 1;
+ auto resultType = find(inst->words[resultTypeIndex]);
+ spvCheck(!found(resultType), DIAG(resultTypeIndex)
+ << "OpVariable Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(OpTypePointer != resultType->second.opcode,
+ DIAG(resultTypeIndex) << "OpVariable Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not a pointer type.";
+ return false);
+ if (opcodeEntry->wordCount < inst->wordCount) {
+ auto initialiserIndex = 4;
+ auto initialiser = find(inst->words[initialiserIndex]);
+ spvCheck(!found(initialiser), DIAG(initialiserIndex)
+ << "OpVariable Initializer <id> '"
+ << inst->words[initialiserIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(!spvOpcodeIsConstant(initialiser->second.opcode),
+ DIAG(initialiserIndex) << "OpVariable Initializer <id> '"
+ << inst->words[initialiserIndex]
+ << "' is not a constant.";
+ return false);
+ }
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpLoad>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto resultTypeIndex = 1;
+ auto resultType = find(inst->words[resultTypeIndex]);
+ spvCheck(!found(resultType), DIAG(resultTypeIndex)
+ << "OpLoad Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not defind.";
+ return false);
+ auto pointerIndex = 3;
+ auto pointer = find(inst->words[pointerIndex]);
+ spvCheck(!found(pointer), DIAG(pointerIndex) << "OpLoad Pointer <id> '"
+ << inst->words[pointerIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(!spvOpcodeIsPointer(pointer->second.opcode),
+ DIAG(pointerIndex) << "OpLoad Pointer <id> '"
+ << inst->words[pointerIndex]
+ << "' is not a pointer.";
+ return false);
+ auto type = find(pointer->second.inst->words[1]);
+ spvCheck(!found(type), assert(0 && "Unreachable!"));
+ spvCheck(resultType != type, DIAG(resultTypeIndex)
+ << "OpLoad Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << " does not match Pointer <id> '"
+ << pointer->second.id << "'s type.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpStore>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto pointerIndex = 1;
+ auto pointer = find(inst->words[pointerIndex]);
+ spvCheck(!found(pointer), DIAG(pointerIndex) << "OpStore Pointer <id> '"
+ << inst->words[pointerIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(!spvOpcodeIsPointer(pointer->second.opcode),
+ DIAG(pointerIndex) << "OpStore Pointer <id> '"
+ << inst->words[pointerIndex]
+ << "' is not a pointer.";
+ return false);
+ auto pointerType = find(pointer->second.inst->words[1]);
+ spvCheck(!found(pointerType), assert(0 && "Unreachable!"));
+ auto type = find(pointerType->second.inst->words[3]);
+ spvCheck(!found(type), assert(0 && "Unreachable!"));
+ spvCheck(OpTypeVoid == type->second.opcode, DIAG(pointerIndex)
+ << "OpStore Pointer <id> '"
+ << inst->words[pointerIndex]
+ << "'s type is void.";
+ return false);
+
+ auto objectIndex = 2;
+ auto object = find(inst->words[objectIndex]);
+ spvCheck(!found(object), DIAG(objectIndex) << "OpStore Object <id> '"
+ << inst->words[objectIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(!spvOpcodeIsObject(object->second.opcode),
+ DIAG(objectIndex) << "OpStore Object <id> '"
+ << inst->words[objectIndex]
+ << "' in not an object.";
+ return false);
+ auto objectType = find(object->second.inst->words[1]);
+ spvCheck(!found(objectType), assert(0 && "Unreachable!"));
+ spvCheck(OpTypeVoid == objectType->second.opcode,
+ DIAG(objectIndex) << "OpStore Object <id> '"
+ << inst->words[objectIndex] << "'s type is void.";
+ return false);
+
+ spvCheck(!spvOpcodeAreTypesEqual(type->second.inst, objectType->second.inst),
+ DIAG(pointerIndex) << "OpStore Pointer <id> '"
+ << inst->words[pointerIndex]
+ << "'s type does not match Object <id> '"
+ << objectType->second.id << "'s type.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpCopyMemory>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto targetIndex = 1;
+ auto target = find(inst->words[targetIndex]);
+ spvCheck(!found(target), DIAG(targetIndex) << "OpCopyMemory Target <id> '"
+ << inst->words[targetIndex]
+ << "' is not defined.";
+ return false);
+ auto sourceIndex = 2;
+ auto source = find(inst->words[sourceIndex]);
+ spvCheck(!found(source), DIAG(targetIndex) << "OpCopyMemory Source <id> '"
+ << inst->words[targetIndex]
+ << "' is not defined.";
+ return false);
+ auto targetPointerType = find(target->second.inst->words[1]);
+ spvCheck(!found(targetPointerType), assert(0 && "Unreachable!"));
+ auto targetType = find(targetPointerType->second.inst->words[3]);
+ spvCheck(!found(targetType), assert(0 && "Unreachable!"));
+ auto sourcePointerType = find(source->second.inst->words[1]);
+ spvCheck(!found(sourcePointerType), assert(0 && "Unreachable!"));
+ auto sourceType = find(sourcePointerType->second.inst->words[3]);
+ spvCheck(!found(sourceType), assert(0 && "Unreachable!"));
+ spvCheck(
+ !spvOpcodeAreTypesEqual(targetType->second.inst, sourceType->second.inst),
+ DIAG(sourceIndex) << "OpCopyMemory Target <id> '"
+ << inst->words[sourceIndex]
+ << "'s type does not match Source <id> '"
+ << sourceType->second.id << "'s type.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpCopyMemorySized>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto targetIndex = 1;
+ auto target = find(inst->words[targetIndex]);
+ spvCheck(!found(target),
+ DIAG(targetIndex) << "OpCopyMemorySized Target <id> '"
+ << inst->words[targetIndex] << "' is not defined.";
+ return false);
+ auto sourceIndex = 2;
+ auto source = find(inst->words[sourceIndex]);
+ spvCheck(!found(source),
+ DIAG(sourceIndex) << "OpCopyMemorySized Source <id> '"
+ << inst->words[sourceIndex] << "' is not defined.";
+ return false);
+ auto sizeIndex = 3;
+ auto size = find(inst->words[sizeIndex]);
+ spvCheck(!found(size), DIAG(sizeIndex) << "OpCopyMemorySized, Size <id> '"
+ << inst->words[sizeIndex]
+ << "' is not defined.";
+ return false);
+ auto targetPointerType = find(target->second.inst->words[1]);
+ spvCheck(!found(targetPointerType), assert(0 && "Unreachable!"));
+ spvCheck(OpTypePointer != targetPointerType->second.opcode,
+ DIAG(targetIndex) << "OpCopyMemorySized Target <id> '"
+ << inst->words[targetIndex]
+ << "' is not a pointer.";
+ return false);
+ auto sourcePointerType = find(source->second.inst->words[1]);
+ spvCheck(!found(sourcePointerType), assert(0 && "Unreachable!"));
+ spvCheck(OpTypePointer != sourcePointerType->second.opcode,
+ DIAG(sourceIndex) << "OpCopyMemorySized Source <id> '"
+ << inst->words[sourceIndex]
+ << "' is not a pointer.";
+ return false);
+ switch (size->second.opcode) {
+ // TODO: The following opcode's are assumed to be valid, refer to the
+ // following bug https://cvs.khronos.org/bugzilla/show_bug.cgi?id=13871 for
+ // clarification
+ case OpConstant:
+ case OpSpecConstant: {
+ auto sizeType = find(size->second.inst->words[1]);
+ spvCheck(!found(sizeType), assert(0 && "Unreachable!"));
+ spvCheck(OpTypeInt != sizeType->second.opcode,
+ DIAG(sizeIndex) << "OpCopyMemorySized Size <id> '"
+ << inst->words[sizeIndex]
+ << "'s type is not an integer type.";
+ return false);
+ } break;
+ case OpVariable: {
+ auto pointerType = find(size->second.inst->words[1]);
+ spvCheck(!found(pointerType), assert(0 && "Unreachable!"));
+ auto sizeType = find(pointerType->second.inst->words[1]);
+ spvCheck(!found(sizeType), assert(0 && "Unreachable!"));
+ spvCheck(OpTypeInt != sizeType->second.opcode,
+ DIAG(sizeIndex) << "OpCopyMemorySized Size <id> '"
+ << inst->words[sizeIndex]
+ << "'s variable type is not an integer type.";
+ return false);
+ } break;
+ default:
+ DIAG(sizeIndex) << "OpCopyMemorySized Size <id> '"
+ << inst->words[sizeIndex]
+ << "' is not a constant or variable.";
+ return false;
+ }
+ // TODO: Check that consant is a least size 1, see the same bug as above for
+ // clarification?
+ return true;
+}
+
+#if 0
+template <>
+bool idUsage::isValid<OpAccessChain>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpInBoundsAccessChain>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpArrayLength>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpImagePointer>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGenericPtrMemSemantics>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+template <>
+bool idUsage::isValid<OpFunction>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto resultTypeIndex = 1;
+ auto resultType = find(inst->words[resultTypeIndex]);
+ spvCheck(!found(resultType), DIAG(resultTypeIndex)
+ << "OpFunction Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not defined.";
+ return false);
+ auto functionTypeIndex = 4;
+ auto functionType = find(inst->words[functionTypeIndex]);
+ spvCheck(!found(functionType), DIAG(functionTypeIndex)
+ << "OpFunction Function Type <id> '"
+ << inst->words[functionTypeIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(OpTypeFunction != functionType->second.opcode,
+ DIAG(functionTypeIndex) << "OpFunction Function Type <id> '"
+ << inst->words[functionTypeIndex]
+ << "' is not a function type.";
+ return false);
+ auto returnType = find(functionType->second.inst->words[2]);
+ spvCheck(!found(returnType), assert(0 && "Unreachable!"));
+ spvCheck(returnType != resultType,
+ DIAG(resultTypeIndex) << "OpFunction Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' does not match the Function Type <id> '"
+ << resultType->second.id << "'s return type.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpFunctionParameter>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto resultTypeIndex = 1;
+ auto resultType = find(inst->words[resultTypeIndex]);
+ spvCheck(!found(resultType), DIAG(resultTypeIndex)
+ << "OpFunctionParameter Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not defined.";
+ return false);
+ auto function = inst - 1;
+ // NOTE: Find OpFunction & ensure OpFunctionParameter is not out of place.
+ uint64_t paramIndex = 0;
+ while (firstInst != function) {
+ spvCheck(OpFunction != function->opcode &&
+ OpFunctionParameter != function->opcode,
+ DIAG(0) << "OpFunctionParameter is not preceded by OpFunction or "
+ "OpFunctionParameter sequence.";
+ return false);
+ if (OpFunction == function->opcode) {
+ break;
+ } else {
+ paramIndex++;
+ }
+ }
+ auto functionType = find(function->words[4]);
+ spvCheck(!found(functionType), assert(0 && "Unreachable!"));
+ auto paramType = find(functionType->second.inst->words[paramIndex + 3]);
+ spvCheck(!found(paramType), assert(0 && "Unreachable!"));
+ spvCheck(
+ !spvOpcodeAreTypesEqual(resultType->second.inst, paramType->second.inst),
+ DIAG(resultTypeIndex) << "OpFunctionParameter Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' does not match the OpTypeFunction parameter "
+ "type of the same index.";
+ return false);
+ return true;
+}
+
+template <>
+bool idUsage::isValid<OpFunctionCall>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto resultTypeIndex = 1;
+ auto resultType = find(inst->words[resultTypeIndex]);
+ spvCheck(!found(resultType), DIAG(resultTypeIndex)
+ << "OpFunctionCall Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not defined.";
+ return false);
+ auto functionIndex = 3;
+ auto function = find(inst->words[functionIndex]);
+ spvCheck(!found(function), DIAG(functionIndex)
+ << "OpFunctionCall Function <id> '"
+ << inst->words[functionIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(OpFunction != function->second.opcode,
+ DIAG(functionIndex) << "OpFunctionCall Function <id> '"
+ << inst->words[functionIndex]
+ << "' is not a function.";
+ return false);
+ auto returnType = find(function->second.inst->words[1]);
+ spvCheck(!found(returnType), assert(0 && "Unreachable!"));
+ spvCheck(
+ !spvOpcodeAreTypesEqual(returnType->second.inst, resultType->second.inst),
+ DIAG(resultTypeIndex)
+ << "OpFunctionCall Result Type <id> '" << inst->words[resultTypeIndex]
+ << "'s type does not match Function <id> '" << returnType->second.id
+ << "'s return type.";
+ return false);
+ auto functionType = find(function->second.inst->words[4]);
+ spvCheck(!found(functionType), assert(0 && "Unreachable!"));
+ auto functionCallArgCount = inst->wordCount - 4;
+ auto functionParamCount = functionType->second.inst->wordCount - 3;
+ spvCheck(
+ functionParamCount != functionCallArgCount,
+ DIAG(inst->wordCount - 1)
+ << "OpFunctionCall Function <id>'s parameter count does not match "
+ "the argument count.";
+ return false);
+ for (uint64_t argumentIndex = 4, paramIndex = 3;
+ argumentIndex < inst->wordCount; argumentIndex++, paramIndex++) {
+ auto argument = find(inst->words[argumentIndex]);
+ spvCheck(!found(argument), DIAG(argumentIndex)
+ << "OpFunctionCall Argument <id> '"
+ << inst->words[argumentIndex]
+ << "' is not defined.";
+ return false);
+ auto argumentType = find(argument->second.inst->words[1]);
+ spvCheck(!found(argumentType), assert(0 && "Unreachable!"));
+ auto parameterType = find(functionType->second.inst->words[paramIndex]);
+ spvCheck(!found(parameterType), assert(0 && "Unreachable!"));
+ spvCheck(!spvOpcodeAreTypesEqual(argumentType->second.inst,
+ parameterType->second.inst),
+ DIAG(argumentIndex) << "OpFunctionCall Argument <id> '"
+ << inst->words[argumentIndex]
+ << "'s type does not match Function <id> '"
+ << parameterType->second.id
+ << "'s parameter type.";
+ return false);
+ }
+ return true;
+}
+
+#if 0
+template <>
+bool idUsage::isValid<OpSampler>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureSample>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {
+}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureSampleDref>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureSampleLod>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureSampleProj>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureSampleGrad>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureSampleOffset>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureSampleProjLod>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureSampleProjGrad>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureSampleLodOffset>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureSampleProjOffset>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureSampleGradOffset>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureSampleProjLodOffset>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureSampleProjGradOffset>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureFetchTexelLod>(const spv_instruction_t *inst) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureFetchTexelOffset>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureFetchSample>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureFetchTexel>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureGather>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {
+}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureGatherOffset>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureGatherOffsets>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureQuerySizeLod>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureQuerySize>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureQueryLevels>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTextureQuerySamples>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpConvertUToF>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpConvertFToS>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpConvertSToF>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpConvertUToF>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpUConvert>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpSConvert>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFConvert>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpConvertPtrToU>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {
+}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpConvertUToPtr>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {
+}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpPtrCastToGeneric>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGenericCastToPtr>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpBitcast>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGenericCastToPtrExplicit>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpSatConvertSToU>(const spv_instruction_t *inst) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpSatConvertUToS>(const spv_instruction_t *inst) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpVectorExtractDynamic>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpVectorInsertDynamic>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpVectorShuffle>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {
+}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpCompositeConstruct>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpCompositeExtract>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpCompositeInsert>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpCopyObject>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpTranspose>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpSNegate>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFNegate>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpNot>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpIAdd>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFAdd>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpISub>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFSub>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpIMul>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFMul>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpUDiv>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpSDiv>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFDiv>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpUMod>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpSRem>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpSMod>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFRem>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFMod>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpVectorTimesScalar>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpMatrixTimesScalar>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpVectorTimesMatrix>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpMatrixTimesVector>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpMatrixTimesMatrix>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpOuterProduct>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpDot>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpShiftRightLogical>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpShiftRightArithmetic>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpShiftLeftLogical>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpBitwiseOr>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpBitwiseXor>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpBitwiseAnd>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpAny>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpAll>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpIsNan>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpIsInf>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpIsFinite>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpIsNormal>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpSignBitSet>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpLessOrGreater>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {
+}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpOrdered>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpUnordered>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpLogicalOr>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpLogicalXor>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpLogicalAnd>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpSelect>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpIEqual>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFOrdEqual>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFUnordEqual>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpINotEqual>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFOrdNotEqual>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFUnordNotEqual>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpULessThan>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpSLessThan>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFOrdLessThan>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFUnordLessThan>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpUGreaterThan>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpSGreaterThan>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFOrdGreaterThan>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFUnordGreaterThan>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpULessThanEqual>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpSLessThanEqual>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFOrdLessThanEqual>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFUnordLessThanEqual>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpUGreaterThanEqual>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpSGreaterThanEqual>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFOrdGreaterThanEqual>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFUnordGreaterThanEqual>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpDPdx>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpDPdy>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFWidth>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpDPdxFine>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpDPdyFine>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFwidthFine>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpDPdxCoarse>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpDPdyCoarse>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpFwidthCoarse>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpPhi>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpLoopMerge>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpSelectionMerge>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpBranch>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpBranchConditional>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpSwitch>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+template <>
+bool idUsage::isValid<OpReturnValue>(const spv_instruction_t *inst,
+ const spv_opcode_desc) {
+ auto valueIndex = 1;
+ auto value = find(inst->words[valueIndex]);
+ spvCheck(!found(value), DIAG(valueIndex) << "OpReturnValue Value <id> '"
+ << inst->words[valueIndex]
+ << "' is not defined.";
+ return false);
+ spvCheck(!spvOpcodeIsValue(value->second.opcode),
+ DIAG(valueIndex) << "OpReturnValue Value <id> '"
+ << inst->words[valueIndex]
+ << "' does not represent a value.";
+ return false);
+ auto valueType = find(value->second.inst->words[1]);
+ spvCheck(!found(valueType), assert(0 && "Unreachable!"));
+ // NOTE: Find OpFunction
+ const spv_instruction_t *function = inst - 1;
+ while (firstInst != function) {
+ spvCheck(OpFunction == function->opcode, break);
+ function--;
+ }
+ spvCheck(OpFunction != function->opcode,
+ DIAG(valueIndex) << "OpReturnValue is not in a basic block.";
+ return false);
+ auto returnType = find(function->words[1]);
+ spvCheck(!found(returnType), assert(0 && "Unreachable!"));
+ if (OpTypePointer == valueType->second.opcode) {
+ auto pointerValueType = find(valueType->second.inst->words[3]);
+ spvCheck(!found(pointerValueType), assert(0 && "Unreachable!"));
+ spvCheck(!spvOpcodeAreTypesEqual(returnType->second.inst,
+ pointerValueType->second.inst),
+ DIAG(valueIndex)
+ << "OpReturnValue Value <id> '" << inst->words[valueIndex]
+ << "'s pointer type does not match OpFunction's return type.";
+ return false);
+ } else {
+ spvCheck(!spvOpcodeAreTypesEqual(returnType->second.inst,
+ valueType->second.inst),
+ DIAG(valueIndex)
+ << "OpReturnValue Value <id> '" << inst->words[valueIndex]
+ << "'s type does not match OpFunction's return type.";
+ return false);
+ }
+ return true;
+}
+
+#if 0
+template <>
+bool idUsage::isValid<OpLifetimeStart>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {
+}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpLifetimeStop>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpAtomicInit>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpAtomicLoad>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpAtomicStore>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpAtomicExchange>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpAtomicCompareExchange>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpAtomicCompareExchangeWeak>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpAtomicIIncrement>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpAtomicIDecrement>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpAtomicIAdd>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpAtomicISub>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpAtomicUMin>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpAtomicUMax>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpAtomicAnd>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpAtomicOr>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpAtomicXor>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpAtomicIMin>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpAtomicIMax>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpEmitStreamVertex>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpEndStreamPrimitive>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpAsyncGroupCopy>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpWaitGroupEvents>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGroupAll>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGroupAny>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGroupBroadcast>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGroupIAdd>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGroupFAdd>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGroupFMin>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGroupUMin>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGroupSMin>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGroupFMax>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGroupUMax>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGroupSMax>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpEnqueueMarker>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {
+}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpEnqueueKernel>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {
+}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGetKernelNDrangeSubGroupCount>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGetKernelNDrangeMaxSubGroupSize>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGetKernelWorkGroupSize>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGetKernelPreferredWorkGroupSizeMultiple>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpRetainEvent>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpReleaseEvent>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpCreateUserEvent>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpIsValidEvent>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpSetUserEventStatus>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpCaptureEventProfilingInfo>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGetDefaultQueue>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpBuildNDRange>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpReadPipe>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpWritePipe>(const spv_instruction_t *inst,
+ const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpReservedReadPipe>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpReservedWritePipe>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpReserveReadPipePackets>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpReserveWritePipePackets>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpCommitReadPipe>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpCommitWritePipe>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpIsValidReserveId>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGetNumPipePackets>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGetMaxPipePackets>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGroupReserveReadPipePackets>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGroupReserveWritePipePackets>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGroupCommitReadPipe>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#if 0
+template <>
+bool idUsage::isValid<OpGroupCommitWritePipe>(
+ const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
+#endif
+
+#undef DIAG
+
+bool idUsage::isValid(const spv_instruction_t *inst) {
+ spv_opcode_desc opcodeEntry = nullptr;
+ spvCheck(spvOpcodeTableValueLookup(opcodeTable, inst->opcode, &opcodeEntry),
+ return false);
+#define CASE(OpCode) \
+ case OpCode: \
+ return isValid<OpCode>(inst, opcodeEntry);
+#define FAIL(OpCode) \
+ case OpCode: \
+ std::cerr << "Not implemented: " << #OpCode << "\n"; \
+ return false;
+ switch (inst->opcode) {
+ FAIL(OpUndef)
+ CASE(OpName)
+ CASE(OpMemberName)
+ CASE(OpLine)
+ CASE(OpDecorate)
+ CASE(OpMemberDecorate)
+ CASE(OpGroupDecorate)
+ FAIL(OpGroupMemberDecorate)
+ FAIL(OpExtInst)
+ CASE(OpEntryPoint)
+ CASE(OpExecutionMode)
+ CASE(OpTypeVector)
+ CASE(OpTypeMatrix)
+ CASE(OpTypeSampler)
+ CASE(OpTypeArray)
+ CASE(OpTypeRuntimeArray)
+ CASE(OpTypeStruct)
+ CASE(OpTypePointer)
+ CASE(OpTypeFunction)
+ CASE(OpTypePipe)
+ CASE(OpConstantTrue)
+ CASE(OpConstantFalse)
+ CASE(OpConstant)
+ CASE(OpConstantComposite)
+ CASE(OpConstantSampler)
+ CASE(OpConstantNull)
+ CASE(OpSpecConstantTrue)
+ CASE(OpSpecConstantFalse)
+ CASE(OpSpecConstant)
+ FAIL(OpSpecConstantComposite)
+ FAIL(OpSpecConstantOp)
+ CASE(OpVariable)
+ CASE(OpLoad)
+ CASE(OpStore)
+ CASE(OpCopyMemory)
+ CASE(OpCopyMemorySized)
+ FAIL(OpAccessChain)
+ FAIL(OpInBoundsAccessChain)
+ FAIL(OpArrayLength)
+ FAIL(OpImagePointer)
+ FAIL(OpGenericPtrMemSemantics)
+ CASE(OpFunction)
+ CASE(OpFunctionParameter)
+ CASE(OpFunctionCall)
+ FAIL(OpSampler)
+ FAIL(OpTextureSample)
+ FAIL(OpTextureSampleDref)
+ FAIL(OpTextureSampleLod)
+ FAIL(OpTextureSampleProj)
+ FAIL(OpTextureSampleGrad)
+ FAIL(OpTextureSampleOffset)
+ FAIL(OpTextureSampleProjLod)
+ FAIL(OpTextureSampleProjGrad)
+ FAIL(OpTextureSampleLodOffset)
+ FAIL(OpTextureSampleProjOffset)
+ FAIL(OpTextureSampleGradOffset)
+ FAIL(OpTextureSampleProjLodOffset)
+ FAIL(OpTextureSampleProjGradOffset)
+ FAIL(OpTextureFetchTexelLod)
+ FAIL(OpTextureFetchTexelOffset)
+ FAIL(OpTextureFetchSample)
+ FAIL(OpTextureFetchTexel)
+ FAIL(OpTextureGather)
+ FAIL(OpTextureGatherOffset)
+ FAIL(OpTextureGatherOffsets)
+ FAIL(OpTextureQuerySizeLod)
+ FAIL(OpTextureQuerySize)
+ FAIL(OpTextureQueryLevels)
+ FAIL(OpTextureQuerySamples)
+ FAIL(OpConvertUToF)
+ FAIL(OpConvertFToS)
+ FAIL(OpConvertSToF)
+ FAIL(OpUConvert)
+ FAIL(OpSConvert)
+ FAIL(OpFConvert)
+ FAIL(OpConvertPtrToU)
+ FAIL(OpConvertUToPtr)
+ FAIL(OpPtrCastToGeneric)
+ FAIL(OpGenericCastToPtr)
+ FAIL(OpBitcast)
+ FAIL(OpGenericCastToPtrExplicit)
+ FAIL(OpSatConvertSToU)
+ FAIL(OpSatConvertUToS)
+ FAIL(OpVectorExtractDynamic)
+ FAIL(OpVectorInsertDynamic)
+ FAIL(OpVectorShuffle)
+ FAIL(OpCompositeConstruct)
+ FAIL(OpCompositeExtract)
+ FAIL(OpCompositeInsert)
+ FAIL(OpCopyObject)
+ FAIL(OpTranspose)
+ FAIL(OpSNegate)
+ FAIL(OpFNegate)
+ FAIL(OpNot)
+ FAIL(OpIAdd)
+ FAIL(OpFAdd)
+ FAIL(OpISub)
+ FAIL(OpFSub)
+ FAIL(OpIMul)
+ FAIL(OpFMul)
+ FAIL(OpUDiv)
+ FAIL(OpSDiv)
+ FAIL(OpFDiv)
+ FAIL(OpUMod)
+ FAIL(OpSRem)
+ FAIL(OpSMod)
+ FAIL(OpFRem)
+ FAIL(OpFMod)
+ FAIL(OpVectorTimesScalar)
+ FAIL(OpMatrixTimesScalar)
+ FAIL(OpVectorTimesMatrix)
+ FAIL(OpMatrixTimesVector)
+ FAIL(OpMatrixTimesMatrix)
+ FAIL(OpOuterProduct)
+ FAIL(OpDot)
+ FAIL(OpShiftRightLogical)
+ FAIL(OpShiftRightArithmetic)
+ FAIL(OpShiftLeftLogical)
+ FAIL(OpBitwiseOr)
+ FAIL(OpBitwiseXor)
+ FAIL(OpBitwiseAnd)
+ FAIL(OpAny)
+ FAIL(OpAll)
+ FAIL(OpIsNan)
+ FAIL(OpIsInf)
+ FAIL(OpIsFinite)
+ FAIL(OpIsNormal)
+ FAIL(OpSignBitSet)
+ FAIL(OpLessOrGreater)
+ FAIL(OpOrdered)
+ FAIL(OpUnordered)
+ FAIL(OpLogicalOr)
+ FAIL(OpLogicalXor)
+ FAIL(OpLogicalAnd)
+ FAIL(OpSelect)
+ FAIL(OpIEqual)
+ FAIL(OpFOrdEqual)
+ FAIL(OpFUnordEqual)
+ FAIL(OpINotEqual)
+ FAIL(OpFOrdNotEqual)
+ FAIL(OpFUnordNotEqual)
+ FAIL(OpULessThan)
+ FAIL(OpSLessThan)
+ FAIL(OpFOrdLessThan)
+ FAIL(OpFUnordLessThan)
+ FAIL(OpUGreaterThan)
+ FAIL(OpSGreaterThan)
+ FAIL(OpFOrdGreaterThan)
+ FAIL(OpFUnordGreaterThan)
+ FAIL(OpULessThanEqual)
+ FAIL(OpSLessThanEqual)
+ FAIL(OpFOrdLessThanEqual)
+ FAIL(OpFUnordLessThanEqual)
+ FAIL(OpUGreaterThanEqual)
+ FAIL(OpSGreaterThanEqual)
+ FAIL(OpFOrdGreaterThanEqual)
+ FAIL(OpFUnordGreaterThanEqual)
+ FAIL(OpDPdx)
+ FAIL(OpDPdy)
+ FAIL(OpFwidth)
+ FAIL(OpDPdxFine)
+ FAIL(OpDPdyFine)
+ FAIL(OpFwidthFine)
+ FAIL(OpDPdxCoarse)
+ FAIL(OpDPdyCoarse)
+ FAIL(OpFwidthCoarse)
+ FAIL(OpPhi)
+ FAIL(OpLoopMerge)
+ FAIL(OpSelectionMerge)
+ FAIL(OpBranch)
+ FAIL(OpBranchConditional)
+ FAIL(OpSwitch)
+ CASE(OpReturnValue)
+ FAIL(OpLifetimeStart)
+ FAIL(OpLifetimeStop)
+ FAIL(OpAtomicInit)
+ FAIL(OpAtomicLoad)
+ FAIL(OpAtomicStore)
+ FAIL(OpAtomicExchange)
+ FAIL(OpAtomicCompareExchange)
+ FAIL(OpAtomicCompareExchangeWeak)
+ FAIL(OpAtomicIIncrement)
+ FAIL(OpAtomicIDecrement)
+ FAIL(OpAtomicIAdd)
+ FAIL(OpAtomicISub)
+ FAIL(OpAtomicUMin)
+ FAIL(OpAtomicUMax)
+ FAIL(OpAtomicAnd)
+ FAIL(OpAtomicOr)
+ FAIL(OpAtomicXor)
+ FAIL(OpAtomicIMin)
+ FAIL(OpAtomicIMax)
+ FAIL(OpEmitStreamVertex)
+ FAIL(OpEndStreamPrimitive)
+ FAIL(OpAsyncGroupCopy)
+ FAIL(OpWaitGroupEvents)
+ FAIL(OpGroupAll)
+ FAIL(OpGroupAny)
+ FAIL(OpGroupBroadcast)
+ FAIL(OpGroupIAdd)
+ FAIL(OpGroupFAdd)
+ FAIL(OpGroupFMin)
+ FAIL(OpGroupUMin)
+ FAIL(OpGroupSMin)
+ FAIL(OpGroupFMax)
+ FAIL(OpGroupUMax)
+ FAIL(OpGroupSMax)
+ FAIL(OpEnqueueMarker)
+ FAIL(OpEnqueueKernel)
+ FAIL(OpGetKernelNDrangeSubGroupCount)
+ FAIL(OpGetKernelNDrangeMaxSubGroupSize)
+ FAIL(OpGetKernelWorkGroupSize)
+ FAIL(OpGetKernelPreferredWorkGroupSizeMultiple)
+ FAIL(OpRetainEvent)
+ FAIL(OpReleaseEvent)
+ FAIL(OpCreateUserEvent)
+ FAIL(OpIsValidEvent)
+ FAIL(OpSetUserEventStatus)
+ FAIL(OpCaptureEventProfilingInfo)
+ FAIL(OpGetDefaultQueue)
+ FAIL(OpBuildNDRange)
+ FAIL(OpReadPipe)
+ FAIL(OpWritePipe)
+ FAIL(OpReservedReadPipe)
+ FAIL(OpReservedWritePipe)
+ FAIL(OpReserveReadPipePackets)
+ FAIL(OpReserveWritePipePackets)
+ FAIL(OpCommitReadPipe)
+ FAIL(OpCommitWritePipe)
+ FAIL(OpIsValidReserveId)
+ FAIL(OpGetNumPipePackets)
+ FAIL(OpGetMaxPipePackets)
+ FAIL(OpGroupReserveReadPipePackets)
+ FAIL(OpGroupReserveWritePipePackets)
+ FAIL(OpGroupCommitReadPipe)
+ FAIL(OpGroupCommitWritePipe)
+ default:
+ return true;
+ }
+#undef FAIL
+#undef CASE
+}
+}//anonymous namespace
+
+spv_result_t spvValidateInstructionIDs(
+ const spv_instruction_t *pInsts, const uint64_t instCount,
+ const spv_id_info_t *pIdUses, const uint64_t idUsesCount,
+ const spv_id_info_t *pIdDefs, const uint64_t idDefsCount,
+ const spv_opcode_table opcodeTable, const spv_operand_table operandTable,
+ const spv_ext_inst_table extInstTable, spv_position position,
+ spv_diagnostic *pDiag) {
+ idUsage idUsage(opcodeTable, operandTable, extInstTable, pIdUses, idUsesCount,
+ pIdDefs, idDefsCount, pInsts, instCount, position, pDiag);
+ for (uint64_t instIndex = 0; instIndex < instCount; ++instIndex) {
+ spvCheck(!idUsage.isValid(&pInsts[instIndex]), return SPV_ERROR_INVALID_ID);
+ position->index += pInsts[instIndex].wordCount;
+ }
+ return SPV_SUCCESS;
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "UnitSPIRV.h"
+
+TEST(BinaryEndianness, InvalidCode) {
+ uint32_t invalidMagicNumber[] = {0};
+ spv_binary_t binary = {invalidMagicNumber, 1};
+ spv_endianness_t endian;
+ ASSERT_EQ(SPV_ERROR_INVALID_BINARY, spvBinaryEndianness(&binary, &endian));
+}
+
+TEST(BinaryEndianness, Little) {
+ uint32_t magicNumber;
+ if (I32_ENDIAN_HOST == I32_ENDIAN_LITTLE) {
+ magicNumber = 0x07230203;
+ } else {
+ magicNumber = 0x03022307;
+ }
+ spv_binary_t binary = {&magicNumber, 1};
+ spv_endianness_t endian;
+ ASSERT_EQ(SPV_SUCCESS, spvBinaryEndianness(&binary, &endian));
+ ASSERT_EQ(SPV_ENDIANNESS_LITTLE, endian);
+}
+
+TEST(BinaryEndianness, Big) {
+ uint32_t magicNumber;
+ if (I32_ENDIAN_HOST == I32_ENDIAN_BIG) {
+ magicNumber = 0x07230203;
+ } else {
+ magicNumber = 0x03022307;
+ }
+ spv_binary_t binary = {&magicNumber, 1};
+ spv_endianness_t endian;
+ ASSERT_EQ(SPV_SUCCESS, spvBinaryEndianness(&binary, &endian));
+ ASSERT_EQ(SPV_ENDIANNESS_BIG, endian);
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "UnitSPIRV.h"
+
+class BinaryHeaderGet : public ::testing::Test {
+ public:
+ BinaryHeaderGet() { memset(code, 0, sizeof(code)); }
+
+ virtual void SetUp() {
+ code[0] = SPV_MAGIC_NUMBER;
+ code[1] = SPV_VERSION_NUMBER;
+ code[2] = SPV_GENERATOR_CODEPLAY;
+ code[3] = 1; // NOTE: Bound
+ code[4] = 0; // NOTE: Schema; reserved
+ code[5] = 0; // NOTE: Instructions
+
+ binary.code = code;
+ binary.wordCount = 6;
+ }
+
+ virtual void TearDown() {}
+
+ uint32_t code[6];
+ spv_binary_t binary;
+};
+
+TEST_F(BinaryHeaderGet, Default) {
+ spv_endianness_t endian;
+ ASSERT_EQ(SPV_SUCCESS, spvBinaryEndianness(&binary, &endian));
+
+ spv_header_t header;
+ ASSERT_EQ(SPV_SUCCESS, spvBinaryHeaderGet(&binary, endian, &header));
+
+ ASSERT_EQ((uint32_t)SPV_MAGIC_NUMBER, header.magic);
+ ASSERT_EQ(99u, header.version);
+ ASSERT_EQ((uint32_t)SPV_GENERATOR_CODEPLAY, header.generator);
+ ASSERT_EQ(1u, header.bound);
+ ASSERT_EQ(0u, header.schema);
+ ASSERT_EQ(&code[5], header.instructions);
+}
+
+TEST_F(BinaryHeaderGet, InvalidCode) {
+ spv_binary_t binary = {nullptr, 0};
+ spv_header_t header;
+ ASSERT_EQ(SPV_ERROR_INVALID_BINARY,
+ spvBinaryHeaderGet(&binary, SPV_ENDIANNESS_LITTLE, &header));
+}
+
+TEST_F(BinaryHeaderGet, InvalidPointerHeader) {
+ ASSERT_EQ(SPV_ERROR_INVALID_POINTER,
+ spvBinaryHeaderGet(&binary, SPV_ENDIANNESS_LITTLE, nullptr));
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "UnitSPIRV.h"
+
+class BinaryToText : public ::testing::Test {
+ public:
+ BinaryToText() : binary(), opcodeTable(nullptr), operandTable(nullptr) {}
+
+ virtual void SetUp() {
+ ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&opcodeTable));
+ ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable));
+ ASSERT_EQ(SPV_SUCCESS, spvExtInstTableGet(&extInstTable));
+
+ const char *textStr = R"(
+OpSource OpenCL 12
+OpMemoryModel Physical64 OpenCL1.2
+OpSourceExtension "PlaceholderExtensionName"
+OpEntryPoint Kernel $1
+OpExecutionMode $1 LocalSizeHint 1 1 1
+OpTypeVoid %2
+OpTypeBool %3
+OpTypeInt %4 8 0
+OpTypeInt %5 8 1
+OpTypeInt %6 16 0
+OpTypeInt %7 16 1
+OpTypeInt %8 32 0
+OpTypeInt %9 32 1
+OpTypeInt %10 64 0
+OpTypeInt %11 64 1
+OpTypeFloat %12 16
+OpTypeFloat %13 32
+OpTypeFloat %14 64
+OpTypeVector %15 4 2
+)";
+ spv_text_t text = {textStr, strlen(textStr)};
+ spv_diagnostic diagnostic = nullptr;
+ spv_result_t error = spvTextToBinary(&text, opcodeTable, operandTable,
+ extInstTable, &binary, &diagnostic);
+ if (error) {
+ spvDiagnosticPrint(diagnostic);
+ spvDiagnosticDestroy(diagnostic);
+ ASSERT_EQ(SPV_SUCCESS, error);
+ }
+ }
+
+ virtual void TearDown() { spvBinaryDestroy(binary); }
+
+ spv_binary binary;
+ spv_opcode_table opcodeTable;
+ spv_operand_table operandTable;
+ spv_ext_inst_table extInstTable;
+};
+
+TEST_F(BinaryToText, Default) {
+ spv_text text = nullptr;
+ spv_diagnostic diagnostic = nullptr;
+ ASSERT_EQ(SPV_SUCCESS,
+ spvBinaryToText(binary, SPV_BINARY_TO_TEXT_OPTION_NONE, opcodeTable,
+ operandTable, extInstTable, &text, &diagnostic));
+ printf("%s", text->str);
+ spvTextDestroy(text);
+}
+
+TEST_F(BinaryToText, InvalidCode) {
+ spv_binary_t binary = {nullptr, 42};
+ spv_text text;
+ spv_diagnostic diagnostic = nullptr;
+ ASSERT_EQ(
+ SPV_ERROR_INVALID_BINARY,
+ spvBinaryToText(&binary, SPV_BINARY_TO_TEXT_OPTION_NONE, opcodeTable,
+ operandTable, extInstTable, &text, &diagnostic));
+ if (diagnostic) {
+ spvDiagnosticPrint(diagnostic);
+ spvDiagnosticDestroy(diagnostic);
+ }
+}
+
+TEST_F(BinaryToText, InvalidTable) {
+ spv_text text;
+ spv_diagnostic diagnostic = nullptr;
+ ASSERT_EQ(SPV_ERROR_INVALID_TABLE,
+ spvBinaryToText(binary, 0, nullptr, operandTable, extInstTable,
+ &text, &diagnostic));
+ ASSERT_EQ(SPV_ERROR_INVALID_TABLE,
+ spvBinaryToText(binary, SPV_BINARY_TO_TEXT_OPTION_NONE, opcodeTable,
+ nullptr, extInstTable, &text, &diagnostic));
+ ASSERT_EQ(SPV_ERROR_INVALID_TABLE,
+ spvBinaryToText(binary, SPV_BINARY_TO_TEXT_OPTION_NONE, opcodeTable,
+ operandTable, nullptr, &text, &diagnostic));
+ if (diagnostic) {
+ spvDiagnosticPrint(diagnostic);
+ spvDiagnosticDestroy(diagnostic);
+ }
+}
+
+TEST_F(BinaryToText, InvalidDiagnostic) {
+ spv_text text;
+ ASSERT_EQ(SPV_ERROR_INVALID_DIAGNOSTIC,
+ spvBinaryToText(binary, SPV_BINARY_TO_TEXT_OPTION_NONE, opcodeTable,
+ operandTable, extInstTable, &text, nullptr));
+}
+
+TEST(BinaryToTextExtInst, Default) {
+ spv_opcode_table opcodeTable;
+ ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&opcodeTable));
+ spv_operand_table operandTable;
+ ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable));
+ spv_ext_inst_table extInstTable;
+ ASSERT_EQ(SPV_SUCCESS, spvExtInstTableGet(&extInstTable));
+ const char *spirv = R"(
+OpCapability Shader
+OpExtInstImport %glsl450 "GLSL.std.450"
+OpMemoryModel Logical Simple
+OpEntryPoint Vertex $main "main"
+OpTypeVoid %void
+OpTypeFloat %float 32
+OpConstant $float %const1.5 1.5
+OpTypeFunction %fnMain %void
+OpFunction $void %main None $fnMain
+OpLabel %lbMain
+OpExtInst $float %result $glsl450 round $const1.5
+OpReturn
+OpFunctionEnd
+)";
+ spv_text_t text = {spirv, strlen(spirv)};
+ spv_binary binary;
+ spv_diagnostic diagnostic;
+ spv_result_t error = spvTextToBinary(&text, opcodeTable, operandTable,
+ extInstTable, &binary, &diagnostic);
+ if (error) {
+ spvDiagnosticPrint(diagnostic);
+ spvDiagnosticDestroy(diagnostic);
+ ASSERT_EQ(SPV_SUCCESS, error);
+ }
+
+ error = spvBinaryToText(
+ binary, SPV_BINARY_TO_TEXT_OPTION_COLOR | SPV_BINARY_TO_TEXT_OPTION_PRINT,
+ opcodeTable, operandTable, extInstTable, nullptr, &diagnostic);
+
+ if (error) {
+ spvDiagnosticPrint(diagnostic);
+ spvDiagnosticDestroy(diagnostic);
+ ASSERT_EQ(SPV_SUCCESS, error);
+ }
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "UnitSPIRV.h"
+
+TEST(DiagnosticPrint, Default) {
+ char message[] = "Test Diagnostic!";
+ spv_diagnostic_t diagnostic = {{2, 3, 5}, message};
+ // TODO: Redirect stderr
+ ASSERT_EQ(SPV_SUCCESS, spvDiagnosticPrint(&diagnostic));
+ // TODO: Validate the output of spvDiagnosticPrint()
+ // TODO: Remove the redirection of stderr
+}
+
+TEST(DiagnosticPrint, InvalidDiagnostic) {
+ ASSERT_EQ(SPV_ERROR_INVALID_DIAGNOSTIC, spvDiagnosticPrint(nullptr));
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "UnitSPIRV.h"
+
+TEST(FixWord, Default) {
+ spv_endianness_t endian;
+ if (I32_ENDIAN_HOST == I32_ENDIAN_LITTLE) {
+ endian = SPV_ENDIANNESS_LITTLE;
+ } else {
+ endian = SPV_ENDIANNESS_BIG;
+ }
+ uint32_t word = 0x53780921;
+ ASSERT_EQ(word, spvFixWord(word, endian));
+}
+
+TEST(FixWord, Reorder) {
+ spv_endianness_t endian;
+ if (I32_ENDIAN_HOST == I32_ENDIAN_LITTLE) {
+ endian = SPV_ENDIANNESS_BIG;
+ } else {
+ endian = SPV_ENDIANNESS_LITTLE;
+ }
+ uint32_t word = 0x53780921;
+ uint32_t result = 0x21097853;
+ ASSERT_EQ(result, spvFixWord(word, endian));
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "UnitSPIRV.h"
+
+TEST(NamedId, Default) {
+ const char *spirv = R"(
+OpCapability Shader
+OpMemoryModel Logical Simple
+OpEntryPoint Vertex $main
+OpTypeVoid %void
+OpTypeFunction %fnMain $void
+OpFunction $void %main None $fnMain
+OpLabel %lbMain
+OpReturn
+OpFunctionEnd)";
+ spv_text_t text;
+ text.str = spirv;
+ text.length = strlen(spirv);
+ spv_opcode_table opcodeTable;
+ ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&opcodeTable));
+ spv_operand_table operandTable;
+ ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable));
+ spv_ext_inst_table extInstTable;
+ ASSERT_EQ(SPV_SUCCESS, spvExtInstTableGet(&extInstTable));
+ spv_binary binary;
+ spv_diagnostic diagnostic;
+ spv_result_t error = spvTextToBinary(&text, opcodeTable, operandTable,
+ extInstTable, &binary, &diagnostic);
+ if (error) {
+ spvDiagnosticPrint(diagnostic);
+ spvDiagnosticDestroy(diagnostic);
+ spvBinaryDestroy(binary);
+ ASSERT_EQ(SPV_SUCCESS, error);
+ }
+ error = spvBinaryToText(
+ binary, SPV_BINARY_TO_TEXT_OPTION_PRINT | SPV_BINARY_TO_TEXT_OPTION_COLOR,
+ opcodeTable, operandTable, extInstTable, nullptr, &diagnostic);
+ if (error) {
+ spvDiagnosticPrint(diagnostic);
+ spvDiagnosticDestroy(diagnostic);
+ spvBinaryDestroy(binary);
+ ASSERT_EQ(SPV_SUCCESS, error);
+ }
+ spvBinaryDestroy(binary);
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "UnitSPIRV.h"
+
+TEST(OpcodeIsVariable, Default) {
+ spv_opcode_desc_t entry = {
+ nullptr, 0, (Op)0, SPV_OPCODE_FLAGS_VARIABLE, 0, {}};
+ ASSERT_NE(0, spvOpcodeIsVariable(&entry));
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "UnitSPIRV.h"
+
+#include <limits>
+
+TEST(OpcodeMake, DISABLED_Default) {
+ for (uint16_t wordCount = 0; wordCount < std::numeric_limits<uint16_t>::max();
+ ++wordCount) {
+ for (uint16_t code = 0; code < std::numeric_limits<uint16_t>::max();
+ ++code) {
+ uint32_t opcode = 0;
+ opcode |= (uint32_t)code;
+ opcode |= (uint32_t)wordCount << 16;
+ ASSERT_EQ(opcode, spvOpcodeMake(wordCount, (Op)code));
+ }
+ }
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "UnitSPIRV.h"
+
+class Requires : public ::testing::TestWithParam<Capability> {
+ public:
+ Requires()
+ : entry({nullptr,
+ 0,
+ (Op)0,
+ SPV_OPCODE_FLAGS_CAPABILITIES,
+ GetParam(),
+ {}}) {}
+
+ virtual void SetUp() {}
+
+ virtual void TearDown() {}
+
+ spv_opcode_desc_t entry;
+};
+
+TEST_P(Requires, Capabilityabilities) {
+ ASSERT_NE(0, spvOpcodeRequiresCapabilities(&entry));
+}
+
+INSTANTIATE_TEST_CASE_P(Op, Requires,
+ ::testing::Values(CapabilityMatrix, CapabilityShader,
+ CapabilityGeometry,
+ CapabilityTessellation,
+ CapabilityAddresses,
+ CapabilityLinkage, CapabilityKernel));
+
+TEST(OpcodeRequiresCapabilityaspvities, None) {
+ spv_opcode_desc_t entry = {nullptr, 0, (Op)0, SPV_OPCODE_FLAGS_NONE, 0, {}};
+ ASSERT_EQ(0, spvOpcodeRequiresCapabilities(&entry));
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "UnitSPIRV.h"
+
+TEST(OpcodeSplit, Default) {
+ uint32_t word = spvOpcodeMake(42, (Op)23);
+ uint16_t wordCount = 0;
+ Op opcode;
+ spvOpcodeSplit(word, &wordCount, &opcode);
+ ASSERT_EQ(42, wordCount);
+ ASSERT_EQ(23, opcode);
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "UnitSPIRV.h"
+
+TEST(OpcodeTableGet, Default) {
+ spv_opcode_table table;
+ ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&table));
+ ASSERT_NE(0, table->count);
+ ASSERT_NE(nullptr, table->entries);
+}
+
+TEST(OpcodeTableGet, InvalidPointerTable) {
+ ASSERT_EQ(SPV_ERROR_INVALID_POINTER, spvOpcodeTableGet(nullptr));
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "UnitSPIRV.h"
+
+TEST(OperandTableGet, Default) {
+ spv_operand_table table;
+ ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&table));
+ ASSERT_NE(0, table->count);
+ ASSERT_NE(nullptr, table->types);
+}
+
+TEST(OperandTableGet, InvalidPointerTable) {
+ ASSERT_EQ(SPV_ERROR_INVALID_POINTER, spvOperandTableGet(nullptr));
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "UnitSPIRV.h"
+
+TEST(TextAdvance, LeadingNewLines) {
+ char textStr[] = "\n\nWord";
+ spv_text_t text = {textStr, strlen(textStr)};
+ spv_position_t position = {};
+ ASSERT_EQ(SPV_SUCCESS, spvTextAdvance(&text, &position));
+ ASSERT_EQ(0, position.column);
+ ASSERT_EQ(2, position.line);
+ ASSERT_EQ(2, position.index);
+}
+
+TEST(TextAdvance, LeadingSpaces) {
+ char textStr[] = " Word";
+ spv_text_t text = {textStr, strlen(textStr)};
+ spv_position_t position = {};
+ ASSERT_EQ(SPV_SUCCESS, spvTextAdvance(&text, &position));
+ ASSERT_EQ(4, position.column);
+ ASSERT_EQ(0, position.line);
+ ASSERT_EQ(4, position.index);
+}
+
+TEST(TextAdvance, LeadingTabs) {
+ char textStr[] = "\t\t\tWord";
+ spv_text_t text = {textStr, strlen(textStr)};
+ spv_position_t position = {};
+ ASSERT_EQ(SPV_SUCCESS, spvTextAdvance(&text, &position));
+ ASSERT_EQ(3, position.column);
+ ASSERT_EQ(0, position.line);
+ ASSERT_EQ(3, position.index);
+}
+
+TEST(TextAdvance, LeadingNewLinesSpacesAndTabs) {
+ char textStr[] = "\n\n\t Word";
+ spv_text_t text = {textStr, strlen(textStr)};
+ spv_position_t position = {};
+ ASSERT_EQ(SPV_SUCCESS, spvTextAdvance(&text, &position));
+ ASSERT_EQ(3, position.column);
+ ASSERT_EQ(2, position.line);
+ ASSERT_EQ(5, position.index);
+}
+
+TEST(TextAdvance, NullTerminator) {
+ char textStr[] = "";
+ spv_text_t text = {textStr, strlen(textStr)};
+ spv_position_t position = {};
+ ASSERT_EQ(SPV_END_OF_STREAM, spvTextAdvance(&text, &position));
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "UnitSPIRV.h"
+
+TEST(TextDestroy, Default) {
+ spv_opcode_table opcodeTable;
+ ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&opcodeTable));
+
+ spv_operand_table operandTable;
+ ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable));
+
+ spv_ext_inst_table extInstTable;
+ ASSERT_EQ(SPV_SUCCESS, spvExtInstTableGet(&extInstTable));
+
+ char textStr[] =
+ "OpSource OpenCL 12\n"
+ "OpMemoryModel Physical64 OpenCL1.2\n"
+ "OpSourceExtension \"PlaceholderExtensionName\"\n"
+ "OpEntryPoint Kernel 0\n"
+ "OpExecutionMode 0 LocalSizeHint 1 1 1\n"
+ "OpTypeVoid 1\n"
+ "OpTypeBool 2\n"
+ "OpTypeInt 3 8 0\n"
+ "OpTypeInt 4 8 1\n"
+ "OpTypeInt 5 16 0\n"
+ "OpTypeInt 6 16 1\n"
+ "OpTypeInt 7 32 0\n"
+ "OpTypeInt 8 32 1\n"
+ "OpTypeInt 9 64 0\n"
+ "OpTypeInt 10 64 1\n"
+ "OpTypeFloat 11 16\n"
+ "OpTypeFloat 12 32\n"
+ "OpTypeFloat 13 64\n"
+ "OpTypeVector 14 3 2\n";
+ spv_text_t text = {textStr, strlen(textStr)};
+ spv_binary binary = nullptr;
+ spv_diagnostic diagnostic = nullptr;
+ EXPECT_EQ(SPV_SUCCESS, spvTextToBinary(&text, opcodeTable, operandTable,
+ extInstTable, &binary, &diagnostic));
+ EXPECT_NE(nullptr, binary);
+ EXPECT_NE(nullptr, binary->code);
+ EXPECT_NE(0, binary->wordCount);
+ if (diagnostic) {
+ spvDiagnosticPrint(diagnostic);
+ ASSERT_TRUE(false);
+ }
+
+ spv_text resultText = nullptr;
+ EXPECT_EQ(SPV_SUCCESS,
+ spvBinaryToText(binary, 0, opcodeTable, operandTable, extInstTable,
+ &resultText, &diagnostic));
+ spvBinaryDestroy(binary);
+ if (diagnostic) {
+ spvDiagnosticPrint(diagnostic);
+ spvDiagnosticDestroy(diagnostic);
+ ASSERT_TRUE(false);
+ }
+ EXPECT_NE(nullptr, text.str);
+ EXPECT_NE(0, text.length);
+ spvTextDestroy(resultText);
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "UnitSPIRV.h"
+
+union char_word_t {
+ char cs[4];
+ uint32_t u;
+};
+
+TEST(TextToBinary, Default) {
+ // TODO: Ensure that on big endian systems that this converts the word to
+ // little endian for encoding comparison!
+ spv_endianness_t endian = SPV_ENDIANNESS_LITTLE;
+
+ const char *textStr = R"(
+OpSource OpenCL 12
+OpMemoryModel Physical64 OpenCL1.2
+OpSourceExtension "PlaceholderExtensionName"
+OpEntryPoint Kernel $1
+OpExecutionMode $1 LocalSizeHint 1 1 1
+OpTypeVoid %2
+OpTypeBool %3
+; commment
+OpTypeInt %4 8 0 ; comment
+OpTypeInt %5 8 1
+OpTypeInt %6 16 0
+OpTypeInt %7 16 1
+OpTypeInt %8 32 0
+OpTypeInt %9 32 1
+OpTypeInt %10 64 0
+OpTypeInt %11 64 1
+OpTypeFloat %12 16
+OpTypeFloat %13 32
+OpTypeFloat %14 64
+OpTypeVector %15 4 2
+)";
+ spv_text_t text = {textStr, strlen(textStr)};
+
+ spv_opcode_table opcodeTable;
+ ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&opcodeTable));
+
+ spv_operand_table operandTable;
+ ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable));
+
+ spv_ext_inst_table extInstTable;
+ ASSERT_EQ(SPV_SUCCESS, spvExtInstTableGet(&extInstTable));
+
+ spv_binary binary;
+ spv_diagnostic diagnostic = nullptr;
+ spv_result_t error = spvTextToBinary(&text, opcodeTable, operandTable,
+ extInstTable, &binary, &diagnostic);
+
+ if (error) {
+ spvDiagnosticPrint(diagnostic);
+ spvDiagnosticDestroy(diagnostic);
+ ASSERT_EQ(SPV_SUCCESS, error);
+ }
+
+ struct bin {
+ bin(spv_binary binary) : binary(binary) {}
+ ~bin() { spvBinaryDestroy(binary); }
+ spv_binary binary;
+ } bin(binary);
+
+ EXPECT_NE(nullptr, text.str);
+ EXPECT_NE(0, text.length);
+
+ // TODO: Verify binary
+ ASSERT_EQ(SPV_MAGIC_NUMBER, binary->code[SPV_INDEX_MAGIC_NUMBER]);
+ ASSERT_EQ(SPV_VERSION_NUMBER, binary->code[SPV_INDEX_VERSION_NUMBER]);
+ ASSERT_EQ(SPV_GENERATOR_CODEPLAY, binary->code[SPV_INDEX_GENERATOR_NUMBER]);
+ ASSERT_EQ(16, binary->code[SPV_INDEX_BOUND]); // TODO: Bound?
+ ASSERT_EQ(0, binary->code[SPV_INDEX_SCHEMA]); // Reserved: schema
+
+ uint64_t instIndex = SPV_INDEX_INSTRUCTION;
+
+ ASSERT_EQ(spvOpcodeMake(3, OpSource), binary->code[instIndex++]);
+ ASSERT_EQ(SourceLanguageOpenCL, binary->code[instIndex++]);
+ ASSERT_EQ(12, binary->code[instIndex++]);
+
+ ASSERT_EQ(spvOpcodeMake(3, OpMemoryModel), binary->code[instIndex++]);
+ ASSERT_EQ(AddressingModelPhysical64, binary->code[instIndex++]);
+ ASSERT_EQ(MemoryModelOpenCL12, binary->code[instIndex++]);
+
+ uint16_t sourceExtensionWordCount =
+ (uint16_t)((strlen("PlaceholderExtensionName") / sizeof(uint32_t)) + 2);
+ ASSERT_EQ(spvOpcodeMake(sourceExtensionWordCount, OpSourceExtension),
+ binary->code[instIndex++]);
+ // TODO: This only works on little endian systems!
+ char_word_t cw = {{'P', 'l', 'a', 'c'}};
+ ASSERT_EQ(spvFixWord(cw.u, endian), binary->code[instIndex++]);
+ cw = {{'e', 'h', 'o', 'l'}};
+ ASSERT_EQ(spvFixWord(cw.u, endian), binary->code[instIndex++]);
+ cw = {{'d', 'e', 'r', 'E'}};
+ ASSERT_EQ(spvFixWord(cw.u, endian), binary->code[instIndex++]);
+ cw = {{'x', 't', 'e', 'n'}};
+ ASSERT_EQ(spvFixWord(cw.u, endian), binary->code[instIndex++]);
+ cw = {{'s', 'i', 'o', 'n'}};
+ ASSERT_EQ(spvFixWord(cw.u, endian), binary->code[instIndex++]);
+ cw = {{'N', 'a', 'm', 'e'}};
+ ASSERT_EQ(spvFixWord(cw.u, endian), binary->code[instIndex++]);
+ ASSERT_EQ(0, binary->code[instIndex++]);
+
+ ASSERT_EQ(spvOpcodeMake(3, OpEntryPoint), binary->code[instIndex++]);
+ ASSERT_EQ(ExecutionModelKernel, binary->code[instIndex++]);
+ ASSERT_EQ(1, binary->code[instIndex++]);
+
+ ASSERT_EQ(spvOpcodeMake(6, OpExecutionMode), binary->code[instIndex++]);
+ ASSERT_EQ(1, binary->code[instIndex++]);
+ ASSERT_EQ(ExecutionModeLocalSizeHint, binary->code[instIndex++]);
+ ASSERT_EQ(1, binary->code[instIndex++]);
+ ASSERT_EQ(1, binary->code[instIndex++]);
+ ASSERT_EQ(1, binary->code[instIndex++]);
+
+ ASSERT_EQ(spvOpcodeMake(2, OpTypeVoid), binary->code[instIndex++]);
+ ASSERT_EQ(2, binary->code[instIndex++]);
+
+ ASSERT_EQ(spvOpcodeMake(2, OpTypeBool), binary->code[instIndex++]);
+ ASSERT_EQ(3, binary->code[instIndex++]);
+
+ ASSERT_EQ(spvOpcodeMake(4, OpTypeInt), binary->code[instIndex++]);
+ ASSERT_EQ(4, binary->code[instIndex++]);
+ ASSERT_EQ(8, binary->code[instIndex++]); // NOTE: 8 bits wide
+ ASSERT_EQ(0, binary->code[instIndex++]); // NOTE: Unsigned
+
+ ASSERT_EQ(spvOpcodeMake(4, OpTypeInt), binary->code[instIndex++]);
+ ASSERT_EQ(5, binary->code[instIndex++]);
+ ASSERT_EQ(8, binary->code[instIndex++]); // NOTE: 8 bits wide
+ ASSERT_EQ(1, binary->code[instIndex++]); // NOTE: Signed
+
+ ASSERT_EQ(spvOpcodeMake(4, OpTypeInt), binary->code[instIndex++]);
+ ASSERT_EQ(6, binary->code[instIndex++]);
+ ASSERT_EQ(16, binary->code[instIndex++]); // NOTE: 16 bits wide
+ ASSERT_EQ(0, binary->code[instIndex++]); // NOTE: Unsigned
+
+ ASSERT_EQ(spvOpcodeMake(4, OpTypeInt), binary->code[instIndex++]);
+ ASSERT_EQ(7, binary->code[instIndex++]);
+ ASSERT_EQ(16, binary->code[instIndex++]); // NOTE: 16 bits wide
+ ASSERT_EQ(1, binary->code[instIndex++]); // NOTE: Signed
+
+ ASSERT_EQ(spvOpcodeMake(4, OpTypeInt), binary->code[instIndex++]);
+ ASSERT_EQ(8, binary->code[instIndex++]);
+ ASSERT_EQ(32, binary->code[instIndex++]); // NOTE: 32 bits wide
+ ASSERT_EQ(0, binary->code[instIndex++]); // NOTE: Unsigned
+
+ ASSERT_EQ(spvOpcodeMake(4, OpTypeInt), binary->code[instIndex++]);
+ ASSERT_EQ(9, binary->code[instIndex++]);
+ ASSERT_EQ(32, binary->code[instIndex++]); // NOTE: 32 bits wide
+ ASSERT_EQ(1, binary->code[instIndex++]); // NOTE: Signed
+
+ ASSERT_EQ(spvOpcodeMake(4, OpTypeInt), binary->code[instIndex++]);
+ ASSERT_EQ(10, binary->code[instIndex++]);
+ ASSERT_EQ(64, binary->code[instIndex++]); // NOTE: 64 bits wide
+ ASSERT_EQ(0, binary->code[instIndex++]); // NOTE: Unsigned
+
+ ASSERT_EQ(spvOpcodeMake(4, OpTypeInt), binary->code[instIndex++]);
+ ASSERT_EQ(11, binary->code[instIndex++]);
+ ASSERT_EQ(64, binary->code[instIndex++]); // NOTE: 64 bits wide
+ ASSERT_EQ(1, binary->code[instIndex++]); // NOTE: Signed
+
+ ASSERT_EQ(spvOpcodeMake(3, OpTypeFloat), binary->code[instIndex++]);
+ ASSERT_EQ(12, binary->code[instIndex++]);
+ ASSERT_EQ(16, binary->code[instIndex++]); // NOTE: 16 bits wide
+
+ ASSERT_EQ(spvOpcodeMake(3, OpTypeFloat), binary->code[instIndex++]);
+ ASSERT_EQ(13, binary->code[instIndex++]);
+ ASSERT_EQ(32, binary->code[instIndex++]); // NOTE: 32 bits wide
+
+ ASSERT_EQ(spvOpcodeMake(3, OpTypeFloat), binary->code[instIndex++]);
+ ASSERT_EQ(14, binary->code[instIndex++]);
+ ASSERT_EQ(64, binary->code[instIndex++]); // NOTE: 64 bits wide
+
+ ASSERT_EQ(spvOpcodeMake(4, OpTypeVector), binary->code[instIndex++]);
+ ASSERT_EQ(15, binary->code[instIndex++]);
+ ASSERT_EQ(4, binary->code[instIndex++]);
+ ASSERT_EQ(2, binary->code[instIndex++]);
+}
+
+class TextToBinaryTest : public ::testing::Test {
+ public:
+ TextToBinaryTest()
+ : binary(nullptr),
+ text(),
+ opcodeTable(nullptr),
+ operandTable(nullptr),
+ diagnostic(nullptr) {}
+
+ virtual void SetUp() {
+ char textStr[] =
+ "OpEntryPoint Kernel 0\n"
+ "OpExecutionMode 0 LocalSizeHint 1 1 1\n";
+ text.str = textStr;
+ text.length = strlen(textStr);
+ ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&opcodeTable));
+ ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable));
+ ASSERT_EQ(SPV_SUCCESS, spvExtInstTableGet(&extInstTable));
+ }
+
+ virtual void TearDown() {
+ if (diagnostic) {
+ spvDiagnosticDestroy(diagnostic);
+ }
+ }
+
+ spv_binary binary;
+ spv_text_t text;
+ spv_opcode_table opcodeTable;
+ spv_operand_table operandTable;
+ spv_ext_inst_table extInstTable;
+ spv_diagnostic diagnostic;
+};
+
+TEST_F(TextToBinaryTest, InvalidText) {
+ spv_text_t text = {nullptr, 0};
+ spv_binary binary;
+ ASSERT_EQ(SPV_ERROR_INVALID_TEXT,
+ spvTextToBinary(&text, opcodeTable, operandTable, extInstTable,
+ &binary, &diagnostic));
+}
+
+TEST_F(TextToBinaryTest, InvalidTable) {
+ ASSERT_EQ(SPV_ERROR_INVALID_TABLE,
+ spvTextToBinary(&text, nullptr, operandTable, extInstTable, &binary,
+ &diagnostic));
+ ASSERT_EQ(SPV_ERROR_INVALID_TABLE,
+ spvTextToBinary(&text, opcodeTable, nullptr, extInstTable, &binary,
+ &diagnostic));
+ ASSERT_EQ(SPV_ERROR_INVALID_TABLE,
+ spvTextToBinary(&text, opcodeTable, operandTable, nullptr, &binary,
+ &diagnostic));
+}
+
+TEST_F(TextToBinaryTest, InvalidPointer) {
+ ASSERT_EQ(SPV_ERROR_INVALID_POINTER,
+ spvTextToBinary(&text, opcodeTable, operandTable, extInstTable,
+ nullptr, &diagnostic));
+}
+
+TEST_F(TextToBinaryTest, InvalidDiagnostic) {
+ spv_binary binary;
+ ASSERT_EQ(SPV_ERROR_INVALID_DIAGNOSTIC,
+ spvTextToBinary(&text, opcodeTable, operandTable, extInstTable,
+ &binary, nullptr));
+}
+
+TEST_F(TextToBinaryTest, InvalidPrefix) {
+ const char *spirv = R"(
+Invalid)";
+ text.str = spirv;
+ text.length = strlen(spirv);
+ ASSERT_EQ(SPV_ERROR_INVALID_TEXT,
+ spvTextToBinary(&text, opcodeTable, operandTable, extInstTable,
+ &binary, &diagnostic));
+ if (diagnostic) {
+ spvDiagnosticPrint(diagnostic);
+ }
+}
+
+TEST_F(TextToBinaryTest, ImmediateIntOpCode) {
+ const char *spirv = R"(
+!0x00FF00FF
+)";
+ text.str = spirv;
+ text.length = strlen(spirv);
+ ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(&text, opcodeTable, operandTable,
+ extInstTable, &binary, &diagnostic));
+ EXPECT_EQ(0x00FF00FF, binary->code[5]);
+ spvBinaryDestroy(binary);
+ if (diagnostic) {
+ spvDiagnosticPrint(diagnostic);
+ }
+}
+
+TEST_F(TextToBinaryTest, ImmediateIntOperand) {
+ const char *spirv = R"(
+OpCapability !0x00FF00FF)";
+ text.str = spirv;
+ text.length = strlen(spirv);
+ EXPECT_EQ(SPV_SUCCESS, spvTextToBinary(&text, opcodeTable, operandTable,
+ extInstTable, &binary, &diagnostic));
+ EXPECT_EQ(0x00FF00FF, binary->code[6]);
+ spvBinaryDestroy(binary);
+ if (diagnostic) {
+ spvDiagnosticPrint(diagnostic);
+ }
+}
+
+TEST_F(TextToBinaryTest, ExtInst) {
+ const char *spirv = R"(
+OpCapability Shader
+OpExtInstImport %glsl450 "GLSL.std.450"
+OpMemoryModel Logical Simple
+OpEntryPoint Vertex $main "main"
+OpTypeVoid %void
+OpTypeFloat %float 32
+OpConstant $float %const1.5 1.5
+OpTypeFunction %fnMain %void
+OpFunction $void %main None $fnMain
+OpLabel %lbMain
+OpExtInst $float %result $glsl450 round $const1.5
+OpReturn
+OpFunctionEnd
+)";
+ text.str = spirv;
+ text.length = strlen(spirv);
+ EXPECT_EQ(SPV_SUCCESS, spvTextToBinary(&text, opcodeTable, operandTable,
+ extInstTable, &binary, &diagnostic));
+ if (binary) {
+ spvBinaryDestroy(binary);
+ }
+ if (diagnostic) {
+ spvDiagnosticPrint(diagnostic);
+ }
+}
+
+TEST_F(TextToBinaryTest, StringSpace) {
+ const char *spirv = R"(
+OpSourceExtension "string with spaces"
+)";
+ text.str = spirv;
+ text.length = strlen(spirv);
+ EXPECT_EQ(SPV_SUCCESS, spvTextToBinary(&text, opcodeTable, operandTable,
+ extInstTable, &binary, &diagnostic));
+ if (binary) {
+ spvBinaryDestroy(binary);
+ }
+ if (diagnostic) {
+ spvDiagnosticPrint(diagnostic);
+ }
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "UnitSPIRV.h"
+
+TEST(TextWordGet, NullTerminator) {
+ char textStr[] = "Word";
+ spv_text_t text = {textStr, strlen(textStr)};
+ spv_position_t startPosition = {};
+ std::string word;
+ spv_position_t endPosition = {};
+ ASSERT_EQ(SPV_SUCCESS,
+ spvTextWordGet(&text, &startPosition, word, &endPosition));
+ ASSERT_EQ(4, endPosition.column);
+ ASSERT_EQ(0, endPosition.line);
+ ASSERT_EQ(4, endPosition.index);
+ ASSERT_STREQ("Word", word.c_str());
+}
+
+TEST(TextWordGet, TabTerminator) {
+ char textStr[] = "Word\t";
+ spv_text_t text = {textStr, strlen(textStr)};
+ spv_position_t startPosition = {};
+ std::string word;
+ spv_position_t endPosition = {};
+ ASSERT_EQ(SPV_SUCCESS,
+ spvTextWordGet(&text, &startPosition, word, &endPosition));
+ ASSERT_EQ(4, endPosition.column);
+ ASSERT_EQ(0, endPosition.line);
+ ASSERT_EQ(4, endPosition.index);
+ ASSERT_STREQ("Word", word.c_str());
+}
+
+TEST(TextWordGet, SpaceTerminator) {
+ char textStr[] = "Word ";
+ spv_text_t text = {textStr, strlen(textStr)};
+ spv_position_t startPosition = {};
+ std::string word;
+ spv_position_t endPosition = {};
+ ASSERT_EQ(SPV_SUCCESS,
+ spvTextWordGet(&text, &startPosition, word, &endPosition));
+ ASSERT_EQ(4, endPosition.column);
+ ASSERT_EQ(0, endPosition.line);
+ ASSERT_EQ(4, endPosition.index);
+ ASSERT_STREQ("Word", word.c_str());
+}
+
+TEST(TextWordGet, MultipleWords) {
+ char textStr[] = "Words in a sentence";
+ spv_text_t text = {textStr, strlen(textStr)};
+ const char *words[] = {"Words", "in", "a", "sentence"};
+
+ spv_position_t startPosition = {};
+ spv_position_t endPosition = {};
+
+ std::string word;
+ for (uint32_t wordIndex = 0; wordIndex < 4; ++wordIndex) {
+ ASSERT_EQ(SPV_SUCCESS,
+ spvTextWordGet(&text, &startPosition, word, &endPosition));
+ ASSERT_EQ(strlen(words[wordIndex]),
+ endPosition.column - startPosition.column);
+ ASSERT_EQ(0, endPosition.line);
+ ASSERT_EQ(strlen(words[wordIndex]),
+ endPosition.index - startPosition.index);
+ ASSERT_STREQ(words[wordIndex], word.c_str());
+
+ startPosition = endPosition;
+ if (3 != wordIndex) {
+ ASSERT_EQ(SPV_SUCCESS, spvTextAdvance(&text, &startPosition));
+ } else {
+ ASSERT_EQ(SPV_END_OF_STREAM, spvTextAdvance(&text, &startPosition));
+ }
+ }
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#ifndef _CODEPLAY_UNITBIL_H_
+#define _CODEPLAY_UNITBIL_H_
+
+#include <libspirv/libspirv.h>
+#include "../source/binary.h"
+#include "../source/diagnostic.h"
+#include "../source/opcode.h"
+#include "../source/text.h"
+#include "../source/validate.h"
+
+#include <gtest/gtest.h>
+
+#include <stdint.h>
+
+// Determine endianness & predicate tests on it
+enum {
+ I32_ENDIAN_LITTLE = 0x03020100ul,
+ I32_ENDIAN_BIG = 0x00010203ul,
+};
+
+static const union {
+ unsigned char bytes[4];
+ uint32_t value;
+} o32_host_order = {{0, 1, 2, 3}};
+
+#define I32_ENDIAN_HOST (o32_host_order.value)
+
+#endif
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "UnitSPIRV.h"
+
+class Validate : public ::testing::Test {
+ public:
+ Validate() : binary(), opcodeTable(nullptr), operandTable(nullptr) {}
+
+ virtual void SetUp() {
+ ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&opcodeTable));
+ ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable));
+ ASSERT_EQ(SPV_SUCCESS, spvExtInstTableGet(&extInstTable));
+ }
+
+ virtual void TearDown() { spvBinaryDestroy(binary); }
+
+ spv_binary binary;
+ spv_opcode_table opcodeTable;
+ spv_operand_table operandTable;
+ spv_ext_inst_table extInstTable;
+};
+
+TEST_F(Validate, DISABLED_Default) {
+ char str[] = R"(
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute 1
+OpExecutionMode 1 LocalSize 1 1 1
+OpTypeVoid 2
+OpTypeFunction 3 2
+OpFunction 2 1 NoControl 3
+OpLabel 4
+OpReturn
+OpFunctionEnd
+)";
+ spv_text_t text = {str, strlen(str)};
+ spv_diagnostic diagnostic = nullptr;
+ ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(&text, opcodeTable, operandTable,
+ extInstTable, &binary, &diagnostic));
+ ASSERT_EQ(SPV_SUCCESS,
+ spvValidate(binary, opcodeTable, operandTable, extInstTable,
+ SPV_VALIDATE_ALL, &diagnostic));
+ if (diagnostic) {
+ spvDiagnosticPrint(diagnostic);
+ spvDiagnosticDestroy(diagnostic);
+ }
+}
+
+TEST_F(Validate, DISABLED_InvalidIdUndefined) {
+ char str[] = R"(
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute 1
+OpExecutionMode 5 LocalSize 1 1 1
+OpTypeVoid 2
+OpTypeFunction 3 2
+OpFunction 2 1 NoControl 3
+OpLabel 4
+OpReturn
+OpFunctionEnd
+)";
+ spv_text_t text = {str, strlen(str)};
+ spv_diagnostic diagnostic = nullptr;
+ ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(&text, opcodeTable, operandTable,
+ extInstTable, &binary, &diagnostic));
+ ASSERT_EQ(SPV_ERROR_INVALID_ID,
+ spvValidate(binary, opcodeTable, operandTable, extInstTable,
+ SPV_VALIDATE_ALL, &diagnostic));
+ ASSERT_NE(nullptr, diagnostic);
+ spvDiagnosticPrint(diagnostic);
+ spvDiagnosticDestroy(diagnostic);
+}
+
+TEST_F(Validate, DISABLED_InvalidIdRedefined) {
+ char str[] = R"(
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute 1
+OpExecutionMode 1 LocalSize 1 1 1
+OpTypeVoid 2
+OpTypeFunction 2 2
+OpFunction 2 1 NoControl 3
+OpLabel 4
+OpReturn
+OpFunctionEnd
+)";
+ spv_text_t text = {str, strlen(str)};
+ spv_diagnostic diagnostic = nullptr;
+ ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(&text, opcodeTable, operandTable,
+ extInstTable, &binary, &diagnostic));
+ // TODO: Fix setting of bound in spvTextTo, then remove this!
+ ASSERT_EQ(SPV_ERROR_INVALID_ID,
+ spvValidate(binary, opcodeTable, operandTable, extInstTable,
+ SPV_VALIDATE_ALL, &diagnostic));
+ ASSERT_NE(nullptr, diagnostic);
+ spvDiagnosticPrint(diagnostic);
+ spvDiagnosticDestroy(diagnostic);
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "UnitSPIRV.h"
+
+// NOTE: The tests in this file are ONLY testing ID usage, there for the input
+// SPIR-V does not follow the logical layout rules from the spec in all cases in
+// order to makes the tests smaller. Validation of the whole module is handled
+// in stages, ID validation is only one of these stages. All validation stages
+// are stand alone.
+
+class ValidateID : public ::testing::Test {
+ public:
+ ValidateID() : opcodeTable(nullptr), operandTable(nullptr), binary() {}
+
+ virtual void SetUp() {
+ ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&opcodeTable));
+ ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable));
+ ASSERT_EQ(SPV_SUCCESS, spvExtInstTableGet(&extInstTable));
+ }
+
+ virtual void TearDown() { spvBinaryDestroy(binary); }
+
+ spv_opcode_table opcodeTable;
+ spv_operand_table operandTable;
+ spv_ext_inst_table extInstTable;
+ spv_binary binary;
+};
+
+#define CHECK(str, expected) \
+ spv_text_t text = {str, strlen(str)}; \
+ spv_diagnostic diagnostic; \
+ spv_result_t error = spvTextToBinary(&text, opcodeTable, operandTable, \
+ extInstTable, &binary, &diagnostic); \
+ if (error) { \
+ spvDiagnosticPrint(diagnostic); \
+ spvDiagnosticDestroy(diagnostic); \
+ ASSERT_EQ(SPV_SUCCESS, error); \
+ } \
+ spv_result_t result = \
+ spvValidate(binary, opcodeTable, operandTable, extInstTable, \
+ SPV_VALIDATE_ID_BIT, &diagnostic); \
+ if (SPV_SUCCESS != result) { \
+ spvDiagnosticPrint(diagnostic); \
+ spvDiagnosticDestroy(diagnostic); \
+ } \
+ ASSERT_EQ(expected, result);
+
+// TODO: OpUndef
+
+TEST_F(ValidateID, OpName) {
+ const char *spirv = R"(
+OpName $2 "name"
+OpTypeInt %1 32 0
+OpTypePointer %2 UniformConstant $1
+OpVariable $2 %3 UniformConstant)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+
+TEST_F(ValidateID, OpMemberNameGood) {
+ const char *spirv = R"(
+OpMemberName $2 0 "foo"
+OpTypeInt %1 32 0
+OpTypeStruct %2 $1)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpMemberNameTypeBad) {
+ const char *spirv = R"(
+OpMemberName $1 0 "foo"
+OpTypeInt %1 32 0)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpMemberNameMemberBad) {
+ const char *spirv = R"(
+OpMemberName $2 1 "foo"
+OpTypeInt %1 32 0
+OpTypeStruct %2 $1)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpLineGood) {
+ const char *spirv = R"(
+OpString %1 "/path/to/source.file"
+OpLine $4 $1 0 0
+OpTypeInt %2 32 0
+OpTypePointer %3 Generic $2
+OpVariable $3 %4 Generic)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpLineFileBad) {
+ const char *spirv = R"(
+OpLine $4 $2 0 0
+OpTypeInt %2 32 0
+OpTypePointer %3 Generic $2
+OpVariable $3 %4 Generic)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpDecorateGood) {
+ const char *spirv = R"(
+OpDecorate $2 GLSLShared
+OpTypeInt %1 64 0
+OpTypeStruct %2 $1 $1)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpDecorateBad) {
+ const char *spirv = R"(
+OpDecorate $1 GLSLShared)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpMemberDecorateGood) {
+ const char *spirv = R"(
+OpMemberDecorate $2 0 Uniform
+OpTypeInt %1 32 0
+OpTypeStruct %2 $1 $1)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpMemberDecorateBad) {
+ const char *spirv = R"(
+OpMemberDecorate $1 0 Uniform
+OpTypeInt %1 32 0)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpMemberDecorateMemberBad) {
+ const char *spirv = R"(
+OpMemberDecorate $2 3 Uniform
+OpTypeInt %1 32 0
+OpTypeStruct %2 $1 $1)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpGroupDecorateGood) {
+ const char *spirv = R"(
+OpDecorationGroup %1
+OpDecorate $1 Uniform
+OpDecorate $1 GLSLStd430
+OpGroupDecorate $1 $3 $4
+OpTypeInt %2 32 0
+OpConstant $2 %3 42
+OpConstant $2 %4 23)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpGroupDecorateDecorationGroupBad) {
+ const char *spirv = R"(
+OpGroupDecorate $2 $3 $4
+OpTypeInt %2 32 0
+OpConstant $2 %3 42
+OpConstant $2 %4 23)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpGroupDecorateTargetBad) {
+ const char *spirv = R"(
+OpDecorationGroup %1
+OpDecorate $1 Uniform
+OpDecorate $1 GLSLStd430
+OpGroupDecorate $1 $3
+OpTypeInt %2 32 0)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+// TODO: OpGroupMemberDecorate
+// TODO: OpExtInst
+
+TEST_F(ValidateID, OpEntryPointGood) {
+ const char *spirv = R"(
+OpEntryPoint GLCompute $3
+OpTypeVoid %1
+OpTypeFunction %2 $1
+OpFunction $1 %3 None $2
+OpLabel %4
+OpReturn
+OpFunctionEnd
+)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpEntryPointFunctionBad) {
+ const char *spirv = R"(
+OpEntryPoint GLCompute $1
+OpTypeVoid %1)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpEntryPointParameterCountBad) {
+ const char *spirv = R"(
+OpEntryPoint GLCompute $3
+OpTypeVoid %1
+OpTypeFunction %2 $1 $1
+OpFunction $1 %3 None $2
+OpLabel %4
+OpReturn
+OpFunctionEnd)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpEntryPointReturnTypeBad) {
+ const char *spirv = R"(
+OpEntryPoint GLCompute $3
+OpTypeInt %1 32 0
+OpTypeFunction %2 $1
+OpFunction $1 %3 None $2
+OpLabel %4
+OpReturn
+OpFunctionEnd)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpExecutionModeGood) {
+ const char *spirv = R"(
+OpEntryPoint GLCompute $3
+OpExecutionMode $3 LocalSize 1 1 1
+OpTypeVoid %1
+OpTypeFunction %2 $1
+OpFunction $1 %3 None $2
+OpLabel %4
+OpReturn
+OpFunctionEnd)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpExecutionModeEntryPointBad) {
+ const char *spirv = R"(
+OpExecutionMode $3 LocalSize 1 1 1
+OpTypeVoid %1
+OpTypeFunction %2 $1
+OpFunction $1 %3 None $2
+OpLabel %4
+OpReturn
+OpFunctionEnd)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpTypeVectorGood) {
+ const char *spirv = R"(
+OpTypeFloat %1 32
+OpTypeVector %2 $1 4)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpTypeVectorComponentTypeBad) {
+ const char *spirv = R"(
+OpTypeFloat %1 32
+OpTypePointer %2 UniformConstant $1
+OpTypeVector %3 $2 4)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpTypeMatrixGood) {
+ const char *spirv = R"(
+OpTypeInt %1 32 0
+OpTypeVector %2 $1 2
+OpTypeMatrix %3 $2 3)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpTypeMatrixColumnTypeBad) {
+ const char *spirv = R"(
+OpTypeInt %1 32 0
+OpTypeMatrix %2 $1 3)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpTypeSamplerGood) {
+ const char *spirv = R"(
+OpTypeFloat %1 32
+OpTypeSampler %2 $1 2D 0 0 0 0)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpTypeSamplerSampledTypeBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeSampler %2 $1 2D 0 0 0 0)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpTypeArrayGood) {
+ const char *spirv = R"(
+OpTypeInt %1 32 0
+OpConstant $1 %2 1
+OpTypeArray %3 $1 $2)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpTypeArrayElementTypeBad) {
+ const char *spirv = R"(
+OpTypeInt %1 32 0
+OpConstant $1 %2 1
+OpTypeArray %3 $2 $2)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpTypeArrayLengthBad) {
+ const char *spirv = R"(
+OpTypeInt %1 32 0
+OpConstant $1 %2 0
+OpTypeArray %3 $1 $2)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpTypeRuntimeArrayGood) {
+ const char *spirv = R"(
+OpTypeInt %1 32 0
+OpTypeRuntimeArray %2 $1)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpTypeRuntimeArrayBad) {
+ const char *spirv = R"(
+OpTypeInt %1 32 0
+OpConstant $1 %2 0
+OpTypeRuntimeArray %3 $2)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+// TODO: Object of this type can only be created with OpVariable using the
+// Unifrom Storage Class
+
+TEST_F(ValidateID, OpTypeStructGood) {
+ const char *spirv = R"(
+OpTypeInt %1 32 0
+OpTypeFloat %2 64
+OpTypePointer %3 Generic $1
+OpTypeStruct %4 $1 $2 $3)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpTypeStructMemberTypeBad) {
+ const char *spirv = R"(
+OpTypeInt %1 32 0
+OpTypeFloat %2 64
+OpConstant $2 %3 0.0
+OpTypeStruct %4 $1 $2 $3)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpTypePointerGood) {
+ const char *spirv = R"(
+OpTypeInt %1 32 0
+OpTypePointer %2 Generic $1)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpTypePointerBad) {
+ const char *spirv = R"(
+OpTypeInt %1 32 0
+OpConstant $1 %2 0
+OpTypePointer %3 Generic $2)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpTypeFunctionGood) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeFunction %2 $1)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpTypeFunctionReturnTypeBad) {
+ const char *spirv = R"(
+OpTypeInt %1 32 0
+OpConstant $1 %2 0
+OpTypeFunction %3 $2)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpTypeFunctionParameterBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 0
+OpConstant $2 %3 0
+OpTypeFunction %4 $1 $2 $3)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpTypePipeGood) {
+ const char *spirv = R"(
+OpTypeFloat %1 32
+OpTypeVector %2 $1 16
+OpTypePipe %3 $2 ReadOnly)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpTypePipeBad) {
+ const char *spirv = R"(
+OpTypeFloat %1 32
+OpConstant $1 %2 0
+OpTypePipe %3 $2 ReadOnly)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpConstantTrueGood) {
+ const char *spirv = R"(
+OpTypeBool %1
+OpConstantTrue $1 %2)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpConstantTrueBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpConstantTrue $1 %2)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpConstantFalseGood) {
+ const char *spirv = R"(
+OpTypeBool %1
+OpConstantFalse $1 %2)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpConstantFalseBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpConstantFalse $1 %2)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpConstantGood) {
+ const char *spirv = R"(
+OpTypeInt %1 32 0
+OpConstant $1 %2 1)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpConstantBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpConstant $1 %2 0)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpConstantCompositeVectorGood) {
+ const char *spirv = R"(
+OpTypeFloat %1 32
+OpTypeVector %2 $1 4
+OpConstant $1 %3 3.14
+OpConstantComposite $2 %4 $3 $3 $3 $3)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpConstantCompositeVectorResultTypeBad) {
+ const char *spirv = R"(
+OpTypeFloat %1 32
+OpTypeVector %2 $1 4
+OpConstant $1 %3 3.14
+OpConstantComposite $1 %4 $3 $3 $3 $3)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpConstantCompositeVectorConstituentBad) {
+ const char *spirv = R"(
+OpTypeFloat %1 32
+OpTypeVector %2 $1 4
+OpTypeInt %4 32 0
+OpConstant $1 %3 3.14
+OpConstant $4 %5 42
+OpConstantComposite $2 %6 $3 $5 $3 $3)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpConstantCompositeMatrixGood) {
+ const char *spirv = R"(
+OpTypeFloat %1 32
+OpTypeVector %2 $1 4
+OpTypeMatrix %3 $2 4
+OpConstant $1 %4 1.0
+OpConstant $1 %5 0.0
+OpConstantComposite $2 %6 $4 $5 $5 $5
+OpConstantComposite $2 %7 $5 $4 $5 $5
+OpConstantComposite $2 %8 $5 $5 $4 $5
+OpConstantComposite $2 %9 $5 $5 $5 $4
+OpConstantComposite $3 %10 $6 $7 $8 $9)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpConstantCompositeMatrixConstituentBad) {
+ const char *spirv = R"(
+OpTypeFloat %1 32
+OpTypeVector %2 $1 4
+OpTypeVector %11 $1 3
+OpTypeMatrix %3 $2 4
+OpConstant $1 %4 1.0
+OpConstant $1 %5 0.0
+OpConstantComposite $2 %6 $4 $5 $5 $5
+OpConstantComposite $2 %7 $5 $4 $5 $5
+OpConstantComposite $2 %8 $5 $5 $4 $5
+OpConstantComposite $11 %9 $5 $5 $5
+OpConstantComposite $3 %10 $6 $7 $8 $9)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpConstantCompositeMatrixColumnTypeBad) {
+ const char *spirv = R"(
+OpTypeInt %1 32 0
+OpTypeFloat %2 32
+OpTypeVector %3 $1 2
+OpTypeVector %4 $3 2
+OpTypeMatrix %5 $2 2
+OpConstant $1 %6 42
+OpConstant $2 %7 3.14
+OpConstantComposite $3 %8 $6 $6
+OpConstantComposite $4 %9 $7 $7
+OpConstantComposite $5 %10 $8 $9)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpConstantCompositeArrayGood) {
+ const char *spirv = R"(
+OpTypeInt %1 32 0
+OpConstant $1 %2 4
+OpTypeArray %3 $1 $2
+OpConstantComposite $3 %4 $2 $2 $2 $2)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpConstantCompositeArrayConstConstituentBad) {
+ const char *spirv = R"(
+OpTypeInt %1 32 0
+OpConstant $1 %2 4
+OpTypeArray %3 $1 $2
+OpConstantComposite $3 %4 $2 $2 $2 $1)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpConstantCompositeArrayConstituentBad) {
+ const char *spirv = R"(
+OpTypeInt %1 32 0
+OpConstant $1 %2 4
+OpTypeArray %3 $1 $2
+OpTypeFloat %5 32
+OpConstant $5 %6 3.14
+OpConstantComposite $3 %4 $2 $2 $2 $6)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpConstantCompositeStructGood) {
+ const char *spirv = R"(
+OpTypeInt %1 32 0
+OpTypeInt %2 64 1
+OpTypeStruct %3 $1 $1 $2
+OpConstant $1 %4 42
+OpConstant $2 %5 4300000000
+OpConstantComposite $3 %6 $4 $4 $5)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpConstantCompositeStructMemberBad) {
+ const char *spirv = R"(
+OpTypeInt %1 32 0
+OpTypeInt %2 64 1
+OpTypeStruct %3 $1 $1 $2
+OpConstant $1 %4 42
+OpConstant $2 %5 4300000000
+OpConstantComposite $3 %6 $4 $5 $4)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpConstantSamplerGood) {
+ const char *spirv = R"(
+OpTypeFloat %1 32
+OpTypeSampler %2 $1 2D 1 0 1 0
+OpConstantSampler $2 %3 ClampToEdge 0 Nearest)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpConstantSamplerResultTypeBad) {
+ const char *spirv = R"(
+OpTypeFloat %1 32
+OpConstantSampler $1 %2 Clamp 0 Nearest)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpConstantNullGood) {
+ const char *spirv = R"(
+OpTypeBool %1
+OpConstantNull $1 %2
+OpTypeInt %3 32 0
+OpConstantNull $3 %4
+OpTypeFloat %5 32
+OpConstantNull $5 %6
+OpTypePointer %7 UniformConstant $3
+OpConstantNull $7 %8
+OpTypeEvent %9
+OpConstantNull $9 %10
+OpTypeDeviceEvent %11
+OpConstantNull $11 %12
+OpTypeReserveId %13
+OpConstantNull $13 %14
+OpTypeQueue %15
+OpConstantNull $15 %16
+OpTypeVector %17 $3 2
+OpConstantNull $17 %18
+OpTypeMatrix %19 $17 2
+OpConstantNull $19 %20
+OpConstant $3 %25 8
+OpTypeArray %21 $3 $25
+OpConstantNull $21 %22
+OpTypeStruct %23 $3 $5 $1
+OpConstantNull $23 %24
+)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpConstantNullBasicBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpConstantNull $1 %2)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpConstantNullArrayBad) {
+ const char *spirv = R"(
+OpTypeInt %1 8 0
+OpTypeInt %2 32 0
+OpTypeSampler %3 $1 2D 0 0 0 0
+OpConstant $2 %4 4
+OpTypeArray %5 $3 $4
+OpConstantNull $5 %6)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpConstantNullStructBad) {
+ const char *spirv = R"(
+OpTypeInt %1 8 0
+OpTypeSampler %2 $1 2D 0 0 0 0
+OpTypeStruct %3 $2 $2
+OpConstantNull $3 %4)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpSpecConstantTrueGood) {
+ const char *spirv = R"(
+OpTypeBool %1
+OpSpecConstantTrue $1 %2)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpSpecConstantTrueBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpSpecConstantTrue $1 %2)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpSpecConstantFalseGood) {
+ const char *spirv = R"(
+OpTypeBool %1
+OpSpecConstantFalse $1 %2)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpSpecConstantFalseBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpSpecConstantFalse $1 %2)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpSpecConstantGood) {
+ const char *spirv = R"(
+OpTypeFloat %1 32
+OpSpecConstant $1 %2 42)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpSpecConstantBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpSpecConstant $1 %2 3.14)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+// TODO: OpSpecConstantComposite
+// TODO: OpSpecConstantOp
+
+TEST_F(ValidateID, OpVariableGood) {
+ const char *spirv = R"(
+OpTypeInt %1 32 1
+OpTypePointer %2 Generic $1
+OpVariable $2 %3 Generic)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpVariableInitializerGood) {
+ const char *spirv = R"(
+OpTypeInt %1 32 1
+OpTypePointer %2 Generic $1
+OpConstant $1 %3 42
+OpVariable $2 %4 Generic $3)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+// TODO: Positive test OpVariable with OpConstantNull of OpTypePointer
+TEST_F(ValidateID, OpVariableResultTypeBad) {
+ const char *spirv = R"(
+OpTypeInt %1 32 1
+OpVariable $1 %2 Generic)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpVariableInitializerBad) {
+ const char *spirv = R"(
+OpTypeInt %1 32 1
+OpTypePointer %2 Generic $1
+OpVariable $2 %3 Generic $2)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpLoadGood) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 1
+OpTypePointer %3 UniformConstant $2
+OpTypeFunction %4 $1
+OpVariable $3 %5 UniformConstant
+OpFunction $1 %6 None $4
+OpLabel %7
+OpLoad $3 %8 $5
+OpReturn
+OpFunctionEnd
+)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpLoadResultTypeBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 1
+OpTypePointer %3 UniformConstant $2
+OpTypeFunction %4 $1
+OpVariable $3 %5 UniformConstant
+OpFunction $1 %6 None $4
+OpLabel %7
+OpLoad $2 %8 $5
+OpReturn
+OpFunctionEnd
+)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpLoadPointerBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 1
+OpTypeFloat %9 32
+OpTypePointer %3 UniformConstant $2
+OpTypeFunction %4 $1
+OpFunction $1 %6 None $4
+OpLabel %7
+OpLoad $9 %8 $3
+OpReturn
+OpFunctionEnd
+)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpStoreGood) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 1
+OpTypePointer %3 UniformConstant $2
+OpTypeFunction %4 $1
+OpConstant $2 %5 42
+OpVariable $3 %6 UniformConstant
+OpFunction $1 %7 None $4
+OpLabel %8
+OpStore $6 $5
+OpReturn
+OpFunctionEnd)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpStorePointerBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 1
+OpTypePointer %3 UniformConstant $2
+OpTypeFunction %4 $1
+OpConstant $2 %5 42
+OpVariable $3 %6 UniformConstant
+OpFunction $1 %7 None $4
+OpLabel %8
+OpStore $3 $5
+OpReturn
+OpFunctionEnd)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpStoreObjectGood) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 1
+OpTypePointer %3 UniformConstant $2
+OpTypeFunction %4 $1
+OpConstant $2 %5 42
+OpVariable $3 %6 UniformConstant
+OpFunction $1 %7 None $4
+OpLabel %8
+OpStore $6 $7
+OpReturn
+OpFunctionEnd)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpStoreTypeBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 1
+OpTypeFloat %9 32
+OpTypePointer %3 UniformConstant $2
+OpTypeFunction %4 $1
+OpConstant $9 %5 3.14
+OpVariable $3 %6 UniformConstant
+OpFunction $1 %7 None $4
+OpLabel %8
+OpStore $6 $5
+OpReturn
+OpFunctionEnd)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpCopyMemoryGood) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 0
+OpTypePointer %3 UniformConstant $2
+OpConstant $2 %4 42
+OpVariable $3 %5 UniformConstant $4
+OpTypePointer %6 Function $2
+OpTypeFunction %7 $1
+OpFunction $1 %8 None $7
+OpLabel %9
+OpVariable $6 %10 Function
+OpCopyMemory $10 $5 None
+OpReturn
+OpFunctionEnd
+)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpCopyMemoryBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 0
+OpTypePointer %3 UniformConstant $2
+OpConstant $2 %4 42
+OpVariable $3 %5 UniformConstant $4
+OpTypeFloat %11 32
+OpTypePointer %6 Function $11
+OpTypeFunction %7 $1
+OpFunction $1 %8 None $7
+OpLabel %9
+OpVariable $6 %10 Function
+OpCopyMemory $10 $5 None
+OpReturn
+OpFunctionEnd
+)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+// TODO: OpCopyMemorySized
+TEST_F(ValidateID, OpCopyMemorySizedGood) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 0
+OpTypePointer %3 UniformConstant $2
+OpTypePointer %4 Function $2
+OpConstant $2 %5 4
+OpVariable $3 %6 UniformConstant $5
+OpTypeFunction %7 $1
+OpFunction $1 %8 None $7
+OpLabel %9
+OpVariable $4 %10 Function
+OpCopyMemorySized $10 $6 $5 None
+OpReturn
+OpFunctionEnd)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpCopyMemorySizedTargetBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 0
+OpTypePointer %3 UniformConstant $2
+OpTypePointer %4 Function $2
+OpConstant $2 %5 4
+OpVariable $3 %6 UniformConstant $5
+OpTypeFunction %7 $1
+OpFunction $1 %8 None $7
+OpLabel %9
+OpCopyMemorySized $9 $6 $5 None
+OpReturn
+OpFunctionEnd)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpCopyMemorySizedSourceBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 0
+OpTypePointer %3 UniformConstant $2
+OpTypePointer %4 Function $2
+OpConstant $2 %5 4
+OpTypeFunction %6 $1
+OpFunction $1 %7 None $6
+OpLabel %8
+OpVariable $4 %9 Function
+OpCopyMemorySized $9 $6 $5 None
+OpReturn
+OpFunctionEnd)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpCopyMemorySizedSizeBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 0
+OpTypePointer %3 UniformConstant $2
+OpTypePointer %4 Function $2
+OpConstant $2 %5 4
+OpVariable $3 %6 UniformConstant $5
+OpTypeFunction %7 $1
+OpFunction $1 %8 None $7
+OpLabel %9
+OpVariable $4 %10 Function
+OpCopyMemorySized $10 $6 $6 None
+OpReturn
+OpFunctionEnd)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpCopyMemorySizedSizeTypeBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 0
+OpTypePointer %3 UniformConstant $2
+OpTypePointer %4 Function $2
+OpConstant $2 %5 4
+OpVariable $3 %6 UniformConstant $5
+OpTypeFunction %7 $1
+OpTypeFloat %11 32
+OpConstant $11 %12 1.0
+OpFunction $1 %8 None $7
+OpLabel %9
+OpVariable $4 %10 Function
+OpCopyMemorySized $10 $6 $12 None
+OpReturn
+OpFunctionEnd)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+// TODO: OpAccessChain
+// TODO: OpInBoundsAccessChain
+// TODO: OpArrayLength
+// TODO: OpImagePointer
+// TODO: OpGenericPtrMemSemantics
+
+TEST_F(ValidateID, OpFunctionGood) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 1
+OpTypeFunction %3 $1 $2 $2
+OpFunction $1 %4 None $3
+OpFunctionEnd)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpFunctionResultTypeBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 1
+OpConstant $2 %5 42
+OpTypeFunction %3 $1 $2 $2
+OpFunction $2 %4 None $3
+OpFunctionEnd)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpFunctionFunctionTypeBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 1
+OpFunction $1 %4 None $2
+OpFunctionEnd)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpFunctionParameterGood) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 0
+OpTypeFunction %3 $1 $2
+OpFunction $1 %4 None $3
+OpFunctionParameter $2 %5
+OpLabel %6
+OpReturn
+OpFunctionEnd)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpFunctionParameterResultTypeBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 0
+OpTypeFunction %3 $1 $2
+OpFunction $1 %4 None $3
+OpFunctionParameter $1 %5
+OpLabel %6
+OpReturn
+OpFunctionEnd)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpFunctionParameterOrderBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 0
+OpTypeFunction %3 $1 $2
+OpTypePointer %7 Function $2
+OpFunction $1 %4 None $3
+OpVariable $7 %8 Function
+OpFunctionParameter $2 %5
+OpLabel %6
+OpReturn
+OpFunctionEnd)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+TEST_F(ValidateID, OpFunctionCallGood) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 0
+OpTypeFunction %3 $2 $2
+OpTypeFunction %4 $1
+OpConstant $2 %5 42 ;21
+
+OpFunction $2 %6 None $3
+OpFunctionParameter $2 %7
+OpLabel %8
+OpLoad $2 %9 $7
+OpReturnValue $9
+OpFunctionEnd
+
+OpFunction $1 %10 None $4
+OpLabel %11
+OpReturn
+OpFunctionCall $2 %12 $6 $5
+OpFunctionEnd)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpFunctionCallResultTypeBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 0
+OpTypeFunction %3 $2 $2
+OpTypeFunction %4 $1
+OpConstant $2 %5 42 ;21
+
+OpFunction $2 %6 None $3
+OpFunctionParameter $2 %7
+OpLabel %8
+OpLoad $2 %9 $7
+OpReturnValue $9
+OpFunctionEnd
+
+OpFunction $1 %10 None $4
+OpLabel %11
+OpReturn
+OpFunctionCall $1 %12 $6 $5
+OpFunctionEnd)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpFunctionCallFunctionBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 0
+OpTypeFunction %3 $2 $2
+OpTypeFunction %4 $1
+OpConstant $2 %5 42 ;21
+
+OpFunction $1 %10 None $4
+OpLabel %11
+OpReturn
+OpFunctionCall $2 %12 $5 $5
+OpFunctionEnd)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+TEST_F(ValidateID, OpFunctionCallArgumentTypeBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 0
+OpTypeFunction %3 $2 $2
+OpTypeFunction %4 $1
+OpConstant $2 %5 42
+
+OpTypeFloat %13 32
+OpConstant $13 %14 3.14
+
+OpFunction $2 %6 None $3
+OpFunctionParameter $2 %7
+OpLabel %8
+OpLoad $2 %9 $7
+OpReturnValue $9
+OpFunctionEnd
+
+OpFunction $1 %10 None $4
+OpLabel %11
+OpReturn
+OpFunctionCall $2 %12 $6 $14
+OpFunctionEnd)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+#if 0
+TEST_F(ValidateID, OpFunctionCallArgumentCountBar) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 0
+OpTypeFunction %3 $2 $2
+OpTypeFunction %4 $1
+OpConstant $2 %5 42 ;21
+
+OpFunction $2 %6 None $3
+OpFunctionParameter $2 %7
+OpLabel %8
+OpLoad $2 %9 $7
+OpReturnValue $9
+OpFunctionEnd
+
+OpFunction $1 %10 None $4
+OpLabel %11
+OpReturn
+OpFunctionCall $2 %12 $6 $5
+OpFunctionEnd)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+#endif
+
+// TODO: OpSampler
+// TODO: OpTextureSample
+// TODO: OpTextureSampleDref
+// TODO: OpTextureSampleLod
+// TODO: OpTextureSampleProj
+// TODO: OpTextureSampleGrad
+// TODO: OpTextureSampleOffset
+// TODO: OpTextureSampleProjLod
+// TODO: OpTextureSampleProjGrad
+// TODO: OpTextureSampleLodOffset
+// TODO: OpTextureSampleProjOffset
+// TODO: OpTextureSampleGradOffset
+// TODO: OpTextureSampleProjLodOffset
+// TODO: OpTextureSampleProjGradOffset
+// TODO: OpTextureFetchTexelLod
+// TODO: OpTextureFetchTexelOffset
+// TODO: OpTextureFetchSample
+// TODO: OpTextureFetchTexel
+// TODO: OpTextureGather
+// TODO: OpTextureGatherOffset
+// TODO: OpTextureGatherOffsets
+// TODO: OpTextureQuerySizeLod
+// TODO: OpTextureQuerySize
+// TODO: OpTextureQueryLevels
+// TODO: OpTextureQuerySamples
+// TODO: OpConvertUToF
+// TODO: OpConvertFToS
+// TODO: OpConvertSToF
+// TODO: OpConvertUToF
+// TODO: OpUConvert
+// TODO: OpSConvert
+// TODO: OpFConvert
+// TODO: OpConvertPtrToU
+// TODO: OpConvertUToPtr
+// TODO: OpPtrCastToGeneric
+// TODO: OpGenericCastToPtr
+// TODO: OpBitcast
+// TODO: OpGenericCastToPtrExplicit
+// TODO: OpSatConvertSToU
+// TODO: OpSatConvertUToS
+// TODO: OpVectorExtractDynamic
+// TODO: OpVectorInsertDynamic
+// TODO: OpVectorShuffle
+// TODO: OpCompositeConstruct
+// TODO: OpCompositeExtract
+// TODO: OpCompositeInsert
+// TODO: OpCopyObject
+// TODO: OpTranspose
+// TODO: OpSNegate
+// TODO: OpFNegate
+// TODO: OpNot
+// TODO: OpIAdd
+// TODO: OpFAdd
+// TODO: OpISub
+// TODO: OpFSub
+// TODO: OpIMul
+// TODO: OpFMul
+// TODO: OpUDiv
+// TODO: OpSDiv
+// TODO: OpFDiv
+// TODO: OpUMod
+// TODO: OpSRem
+// TODO: OpSMod
+// TODO: OpFRem
+// TODO: OpFMod
+// TODO: OpVectorTimesScalar
+// TODO: OpMatrixTimesScalar
+// TODO: OpVectorTimesMatrix
+// TODO: OpMatrixTimesVector
+// TODO: OpMatrixTimesMatrix
+// TODO: OpOuterProduct
+// TODO: OpDot
+// TODO: OpShiftRightLogical
+// TODO: OpShiftRightArithmetic
+// TODO: OpShiftLeftLogical
+// TODO: OpBitwiseOr
+// TODO: OpBitwiseXor
+// TODO: OpBitwiseAnd
+// TODO: OpAny
+// TODO: OpAll
+// TODO: OpIsNan
+// TODO: OpIsInf
+// TODO: OpIsFinite
+// TODO: OpIsNormal
+// TODO: OpSignBitSet
+// TODO: OpLessOrGreater
+// TODO: OpOrdered
+// TODO: OpUnordered
+// TODO: OpLogicalOr
+// TODO: OpLogicalXor
+// TODO: OpLogicalAnd
+// TODO: OpSelect
+// TODO: OpIEqual
+// TODO: OpFOrdEqual
+// TODO: OpFUnordEqual
+// TODO: OpINotEqual
+// TODO: OpFOrdNotEqual
+// TODO: OpFUnordNotEqual
+// TODO: OpULessThan
+// TODO: OpSLessThan
+// TODO: OpFOrdLessThan
+// TODO: OpFUnordLessThan
+// TODO: OpUGreaterThan
+// TODO: OpSGreaterThan
+// TODO: OpFOrdGreaterThan
+// TODO: OpFUnordGreaterThan
+// TODO: OpULessThanEqual
+// TODO: OpSLessThanEqual
+// TODO: OpFOrdLessThanEqual
+// TODO: OpFUnordLessThanEqual
+// TODO: OpUGreaterThanEqual
+// TODO: OpSGreaterThanEqual
+// TODO: OpFOrdGreaterThanEqual
+// TODO: OpFUnordGreaterThanEqual
+// TODO: OpDPdx
+// TODO: OpDPdy
+// TODO: OpFWidth
+// TODO: OpDPdxFine
+// TODO: OpDPdyFine
+// TODO: OpFwidthFine
+// TODO: OpDPdxCoarse
+// TODO: OpDPdyCoarse
+// TODO: OpFwidthCoarse
+// TODO: OpPhi
+// TODO: OpLoopMerge
+// TODO: OpSelectionMerge
+// TODO: OpBranch
+// TODO: OpBranchConditional
+// TODO: OpSwitch
+
+TEST_F(ValidateID, OpReturnValueConstantGood) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 0
+OpTypeFunction %3 $2 $2
+OpConstant $2 %4 42
+OpFunction $2 %5 None $3
+OpLabel %6
+OpReturnValue $4
+OpFunctionEnd)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpReturnValueVariableGood) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 0 ;10
+OpTypeFunction %3 $2 $2 ;14
+OpTypePointer %8 Function $2 ;18
+OpConstant $2 %4 42 ;22
+OpFunction $2 %5 None $3 ;27
+OpLabel %6 ;29
+OpVariable $8 %7 Function $4 ;34
+OpReturnValue $7 ;36
+OpFunctionEnd)";
+ CHECK(spirv, SPV_SUCCESS);
+}
+TEST_F(ValidateID, OpReturnValueBad) {
+ const char *spirv = R"(
+OpTypeVoid %1
+OpTypeInt %2 32 0
+OpTypeFunction %3 $2 $2
+OpConstant $2 %4 42
+OpFunction $2 %5 None $3
+OpLabel %6
+OpReturnValue $1
+OpFunctionEnd)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+
+// TODO: OpLifetimeStart
+// TODO: OpLifetimeStop
+// TODO: OpAtomicInit
+// TODO: OpAtomicLoad
+// TODO: OpAtomicStore
+// TODO: OpAtomicExchange
+// TODO: OpAtomicCompareExchange
+// TODO: OpAtomicCompareExchangeWeak
+// TODO: OpAtomicIIncrement
+// TODO: OpAtomicIDecrement
+// TODO: OpAtomicIAdd
+// TODO: OpAtomicISub
+// TODO: OpAtomicUMin
+// TODO: OpAtomicUMax
+// TODO: OpAtomicAnd
+// TODO: OpAtomicOr
+// TODO: OpAtomicXor
+// TODO: OpAtomicIMin
+// TODO: OpAtomicIMax
+// TODO: OpEmitStreamVertex
+// TODO: OpEndStreamPrimitive
+// TODO: OpAsyncGroupCopy
+// TODO: OpWaitGroupEvents
+// TODO: OpGroupAll
+// TODO: OpGroupAny
+// TODO: OpGroupBroadcast
+// TODO: OpGroupIAdd
+// TODO: OpGroupFAdd
+// TODO: OpGroupFMin
+// TODO: OpGroupUMin
+// TODO: OpGroupSMin
+// TODO: OpGroupFMax
+// TODO: OpGroupUMax
+// TODO: OpGroupSMax
+// TODO: OpEnqueueMarker
+// TODO: OpEnqueueKernel
+// TODO: OpGetKernelNDrangeSubGroupCount
+// TODO: OpGetKernelNDrangeMaxSubGroupSize
+// TODO: OpGetKernelWorkGroupSize
+// TODO: OpGetKernelPreferredWorkGroupSizeMultiple
+// TODO: OpRetainEvent
+// TODO: OpReleaseEvent
+// TODO: OpCreateUserEvent
+// TODO: OpIsValidEvent
+// TODO: OpSetUserEventStatus
+// TODO: OpCaptureEventProfilingInfo
+// TODO: OpGetDefaultQueue
+// TODO: OpBuildNDRange
+// TODO: OpReadPipe
+// TODO: OpWritePipe
+// TODO: OpReservedReadPipe
+// TODO: OpReservedWritePipe
+// TODO: OpReserveReadPipePackets
+// TODO: OpReserveWritePipePackets
+// TODO: OpCommitReadPipe
+// TODO: OpCommitWritePipe
+// TODO: OpIsValidReserveId
+// TODO: OpGetNumPipePackets
+// TODO: OpGetMaxPipePackets
+// TODO: OpGroupReserveReadPipePackets
+// TODO: OpGroupReserveWritePipePackets
+// TODO: OpGroupCommitReadPipe
+// TODO: OpGroupCommitWritePipe
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include <gtest/gtest.h>
+
+int main(int argc, char **argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include <libspirv/libspirv.h>
+
+#include <stdio.h>
+#include <vector>
+
+void print_usage(char *argv0) {
+ printf(
+ "Assemble a *.svasm file into a *.sv binary.\n\n"
+ "USAGE: %s [options] <filename>\n\n"
+ " -o Set the output filename\n",
+ argv0);
+}
+
+int main(int argc, char **argv) {
+ if (2 > argc) {
+ print_usage(argv[0]);
+ return 1;
+ }
+
+ const char *inFile = nullptr;
+ const char *outFile = nullptr;
+
+ for (int argi = 1; argi < argc; ++argi) {
+ if ('-' == argv[argi][0]) {
+ switch (argv[argi][1]) {
+ case 'o': {
+ if (!outFile && argi + 1 < argc) {
+ outFile = argv[++argi];
+ } else {
+ print_usage(argv[0]);
+ return 1;
+ }
+ } break;
+ default:
+ print_usage(argv[0]);
+ return 1;
+ }
+ } else {
+ if (!inFile) {
+ inFile = argv[argi];
+ } else {
+ print_usage(argv[0]);
+ return 1;
+ }
+ }
+ }
+
+ if (!outFile) {
+ outFile = "out.spv";
+ }
+
+ spvCheck(!inFile, fprintf(stderr, "error: input file is empty.\n"); return 1);
+
+ std::vector<char> contents;
+ if (FILE *fp = fopen(inFile, "r")) {
+ char buf[1024];
+ while (size_t len = fread(buf, 1, sizeof(buf), fp))
+ contents.insert(contents.end(), buf, buf + len);
+ fclose(fp);
+ } else {
+ fprintf(stderr, "error: file does not exist '%s'\n", inFile);
+ return 1;
+ }
+
+ spv_text_t text = {contents.data(), contents.size()};
+
+ spv_opcode_table opcodeTable;
+ spv_result_t error = spvOpcodeTableGet(&opcodeTable);
+ spvCheck(error, fprintf(stderr, "error: internal malfunction\n");
+ return error);
+
+ spv_operand_table operandTable;
+ error = spvOperandTableGet(&operandTable);
+ spvCheck(error, fprintf(stderr, "error: internal malfunction\n");
+ return error);
+
+ spv_ext_inst_table extInstTable;
+ error = spvExtInstTableGet(&extInstTable);
+ spvCheck(error, fprintf(stderr, "error: Internal malfunction.\n"));
+
+ spv_binary binary;
+ spv_diagnostic diagnostic = nullptr;
+ error = spvTextToBinary(&text, opcodeTable, operandTable, extInstTable,
+ &binary, &diagnostic);
+ spvCheck(error, spvDiagnosticPrint(diagnostic);
+ spvDiagnosticDestroy(diagnostic); return error);
+
+ if (FILE *fp = fopen(outFile, "wb")) {
+ size_t written =
+ fwrite(binary->code, sizeof(uint32_t), (size_t)binary->wordCount, fp);
+ if (binary->wordCount != written) {
+ fprintf(stderr, "error: could not write to file '%s'\n", outFile);
+ return 1;
+ }
+ } else {
+ fprintf(stderr, "error: could not open file '%s'\n", outFile);
+ return 1;
+ }
+
+ spvBinaryDestroy(binary);
+
+ return 0;
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include <libspirv/libspirv.h>
+
+#include <stdio.h>
+#include <vector>
+
+void print_usage(char *argv0) {
+ printf(
+ "Dissassemble a *.sv file into a *.svasm text file.\n\n"
+ "USAGE: %s [options] <filename>\n\n"
+ " -o <filename> Set the output filename\n"
+ " -p Print dissassembly to stdout, this\n"
+ " overrides file output\n",
+ argv0);
+}
+
+int main(int argc, char **argv) {
+ if (2 > argc) {
+ print_usage(argv[0]);
+ return 1;
+ }
+
+ uint32_t options = SPV_BINARY_TO_TEXT_OPTION_NONE;
+ const char *inFile = nullptr;
+ const char *outFile = nullptr;
+
+ for (int argi = 1; argi < argc; ++argi) {
+ if ('-' == argv[argi][0]) {
+ switch (argv[argi][1]) {
+ case 'o': {
+ if (!outFile && argi + 1 < argc) {
+ outFile = argv[++argi];
+ } else {
+ print_usage(argv[0]);
+ return 1;
+ }
+ } break;
+ case 'p': {
+ options |= SPV_BINARY_TO_TEXT_OPTION_PRINT;
+#ifdef SPV_COLOR_TERMINAL
+ options |= SPV_BINARY_TO_TEXT_OPTION_COLOR;
+#endif
+ } break;
+ default:
+ print_usage(argv[0]);
+ return 1;
+ }
+ } else {
+ if (!inFile) {
+ inFile = argv[argi];
+ } else {
+ print_usage(argv[0]);
+ return 1;
+ }
+ }
+ }
+
+ if (!outFile) {
+ outFile = "out.spvasm";
+ }
+
+ spvCheck(!inFile, fprintf(stderr, "error: input file is empty.\n"); return 1);
+
+ std::vector<uint32_t> contents;
+ if (FILE *fp = fopen(inFile, "rb")) {
+ uint32_t buf[1024];
+ while (size_t len = fread(buf, sizeof(uint32_t), 1024, fp)) {
+ contents.insert(contents.end(), buf, buf + len);
+ }
+ fclose(fp);
+ } else {
+ fprintf(stderr, "error: file does not exist '%s'\n", inFile);
+ return 1;
+ }
+
+ spv_binary_t binary = {contents.data(), contents.size()};
+
+ spv_opcode_table opcodeTable;
+ spv_result_t error = spvOpcodeTableGet(&opcodeTable);
+ spvCheck(error, fprintf(stderr, "error: internal malfunction\n");
+ return error);
+
+ spv_operand_table operandTable;
+ error = spvOperandTableGet(&operandTable);
+ spvCheck(error, fprintf(stderr, "error: internal malfunction\n");
+ return error);
+
+ spv_ext_inst_table extInstTable;
+ error = spvExtInstTableGet(&extInstTable);
+ spvCheck(error, fprintf(stderr, "error: Internal malfunction.\n"));
+
+ spv_text text;
+ spv_diagnostic diagnostic = nullptr;
+ error = spvBinaryToText(&binary, options, opcodeTable, operandTable,
+ extInstTable, &text, &diagnostic);
+ spvCheck(error, spvDiagnosticPrint(diagnostic);
+ spvDiagnosticDestroy(diagnostic); return error);
+
+ if (spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_PRINT, options)) {
+ printf("%s", text->str);
+ } else {
+ if (FILE *fp = fopen(outFile, "w")) {
+ size_t written = fwrite(text->str, sizeof(char), (size_t)text->length, fp);
+ if (text->length != written) {
+ spvTextDestroy(text);
+ fprintf(stderr, "error: could not write to file '%s'\n", outFile);
+ return 1;
+ }
+ } else {
+ spvTextDestroy(text);
+ fprintf(stderr, "error: could not open file '%s'\n", outFile);
+ return 1;
+ }
+ }
+
+ spvTextDestroy(text);
+
+ return 0;
+}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+// https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include <libspirv/libspirv.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <vector>
+
+void print_usage(char *argv0) {
+ printf(
+ "Validate a SPIR-V binary file.\n\n"
+ "USAGE: %s [options] <filename>\n\n"
+ " -basic Perform basic validation (disabled)\n"
+ " -layout Perform layout validation "
+ "(disabled)\n"
+ " -id Perform id validation (default ON)\n"
+ " -capability <capability> Performs OpCode validation "
+ "(disabled)\n",
+ argv0);
+}
+
+int main(int argc, char **argv) {
+ if (2 > argc) {
+ print_usage(argv[0]);
+ return 1;
+ }
+
+ const char *inFile = nullptr;
+ uint32_t options = 0;
+
+ for (int argi = 1; argi < argc; ++argi) {
+ if ('-' == argv[argi][0]) {
+ if (!strcmp("basic", argv[argi] + 1)) {
+ options |= SPV_VALIDATE_BASIC_BIT;
+ } else if (!strcmp("layout", argv[argi] + 1)) {
+ options |= SPV_VALIDATE_LAYOUT_BIT;
+ } else if (!strcmp("id", argv[argi] + 1)) {
+ options |= SPV_VALIDATE_ID_BIT;
+ } else if (!strcmp("rules", argv[argi] + 1)) {
+ options |= SPV_VALIDATE_RULES_BIT;
+ } else {
+ print_usage(argv[0]);
+ return 1;
+ }
+ } else {
+ if (!inFile) {
+ inFile = argv[argi];
+ } else {
+ print_usage(argv[0]);
+ return 1;
+ }
+ }
+ }
+
+ spvCheck(!inFile, fprintf(stderr, "error: input file is empty.\n"); return 1);
+
+ std::vector<uint32_t> contents;
+ if (FILE *fp = fopen(inFile, "rb")) {
+ uint32_t buf[1024];
+ while (size_t len = fread(buf, sizeof(uint32_t),
+ sizeof(buf) / sizeof(uint32_t), fp)) {
+ contents.insert(contents.end(), buf, buf + len);
+ }
+ fclose(fp);
+ } else {
+ fprintf(stderr, "error: file does not exist '%s'\n", inFile);
+ return 1;
+ }
+
+ spv_binary_t binary = {contents.data(), contents.size()};
+
+ spv_opcode_table opcodeTable;
+ spv_result_t error = spvOpcodeTableGet(&opcodeTable);
+ spvCheck(error, fprintf(stderr, "error: internal malfunction\n");
+ return error);
+
+ spv_operand_table operandTable;
+ error = spvOperandTableGet(&operandTable);
+ spvCheck(error, fprintf(stderr, "error: internal malfunction\n");
+ return error);
+
+ spv_ext_inst_table extInstTable;
+ error = spvExtInstTableGet(&extInstTable);
+ spvCheck(error, fprintf(stderr, "error: Internal malfunction.\n"));
+
+ spv_diagnostic diagnostic = nullptr;
+ error = spvValidate(&binary, opcodeTable, operandTable, extInstTable, options,
+ &diagnostic);
+ spvCheck(error, spvDiagnosticPrint(diagnostic);
+ spvDiagnosticDestroy(diagnostic); return error);
+
+ return 0;
+}