Merge remote-tracking branch 'aosp/upstream-master'

Pulls in the following:
27d98e2 Merge pull request #181 from antiagainst/readme
29ca6f9 Use footnotes for links in README.md.
4897864 Grammar update: OpPhi now uses PairIdRefIdRef as the last operand.
11636fb Update the core grammar.
469f0e8 Make paths to grammar output files
8ba7c92 Remove revision from SPV_ENV_*.
670c0ac Allow to only build certain grammar tables.
051e067 Remove the outdated patch file.
7649c73 Fix MSVC error C2797.
80e416c Use JSON grammar files to generate extended instruction sets.
9ca2d6d Rname grammar.json to spirv.core.grammar.json and add version info.
3fb2676 Fix validation of array length.
6fa3f8a Remove dependency on SPIR-V headers in libspirv.h.
d03c0a1 Enable linking against libSPIRV-Tools from linux shared libraries
c9b2285 Fix spelling mistakes
4f293b7 Use the JSON grammar file to generate various info tables.
a1de2b3 Handle CRLF in assembly text.
3d27da4 Add a target environment to spvContextCreate().
6836e17 OpExecutionMode only takes a single ExecutionMode
4529146 Capability fix: ImageReadWrite & ImageMipmap require ImageBasic.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 11f5379..bd80545 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -29,6 +29,8 @@
 enable_testing()
 set(SPIRV_TOOLS "SPIRV-Tools")
 
+set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+
 if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
   add_definitions(-DSPIRV_LINUX)
 elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
@@ -135,6 +137,18 @@
   ${spirv-tools_SOURCE_DIR}
   COMMENT "Update build-version.inc in the Spirv-tools build directory (if necessary).")
 
+add_custom_target(spirv-tools-build-tables
+  ${PYTHON_EXECUTABLE}
+  ${CMAKE_CURRENT_SOURCE_DIR}/utils/generate_grammar_tables.py
+  --spirv-core-grammar=${spirv-tools_SOURCE_DIR}/source/spirv.core.grammar.json
+  --extinst-glsl-grammar=${spirv-tools_SOURCE_DIR}/source/extinst.glsl.std.450.grammar.json
+  --extinst-opencl-grammar=${spirv-tools_SOURCE_DIR}/source/extinst.opencl.std.grammar.json
+  --core-insts-output=${spirv-tools_BINARY_DIR}/core.insts.inc
+  --glsl-insts-output=${spirv-tools_BINARY_DIR}/glsl.std.450.insts.inc
+  --opencl-insts-output=${spirv-tools_BINARY_DIR}/opencl.std.insts.inc
+  --operand-kinds-output=${spirv-tools_BINARY_DIR}/operand.kinds.inc
+  COMMENT "Generate info tables for SPIR-V instructions and operands.")
+
 # Defaults to OFF if the user didn't set it.
 option(SPIRV_SKIP_EXECUTABLES
        "Skip building the executable and tests along with the library"
@@ -149,9 +163,3 @@
 
 install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/spirv-tools/libspirv.h
   DESTINATION include/spirv-tools/)
-# The installation is broken without these header files from the SPIR-V Registry.
-# The libspirv.h header includes them.
-install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/spirv/spirv.h
-              ${CMAKE_CURRENT_SOURCE_DIR}/include/spirv/GLSL.std.450.h
-              ${CMAKE_CURRENT_SOURCE_DIR}/include/spirv/OpenCL.std.h
-  DESTINATION include/spirv/)
diff --git a/README.md b/README.md
index 18f5368..f4edf57 100644
--- a/README.md
+++ b/README.md
@@ -15,8 +15,8 @@
 The interfaces are still under development, and are expected to change.
 
 SPIR-V is defined by the Khronos Group Inc.
-See the [SPIR-V Registry](https://www.khronos.org/registry/spir-v/) for the
-SPIR-V specification, headers, and XML registry.
+See the [SPIR-V Registry][spirv-registry] for the SPIR-V specification,
+headers, and XML registry.
 
 ## Supported features
 
@@ -38,12 +38,12 @@
 ## Source code
 
 The SPIR-V Tools are maintained by members of the The Khronos Group Inc.,
-at [https://github.com/KhronosGroup/SPIRV-Tools](https://github.com/KhronosGroup/SPIRV-Tools).
+at https://github.com/KhronosGroup/SPIRV-Tools.
 
 Contributions via merge request are welcome. Changes should:
 * Be provided under the [Khronos license](#license).
 * Include tests to cover updated functionality.
-* C++ code should follow the [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html).
+* C++ code should follow the [Google C++ Style Guide][cpp-style-guide].
 * Code should be formatted with `clang-format`.  Settings are defined by
   the included [.clang-format](.clang-format) file.
 
@@ -52,22 +52,20 @@
 ### Source code organization
 
 * `external/googletest`: Intended location for the
-  [googletest](https://github.com/google/googletest) sources, not provided
-* `include/` : API clients should add this directory to the include search
-  path
+  [googletest][googletest] sources, not provided
+* `include/`: API clients should add this directory to the include search path
 * `include/spirv-tools/libspirv.h`: C API public interface
 * `include/spirv/` : Contains header files from the SPIR-V Registry, required
   by the public API.
 * `source/`: API implementation
-* `test/`: Tests, using the [googletest](https://github.com/google/googletest)
-  framework.
+* `test/`: Tests, using the [googletest][googletest] framework
 * `tools/`: Command line executables
 
 ### Tests
 
 The project contains a number of tests, used to drive development
 and ensure correctness.  The tests are written using the
-[googletest](https://github.com/google/googletest) framework.  The `googletest`
+[googletest][googletest] framework.  The `googletest`
 source is not provided with this project.  There are two ways to enable
 tests:
 * If SPIR-V Tools is configured as part of an enclosing project, then the
@@ -77,16 +75,14 @@
   configuring and building the project.
 
 *Note*: You must use a version of googletest that includes
-[a fix](https://github.com/google/googletest/pull/612) for
-[googletest issue 610](https://github.com/google/googletest/issues/610).
+[a fix][googletest-pull-612] for [googletest issue 610][googletest-issue-610].
 The fix is included on the googletest master branch any time after 2015-11-10.
 In particular, googletest must be newer than version 1.7.0.
 
 ## Build
 
-The project uses [CMake](https://cmake.org/) to generate platform-specific
-build configurations.  To generate these build files, issue the following
-commands:
+The project uses [CMake][cmake] to generate platform-specific build
+configurations.  To generate these build files, issue the following commands:
 
 ```
 mkdir <spirv-dir>/build
@@ -104,10 +100,9 @@
 * `SPIRV_COLOR_TERMINAL={ON|OFF}`, default `ON` - Enables color console output.
 * `SPIRV_SKIP_EXECUTABLES={ON|OFF}`, default `OFF`- Build only the library, not
   the command line tools.  This will also prevent the tests from being built.
-* `SPIRV_USE_SANITIZER=<sanitizer>`, default is no sanitizing - 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).
+* `SPIRV_USE_SANITIZER=<sanitizer>`, default is no sanitizing - On UNIX
+  platforms with an appropriate version of `clang` this option enables the use
+  of the sanitizers documented [here][clang-sanitizers].
   This should only be used with a debug build.
 * `SPIRV_WARN_EVERYTHING={ON|OFF}`, default `OFF` - On UNIX platforms enable
   more strict warnings.  The code might not compile with this option enabled.
@@ -123,10 +118,10 @@
 
 The library provides a C API, but the internals use C++11.
 
-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>/libSPIRV-Tools.a` or
+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>/libSPIRV-Tools.a` or
 `<spirv-build-dir>/SPIRV-Tools.lib`.
 
 * `SPIRV-Tools` CMake target: Creates the static library:
@@ -250,3 +245,11 @@
 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
 ```
+
+[spirv-registry]: https://www.khronos.org/registry/spir-v/
+[googletest]: https://github.com/google/googletest
+[googletest-pull-612]: https://github.com/google/googletest/pull/612
+[googletest-issue-610]: https://github.com/google/googletest/issues/610
+[CMake]: https://cmake.org/
+[cpp-style-guide]: https://google.github.io/styleguide/cppguide.html
+[clang-sanitizers]: http://clang.llvm.org/docs/UsersManual.html#controlling-code-generation
diff --git a/include/spirv-tools/libspirv.h b/include/spirv-tools/libspirv.h
index ac44ae8..3a2f2d6 100644
--- a/include/spirv-tools/libspirv.h
+++ b/include/spirv-tools/libspirv.h
@@ -27,10 +27,6 @@
 #ifndef SPIRV_TOOLS_LIBSPIRV_H_
 #define SPIRV_TOOLS_LIBSPIRV_H_
 
-#include "spirv/GLSL.std.450.h"
-#include "spirv/OpenCL.std.h"
-#include "spirv/spirv.h"
-
 #ifdef __cplusplus
 extern "C" {
 #else
@@ -40,18 +36,8 @@
 #include <stddef.h>
 #include <stdint.h>
 
-// Versions
-// This library is based on SPIR-V 1.0 Rev2
-// TODO(dneto): Use the values from the SPIR-V header, when it's updated for
-// SPIR-V 1.0 public release.
-#define SPV_SPIRV_VERSION_MAJOR (SPV_VERSION >> 16)
-#define SPV_SPIRV_VERSION_MINOR (SPV_VERSION & 0xffff)
-#define SPV_SPIRV_VERSION_REVISION (SPV_REVISION)
-
 // Helpers
 
-#define spvIsInBitfield(value, bitfield) ((value) == ((value)&bitfield))
-
 #define SPV_BIT(shift) (1 << (shift))
 
 #define SPV_FORCE_16_BIT_ENUM(name) _##name = 0x7fff
@@ -205,8 +191,6 @@
   SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER,
   // An optional literal string.
   SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING,
-  // An optional execution mode.
-  SPV_OPERAND_TYPE_OPTIONAL_EXECUTION_MODE,
   // An optional access qualifier
   SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER,
   // An optional context-independent value, or CIV.  CIVs are tokens that we can
@@ -225,9 +209,7 @@
   // where the literal number must always be an integer of some sort.
   SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID,
   // A sequence of zero or more pairs of (Id, Literal integer)
-  SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER,
-  // A sequence of zero or more execution modes
-  LAST_VARIABLE(SPV_OPERAND_TYPE_VARIABLE_EXECUTION_MODE),
+  LAST_VARIABLE(SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER),
 
   // This is a sentinel value, and does not represent an operand type.
   // It should come last.
@@ -291,7 +273,7 @@
   const uint32_t* words;
   // The number of words in this instruction.
   uint16_t num_words;
-  SpvOp opcode;
+  uint16_t opcode;
   // The extended instruction type, if opcode is OpExtInst.  Otherwise
   // this is the "none" value.
   spv_ext_inst_type_t ext_inst_type;
@@ -347,8 +329,19 @@
 
 // Platform API
 
-// Creates a context object.
-spv_context spvContextCreate();
+// Certain target environments impose additional restrictions on SPIR-V, so it's
+// often necessary to specify which one applies.  SPV_ENV_UNIVERSAL means
+// environment-agnostic SPIR-V.
+typedef enum {
+  SPV_ENV_UNIVERSAL_1_0,  // SPIR-V 1.0 latest revision, no other restrictions.
+  SPV_ENV_VULKAN_1_0,     // Vulkan 1.0 latest revision.
+} spv_target_env;
+
+// Returns a string describing the given SPIR-V target environment.
+const char* spvTargetEnvDescription(spv_target_env env);
+
+// Creates a context object.  Returns null if env is invalid.
+spv_context spvContextCreate(spv_target_env env);
 
 // Destroys the given context object.
 void spvContextDestroy(spv_context context);
@@ -377,10 +370,11 @@
 // pointer.
 void spvBinaryDestroy(spv_binary binary);
 
-// Validates a SPIR-V binary for correctness.
+// Validates a SPIR-V binary for correctness. Any errors will be written into
+// *diagnostic.
 spv_result_t spvValidate(const spv_const_context context,
                          const spv_const_binary binary,
-                         spv_diagnostic* pDiagnostic);
+                         spv_diagnostic* diagnostic);
 
 // Creates a diagnostic object. The position parameter specifies the location in
 // the text/binary stream. The message parameter, copied into the diagnostic
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
index ca8ee89..e3b14a7 100644
--- a/source/CMakeLists.txt
+++ b/source/CMakeLists.txt
@@ -29,6 +29,7 @@
   ${spirv-tools_SOURCE_DIR}/include/spirv/spirv.h
   ${spirv-tools_SOURCE_DIR}/include/spirv/GLSL.std.450.h
   ${spirv-tools_SOURCE_DIR}/include/spirv/OpenCL.std.h
+
   ${CMAKE_CURRENT_SOURCE_DIR}/util/bitutils.h
   ${CMAKE_CURRENT_SOURCE_DIR}/util/hex_float.h
   ${CMAKE_CURRENT_SOURCE_DIR}/assembly_grammar.h
@@ -46,16 +47,18 @@
   ${CMAKE_CURRENT_SOURCE_DIR}/text.h
   ${CMAKE_CURRENT_SOURCE_DIR}/text_handler.h
   ${CMAKE_CURRENT_SOURCE_DIR}/validate.h
+
   ${CMAKE_CURRENT_SOURCE_DIR}/assembly_grammar.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/binary.cpp
-  ${CMAKE_CURRENT_SOURCE_DIR}/disassemble.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/diagnostic.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/disassemble.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/ext_inst.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/instruction.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/opcode.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/operand.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/print.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/spirv_endian.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/spirv_target_env.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/table.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/text.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/text_handler.cpp
@@ -69,7 +72,11 @@
 
 add_library(${SPIRV_TOOLS} ${SPIRV_SOURCES})
 spvtools_default_compile_options(${SPIRV_TOOLS})
-target_include_directories(${SPIRV_TOOLS} PUBLIC ${spirv-tools_SOURCE_DIR}/include)
+target_include_directories(${SPIRV_TOOLS}
+  PUBLIC ${spirv-tools_SOURCE_DIR}/include
+  PRIVATE ${spirv-tools_BINARY_DIR}
+  )
+add_dependencies(${SPIRV_TOOLS} spirv-tools-build-tables)
 
 install(TARGETS ${SPIRV_TOOLS}
   RUNTIME DESTINATION bin
diff --git a/source/assembly_grammar.h b/source/assembly_grammar.h
index 3364f71..56ff226 100644
--- a/source/assembly_grammar.h
+++ b/source/assembly_grammar.h
@@ -29,6 +29,7 @@
 
 #include "operand.h"
 #include "spirv-tools/libspirv.h"
+#include "spirv/spirv.h"
 #include "table.h"
 
 namespace libspirv {
@@ -38,13 +39,17 @@
 class AssemblyGrammar {
  public:
   explicit AssemblyGrammar(const spv_const_context context)
-      : operandTable_(context->operand_table),
+      : target_env_(context->target_env),
+        operandTable_(context->operand_table),
         opcodeTable_(context->opcode_table),
         extInstTable_(context->ext_inst_table) {}
 
   // Returns true if the internal tables have been initialized with valid data.
   bool isValid() const;
 
+  // Returns the SPIR-V target environment.
+  spv_target_env target_env() const { return target_env_; }
+
   // Fills in the desc parameter with the information about the opcode
   // of the given name. Returns SPV_SUCCESS if the opcode was found, and
   // SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.
@@ -115,6 +120,7 @@
                                   spv_operand_pattern_t* pattern) const;
 
  private:
+  const spv_target_env target_env_;
   const spv_operand_table operandTable_;
   const spv_opcode_table opcodeTable_;
   const spv_ext_inst_table extInstTable_;
diff --git a/source/binary.cpp b/source/binary.cpp
index 5c6aa8f..b3cdc33 100644
--- a/source/binary.cpp
+++ b/source/binary.cpp
@@ -300,8 +300,8 @@
                         << inst_word_count;
   }
   spv_opcode_desc opcode_desc;
-  if (grammar_.lookupOpcode(inst.opcode, &opcode_desc))
-    return diagnostic() << "Invalid opcode: " << int(inst.opcode);
+  if (grammar_.lookupOpcode(static_cast<SpvOp>(inst.opcode), &opcode_desc))
+    return diagnostic() << "Invalid opcode: " << inst.opcode;
 
   // Advance past the opcode word.  But remember the of the start
   // of the instruction.
@@ -397,6 +397,7 @@
                                   std::vector<uint32_t>* words,
                                   std::vector<spv_parsed_operand_t>* operands,
                                   spv_operand_pattern_t* expected_operands) {
+  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
   // We'll fill in this result as we go along.
   spv_parsed_operand_t parsed_operand;
   parsed_operand.offset = uint16_t(_.word_index - inst_offset);
@@ -414,7 +415,7 @@
   parsed_operand.number_bit_width = 0;
 
   if (_.word_index >= _.num_words)
-    return exhaustedInputDiagnostic(inst_offset, inst->opcode, type);
+    return exhaustedInputDiagnostic(inst_offset, opcode, type);
 
   const uint32_t word = peek();
 
@@ -442,9 +443,8 @@
       // A regular value maps to its type.  Some instructions (e.g. OpLabel)
       // have no type Id, and will map to 0.  The result Id for a
       // type-generating instruction (e.g. OpTypeInt) maps to itself.
-      _.id_to_type_id[inst->result_id] = spvOpcodeGeneratesType(inst->opcode)
-                                             ? inst->result_id
-                                             : inst->type_id;
+      _.id_to_type_id[inst->result_id] =
+          spvOpcodeGeneratesType(opcode) ? inst->result_id : inst->type_id;
       break;
 
     case SPV_OPERAND_TYPE_ID:
@@ -452,7 +452,7 @@
       if (!word) return diagnostic(SPV_ERROR_INVALID_ID) << "Id is 0";
       parsed_operand.type = SPV_OPERAND_TYPE_ID;
 
-      if (inst->opcode == SpvOpExtInst && parsed_operand.offset == 3) {
+      if (opcode == SpvOpExtInst && parsed_operand.offset == 3) {
         // The current word is the extended instruction set Id.
         // Set the extended instruction set type for the current instruction.
         auto ext_inst_type_iter = _.import_id_to_ext_inst_type.find(word);
@@ -473,7 +473,7 @@
       break;
 
     case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: {
-      assert(SpvOpExtInst == inst->opcode);
+      assert(SpvOpExtInst == opcode);
       assert(inst->ext_inst_type != SPV_EXT_INST_TYPE_NONE);
       spv_ext_inst_desc ext_inst;
       if (grammar_.lookupExtInst(inst->ext_inst_type, word, &ext_inst))
@@ -482,7 +482,7 @@
     } break;
 
     case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: {
-      assert(SpvOpSpecConstantOp == inst->opcode);
+      assert(SpvOpSpecConstantOp == opcode);
       if (grammar_.lookupSpecConstantOpcode(SpvOp(word))) {
         return diagnostic() << "Invalid " << spvOperandTypeStr(type) << ": "
                             << word;
@@ -514,7 +514,7 @@
     case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
     case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
       parsed_operand.type = SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER;
-      if (inst->opcode == SpvOpSwitch) {
+      if (opcode == SpvOpSwitch) {
         // The literal operands have the same type as the value
         // referenced by the selector Id.
         const uint32_t selector_id = peekAt(inst_offset + 1);
@@ -540,8 +540,7 @@
                               << " is not a scalar integer";
         }
       } else {
-        assert(inst->opcode == SpvOpConstant ||
-               inst->opcode == SpvOpSpecConstant);
+        assert(opcode == SpvOpConstant || opcode == SpvOpSpecConstant);
         // The literal number type is determined by the type Id for the
         // constant.
         assert(inst->type_id);
@@ -565,7 +564,7 @@
       // If there was no terminating null byte, then that's an end-of-input
       // error.
       if (string_num_content_bytes == remaining_input_bytes)
-        return exhaustedInputDiagnostic(inst_offset, inst->opcode, type);
+        return exhaustedInputDiagnostic(inst_offset, opcode, type);
       // Account for null in the word length, so add 1 for null, then add 3 to
       // make sure we round up.  The following is equivalent to:
       //    (string_num_content_bytes + 1 + 3) / 4
@@ -582,7 +581,7 @@
       parsed_operand.num_words = uint16_t(string_num_words);
       parsed_operand.type = SPV_OPERAND_TYPE_LITERAL_STRING;
 
-      if (SpvOpExtInstImport == inst->opcode) {
+      if (SpvOpExtInstImport == opcode) {
         // Record the extended instruction type for the ID for this import.
         // There is only one string literal argument to OpExtInstImport,
         // so it's sufficient to guard this just on the opcode.
@@ -599,9 +598,6 @@
       }
     } break;
 
-    case SPV_OPERAND_TYPE_OPTIONAL_EXECUTION_MODE:
-      parsed_operand.type = SPV_OPERAND_TYPE_EXECUTION_MODE;
-    // Fall through
     case SPV_OPERAND_TYPE_CAPABILITY:
     case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
     case SPV_OPERAND_TYPE_EXECUTION_MODEL:
@@ -699,7 +695,7 @@
   // handled earlier.)  For example, this error can occur for a multi-word
   // argument to OpConstant, or a multi-word case literal operand for OpSwitch.
   if (_.num_words < index_after_operand)
-    return exhaustedInputDiagnostic(inst_offset, inst->opcode, type);
+    return exhaustedInputDiagnostic(inst_offset, opcode, type);
 
   if (_.requires_endian_conversion) {
     // Copy instruction words.  Translate to native endianness as needed.
@@ -745,13 +741,14 @@
 
 void Parser::recordNumberType(size_t inst_offset,
                               const spv_parsed_instruction_t* inst) {
-  if (spvOpcodeGeneratesType(inst->opcode)) {
+  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+  if (spvOpcodeGeneratesType(opcode)) {
     NumberType info = {SPV_NUMBER_NONE, 0};
-    if (SpvOpTypeInt == inst->opcode) {
+    if (SpvOpTypeInt == opcode) {
       const bool is_signed = peekAt(inst_offset + 3) != 0;
       info.type = is_signed ? SPV_NUMBER_SIGNED_INT : SPV_NUMBER_UNSIGNED_INT;
       info.bit_width = peekAt(inst_offset + 2);
-    } else if (SpvOpTypeFloat == inst->opcode) {
+    } else if (SpvOpTypeFloat == opcode) {
       info.type = SPV_NUMBER_FLOATING;
       info.bit_width = peekAt(inst_offset + 2);
     }
diff --git a/source/disassemble.cpp b/source/disassemble.cpp
index 9fae7e5..53e07cb 100644
--- a/source/disassemble.cpp
+++ b/source/disassemble.cpp
@@ -182,7 +182,7 @@
     stream_ << std::string(indent_, ' ');
   }
 
-  stream_ << "Op" << spvOpcodeString(inst.opcode);
+  stream_ << "Op" << spvOpcodeString(static_cast<SpvOp>(inst.opcode));
 
   for (uint16_t i = 0; i < inst.num_operands; i++) {
     const spv_operand_type_t type = inst.operands[i].type;
diff --git a/source/ext_inst.cpp b/source/ext_inst.cpp
index 7ae384e..f612fa9 100644
--- a/source/ext_inst.cpp
+++ b/source/ext_inst.cpp
@@ -28,135 +28,16 @@
 
 #include <string.h>
 
+#include "spirv/GLSL.std.450.h"
+#include "spirv/OpenCL.std.h"
 #include "spirv_definition.h"
 
-/// Generate a spv_ext_inst_desc_t literal for a GLSL std450 extended
-/// instruction with one/two/three <id> parameter(s).
-#define GLSL450Inst1(name) \
-  #name, GLSLstd450::GLSLstd450##name, 0, { SPV_OPERAND_TYPE_ID }
-#define GLSL450Inst1Cap(name, cap)                        \
-  #name, GLSLstd450::GLSLstd450##name,                    \
-          SPV_CAPABILITY_AS_MASK(SpvCapability##cap), { \
-    SPV_OPERAND_TYPE_ID                                   \
-  }
-#define GLSL450Inst2(name)                   \
-  #name, GLSLstd450::GLSLstd450##name, 0, {  \
-    SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID \
-  }
-#define GLSL450Inst2Cap(name, cap)                  \
-  #name, GLSLstd450::GLSLstd450##name,              \
-      SPV_CAPABILITY_AS_MASK(SpvCapability##cap), { \
-    SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID        \
-  }
-#define GLSL450Inst3(name)                                        \
-  #name, GLSLstd450::GLSLstd450##name, 0, {                       \
-    SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID \
-  }
-
 static const spv_ext_inst_desc_t glslStd450Entries[] = {
-    {GLSL450Inst1(Round)},
-    {GLSL450Inst1(RoundEven)},
-    {GLSL450Inst1(Trunc)},
-    {GLSL450Inst1(FAbs)},
-    {GLSL450Inst1(SAbs)},
-    {GLSL450Inst1(FSign)},
-    {GLSL450Inst1(SSign)},
-    {GLSL450Inst1(Floor)},
-    {GLSL450Inst1(Ceil)},
-    {GLSL450Inst1(Fract)},
-    {GLSL450Inst1(Radians)},
-    {GLSL450Inst1(Degrees)},
-    {GLSL450Inst1(Sin)},
-    {GLSL450Inst1(Cos)},
-    {GLSL450Inst1(Tan)},
-    {GLSL450Inst1(Asin)},
-    {GLSL450Inst1(Acos)},
-    {GLSL450Inst1(Atan)},
-    {GLSL450Inst1(Sinh)},
-    {GLSL450Inst1(Cosh)},
-    {GLSL450Inst1(Tanh)},
-    {GLSL450Inst1(Asinh)},
-    {GLSL450Inst1(Acosh)},
-    {GLSL450Inst1(Atanh)},
-    {GLSL450Inst2(Atan2)},
-    {GLSL450Inst2(Pow)},
-    {GLSL450Inst1(Exp)},
-    {GLSL450Inst1(Log)},
-    {GLSL450Inst1(Exp2)},
-    {GLSL450Inst1(Log2)},
-    {GLSL450Inst1(Sqrt)},
-    {GLSL450Inst1(InverseSqrt)},
-    {GLSL450Inst1(Determinant)},
-    {GLSL450Inst1(MatrixInverse)},
-    {GLSL450Inst2(Modf)},
-    {GLSL450Inst1(ModfStruct)},
-    {GLSL450Inst2(FMin)},
-    {GLSL450Inst2(UMin)},
-    {GLSL450Inst2(SMin)},
-    {GLSL450Inst2(FMax)},
-    {GLSL450Inst2(UMax)},
-    {GLSL450Inst2(SMax)},
-    {GLSL450Inst3(FClamp)},
-    {GLSL450Inst3(UClamp)},
-    {GLSL450Inst3(SClamp)},
-    {GLSL450Inst3(FMix)},
-    {GLSL450Inst3(IMix)},
-    {GLSL450Inst2(Step)},
-    {GLSL450Inst3(SmoothStep)},
-    {GLSL450Inst3(Fma)},
-    {GLSL450Inst2(Frexp)},
-    {GLSL450Inst1(FrexpStruct)},
-    {GLSL450Inst2(Ldexp)},
-    {GLSL450Inst1(PackSnorm4x8)},
-    {GLSL450Inst1(PackUnorm4x8)},
-    {GLSL450Inst1(PackSnorm2x16)},
-    {GLSL450Inst1(PackUnorm2x16)},
-    {GLSL450Inst1(PackHalf2x16)},
-    {GLSL450Inst1Cap(PackDouble2x32, Float64)},
-    {GLSL450Inst1(UnpackSnorm2x16)},
-    {GLSL450Inst1(UnpackUnorm2x16)},
-    {GLSL450Inst1(UnpackHalf2x16)},
-    {GLSL450Inst1(UnpackSnorm4x8)},
-    {GLSL450Inst1(UnpackUnorm4x8)},
-    {GLSL450Inst1(UnpackDouble2x32)},
-    {GLSL450Inst1(Length)},
-    {GLSL450Inst2(Distance)},
-    {GLSL450Inst2(Cross)},
-    {GLSL450Inst1(Normalize)},
-    {GLSL450Inst3(FaceForward)},
-    {GLSL450Inst2(Reflect)},
-    {GLSL450Inst3(Refract)},
-    {GLSL450Inst1(FindILsb)},
-    {GLSL450Inst1(FindSMsb)},
-    {GLSL450Inst1(FindUMsb)},
-    {GLSL450Inst1Cap(InterpolateAtCentroid, InterpolationFunction)},
-    {GLSL450Inst2Cap(InterpolateAtSample, InterpolationFunction)},
-    {GLSL450Inst2Cap(InterpolateAtOffset, InterpolationFunction)},
-    {GLSL450Inst2(NMin)},
-    {GLSL450Inst2(NMax)},
-    {GLSL450Inst2(NClamp)},
+#include "glsl.std.450.insts.inc"
 };
 
 static const spv_ext_inst_desc_t openclEntries[] = {
-#define ExtInst(Name, Opcode, OperandList) \
-  { #Name, Opcode, 0, OperandList }           \
-  ,
-#define EmptyList \
-  {}
-#define List(...) \
-  { __VA_ARGS__ }
-#define OperandId SPV_OPERAND_TYPE_ID
-#define OperandLiteralNumber SPV_OPERAND_TYPE_LITERAL_INTEGER
-#define OperandFPRoundingMode SPV_OPERAND_TYPE_FP_ROUNDING_MODE
-#define OperandVariableIds SPV_OPERAND_TYPE_VARIABLE_ID
-#include "opencl_std_ext_inst.inc"
-#undef ExtList
-#undef EmptyList
-#undef List
-#undef OperandId
-#undef OperandLiteralNumber
-#undef OperandFPRoundingMode
-#undef OperandVariableIds
+#include "opencl.std.insts.inc"
 };
 
 spv_result_t spvExtInstTableGet(spv_ext_inst_table* pExtInstTable) {
diff --git a/source/extinst.glsl.std.450.grammar.json b/source/extinst.glsl.std.450.grammar.json
new file mode 100644
index 0000000..b39142f
--- /dev/null
+++ b/source/extinst.glsl.std.450.grammar.json
@@ -0,0 +1,640 @@
+{
+  "copyright" : [
+    "Copyright (c) 2014-2016 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."
+  ],
+  "version" : 100,
+  "revision" : 2,
+  "instructions" : [
+    {
+      "opname" : "Round",
+      "opcode" : 1,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "RoundEven",
+      "opcode" : 2,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Trunc",
+      "opcode" : 3,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "FAbs",
+      "opcode" : 4,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "SAbs",
+      "opcode" : 5,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "FSign",
+      "opcode" : 6,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "SSign",
+      "opcode" : 7,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Floor",
+      "opcode" : 8,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Ceil",
+      "opcode" : 9,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Fract",
+      "opcode" : 10,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Radians",
+      "opcode" : 11,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Degrees",
+      "opcode" : 12,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Sin",
+      "opcode" : 13,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Cos",
+      "opcode" : 14,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Tan",
+      "opcode" : 15,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Asin",
+      "opcode" : 16,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Acos",
+      "opcode" : 17,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Atan",
+      "opcode" : 18,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Sinh",
+      "opcode" : 19,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Cosh",
+      "opcode" : 20,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Tanh",
+      "opcode" : 21,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Asinh",
+      "opcode" : 22,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Acosh",
+      "opcode" : 23,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Atanh",
+      "opcode" : 24,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Atan2",
+      "opcode" : 25,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Pow",
+      "opcode" : 26,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Exp",
+      "opcode" : 27,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Log",
+      "opcode" : 28,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Exp2",
+      "opcode" : 29,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Log2",
+      "opcode" : 30,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Sqrt",
+      "opcode" : 31,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "InverseSqrt",
+      "opcode" : 32,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Determinant",
+      "opcode" : 33,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "MatrixInverse",
+      "opcode" : 34,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Modf",
+      "opcode" : 35,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "ModfStruct",
+      "opcode" : 36,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "FMin",
+      "opcode" : 37,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "UMin",
+      "opcode" : 38,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "SMin",
+      "opcode" : 39,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "FMax",
+      "opcode" : 40,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "UMax",
+      "opcode" : 41,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "SMax",
+      "opcode" : 42,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "FClamp",
+      "opcode" : 43,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "UClamp",
+      "opcode" : 44,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "SClamp",
+      "opcode" : 45,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "FMix",
+      "opcode" : 46,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "IMix",
+      "opcode" : 47,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Step",
+      "opcode" : 48,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "SmoothStep",
+      "opcode" : 49,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Fma",
+      "opcode" : 50,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Frexp",
+      "opcode" : 51,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "FrexpStruct",
+      "opcode" : 52,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Ldexp",
+      "opcode" : 53,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "PackSnorm4x8",
+      "opcode" : 54,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "PackUnorm4x8",
+      "opcode" : 55,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "PackSnorm2x16",
+      "opcode" : 56,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "PackUnorm2x16",
+      "opcode" : 57,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "PackHalf2x16",
+      "opcode" : 58,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "PackDouble2x32",
+      "opcode" : 59,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ],
+      "capabilities" : [ "Float64" ]
+    },
+    {
+      "opname" : "UnpackSnorm2x16",
+      "opcode" : 60,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "UnpackUnorm2x16",
+      "opcode" : 61,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "UnpackHalf2x16",
+      "opcode" : 62,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "UnpackSnorm4x8",
+      "opcode" : 63,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "UnpackUnorm4x8",
+      "opcode" : 64,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "UnpackDouble2x32",
+      "opcode" : 65,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Length",
+      "opcode" : 66,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Distance",
+      "opcode" : 67,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Cross",
+      "opcode" : 68,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Normalize",
+      "opcode" : 69,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "FaceForward",
+      "opcode" : 70,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Reflect",
+      "opcode" : 71,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "Refract",
+      "opcode" : 72,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "FindILsb",
+      "opcode" : 73,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "FindSMsb",
+      "opcode" : 74,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "FindUMsb",
+      "opcode" : 75,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "InterpolateAtCentroid",
+      "opcode" : 76,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ],
+      "capabilities" : [ "InterpolationFunction" ]
+    },
+    {
+      "opname" : "InterpolateAtSample",
+      "opcode" : 77,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ],
+      "capabilities" : [ "InterpolationFunction" ]
+    },
+    {
+      "opname" : "InterpolateAtOffset",
+      "opcode" : 78,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ],
+      "capabilities" : [ "InterpolationFunction" ]
+    },
+    {
+      "opname" : "NMin",
+      "opcode" : 79,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "NMax",
+      "opcode" : 80,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "NClamp",
+      "opcode" : 81,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    }
+  ]
+}
diff --git a/source/extinst.opencl.std.grammar.json b/source/extinst.opencl.std.grammar.json
new file mode 100644
index 0000000..1145a47
--- /dev/null
+++ b/source/extinst.opencl.std.grammar.json
@@ -0,0 +1,1277 @@
+{
+  "copyright" : [
+    "Copyright (c) 2014-2016 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."
+  ],
+  "instructions" : [
+    {
+      "opname" : "acos",
+      "opcode" : 0,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "acosh",
+      "opcode" : 1,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "acospi",
+      "opcode" : 2,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "asin",
+      "opcode" : 3,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "asinh",
+      "opcode" : 4,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "asinpi",
+      "opcode" : 5,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "atan",
+      "opcode" : 6,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "atan2",
+      "opcode" : 7,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "atanh",
+      "opcode" : 8,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "atanpi",
+      "opcode" : 9,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "atan2pi",
+      "opcode" : 10,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "cbrt",
+      "opcode" : 11,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "ceil",
+      "opcode" : 12,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "copysign",
+      "opcode" : 13,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "cos",
+      "opcode" : 14,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "cosh",
+      "opcode" : 15,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "cospi",
+      "opcode" : 16,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "erfc",
+      "opcode" : 17,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "erf",
+      "opcode" : 18,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "exp",
+      "opcode" : 19,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "exp2",
+      "opcode" : 20,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "exp10",
+      "opcode" : 21,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "expm1",
+      "opcode" : 22,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "fabs",
+      "opcode" : 23,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "fdim",
+      "opcode" : 24,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "floor",
+      "opcode" : 25,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "fma",
+      "opcode" : 26,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "fmax",
+      "opcode" : 27,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "fmin",
+      "opcode" : 28,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "fmod",
+      "opcode" : 29,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "fract",
+      "opcode" : 30,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "frexp",
+      "opcode" : 31,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "hypot",
+      "opcode" : 32,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "ilogb",
+      "opcode" : 33,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "ldexp",
+      "opcode" : 34,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "lgamma",
+      "opcode" : 35,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "lgamma_r",
+      "opcode" : 36,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "log",
+      "opcode" : 37,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "log2",
+      "opcode" : 38,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "log10",
+      "opcode" : 39,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "log1p",
+      "opcode" : 40,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "logb",
+      "opcode" : 41,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "mad",
+      "opcode" : 42,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "maxmag",
+      "opcode" : 43,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "minmag",
+      "opcode" : 44,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "modf",
+      "opcode" : 45,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "nan",
+      "opcode" : 46,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "nextafter",
+      "opcode" : 47,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "pow",
+      "opcode" : 48,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "pown",
+      "opcode" : 49,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "powr",
+      "opcode" : 50,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "remainder",
+      "opcode" : 51,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "remquo",
+      "opcode" : 52,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "rint",
+      "opcode" : 53,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "rootn",
+      "opcode" : 54,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "round",
+      "opcode" : 55,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "rsqrt",
+      "opcode" : 56,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "sin",
+      "opcode" : 57,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "sincos",
+      "opcode" : 58,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "sinh",
+      "opcode" : 59,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "sinpi",
+      "opcode" : 60,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "sqrt",
+      "opcode" : 61,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "tan",
+      "opcode" : 62,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "tanh",
+      "opcode" : 63,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "tanpi",
+      "opcode" : 64,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "tgamma",
+      "opcode" : 65,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "trunc",
+      "opcode" : 66,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "half_cos",
+      "opcode" : 67,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "half_divide",
+      "opcode" : 68,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "half_exp",
+      "opcode" : 69,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "half_exp2",
+      "opcode" : 70,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "half_exp10",
+      "opcode" : 71,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "half_log",
+      "opcode" : 72,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "half_log2",
+      "opcode" : 73,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "half_log10",
+      "opcode" : 74,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "half_powr",
+      "opcode" : 75,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "half_recip",
+      "opcode" : 76,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "half_rsqrt",
+      "opcode" : 77,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "half_sin",
+      "opcode" : 78,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "half_sqrt",
+      "opcode" : 79,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "half_tan",
+      "opcode" : 80,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "native_cos",
+      "opcode" : 81,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "native_divide",
+      "opcode" : 82,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "native_exp",
+      "opcode" : 83,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "native_exp2",
+      "opcode" : 84,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "native_exp10",
+      "opcode" : 85,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "native_log",
+      "opcode" : 86,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "native_log2",
+      "opcode" : 87,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "native_log10",
+      "opcode" : 88,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "native_powr",
+      "opcode" : 89,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "native_recip",
+      "opcode" : 90,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "native_rsqrt",
+      "opcode" : 91,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "native_sin",
+      "opcode" : 92,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "native_sqrt",
+      "opcode" : 93,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "native_tan",
+      "opcode" : 94,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "fclamp",
+      "opcode" : 95,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "degrees",
+      "opcode" : 96,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "fmax_common",
+      "opcode" : 97,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "fmin_common",
+      "opcode" : 98,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "mix",
+      "opcode" : 99,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "radians",
+      "opcode" : 100,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "step",
+      "opcode" : 101,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "smoothstep",
+      "opcode" : 102,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "sign",
+      "opcode" : 103,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "cross",
+      "opcode" : 104,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "distance",
+      "opcode" : 105,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "length",
+      "opcode" : 106,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "normalize",
+      "opcode" : 107,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "fast_distance",
+      "opcode" : 108,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "fast_length",
+      "opcode" : 109,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "fast_normalize",
+      "opcode" : 110,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "s_abs",
+      "opcode" : 141,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "s_abs_diff",
+      "opcode" : 142,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "s_add_sat",
+      "opcode" : 143,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "u_add_sat",
+      "opcode" : 144,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "s_hadd",
+      "opcode" : 145,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "u_hadd",
+      "opcode" : 146,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "s_rhadd",
+      "opcode" : 147,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "u_rhadd",
+      "opcode" : 148,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "s_clamp",
+      "opcode" : 149,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "u_clamp",
+      "opcode" : 150,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "clz",
+      "opcode" : 151,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "ctz",
+      "opcode" : 152,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "s_mad_hi",
+      "opcode" : 153,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "u_mad_sat",
+      "opcode" : 154,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "s_mad_sat",
+      "opcode" : 155,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "s_max",
+      "opcode" : 156,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "u_max",
+      "opcode" : 157,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "s_min",
+      "opcode" : 158,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "u_min",
+      "opcode" : 159,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "s_mul_hi",
+      "opcode" : 160,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "rotate",
+      "opcode" : 161,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "s_sub_sat",
+      "opcode" : 162,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "u_sub_sat",
+      "opcode" : 163,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "u_upsample",
+      "opcode" : 164,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "s_upsample",
+      "opcode" : 165,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "popcount",
+      "opcode" : 166,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "s_mad24",
+      "opcode" : 167,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "u_mad24",
+      "opcode" : 168,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "s_mul24",
+      "opcode" : 169,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "u_mul24",
+      "opcode" : 170,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "vloadn",
+      "opcode" : 171,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "LiteralInteger" }
+      ]
+    },
+    {
+      "opname" : "vstoren",
+      "opcode" : 172,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "vload_half",
+      "opcode" : 173,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "vload_halfn",
+      "opcode" : 174,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "LiteralInteger" }
+      ]
+    },
+    {
+      "opname" : "vstore_half",
+      "opcode" : 175,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "vstore_half_r",
+      "opcode" : 176,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "FPRoundingMode" }
+      ]
+    },
+    {
+      "opname" : "vstore_halfn",
+      "opcode" : 177,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "vstore_halfn_r",
+      "opcode" : 178,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "FPRoundingMode" }
+      ]
+    },
+    {
+      "opname" : "vloada_halfn",
+      "opcode" : 179,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "LiteralInteger" }
+      ]
+    },
+    {
+      "opname" : "vstorea_halfn",
+      "opcode" : 180,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "vstorea_halfn_r",
+      "opcode" : 181,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "FPRoundingMode" }
+      ]
+    },
+    {
+      "opname" : "shuffle",
+      "opcode" : 182,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "shuffle2",
+      "opcode" : 183,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "printf",
+      "opcode" : 184,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef", "quantifier" : "*" }
+      ]
+    },
+    {
+      "opname" : "prefetch",
+      "opcode" : 185,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "bitselect",
+      "opcode" : 186,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "select",
+      "opcode" : 187,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "u_abs",
+      "opcode" : 201,
+      "operands" : [
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "u_abs_diff",
+      "opcode" : 202,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "u_mul_hi",
+      "opcode" : 203,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    },
+    {
+      "opname" : "u_mad_hi",
+      "opcode" : 204,
+      "operands" : [
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" },
+        { "kind" : "IdRef" }
+      ]
+    }
+  ]
+}
diff --git a/source/opcode.cpp b/source/opcode.cpp
index 1a37a6a..518da26 100644
--- a/source/opcode.cpp
+++ b/source/opcode.cpp
@@ -35,7 +35,6 @@
 #include "spirv-tools/libspirv.h"
 #include "spirv_constant.h"
 #include "spirv_endian.h"
-#include "spirv_operands.h"
 
 namespace {
 
@@ -49,246 +48,11 @@
 // TODO(dneto): Some of the macros are quite unreadable.  We could make
 // good use of constexpr functions, but some compilers don't support that yet.
 const spv_opcode_desc_t opcodeTableEntries[] = {
-#define EmptyList \
-  {}
-#define List(...) \
-  { __VA_ARGS__ }
-#define Capability(X) SPV_CAPABILITY_AS_MASK(SpvCapability##X)
-#define Capability2(X, Y) Capability(X) | Capability(Y)
-#define SpvCapabilityNone \
-  0  // Needed so Capability(None) still expands to valid syntax.
-#define Instruction(Name, HasResult, HasType, NumLogicalOperands,        \
-                    NumCapabilities, CapabilityRequired, IsVariable,     \
-                    LogicalArgsList)                                     \
-  {#Name,     SpvOp##Name, (NumCapabilities) ? (CapabilityRequired) : 0, \
-   0,         {}, /* Filled in later. Operand list, including            \
-                     result id and type id, if needed */                 \
-   HasResult, HasType,     LogicalArgsList},
-#include "opcode.inc"
-#undef EmptyList
-#undef List
-#undef Capability
-#undef Capability2
-#undef CapabilityNone
-#undef Instruction
+#include "core.insts.inc"
 };
 
-// Opcode API
-
-// Converts the given operand class enum (from the SPIR-V document generation
-// logic) to the operand type required by the parser.  The SPV_OPERAND_TYPE_NONE
-// value indicates there is no current operand and no further operands.
-// This only applies to logical operands.
-spv_operand_type_t convertOperandClassToType(SpvOp opcode,
-                                             OperandClass operandClass) {
-  // The spec document generator uses OptionalOperandLiteral for several kinds
-  // of repeating values.  Our parser needs more specific information about
-  // what is being repeated.
-  if (operandClass == OperandOptionalLiteral) {
-    switch (opcode) {
-      case SpvOpExecutionMode:
-        return SPV_OPERAND_TYPE_VARIABLE_EXECUTION_MODE;
-      default:
-        break;
-    }
-  } else if (operandClass == OperandVariableLiterals) {
-    switch (opcode) {
-      case SpvOpConstant:
-      case SpvOpSpecConstant:
-        // The number type is determined by the type Id operand.
-        return SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER;
-      case SpvOpDecorate:
-      case SpvOpMemberDecorate:
-        // The operand types at the end of the instruction are
-        // determined instead by the decoration kind.
-        return SPV_OPERAND_TYPE_NONE;
-      default:
-        break;
-    }
-  }
-
-  switch (operandClass) {
-    case OperandNone:
-      return SPV_OPERAND_TYPE_NONE;
-    case OperandId:
-      return SPV_OPERAND_TYPE_ID;
-    case OperandOptionalId:
-      return SPV_OPERAND_TYPE_OPTIONAL_ID;
-    case OperandVariableIds:
-      if (opcode == SpvOpSpecConstantOp) {
-        // These are the operands to the specialization constant opcode.
-        // The assembler and binary parser set up the extra Id and literal
-        // arguments when processing the opcode operand.  So don't add
-        // an operand type for them here.
-        return SPV_OPERAND_TYPE_NONE;
-      }
-      return SPV_OPERAND_TYPE_VARIABLE_ID;
-    // The spec only uses OptionalLiteral for an optional literal number.
-    case OperandOptionalLiteral:
-      return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER;
-    case OperandOptionalLiteralString:
-      return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING;
-    // This is only used for sequences of literal numbers.
-    case OperandVariableLiterals:
-      return SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER;
-    case OperandLiteralNumber:
-      if (opcode == SpvOpExtInst) {
-        // We use a special operand type for the extension instruction number.
-        // For now, we assume there is only one LiteraNumber argument to
-        // OpExtInst, and it is the extension instruction argument.
-        // See the ExtInst entry in opcode.inc
-        // TODO(dneto): Use a function to confirm the assumption, and to verify
-        // that the index into the operandClass is 1, as expected.
-        return SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER;
-      } else if (opcode == SpvOpSpecConstantOp) {
-        // Use a special operand type for the opcode operand, so we can
-        // use mnemonic names instead of the numbers.  For example, the
-        // assembler should accept "IAdd" instead of the numeric value of
-        // SpvOpIAdd.
-        return SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER;
-      }
-      return SPV_OPERAND_TYPE_LITERAL_INTEGER;
-    case OperandLiteralString:
-      return SPV_OPERAND_TYPE_LITERAL_STRING;
-    case OperandSource:
-      return SPV_OPERAND_TYPE_SOURCE_LANGUAGE;
-    case OperandExecutionModel:
-      return SPV_OPERAND_TYPE_EXECUTION_MODEL;
-    case OperandAddressing:
-      return SPV_OPERAND_TYPE_ADDRESSING_MODEL;
-    case OperandMemory:
-      return SPV_OPERAND_TYPE_MEMORY_MODEL;
-    case OperandExecutionMode:
-      return SPV_OPERAND_TYPE_EXECUTION_MODE;
-    case OperandStorage:
-      return SPV_OPERAND_TYPE_STORAGE_CLASS;
-    case OperandDimensionality:
-      return SPV_OPERAND_TYPE_DIMENSIONALITY;
-    case OperandSamplerAddressingMode:
-      return SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE;
-    case OperandSamplerFilterMode:
-      return SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE;
-    case OperandSamplerImageFormat:
-      return SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT;
-    case OperandImageChannelOrder:
-      // This is only used to describe the value generated by OpImageQueryOrder.
-      // It is not used as an operand.
-      break;
-    case OperandImageChannelDataType:
-      // This is only used to describe the value generated by
-      // OpImageQueryFormat. It is not used as an operand.
-      break;
-    case OperandImageOperands:
-      return SPV_OPERAND_TYPE_IMAGE;
-    case OperandOptionalImageOperands:
-      return SPV_OPERAND_TYPE_OPTIONAL_IMAGE;
-    case OperandFPFastMath:
-      return SPV_OPERAND_TYPE_FP_FAST_MATH_MODE;
-    case OperandFPRoundingMode:
-      return SPV_OPERAND_TYPE_FP_ROUNDING_MODE;
-    case OperandLinkageType:
-      return SPV_OPERAND_TYPE_LINKAGE_TYPE;
-    case OperandAccessQualifier:
-      return SPV_OPERAND_TYPE_ACCESS_QUALIFIER;
-    case OperandOptionalAccessQualifier:
-      return SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER;
-    case OperandFuncParamAttr:
-      return SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE;
-    case OperandDecoration:
-      return SPV_OPERAND_TYPE_DECORATION;
-    case OperandBuiltIn:
-      return SPV_OPERAND_TYPE_BUILT_IN;
-    case OperandSelect:
-      return SPV_OPERAND_TYPE_SELECTION_CONTROL;
-    case OperandLoop:
-      return SPV_OPERAND_TYPE_LOOP_CONTROL;
-    case OperandFunction:
-      return SPV_OPERAND_TYPE_FUNCTION_CONTROL;
-    case OperandMemorySemantics:
-      return SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID;
-    case OperandMemoryAccess:
-      // This case does not occur in the table for SPIR-V 0.99 Rev 32.
-      // We expect that it will become SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
-      // and we can remove the special casing above for memory operation
-      // instructions.
-      break;
-    case OperandOptionalMemoryAccess:
-      // Expect an optional mask.  When the Aligned bit is set in the mask,
-      // we will later add the expectation of a literal number operand.
-      return SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS;
-    case OperandScope:
-      return SPV_OPERAND_TYPE_SCOPE_ID;
-    case OperandGroupOperation:
-      return SPV_OPERAND_TYPE_GROUP_OPERATION;
-    case OperandKernelEnqueueFlags:
-      return SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS;
-    case OperandKernelProfilingInfo:
-      return SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO;
-    case OperandCapability:
-      return SPV_OPERAND_TYPE_CAPABILITY;
-
-    // Used by GroupMemberDecorate
-    case OperandVariableIdLiteral:
-      return SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER;
-
-    // Used by Switch
-    case OperandVariableLiteralId:
-      return SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID;
-
-    // These exceptional cases shouldn't occur.
-    case OperandCount:
-    default:
-      break;
-  }
-  assert(0 && "Unexpected operand class");
-  return SPV_OPERAND_TYPE_NONE;
-}
-
 }  // anonymous namespace
 
-// Finish populating the opcodeTableEntries array.
-void spvOpcodeTableInitialize(spv_opcode_desc_t* entries,
-                              uint32_t num_entries) {
-  // Compute the operandTypes field for each entry.
-  for (uint32_t i = 0; i < num_entries; ++i) {
-    spv_opcode_desc_t& opcode = entries[i];
-    opcode.numTypes = 0;
-    // Type ID always comes first, if present.
-    if (opcode.hasType)
-      opcode.operandTypes[opcode.numTypes++] = SPV_OPERAND_TYPE_TYPE_ID;
-    // Result ID always comes next, if present
-    if (opcode.hasResult)
-      opcode.operandTypes[opcode.numTypes++] = SPV_OPERAND_TYPE_RESULT_ID;
-    const uint16_t maxNumOperands = static_cast<uint16_t>(
-        sizeof(opcode.operandTypes) / sizeof(opcode.operandTypes[0]));
-    const uint16_t maxNumClasses = static_cast<uint16_t>(
-        sizeof(opcode.operandClass) / sizeof(opcode.operandClass[0]));
-    for (uint16_t classIndex = 0;
-         opcode.numTypes < maxNumOperands && classIndex < maxNumClasses;
-         classIndex++) {
-      const OperandClass operandClass = opcode.operandClass[classIndex];
-      const auto operandType =
-          convertOperandClassToType(opcode.opcode, operandClass);
-      opcode.operandTypes[opcode.numTypes++] = operandType;
-      // The OperandNone value is not explicitly represented in the .inc file.
-      // However, it is the zero value, and is created via implicit value
-      // initialization.  It converts to SPV_OPERAND_TYPE_NONE.
-      // The SPV_OPERAND_TYPE_NONE operand type indicates no current or futher
-      // operands.
-      if (operandType == SPV_OPERAND_TYPE_NONE) {
-        opcode.numTypes--;
-        break;
-      }
-    }
-
-    // We should have written the terminating SPV_OPERAND_TYPE_NONE entry, but
-    // also without overflowing.
-    assert((opcode.numTypes < maxNumOperands) &&
-           "Operand class list is too long.  Expand "
-           "spv_opcode_desc_t.operandClass");
-  }
-}
-
 const char* spvGeneratorStr(uint32_t generator) {
   switch (generator) {
     case SPV_GENERATOR_KHRONOS:
@@ -318,31 +82,29 @@
   return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
 }
 
-void spvOpcodeSplit(const uint32_t word, uint16_t* pWordCount, SpvOp* pOpcode) {
+void spvOpcodeSplit(const uint32_t word, uint16_t* pWordCount,
+                    uint16_t* pOpcode) {
   if (pWordCount) {
     *pWordCount = (uint16_t)((0xffff0000 & word) >> 16);
   }
   if (pOpcode) {
-    *pOpcode = (SpvOp)(0x0000ffff & word);
+    *pOpcode = 0x0000ffff & word;
   }
 }
 
+// Evaluates to the number of elements of array A.
+// If we could use constexpr, then we could make this a template function.
+// If the source arrays were std::array, then we could have used
+// std::array::size.
+#define ARRAY_SIZE(A) (static_cast<uint32_t>(sizeof(A) / sizeof(A[0])))
+
 spv_result_t spvOpcodeTableGet(spv_opcode_table* pInstTable) {
   if (!pInstTable) return SPV_ERROR_INVALID_POINTER;
 
-  const uint32_t size = sizeof(opcodeTableEntries);
-  spv_opcode_desc_t* copied_entries =
-      static_cast<spv_opcode_desc_t*>(::malloc(size));
-  if (!copied_entries) return SPV_ERROR_OUT_OF_MEMORY;
-  ::memcpy(copied_entries, opcodeTableEntries, size);
+  static const spv_opcode_table_t table = {ARRAY_SIZE(opcodeTableEntries),
+                                           opcodeTableEntries};
 
-  const uint32_t count = static_cast<uint32_t>(sizeof(opcodeTableEntries) /
-                                               sizeof(spv_opcode_desc_t));
-  spv_opcode_table_t* table = new spv_opcode_table_t{count, copied_entries};
-
-  spvOpcodeTableInitialize(copied_entries, count);
-
-  *pInstTable = table;
+  *pInstTable = &table;
 
   return SPV_SUCCESS;
 }
@@ -401,26 +163,22 @@
     pInst->words[wordIndex] = spvFixWord(words[wordIndex], endian);
     if (!wordIndex) {
       uint16_t thisWordCount;
-      SpvOp thisOpcode;
+      uint16_t thisOpcode;
       spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
-      assert(opcode == thisOpcode && wordCount == thisWordCount &&
-             "Endianness failed!");
+      assert(opcode == static_cast<SpvOp>(thisOpcode) &&
+             wordCount == thisWordCount && "Endianness failed!");
     }
   }
 }
 
 const char* spvOpcodeString(const SpvOp opcode) {
-// Use the syntax table so it's sure to be complete.
-#define Instruction(Name, ...) \
-  case SpvOp##Name:            \
-    return #Name;
-  switch (opcode) {
-#include "opcode.inc"
-    default:
-      assert(0 && "Unreachable!");
+  for (uint32_t i = 0;
+       i < sizeof(opcodeTableEntries) / sizeof(spv_opcode_desc_t); ++i) {
+    if (opcodeTableEntries[i].opcode == opcode)
+      return opcodeTableEntries[i].name;
   }
+  assert(0 && "Unreachable!");
   return "unknown";
-#undef Instruction
 }
 
 int32_t spvOpcodeIsScalarType(const SpvOp opcode) {
@@ -441,13 +199,12 @@
     case SpvOpConstant:
     case SpvOpConstantComposite:
     case SpvOpConstantSampler:
-    // case SpvOpConstantNull:
     case SpvOpConstantNull:
     case SpvOpSpecConstantTrue:
     case SpvOpSpecConstantFalse:
     case SpvOpSpecConstant:
     case SpvOpSpecConstantComposite:
-      // case SpvOpSpecConstantOp:
+    case SpvOpSpecConstantOp:
       return true;
     default:
       return false;
diff --git a/source/opcode.h b/source/opcode.h
index 786c1f4..737af8c 100644
--- a/source/opcode.h
+++ b/source/opcode.h
@@ -29,6 +29,7 @@
 
 #include "instruction.h"
 #include "spirv-tools/libspirv.h"
+#include "spirv/spirv.h"
 #include "table.h"
 
 // Returns the name of a registered SPIR-V generator as a null-terminated
@@ -43,7 +44,8 @@
 uint32_t spvOpcodeMake(uint16_t word_count, SpvOp opcode);
 
 // Splits word into into two constituent parts: word_count and opcode.
-void spvOpcodeSplit(const uint32_t word, uint16_t* word_count, SpvOp* opcode);
+void spvOpcodeSplit(const uint32_t word, uint16_t* word_count,
+                    uint16_t* opcode);
 
 // Finds the named opcode in the given opcode table. On success, returns
 // SPV_SUCCESS and writes a handle of the table entry into *entry.
diff --git a/source/opcode.inc b/source/opcode.inc
deleted file mode 100644
index 6199e18..0000000
--- a/source/opcode.inc
+++ /dev/null
@@ -1,310 +0,0 @@
-// Instruction fields are:
-//    name - skips the "Op" prefix
-//    {0|1} - whether the instruction generates a result Id
-//    {0|1} - whether the instruction encodes the type of the result Id
-//    numLogicalOperands - does not include result id or type id
-//    numCapabilities - we only handle 0 or 1 required capabilities
-//    Capability(<capability-name>) - capability required to use this instruction. Might be None.
-//       There can be Capability2(a,b) for dependence on two capabilities.
-//    {0|1} - whether the instruction is variable number of logical operands
-//    EmptyList or List(...) - list of classes of logical operands
-// Example use:
-// #define EmptyList {}
-// #define List(...) {__VA_ARGS__}
-// #define Capability(C) Capability##C
-// #define CapabilityNone -1
-// #define Instruction(Name,HasResult,HasType,NumLogicalOperands,CapabiltyRequired,IsVariable,LogicalArgsList)
-Instruction(Nop, 0, 0, 0, 0, Capability(None), 0, EmptyList)
-Instruction(Undef, 1, 1, 0, 0, Capability(None), 0, EmptyList)
-Instruction(SourceContinued, 0, 0, 1, 0, Capability(None), 1, List(OperandLiteralString))
-Instruction(Source, 0, 0, 4, 0, Capability(None), 1, List(OperandSource, OperandLiteralNumber, OperandOptionalId, OperandOptionalLiteralString))
-Instruction(SourceExtension, 0, 0, 1, 0, Capability(None), 1, List(OperandLiteralString))
-Instruction(Name, 0, 0, 2, 0, Capability(None), 1, List(OperandId, OperandLiteralString))
-Instruction(MemberName, 0, 0, 3, 0, Capability(None), 1, List(OperandId, OperandLiteralNumber, OperandLiteralString))
-Instruction(String, 1, 0, 1, 0, Capability(None), 1, List(OperandLiteralString))
-Instruction(Line, 0, 0, 3, 0, Capability(None), 0, List(OperandId, OperandLiteralNumber, OperandLiteralNumber))
-Instruction(Extension, 0, 0, 1, 0, Capability(None), 1, List(OperandLiteralString))
-Instruction(ExtInstImport, 1, 0, 1, 0, Capability(None), 1, List(OperandLiteralString))
-Instruction(ExtInst, 1, 1, 3, 0, Capability(None), 1, List(OperandId, OperandLiteralNumber, OperandVariableIds))
-Instruction(MemoryModel, 0, 0, 2, 0, Capability(None), 0, List(OperandAddressing, OperandMemory))
-Instruction(EntryPoint, 0, 0, 4, 0, Capability(None), 1, List(OperandExecutionModel, OperandId, OperandLiteralString, OperandVariableIds))
-Instruction(ExecutionMode, 0, 0, 3, 0, Capability(None), 1, List(OperandId, OperandExecutionMode, OperandOptionalLiteral))
-Instruction(Capability, 0, 0, 1, 0, Capability(None), 0, List(OperandCapability))
-Instruction(TypeVoid, 1, 0, 0, 0, Capability(None), 0, EmptyList)
-Instruction(TypeBool, 1, 0, 0, 0, Capability(None), 0, EmptyList)
-Instruction(TypeInt, 1, 0, 2, 0, Capability(None), 0, List(OperandLiteralNumber, OperandLiteralNumber))
-Instruction(TypeFloat, 1, 0, 1, 0, Capability(None), 0, List(OperandLiteralNumber))
-Instruction(TypeVector, 1, 0, 2, 0, Capability(None), 0, List(OperandId, OperandLiteralNumber))
-Instruction(TypeMatrix, 1, 0, 2, 1, Capability(Matrix), 0, List(OperandId, OperandLiteralNumber))
-Instruction(TypeImage, 1, 0, 8, 0, Capability(None), 1, List(OperandId, OperandDimensionality, OperandLiteralNumber, OperandLiteralNumber, OperandLiteralNumber, OperandLiteralNumber, OperandSamplerImageFormat, OperandOptionalAccessQualifier))
-Instruction(TypeSampler, 1, 0, 0, 0, Capability(None), 0, EmptyList)
-Instruction(TypeSampledImage, 1, 0, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(TypeArray, 1, 0, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(TypeRuntimeArray, 1, 0, 1, 1, Capability(Shader), 0, List(OperandId))
-Instruction(TypeStruct, 1, 0, 1, 0, Capability(None), 1, List(OperandVariableIds))
-Instruction(TypeOpaque, 1, 0, 1, 1, Capability(Kernel), 1, List(OperandLiteralString))
-Instruction(TypePointer, 1, 0, 2, 0, Capability(None), 0, List(OperandStorage, OperandId))
-Instruction(TypeFunction, 1, 0, 2, 0, Capability(None), 1, List(OperandId, OperandVariableIds))
-Instruction(TypeEvent, 1, 0, 0, 1, Capability(Kernel), 0, EmptyList)
-Instruction(TypeDeviceEvent, 1, 0, 0, 1, Capability(DeviceEnqueue), 0, EmptyList)
-Instruction(TypeReserveId, 1, 0, 0, 1, Capability(Pipes), 0, EmptyList)
-Instruction(TypeQueue, 1, 0, 0, 1, Capability(DeviceEnqueue), 0, EmptyList)
-Instruction(TypePipe, 1, 0, 1, 1, Capability(Pipes), 0, List(OperandAccessQualifier))
-Instruction(TypeForwardPointer, 0, 0, 2, 1, Capability(Addresses), 0, List(OperandId, OperandStorage))
-Instruction(ConstantTrue, 1, 1, 0, 0, Capability(None), 0, EmptyList)
-Instruction(ConstantFalse, 1, 1, 0, 0, Capability(None), 0, EmptyList)
-Instruction(Constant, 1, 1, 1, 0, Capability(None), 1, List(OperandVariableLiterals))
-Instruction(ConstantComposite, 1, 1, 1, 0, Capability(None), 1, List(OperandVariableIds))
-Instruction(ConstantSampler, 1, 1, 3, 1, Capability(LiteralSampler), 0, List(OperandSamplerAddressingMode, OperandLiteralNumber, OperandSamplerFilterMode))
-Instruction(ConstantNull, 1, 1, 0, 0, Capability(None), 0, EmptyList)
-Instruction(SpecConstantTrue, 1, 1, 0, 0, Capability(None), 0, EmptyList)
-Instruction(SpecConstantFalse, 1, 1, 0, 0, Capability(None), 0, EmptyList)
-Instruction(SpecConstant, 1, 1, 1, 0, Capability(None), 1, List(OperandVariableLiterals))
-Instruction(SpecConstantComposite, 1, 1, 1, 0, Capability(None), 1, List(OperandVariableIds))
-Instruction(SpecConstantOp, 1, 1, 2, 0, Capability(None), 1, List(OperandLiteralNumber, OperandVariableIds))
-Instruction(Function, 1, 1, 2, 0, Capability(None), 0, List(OperandFunction, OperandId))
-Instruction(FunctionParameter, 1, 1, 0, 0, Capability(None), 0, EmptyList)
-Instruction(FunctionEnd, 0, 0, 0, 0, Capability(None), 0, EmptyList)
-Instruction(FunctionCall, 1, 1, 2, 0, Capability(None), 1, List(OperandId, OperandVariableIds))
-Instruction(Variable, 1, 1, 2, 0, Capability(None), 1, List(OperandStorage, OperandOptionalId))
-Instruction(ImageTexelPointer, 1, 1, 3, 0, Capability(None), 0, List(OperandId, OperandId, OperandId))
-Instruction(Load, 1, 1, 2, 0, Capability(None), 1, List(OperandId, OperandOptionalMemoryAccess))
-Instruction(Store, 0, 0, 3, 0, Capability(None), 1, List(OperandId, OperandId, OperandOptionalMemoryAccess))
-Instruction(CopyMemory, 0, 0, 3, 0, Capability(None), 1, List(OperandId, OperandId, OperandOptionalMemoryAccess))
-Instruction(CopyMemorySized, 0, 0, 4, 1, Capability(Addresses), 1, List(OperandId, OperandId, OperandId, OperandOptionalMemoryAccess))
-Instruction(AccessChain, 1, 1, 2, 0, Capability(None), 1, List(OperandId, OperandVariableIds))
-Instruction(InBoundsAccessChain, 1, 1, 2, 0, Capability(None), 1, List(OperandId, OperandVariableIds))
-Instruction(PtrAccessChain, 1, 1, 3, 1, Capability(Addresses), 1, List(OperandId, OperandId, OperandVariableIds))
-Instruction(ArrayLength, 1, 1, 2, 1, Capability(Shader), 0, List(OperandId, OperandLiteralNumber))
-Instruction(GenericPtrMemSemantics, 1, 1, 1, 1, Capability(Kernel), 0, List(OperandId))
-Instruction(InBoundsPtrAccessChain, 1, 1, 3, 1, Capability(Addresses), 1, List(OperandId, OperandId, OperandVariableIds))
-Instruction(Decorate, 0, 0, 3, 0, Capability(None), 1, List(OperandId, OperandDecoration, OperandVariableLiterals))
-Instruction(MemberDecorate, 0, 0, 4, 0, Capability(None), 1, List(OperandId, OperandLiteralNumber, OperandDecoration, OperandVariableLiterals))
-Instruction(DecorationGroup, 1, 0, 0, 0, Capability(None), 0, EmptyList)
-Instruction(GroupDecorate, 0, 0, 2, 0, Capability(None), 1, List(OperandId, OperandVariableIds))
-Instruction(GroupMemberDecorate, 0, 0, 2, 0, Capability(None), 1, List(OperandId, OperandVariableIdLiteral))
-Instruction(VectorExtractDynamic, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(VectorInsertDynamic, 1, 1, 3, 0, Capability(None), 0, List(OperandId, OperandId, OperandId))
-Instruction(VectorShuffle, 1, 1, 3, 0, Capability(None), 1, List(OperandId, OperandId, OperandVariableLiterals))
-Instruction(CompositeConstruct, 1, 1, 1, 0, Capability(None), 1, List(OperandVariableIds))
-Instruction(CompositeExtract, 1, 1, 2, 0, Capability(None), 1, List(OperandId, OperandVariableLiterals))
-Instruction(CompositeInsert, 1, 1, 3, 0, Capability(None), 1, List(OperandId, OperandId, OperandVariableLiterals))
-Instruction(CopyObject, 1, 1, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(Transpose, 1, 1, 1, 1, Capability(Matrix), 0, List(OperandId))
-Instruction(SampledImage, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(ImageSampleImplicitLod, 1, 1, 4, 1, Capability(Shader), 1, List(OperandId, OperandId, OperandOptionalImageOperands))
-Instruction(ImageSampleExplicitLod, 1, 1, 5, 0, Capability(None), 1, List(OperandId, OperandId, OperandImageOperands))
-Instruction(ImageSampleDrefImplicitLod, 1, 1, 5, 1, Capability(Shader), 1, List(OperandId, OperandId, OperandId, OperandOptionalImageOperands))
-Instruction(ImageSampleDrefExplicitLod, 1, 1, 6, 1, Capability(Shader), 1, List(OperandId, OperandId, OperandId, OperandImageOperands))
-Instruction(ImageSampleProjImplicitLod, 1, 1, 4, 1, Capability(Shader), 1, List(OperandId, OperandId, OperandOptionalImageOperands))
-Instruction(ImageSampleProjExplicitLod, 1, 1, 5, 1, Capability(Shader), 1, List(OperandId, OperandId, OperandImageOperands))
-Instruction(ImageSampleProjDrefImplicitLod, 1, 1, 5, 1, Capability(Shader), 1, List(OperandId, OperandId, OperandId, OperandOptionalImageOperands))
-Instruction(ImageSampleProjDrefExplicitLod, 1, 1, 6, 1, Capability(Shader), 1, List(OperandId, OperandId, OperandId, OperandImageOperands))
-Instruction(ImageFetch, 1, 1, 4, 0, Capability(None), 1, List(OperandId, OperandId, OperandOptionalImageOperands))
-Instruction(ImageGather, 1, 1, 5, 1, Capability(Shader), 1, List(OperandId, OperandId, OperandId, OperandOptionalImageOperands))
-Instruction(ImageDrefGather, 1, 1, 5, 1, Capability(Shader), 1, List(OperandId, OperandId, OperandId, OperandOptionalImageOperands))
-Instruction(ImageRead, 1, 1, 4, 0, Capability(None), 1, List(OperandId, OperandId, OperandOptionalImageOperands))
-Instruction(ImageWrite, 0, 0, 5, 0, Capability(None), 1, List(OperandId, OperandId, OperandId, OperandOptionalImageOperands))
-Instruction(Image, 1, 1, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(ImageQueryFormat, 1, 1, 1, 1, Capability(Kernel), 0, List(OperandId))
-Instruction(ImageQueryOrder, 1, 1, 1, 1, Capability(Kernel), 0, List(OperandId))
-Instruction(ImageQuerySizeLod, 1, 1, 2, 2, Capability2(Kernel,ImageQuery), 0, List(OperandId, OperandId))
-Instruction(ImageQuerySize, 1, 1, 1, 2, Capability2(Kernel,ImageQuery), 0, List(OperandId))
-Instruction(ImageQueryLod, 1, 1, 2, 1, Capability(ImageQuery), 0, List(OperandId, OperandId))
-Instruction(ImageQueryLevels, 1, 1, 1, 2, Capability2(Kernel,ImageQuery), 0, List(OperandId))
-Instruction(ImageQuerySamples, 1, 1, 1, 2, Capability2(Kernel,ImageQuery), 0, List(OperandId))
-Instruction(ConvertFToU, 1, 1, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(ConvertFToS, 1, 1, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(ConvertSToF, 1, 1, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(ConvertUToF, 1, 1, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(UConvert, 1, 1, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(SConvert, 1, 1, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(FConvert, 1, 1, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(QuantizeToF16, 1, 1, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(ConvertPtrToU, 1, 1, 1, 1, Capability(Addresses), 0, List(OperandId))
-Instruction(SatConvertSToU, 1, 1, 1, 1, Capability(Kernel), 0, List(OperandId))
-Instruction(SatConvertUToS, 1, 1, 1, 1, Capability(Kernel), 0, List(OperandId))
-Instruction(ConvertUToPtr, 1, 1, 1, 1, Capability(Addresses), 0, List(OperandId))
-Instruction(PtrCastToGeneric, 1, 1, 1, 1, Capability(Kernel), 0, List(OperandId))
-Instruction(GenericCastToPtr, 1, 1, 1, 1, Capability(Kernel), 0, List(OperandId))
-Instruction(GenericCastToPtrExplicit, 1, 1, 2, 1, Capability(Kernel), 0, List(OperandId, OperandStorage))
-Instruction(Bitcast, 1, 1, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(SNegate, 1, 1, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(FNegate, 1, 1, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(IAdd, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(FAdd, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(ISub, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(FSub, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(IMul, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(FMul, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(UDiv, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(SDiv, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(FDiv, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(UMod, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(SRem, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(SMod, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(FRem, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(FMod, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(VectorTimesScalar, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(MatrixTimesScalar, 1, 1, 2, 1, Capability(Matrix), 0, List(OperandId, OperandId))
-Instruction(VectorTimesMatrix, 1, 1, 2, 1, Capability(Matrix), 0, List(OperandId, OperandId))
-Instruction(MatrixTimesVector, 1, 1, 2, 1, Capability(Matrix), 0, List(OperandId, OperandId))
-Instruction(MatrixTimesMatrix, 1, 1, 2, 1, Capability(Matrix), 0, List(OperandId, OperandId))
-Instruction(OuterProduct, 1, 1, 2, 1, Capability(Matrix), 0, List(OperandId, OperandId))
-Instruction(Dot, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(IAddCarry, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(ISubBorrow, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(UMulExtended, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(SMulExtended, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(Any, 1, 1, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(All, 1, 1, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(IsNan, 1, 1, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(IsInf, 1, 1, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(IsFinite, 1, 1, 1, 1, Capability(Kernel), 0, List(OperandId))
-Instruction(IsNormal, 1, 1, 1, 1, Capability(Kernel), 0, List(OperandId))
-Instruction(SignBitSet, 1, 1, 1, 1, Capability(Kernel), 0, List(OperandId))
-Instruction(LessOrGreater, 1, 1, 2, 1, Capability(Kernel), 0, List(OperandId, OperandId))
-Instruction(Ordered, 1, 1, 2, 1, Capability(Kernel), 0, List(OperandId, OperandId))
-Instruction(Unordered, 1, 1, 2, 1, Capability(Kernel), 0, List(OperandId, OperandId))
-Instruction(LogicalEqual, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(LogicalNotEqual, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(LogicalOr, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(LogicalAnd, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(LogicalNot, 1, 1, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(Select, 1, 1, 3, 0, Capability(None), 0, List(OperandId, OperandId, OperandId))
-Instruction(IEqual, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(INotEqual, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(UGreaterThan, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(SGreaterThan, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(UGreaterThanEqual, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(SGreaterThanEqual, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(ULessThan, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(SLessThan, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(ULessThanEqual, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(SLessThanEqual, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(FOrdEqual, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(FUnordEqual, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(FOrdNotEqual, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(FUnordNotEqual, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(FOrdLessThan, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(FUnordLessThan, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(FOrdGreaterThan, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(FUnordGreaterThan, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(FOrdLessThanEqual, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(FUnordLessThanEqual, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(FOrdGreaterThanEqual, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(FUnordGreaterThanEqual, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(ShiftRightLogical, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(ShiftRightArithmetic, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(ShiftLeftLogical, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(BitwiseOr, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(BitwiseXor, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(BitwiseAnd, 1, 1, 2, 0, Capability(None), 0, List(OperandId, OperandId))
-Instruction(Not, 1, 1, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(BitFieldInsert, 1, 1, 4, 1, Capability(Shader), 0, List(OperandId, OperandId, OperandId, OperandId))
-Instruction(BitFieldSExtract, 1, 1, 3, 1, Capability(Shader), 0, List(OperandId, OperandId, OperandId))
-Instruction(BitFieldUExtract, 1, 1, 3, 1, Capability(Shader), 0, List(OperandId, OperandId, OperandId))
-Instruction(BitReverse, 1, 1, 1, 1, Capability(Shader), 0, List(OperandId))
-Instruction(BitCount, 1, 1, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(DPdx, 1, 1, 1, 1, Capability(Shader), 0, List(OperandId))
-Instruction(DPdy, 1, 1, 1, 1, Capability(Shader), 0, List(OperandId))
-Instruction(Fwidth, 1, 1, 1, 1, Capability(Shader), 0, List(OperandId))
-Instruction(DPdxFine, 1, 1, 1, 1, Capability(DerivativeControl), 0, List(OperandId))
-Instruction(DPdyFine, 1, 1, 1, 1, Capability(DerivativeControl), 0, List(OperandId))
-Instruction(FwidthFine, 1, 1, 1, 1, Capability(DerivativeControl), 0, List(OperandId))
-Instruction(DPdxCoarse, 1, 1, 1, 1, Capability(DerivativeControl), 0, List(OperandId))
-Instruction(DPdyCoarse, 1, 1, 1, 1, Capability(DerivativeControl), 0, List(OperandId))
-Instruction(FwidthCoarse, 1, 1, 1, 1, Capability(DerivativeControl), 0, List(OperandId))
-Instruction(EmitVertex, 0, 0, 0, 1, Capability(Geometry), 0, EmptyList)
-Instruction(EndPrimitive, 0, 0, 0, 1, Capability(Geometry), 0, EmptyList)
-Instruction(EmitStreamVertex, 0, 0, 1, 1, Capability(GeometryStreams), 0, List(OperandId))
-Instruction(EndStreamPrimitive, 0, 0, 1, 1, Capability(GeometryStreams), 0, List(OperandId))
-Instruction(ControlBarrier, 0, 0, 3, 0, Capability(None), 0, List(OperandScope, OperandScope, OperandMemorySemantics))
-Instruction(MemoryBarrier, 0, 0, 2, 0, Capability(None), 0, List(OperandScope, OperandMemorySemantics))
-Instruction(AtomicLoad, 1, 1, 3, 0, Capability(None), 0, List(OperandId, OperandScope, OperandMemorySemantics))
-Instruction(AtomicStore, 0, 0, 4, 0, Capability(None), 0, List(OperandId, OperandScope, OperandMemorySemantics, OperandId))
-Instruction(AtomicExchange, 1, 1, 4, 0, Capability(None), 0, List(OperandId, OperandScope, OperandMemorySemantics, OperandId))
-Instruction(AtomicCompareExchange, 1, 1, 6, 0, Capability(None), 0, List(OperandId, OperandScope, OperandMemorySemantics, OperandMemorySemantics, OperandId, OperandId))
-Instruction(AtomicCompareExchangeWeak, 1, 1, 6, 1, Capability(Kernel), 0, List(OperandId, OperandScope, OperandMemorySemantics, OperandMemorySemantics, OperandId, OperandId))
-Instruction(AtomicIIncrement, 1, 1, 3, 0, Capability(None), 0, List(OperandId, OperandScope, OperandMemorySemantics))
-Instruction(AtomicIDecrement, 1, 1, 3, 0, Capability(None), 0, List(OperandId, OperandScope, OperandMemorySemantics))
-Instruction(AtomicIAdd, 1, 1, 4, 0, Capability(None), 0, List(OperandId, OperandScope, OperandMemorySemantics, OperandId))
-Instruction(AtomicISub, 1, 1, 4, 0, Capability(None), 0, List(OperandId, OperandScope, OperandMemorySemantics, OperandId))
-Instruction(AtomicSMin, 1, 1, 4, 0, Capability(None), 0, List(OperandId, OperandScope, OperandMemorySemantics, OperandId))
-Instruction(AtomicUMin, 1, 1, 4, 0, Capability(None), 0, List(OperandId, OperandScope, OperandMemorySemantics, OperandId))
-Instruction(AtomicSMax, 1, 1, 4, 0, Capability(None), 0, List(OperandId, OperandScope, OperandMemorySemantics, OperandId))
-Instruction(AtomicUMax, 1, 1, 4, 0, Capability(None), 0, List(OperandId, OperandScope, OperandMemorySemantics, OperandId))
-Instruction(AtomicAnd, 1, 1, 4, 0, Capability(None), 0, List(OperandId, OperandScope, OperandMemorySemantics, OperandId))
-Instruction(AtomicOr, 1, 1, 4, 0, Capability(None), 0, List(OperandId, OperandScope, OperandMemorySemantics, OperandId))
-Instruction(AtomicXor, 1, 1, 4, 0, Capability(None), 0, List(OperandId, OperandScope, OperandMemorySemantics, OperandId))
-Instruction(Phi, 1, 1, 1, 0, Capability(None), 1, List(OperandVariableIds))
-Instruction(LoopMerge, 0, 0, 3, 0, Capability(None), 0, List(OperandId, OperandId, OperandLoop))
-Instruction(SelectionMerge, 0, 0, 2, 0, Capability(None), 0, List(OperandId, OperandSelect))
-Instruction(Label, 1, 0, 0, 0, Capability(None), 0, EmptyList)
-Instruction(Branch, 0, 0, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(BranchConditional, 0, 0, 4, 0, Capability(None), 1, List(OperandId, OperandId, OperandId, OperandVariableLiterals))
-Instruction(Switch, 0, 0, 3, 0, Capability(None), 1, List(OperandId, OperandId, OperandVariableLiteralId))
-Instruction(Kill, 0, 0, 0, 1, Capability(Shader), 0, EmptyList)
-Instruction(Return, 0, 0, 0, 0, Capability(None), 0, EmptyList)
-Instruction(ReturnValue, 0, 0, 1, 0, Capability(None), 0, List(OperandId))
-Instruction(Unreachable, 0, 0, 0, 0, Capability(None), 0, EmptyList)
-Instruction(LifetimeStart, 0, 0, 2, 1, Capability(Kernel), 0, List(OperandId, OperandLiteralNumber))
-Instruction(LifetimeStop, 0, 0, 2, 1, Capability(Kernel), 0, List(OperandId, OperandLiteralNumber))
-Instruction(GroupAsyncCopy, 1, 1, 6, 1, Capability(Kernel), 0, List(OperandScope, OperandId, OperandId, OperandId, OperandId, OperandId))
-Instruction(GroupWaitEvents, 0, 0, 3, 1, Capability(Kernel), 0, List(OperandScope, OperandId, OperandId))
-Instruction(GroupAll, 1, 1, 2, 1, Capability(Groups), 0, List(OperandScope, OperandId))
-Instruction(GroupAny, 1, 1, 2, 1, Capability(Groups), 0, List(OperandScope, OperandId))
-Instruction(GroupBroadcast, 1, 1, 3, 1, Capability(Groups), 0, List(OperandScope, OperandId, OperandId))
-Instruction(GroupIAdd, 1, 1, 3, 1, Capability(Groups), 0, List(OperandScope, OperandGroupOperation, OperandId))
-Instruction(GroupFAdd, 1, 1, 3, 1, Capability(Groups), 0, List(OperandScope, OperandGroupOperation, OperandId))
-Instruction(GroupFMin, 1, 1, 3, 1, Capability(Groups), 0, List(OperandScope, OperandGroupOperation, OperandId))
-Instruction(GroupUMin, 1, 1, 3, 1, Capability(Groups), 0, List(OperandScope, OperandGroupOperation, OperandId))
-Instruction(GroupSMin, 1, 1, 3, 1, Capability(Groups), 0, List(OperandScope, OperandGroupOperation, OperandId))
-Instruction(GroupFMax, 1, 1, 3, 1, Capability(Groups), 0, List(OperandScope, OperandGroupOperation, OperandId))
-Instruction(GroupUMax, 1, 1, 3, 1, Capability(Groups), 0, List(OperandScope, OperandGroupOperation, OperandId))
-Instruction(GroupSMax, 1, 1, 3, 1, Capability(Groups), 0, List(OperandScope, OperandGroupOperation, OperandId))
-Instruction(ReadPipe, 1, 1, 4, 1, Capability(Pipes), 0, List(OperandId, OperandId, OperandId, OperandId))
-Instruction(WritePipe, 1, 1, 4, 1, Capability(Pipes), 0, List(OperandId, OperandId, OperandId, OperandId))
-Instruction(ReservedReadPipe, 1, 1, 6, 1, Capability(Pipes), 0, List(OperandId, OperandId, OperandId, OperandId, OperandId, OperandId))
-Instruction(ReservedWritePipe, 1, 1, 6, 1, Capability(Pipes), 0, List(OperandId, OperandId, OperandId, OperandId, OperandId, OperandId))
-Instruction(ReserveReadPipePackets, 1, 1, 4, 1, Capability(Pipes), 0, List(OperandId, OperandId, OperandId, OperandId))
-Instruction(ReserveWritePipePackets, 1, 1, 4, 1, Capability(Pipes), 0, List(OperandId, OperandId, OperandId, OperandId))
-Instruction(CommitReadPipe, 0, 0, 4, 1, Capability(Pipes), 0, List(OperandId, OperandId, OperandId, OperandId))
-Instruction(CommitWritePipe, 0, 0, 4, 1, Capability(Pipes), 0, List(OperandId, OperandId, OperandId, OperandId))
-Instruction(IsValidReserveId, 1, 1, 1, 1, Capability(Pipes), 0, List(OperandId))
-Instruction(GetNumPipePackets, 1, 1, 3, 1, Capability(Pipes), 0, List(OperandId, OperandId, OperandId))
-Instruction(GetMaxPipePackets, 1, 1, 3, 1, Capability(Pipes), 0, List(OperandId, OperandId, OperandId))
-Instruction(GroupReserveReadPipePackets, 1, 1, 5, 1, Capability(Pipes), 0, List(OperandScope, OperandId, OperandId, OperandId, OperandId))
-Instruction(GroupReserveWritePipePackets, 1, 1, 5, 1, Capability(Pipes), 0, List(OperandScope, OperandId, OperandId, OperandId, OperandId))
-Instruction(GroupCommitReadPipe, 0, 0, 5, 1, Capability(Pipes), 0, List(OperandScope, OperandId, OperandId, OperandId, OperandId))
-Instruction(GroupCommitWritePipe, 0, 0, 5, 1, Capability(Pipes), 0, List(OperandScope, OperandId, OperandId, OperandId, OperandId))
-Instruction(EnqueueMarker, 1, 1, 4, 1, Capability(DeviceEnqueue), 0, List(OperandId, OperandId, OperandId, OperandId))
-Instruction(EnqueueKernel, 1, 1, 11, 1, Capability(DeviceEnqueue), 1, List(OperandId, OperandId, OperandId, OperandId, OperandId, OperandId, OperandId, OperandId, OperandId, OperandId, OperandVariableIds))
-Instruction(GetKernelNDrangeSubGroupCount, 1, 1, 5, 1, Capability(DeviceEnqueue), 0, List(OperandId, OperandId, OperandId, OperandId, OperandId))
-Instruction(GetKernelNDrangeMaxSubGroupSize, 1, 1, 5, 1, Capability(DeviceEnqueue), 0, List(OperandId, OperandId, OperandId, OperandId, OperandId))
-Instruction(GetKernelWorkGroupSize, 1, 1, 4, 1, Capability(DeviceEnqueue), 0, List(OperandId, OperandId, OperandId, OperandId))
-Instruction(GetKernelPreferredWorkGroupSizeMultiple, 1, 1, 4, 1, Capability(DeviceEnqueue), 0, List(OperandId, OperandId, OperandId, OperandId))
-Instruction(RetainEvent, 0, 0, 1, 1, Capability(DeviceEnqueue), 0, List(OperandId))
-Instruction(ReleaseEvent, 0, 0, 1, 1, Capability(DeviceEnqueue), 0, List(OperandId))
-Instruction(CreateUserEvent, 1, 1, 0, 1, Capability(DeviceEnqueue), 0, EmptyList)
-Instruction(IsValidEvent, 1, 1, 1, 1, Capability(DeviceEnqueue), 0, List(OperandId))
-Instruction(SetUserEventStatus, 0, 0, 2, 1, Capability(DeviceEnqueue), 0, List(OperandId, OperandId))
-Instruction(CaptureEventProfilingInfo, 0, 0, 3, 1, Capability(DeviceEnqueue), 0, List(OperandId, OperandId, OperandId))
-Instruction(GetDefaultQueue, 1, 1, 0, 1, Capability(DeviceEnqueue), 0, EmptyList)
-Instruction(BuildNDRange, 1, 1, 3, 1, Capability(DeviceEnqueue), 0, List(OperandId, OperandId, OperandId))
-Instruction(ImageSparseSampleImplicitLod, 1, 1, 4, 1, Capability(SparseResidency), 1, List(OperandId, OperandId, OperandOptionalImageOperands))
-Instruction(ImageSparseSampleExplicitLod, 1, 1, 5, 1, Capability(SparseResidency), 1, List(OperandId, OperandId, OperandImageOperands))
-Instruction(ImageSparseSampleDrefImplicitLod, 1, 1, 5, 1, Capability(SparseResidency), 1, List(OperandId, OperandId, OperandId, OperandOptionalImageOperands))
-Instruction(ImageSparseSampleDrefExplicitLod, 1, 1, 6, 1, Capability(SparseResidency), 1, List(OperandId, OperandId, OperandId, OperandImageOperands))
-Instruction(ImageSparseSampleProjImplicitLod, 1, 1, 4, 1, Capability(SparseResidency), 1, List(OperandId, OperandId, OperandOptionalImageOperands))
-Instruction(ImageSparseSampleProjExplicitLod, 1, 1, 5, 1, Capability(SparseResidency), 1, List(OperandId, OperandId, OperandImageOperands))
-Instruction(ImageSparseSampleProjDrefImplicitLod, 1, 1, 5, 1, Capability(SparseResidency), 1, List(OperandId, OperandId, OperandId, OperandOptionalImageOperands))
-Instruction(ImageSparseSampleProjDrefExplicitLod, 1, 1, 6, 1, Capability(SparseResidency), 1, List(OperandId, OperandId, OperandId, OperandImageOperands))
-Instruction(ImageSparseFetch, 1, 1, 4, 1, Capability(SparseResidency), 1, List(OperandId, OperandId, OperandOptionalImageOperands))
-Instruction(ImageSparseGather, 1, 1, 5, 1, Capability(SparseResidency), 1, List(OperandId, OperandId, OperandId, OperandOptionalImageOperands))
-Instruction(ImageSparseDrefGather, 1, 1, 5, 1, Capability(SparseResidency), 1, List(OperandId, OperandId, OperandId, OperandOptionalImageOperands))
-Instruction(ImageSparseTexelsResident, 1, 1, 1, 1, Capability(SparseResidency), 0, List(OperandId))
-Instruction(NoLine, 0, 0, 0, 0, Capability(None), 0, EmptyList)
-Instruction(AtomicFlagTestAndSet, 1, 1, 3, 1, Capability(Kernel), 0, List(OperandId, OperandScope, OperandMemorySemantics))
-Instruction(AtomicFlagClear, 0, 0, 3, 1, Capability(Kernel), 0, List(OperandId, OperandScope, OperandMemorySemantics))
-Instruction(ImageSparseRead, 1, 1, 4, 1, Capability(SparseResidency), 1, List(OperandId, OperandId, OperandOptionalImageOperands))
diff --git a/source/opencl_std_ext_inst.inc b/source/opencl_std_ext_inst.inc
deleted file mode 100644
index c9ad7a4..0000000
--- a/source/opencl_std_ext_inst.inc
+++ /dev/null
@@ -1,169 +0,0 @@
-
-// OpenCL extended instructions table, one instruction per line.
-// All instructions have a result type and a result ID.
-// Fields in this file are:
-//  - name
-//  - extended instruction index
-//  - EmptyList, or List of operand classes.
-ExtInst(acos, 0, List(OperandId))
-ExtInst(acosh, 1, List(OperandId))
-ExtInst(acospi, 2, List(OperandId))
-ExtInst(asin, 3, List(OperandId))
-ExtInst(asinh, 4, List(OperandId))
-ExtInst(asinpi, 5, List(OperandId))
-ExtInst(atan, 6, List(OperandId))
-ExtInst(atan2, 7, List(OperandId, OperandId))
-ExtInst(atanh, 8, List(OperandId))
-ExtInst(atanpi, 9, List(OperandId))
-ExtInst(atan2pi, 10, List(OperandId, OperandId))
-ExtInst(cbrt, 11, List(OperandId))
-ExtInst(ceil, 12, List(OperandId))
-ExtInst(copysign, 13, List(OperandId, OperandId))
-ExtInst(cos, 14, List(OperandId))
-ExtInst(cosh, 15, List(OperandId))
-ExtInst(cospi, 16, List(OperandId))
-ExtInst(erfc, 17, List(OperandId))
-ExtInst(erf, 18, List(OperandId))
-ExtInst(exp, 19, List(OperandId))
-ExtInst(exp2, 20, List(OperandId))
-ExtInst(exp10, 21, List(OperandId))
-ExtInst(expm1, 22, List(OperandId))
-ExtInst(fabs, 23, List(OperandId))
-ExtInst(fdim, 24, List(OperandId, OperandId))
-ExtInst(floor, 25, List(OperandId))
-ExtInst(fma, 26, List(OperandId, OperandId, OperandId))
-ExtInst(fmax, 27, List(OperandId, OperandId))
-ExtInst(fmin, 28, List(OperandId, OperandId))
-ExtInst(fmod, 29, List(OperandId, OperandId))
-ExtInst(fract, 30, List(OperandId, OperandId))
-ExtInst(frexp, 31, List(OperandId, OperandId))
-ExtInst(hypot, 32, List(OperandId, OperandId))
-ExtInst(ilogb, 33, List(OperandId))
-ExtInst(ldexp, 34, List(OperandId, OperandId))
-ExtInst(lgamma, 35, List(OperandId))
-ExtInst(lgamma_r, 36, List(OperandId, OperandId))
-ExtInst(log, 37, List(OperandId))
-ExtInst(log2, 38, List(OperandId))
-ExtInst(log10, 39, List(OperandId))
-ExtInst(log1p, 40, List(OperandId))
-ExtInst(logb, 41, List(OperandId))
-ExtInst(mad, 42, List(OperandId, OperandId, OperandId))
-ExtInst(maxmag, 43, List(OperandId, OperandId))
-ExtInst(minmag, 44, List(OperandId, OperandId))
-ExtInst(modf, 45, List(OperandId, OperandId))
-ExtInst(nan, 46, List(OperandId))
-ExtInst(nextafter, 47, List(OperandId, OperandId))
-ExtInst(pow, 48, List(OperandId, OperandId, OperandId))
-ExtInst(pown, 49, List(OperandId))
-ExtInst(powr, 50, List(OperandId, OperandId))
-ExtInst(remainder, 51, List(OperandId, OperandId))
-ExtInst(remquo, 52, List(OperandId, OperandId, OperandId))
-ExtInst(rint, 53, List(OperandId))
-ExtInst(rootn, 54, List(OperandId, OperandId))
-ExtInst(round, 55, List(OperandId))
-ExtInst(rsqrt, 56, List(OperandId))
-ExtInst(sin, 57, List(OperandId))
-ExtInst(sincos, 58, List(OperandId, OperandId))
-ExtInst(sinh, 59, List(OperandId))
-ExtInst(sinpi, 60, List(OperandId))
-ExtInst(sqrt, 61, List(OperandId))
-ExtInst(tan, 62, List(OperandId))
-ExtInst(tanh, 63, List(OperandId))
-ExtInst(tanpi, 64, List(OperandId))
-ExtInst(tgamma, 65, List(OperandId))
-ExtInst(trunc, 66, List(OperandId))
-ExtInst(half_cos, 67, List(OperandId))
-ExtInst(half_divide, 68, List(OperandId, OperandId))
-ExtInst(half_exp, 69, List(OperandId))
-ExtInst(half_exp2, 70, List(OperandId))
-ExtInst(half_exp10, 71, List(OperandId))
-ExtInst(half_log, 72, List(OperandId))
-ExtInst(half_log2, 73, List(OperandId))
-ExtInst(half_log10, 74, List(OperandId))
-ExtInst(half_powr, 75, List(OperandId, OperandId))
-ExtInst(half_recip, 76, List(OperandId))
-ExtInst(half_rsqrt, 77, List(OperandId))
-ExtInst(half_sin, 78, List(OperandId))
-ExtInst(half_sqrt, 79, List(OperandId))
-ExtInst(half_tan, 80, List(OperandId))
-ExtInst(native_cos, 81, List(OperandId))
-ExtInst(native_divide, 82, List(OperandId, OperandId))
-ExtInst(native_exp, 83, List(OperandId))
-ExtInst(native_exp2, 84, List(OperandId))
-ExtInst(native_exp10, 85, List(OperandId))
-ExtInst(native_log, 86, List(OperandId))
-ExtInst(native_log2, 87, List(OperandId))
-ExtInst(native_log10, 88, List(OperandId))
-ExtInst(native_powr, 89, List(OperandId, OperandId))
-ExtInst(native_recip, 90, List(OperandId))
-ExtInst(native_rsqrt, 91, List(OperandId))
-ExtInst(native_sin, 92, List(OperandId))
-ExtInst(native_sqrt, 93, List(OperandId))
-ExtInst(native_tan, 94, List(OperandId))
-ExtInst(fclamp, 95, List(OperandId, OperandId, OperandId))
-ExtInst(degrees, 96, List(OperandId))
-ExtInst(fmax_common, 97, List(OperandId, OperandId))
-ExtInst(fmin_common, 98, List(OperandId, OperandId))
-ExtInst(mix, 99, List(OperandId, OperandId, OperandId))
-ExtInst(radians, 100, List(OperandId))
-ExtInst(step, 101, List(OperandId, OperandId))
-ExtInst(smoothstep, 102, List(OperandId, OperandId, OperandId))
-ExtInst(sign, 103, List(OperandId))
-ExtInst(cross, 104, List(OperandId, OperandId))
-ExtInst(distance, 105, List(OperandId, OperandId))
-ExtInst(length, 106, List(OperandId))
-ExtInst(normalize, 107, List(OperandId))
-ExtInst(fast_distance, 108, List(OperandId, OperandId))
-ExtInst(fast_length, 109, List(OperandId))
-ExtInst(fast_normalize, 110, List(OperandId))
-ExtInst(s_abs, 141, List(OperandId))
-ExtInst(s_abs_diff, 142, List(OperandId, OperandId))
-ExtInst(s_add_sat, 143, List(OperandId, OperandId))
-ExtInst(u_add_sat, 144, List(OperandId, OperandId))
-ExtInst(s_hadd, 145, List(OperandId, OperandId))
-ExtInst(u_hadd, 146, List(OperandId, OperandId))
-ExtInst(s_rhadd, 147, List(OperandId, OperandId))
-ExtInst(u_rhadd, 148, List(OperandId, OperandId))
-ExtInst(s_clamp, 149, List(OperandId, OperandId, OperandId))
-ExtInst(u_clamp, 150, List(OperandId, OperandId, OperandId))
-ExtInst(clz, 151, List(OperandId))
-ExtInst(ctz, 152, List(OperandId))
-ExtInst(s_mad_hi, 153, List(OperandId, OperandId, OperandId))
-ExtInst(u_mad_sat, 154, List(OperandId, OperandId, OperandId))
-ExtInst(s_mad_sat, 155, List(OperandId, OperandId, OperandId))
-ExtInst(s_max, 156, List(OperandId, OperandId))
-ExtInst(u_max, 157, List(OperandId, OperandId))
-ExtInst(s_min, 158, List(OperandId, OperandId))
-ExtInst(u_min, 159, List(OperandId, OperandId))
-ExtInst(s_mul_hi, 160, List(OperandId, OperandId))
-ExtInst(rotate, 161, List(OperandId, OperandId))
-ExtInst(s_sub_sat, 162, List(OperandId, OperandId))
-ExtInst(u_sub_sat, 163, List(OperandId, OperandId))
-ExtInst(u_upsample, 164, List(OperandId, OperandId))
-ExtInst(s_upsample, 165, List(OperandId, OperandId))
-ExtInst(popcount, 166, List(OperandId))
-ExtInst(s_mad24, 167, List(OperandId, OperandId, OperandId))
-ExtInst(u_mad24, 168, List(OperandId, OperandId, OperandId))
-ExtInst(s_mul24, 169, List(OperandId, OperandId))
-ExtInst(u_mul24, 170, List(OperandId, OperandId))
-ExtInst(vloadn, 171, List(OperandId, OperandId, OperandLiteralNumber))
-ExtInst(vstoren, 172, List(OperandId, OperandId, OperandId))
-ExtInst(vload_half, 173, List(OperandId, OperandId))
-ExtInst(vload_halfn, 174, List(OperandId, OperandId, OperandLiteralNumber))
-ExtInst(vstore_half, 175, List(OperandId, OperandId, OperandId))
-ExtInst(vstore_half_r, 176, List(OperandId, OperandId, OperandId, OperandFPRoundingMode))
-ExtInst(vstore_halfn, 177, List(OperandId, OperandId, OperandId))
-ExtInst(vstore_halfn_r, 178, List(OperandId, OperandId, OperandId, OperandFPRoundingMode))
-ExtInst(vloada_halfn, 179, List(OperandId, OperandId, OperandLiteralNumber))
-ExtInst(vstorea_halfn, 180, List(OperandId, OperandId, OperandId))
-ExtInst(vstorea_halfn_r, 181, List(OperandId, OperandId, OperandId, OperandFPRoundingMode))
-ExtInst(shuffle, 182, List(OperandId, OperandId))
-ExtInst(shuffle2, 183, List(OperandId, OperandId, OperandId))
-ExtInst(printf, 184, List(OperandId, OperandVariableIds))
-ExtInst(prefetch, 185, List(OperandId, OperandId))
-ExtInst(bitselect, 186, List(OperandId, OperandId, OperandId))
-ExtInst(select, 187, List(OperandId, OperandId, OperandId))
-ExtInst(u_abs, 201, List(OperandId))
-ExtInst(u_abs_diff, 202, List(OperandId, OperandId))
-ExtInst(u_mul_hi, 203, List(OperandId, OperandId))
-ExtInst(u_mad_hi, 204, List(OperandId, OperandId, OperandId))
diff --git a/source/operand.cpp b/source/operand.cpp
index 7a2c075..5de3f43 100644
--- a/source/operand.cpp
+++ b/source/operand.cpp
@@ -29,1066 +29,21 @@
 #include <assert.h>
 #include <string.h>
 
-static const spv_operand_desc_t sourceLanguageEntries[] = {
-    {"Unknown", SpvSourceLanguageUnknown, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"ESSL", SpvSourceLanguageESSL, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"GLSL", SpvSourceLanguageGLSL, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"OpenCL_C", SpvSourceLanguageOpenCL_C, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"OpenCL_CPP", SpvSourceLanguageOpenCL_CPP, 0, {SPV_OPERAND_TYPE_NONE}},
-};
-
-static const spv_operand_desc_t executionModelEntries[] = {
-    {"Vertex",
-     SpvExecutionModelVertex,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"TessellationControl",
-     SpvExecutionModelTessellationControl,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"TessellationEvaluation",
-     SpvExecutionModelTessellationEvaluation,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Geometry",
-     SpvExecutionModelGeometry,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityGeometry),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Fragment",
-     SpvExecutionModelFragment,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"GLCompute",
-     SpvExecutionModelGLCompute,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Kernel",
-     SpvExecutionModelKernel,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-};
-
-static const spv_operand_desc_t addressingModelEntries[] = {
-    {"Logical", SpvAddressingModelLogical, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"Physical32",
-     SpvAddressingModelPhysical32,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityAddresses),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Physical64",
-     SpvAddressingModelPhysical64,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityAddresses),
-     {SPV_OPERAND_TYPE_NONE}},
-};
-
-static const spv_operand_desc_t memoryModelEntries[] = {
-    {"Simple",
-     SpvMemoryModelSimple,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"GLSL450",
-     SpvMemoryModelGLSL450,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"OpenCL",
-     SpvMemoryModelOpenCL,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-};
-
-// Execution mode requiring the given capability and having no operands.
-#define ExecMode0(mode, cap)                                                   \
-  #mode, SpvExecutionMode##mode, SPV_CAPABILITY_AS_MASK(SpvCapability##cap), { \
-    SPV_OPERAND_TYPE_NONE                                                      \
-  }
-// Execution mode requiring the given capability and having one literal number
-// operand.
-#define ExecMode1(mode, cap)                                                   \
-  #mode, SpvExecutionMode##mode, SPV_CAPABILITY_AS_MASK(SpvCapability##cap), { \
-    SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE                    \
-  }
-static const spv_operand_desc_t executionModeEntries[] = {
-    {ExecMode1(Invocations, Geometry)},
-    {ExecMode0(SpacingEqual, Tessellation)},
-    {ExecMode0(SpacingFractionalEven, Tessellation)},
-    {ExecMode0(SpacingFractionalOdd, Tessellation)},
-    {ExecMode0(VertexOrderCw, Tessellation)},
-    {ExecMode0(VertexOrderCcw, Tessellation)},
-    {ExecMode0(PixelCenterInteger, Shader)},
-    {ExecMode0(OriginUpperLeft, Shader)},
-    {ExecMode0(OriginLowerLeft, Shader)},
-    {ExecMode0(EarlyFragmentTests, Shader)},
-    {ExecMode0(PointMode, Tessellation)},
-    {ExecMode0(Xfb, TransformFeedback)},
-    {ExecMode0(DepthReplacing, Shader)},
-    {ExecMode0(DepthGreater, Shader)},
-    {ExecMode0(DepthLess, Shader)},
-    {ExecMode0(DepthUnchanged, Shader)},
-    {"LocalSize",
-     SpvExecutionModeLocalSize,
-     0,
-     {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER,
-      SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
-    {"LocalSizeHint",
-     SpvExecutionModeLocalSizeHint,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER,
-      SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
-    {ExecMode0(InputPoints, Geometry)},
-    {ExecMode0(InputLines, Geometry)},
-    {ExecMode0(InputLinesAdjacency, Geometry)},
-    {"Triangles",
-     SpvExecutionModeTriangles,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityGeometry) |
-         SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
-     {SPV_OPERAND_TYPE_NONE}},
-    {ExecMode0(InputTrianglesAdjacency, Geometry)},
-    {ExecMode0(Quads, Tessellation)},
-    {ExecMode0(Isolines, Tessellation)},
-    {"OutputVertices",
-     SpvExecutionModeOutputVertices,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityGeometry) |
-         SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
-     {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
-    {ExecMode0(OutputPoints, Geometry)},
-    {ExecMode0(OutputLineStrip, Geometry)},
-    {ExecMode0(OutputTriangleStrip, Geometry)},
-    {ExecMode1(VecTypeHint, Kernel)},
-    {ExecMode0(ContractionOff, Kernel)},
-};
-#undef ExecMode0
-#undef ExecMode1
-
-static const spv_operand_desc_t storageClassEntries[] = {
-    // TODO(dneto): There are more storage classes in Rev32 and later.
-    {"UniformConstant",
-     SpvStorageClassUniformConstant,
-     0,
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Input",
-     SpvStorageClassInput,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Uniform",
-     SpvStorageClassUniform,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Output",
-     SpvStorageClassOutput,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Workgroup", SpvStorageClassWorkgroup, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"CrossWorkgroup",
-     SpvStorageClassCrossWorkgroup,
-     0,
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Private",
-     SpvStorageClassPrivate,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Function", SpvStorageClassFunction, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"Generic",
-     SpvStorageClassGeneric,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityGenericPointer),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"PushConstant",
-     SpvStorageClassPushConstant,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"AtomicCounter",
-     SpvStorageClassAtomicCounter,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityAtomicStorage),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Image", SpvStorageClassImage, 0, {SPV_OPERAND_TYPE_NONE}},
-};
-
-static const spv_operand_desc_t dimensionalityEntries[] = {
-    {"1D",
-     SpvDim1D,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilitySampled1D),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"2D", SpvDim2D, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"3D", SpvDim3D, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"Cube",
-     SpvDimCube,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Rect",
-     SpvDimRect,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilitySampledRect),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Buffer",
-     SpvDimBuffer,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilitySampledBuffer),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"SubpassData",
-     SpvDimSubpassData,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityInputAttachment),
-     {SPV_OPERAND_TYPE_NONE}},
-};
-
-static const spv_operand_desc_t samplerAddressingModeEntries[] = {
-    {"None",
-     SpvSamplerAddressingModeNone,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"ClampToEdge",
-     SpvSamplerAddressingModeClampToEdge,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Clamp",
-     SpvSamplerAddressingModeClamp,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Repeat",
-     SpvSamplerAddressingModeRepeat,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"RepeatMirrored",
-     SpvSamplerAddressingModeRepeatMirrored,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-};
-
-static const spv_operand_desc_t samplerFilterModeEntries[] = {
-    {"Nearest",
-     SpvSamplerFilterModeNearest,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Linear",
-     SpvSamplerFilterModeLinear,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-};
-
-static const spv_operand_desc_t samplerImageFormatEntries[] = {
-#define CASE0(NAME)                                           \
-  {                                                           \
-    #NAME, SpvImageFormat##NAME, 0, { SPV_OPERAND_TYPE_NONE } \
-  }
-#define CASE(NAME, CAP)                                                        \
-  {                                                                            \
-    #NAME, SpvImageFormat##NAME, SPV_CAPABILITY_AS_MASK(SpvCapability##CAP), { \
-      SPV_OPERAND_TYPE_NONE                                                    \
-    }                                                                          \
-  }
-    // clang-format off
-  CASE0(Unknown),
-  CASE(Rgba32f, Shader),
-  CASE(Rgba16f, Shader),
-  CASE(R32f, Shader),
-  CASE(Rgba8, Shader),
-  CASE(Rgba8Snorm, Shader),
-  CASE(Rg32f, StorageImageExtendedFormats),
-  CASE(Rg16f, StorageImageExtendedFormats),
-  CASE(R11fG11fB10f, StorageImageExtendedFormats),
-  CASE(R16f, StorageImageExtendedFormats),
-  CASE(Rgba16, StorageImageExtendedFormats),
-  CASE(Rgb10A2, StorageImageExtendedFormats),
-  CASE(Rg16, StorageImageExtendedFormats),
-  CASE(Rg8, StorageImageExtendedFormats),
-  CASE(R16, StorageImageExtendedFormats),
-  CASE(R8, StorageImageExtendedFormats),
-  CASE(Rgba16Snorm, StorageImageExtendedFormats),
-  CASE(Rg16Snorm, StorageImageExtendedFormats),
-  CASE(Rg8Snorm, StorageImageExtendedFormats),
-  CASE(R16Snorm, StorageImageExtendedFormats),
-  CASE(R8Snorm, StorageImageExtendedFormats),
-  CASE(Rgba32i, Shader),
-  CASE(Rgba16i, Shader),
-  CASE(Rgba8i, Shader),
-  CASE(R32i, Shader),
-  CASE(Rg32i, StorageImageExtendedFormats),
-  CASE(Rg16i, StorageImageExtendedFormats),
-  CASE(Rg8i, StorageImageExtendedFormats),
-  CASE(R16i, StorageImageExtendedFormats),
-  CASE(R8i, StorageImageExtendedFormats),
-  CASE(Rgba32ui, Shader),
-  CASE(Rgba16ui, Shader),
-  CASE(Rgba8ui, Shader),
-  CASE(R32ui, Shader),
-  CASE(Rgb10a2ui, StorageImageExtendedFormats),
-  CASE(Rg32ui, StorageImageExtendedFormats),
-  CASE(Rg16ui, StorageImageExtendedFormats),
-  CASE(Rg8ui, StorageImageExtendedFormats),
-  CASE(R16ui, StorageImageExtendedFormats),
-  CASE(R8ui, StorageImageExtendedFormats),
-// clang-format on
-#undef CASE
-};
-
-// All image channel orders depend on the Kernel capability.
-#define CASE(NAME)                                     \
-  {                                                    \
-    #NAME, SpvImageChannelOrder##NAME,                 \
-        SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel), { \
-      SPV_OPERAND_TYPE_NONE                            \
-    }                                                  \
-  }
-static const spv_operand_desc_t imageChannelOrderEntries[] = {
-    CASE(R),    CASE(A),     CASE(RG),    CASE(RA),        CASE(RGB),
-    CASE(RGBA), CASE(BGRA),  CASE(ARGB),  CASE(Intensity), CASE(Luminance),
-    CASE(Rx),   CASE(RGx),   CASE(RGBx),  CASE(Depth),     CASE(DepthStencil),
-    CASE(sRGB), CASE(sRGBx), CASE(sRGBA), CASE(sBGRA),
-};
-#undef CASE
-
-// All image channel data types depend on the Kernel capability.
-#define CASE(NAME)                                     \
-  {                                                    \
-    #NAME, SpvImageChannelDataType##NAME,              \
-        SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel), { \
-      SPV_OPERAND_TYPE_NONE                            \
-    }                                                  \
-  }
-static const spv_operand_desc_t imageChannelDataTypeEntries[] = {
-    CASE(SnormInt8),      CASE(SnormInt16),       CASE(UnormInt8),
-    CASE(UnormInt16),     CASE(UnormShort565),    CASE(UnormShort555),
-    CASE(UnormInt101010), CASE(SignedInt8),       CASE(SignedInt16),
-    CASE(SignedInt32),    CASE(UnsignedInt8),     CASE(UnsignedInt16),
-    CASE(UnsignedInt32),  CASE(HalfFloat),        CASE(Float),
-    CASE(UnormInt24),     CASE(UnormInt101010_2),
-};
-#undef CASE
-
-// Image operand definitions.  Each enum value is a mask.  When that mask
-// bit is set, the instruction should have further ID operands.
-// Some mask values depend on a capability.
-static const spv_operand_desc_t imageOperandEntries[] = {
-// Rev32 and later adds many more enums.
-#define CASE(NAME) #NAME, SpvImageOperands##NAME##Mask, 0
-#define CASE_CAP(NAME, CAP) #NAME, SpvImageOperands##NAME##Mask, CAP
-#define ID SPV_OPERAND_TYPE_ID
-#define NONE SPV_OPERAND_TYPE_NONE
-    {"None", SpvImageOperandsMaskNone, 0, {NONE}},
-    {CASE_CAP(Bias, SPV_CAPABILITY_AS_MASK(SpvCapabilityShader)), {ID, NONE}},
-    {CASE(Lod), {ID, NONE}},
-    {CASE(Grad), {ID, ID, NONE}},
-    {CASE(ConstOffset), {ID, NONE}},
-    {CASE_CAP(Offset, SPV_CAPABILITY_AS_MASK(SpvCapabilityImageGatherExtended)),
-     {ID, NONE}},
-    {CASE(ConstOffsets), {ID, NONE}},
-    {CASE(Sample), {ID, NONE}},
-    {CASE_CAP(MinLod, SPV_CAPABILITY_AS_MASK(SpvCapabilityMinLod)), {ID, NONE}},
-#undef CASE
-#undef CASE_CAP
-#undef ID
-#undef NONE
-};
-
-static const spv_operand_desc_t fpFastMathModeEntries[] = {
-    {"None", SpvFPFastMathModeMaskNone, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"NotNaN",
-     SpvFPFastMathModeNotNaNMask,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"NotInf",
-     SpvFPFastMathModeNotInfMask,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"NSZ",
-     SpvFPFastMathModeNSZMask,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"AllowRecip",
-     SpvFPFastMathModeAllowRecipMask,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Fast",
-     SpvFPFastMathModeFastMask,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-};
-
-static const spv_operand_desc_t fpRoundingModeEntries[] = {
-    {"RTE",
-     SpvFPRoundingModeRTE,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"RTZ",
-     SpvFPRoundingModeRTZ,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"RTP",
-     SpvFPRoundingModeRTP,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"RTN",
-     SpvFPRoundingModeRTN,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-};
-
-static const spv_operand_desc_t linkageTypeEntries[] = {
-    {"Export",
-     SpvLinkageTypeExport,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityLinkage),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Import",
-     SpvLinkageTypeImport,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityLinkage),
-     {SPV_OPERAND_TYPE_NONE}},
-};
-
-static const spv_operand_desc_t accessQualifierEntries[] = {
-    {"ReadOnly",
-     SpvAccessQualifierReadOnly,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"WriteOnly",
-     SpvAccessQualifierWriteOnly,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"ReadWrite",
-     SpvAccessQualifierReadWrite,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-};
-
-static const spv_operand_desc_t functionParameterAttributeEntries[] = {
-    {"Zext",
-     SpvFunctionParameterAttributeZext,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Sext",
-     SpvFunctionParameterAttributeSext,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"ByVal",
-     SpvFunctionParameterAttributeByVal,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Sret",
-     SpvFunctionParameterAttributeSret,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"NoAlias",
-     SpvFunctionParameterAttributeNoAlias,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"NoCapture",
-     SpvFunctionParameterAttributeNoCapture,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"NoWrite",
-     SpvFunctionParameterAttributeNoWrite,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"NoReadWrite",
-     SpvFunctionParameterAttributeNoReadWrite,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-};
-
-static const spv_operand_desc_t decorationEntries[] = {
-    {"RelaxedPrecision",
-     SpvDecorationRelaxedPrecision,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {
-        "SpecId",
-        SpvDecorationSpecId,
-        SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-        {SPV_OPERAND_TYPE_LITERAL_INTEGER},
-    },
-    {"Block",
-     SpvDecorationBlock,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"BufferBlock",
-     SpvDecorationBufferBlock,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"RowMajor",
-     SpvDecorationRowMajor,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityMatrix),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"ColMajor",
-     SpvDecorationColMajor,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityMatrix),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"ArrayStride",
-     SpvDecorationArrayStride,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
-    {"MatrixStride",
-     SpvDecorationMatrixStride,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityMatrix),
-     {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
-    {"GLSLShared",
-     SpvDecorationGLSLShared,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"GLSLPacked",
-     SpvDecorationGLSLPacked,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"CPacked",
-     SpvDecorationCPacked,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"BuiltIn",
-     SpvDecorationBuiltIn,
-     0,
-     {SPV_OPERAND_TYPE_BUILT_IN, SPV_OPERAND_TYPE_NONE}},
-    {"NoPerspective",
-     SpvDecorationNoPerspective,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Flat",
-     SpvDecorationFlat,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Patch",
-     SpvDecorationPatch,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Centroid",
-     SpvDecorationCentroid,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Sample",
-     SpvDecorationSample,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilitySampleRateShading),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Invariant",
-     SpvDecorationInvariant,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Restrict", SpvDecorationRestrict, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"Aliased", SpvDecorationAliased, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"Volatile", SpvDecorationVolatile, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"Constant",
-     SpvDecorationConstant,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Coherent", SpvDecorationCoherent, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"NonWritable", SpvDecorationNonWritable, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"NonReadable", SpvDecorationNonReadable, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"Uniform",
-     SpvDecorationUniform,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"SaturatedConversion",
-     SpvDecorationSaturatedConversion,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Stream",
-     SpvDecorationStream,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityGeometryStreams),
-     {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
-    {"Location",
-     SpvDecorationLocation,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
-    {"Component",
-     SpvDecorationComponent,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
-    {"Index",
-     SpvDecorationIndex,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
-    {"Binding",
-     SpvDecorationBinding,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
-    {"DescriptorSet",
-     SpvDecorationDescriptorSet,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
-    {"Offset",
-     SpvDecorationOffset,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
-    {"XfbBuffer",
-     SpvDecorationXfbBuffer,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityTransformFeedback),
-     {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
-    {"XfbStride",
-     SpvDecorationXfbStride,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityTransformFeedback),
-     {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
-    {"FuncParamAttr",
-     SpvDecorationFuncParamAttr,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE, SPV_OPERAND_TYPE_NONE}},
-    {"FPRoundingMode",
-     SpvDecorationFPRoundingMode,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_NONE}},
-    {"FPFastMathMode",
-     SpvDecorationFPFastMathMode,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_FP_FAST_MATH_MODE, SPV_OPERAND_TYPE_NONE}},
-    {"LinkageAttributes",
-     SpvDecorationLinkageAttributes,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityLinkage),
-     {SPV_OPERAND_TYPE_LITERAL_STRING, SPV_OPERAND_TYPE_LINKAGE_TYPE,
-      SPV_OPERAND_TYPE_NONE}},
-    {"NoContraction",
-     SpvDecorationNoContraction,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"InputAttachmentIndex",
-     SpvDecorationInputAttachmentIndex,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityInputAttachment),
-     {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
-    {"Alignment",
-     SpvDecorationAlignment,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
-};
-
-static const spv_operand_desc_t builtInEntries[] = {
-    {"Position",
-     SpvBuiltInPosition,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"PointSize",
-     SpvBuiltInPointSize,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"ClipDistance",
-     SpvBuiltInClipDistance,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityClipDistance),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"CullDistance",
-     SpvBuiltInCullDistance,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityCullDistance),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"VertexId",
-     SpvBuiltInVertexId,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"InstanceId",
-     SpvBuiltInInstanceId,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"PrimitiveId",
-     SpvBuiltInPrimitiveId,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityGeometry) |
-         SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"InvocationId",
-     SpvBuiltInInvocationId,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityGeometry) |
-         SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Layer",
-     SpvBuiltInLayer,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityGeometry),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"ViewportIndex",
-     SpvBuiltInViewportIndex,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityMultiViewport),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"TessLevelOuter",
-     SpvBuiltInTessLevelOuter,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"TessLevelInner",
-     SpvBuiltInTessLevelInner,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"TessCoord",
-     SpvBuiltInTessCoord,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"PatchVertices",
-     SpvBuiltInPatchVertices,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"FragCoord",
-     SpvBuiltInFragCoord,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"PointCoord",
-     SpvBuiltInPointCoord,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"FrontFacing",
-     SpvBuiltInFrontFacing,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"SampleId",
-     SpvBuiltInSampleId,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilitySampleRateShading),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"SamplePosition",
-     SpvBuiltInSamplePosition,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilitySampleRateShading),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"SampleMask",
-     SpvBuiltInSampleMask,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilitySampleRateShading),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"FragDepth",
-     SpvBuiltInFragDepth,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"HelperInvocation",
-     SpvBuiltInHelperInvocation,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"NumWorkgroups", SpvBuiltInNumWorkgroups, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"WorkgroupSize", SpvBuiltInWorkgroupSize, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"WorkgroupId", SpvBuiltInWorkgroupId, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"LocalInvocationId",
-     SpvBuiltInLocalInvocationId,
-     0,
-     {SPV_OPERAND_TYPE_NONE}},
-    {"GlobalInvocationId",
-     SpvBuiltInGlobalInvocationId,
-     0,
-     {SPV_OPERAND_TYPE_NONE}},
-    {"LocalInvocationIndex",
-     SpvBuiltInLocalInvocationIndex,
-     0,
-     {SPV_OPERAND_TYPE_NONE}},
-    {"WorkDim",
-     SpvBuiltInWorkDim,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"GlobalSize",
-     SpvBuiltInGlobalSize,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"EnqueuedWorkgroupSize",
-     SpvBuiltInEnqueuedWorkgroupSize,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"GlobalOffset",
-     SpvBuiltInGlobalOffset,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"GlobalLinearId",
-     SpvBuiltInGlobalLinearId,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"SubgroupSize",
-     SpvBuiltInSubgroupSize,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"SubgroupMaxSize",
-     SpvBuiltInSubgroupMaxSize,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"NumSubgroups",
-     SpvBuiltInNumSubgroups,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"NumEnqueuedSubgroups",
-     SpvBuiltInNumEnqueuedSubgroups,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"SubgroupId",
-     SpvBuiltInSubgroupId,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"SubgroupLocalInvocationId",
-     SpvBuiltInSubgroupLocalInvocationId,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"VertexIndex",
-     SpvBuiltInVertexIndex,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"InstanceIndex",
-     SpvBuiltInInstanceIndex,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-};
-
-static const spv_operand_desc_t selectionControlEntries[] = {
-    {"None", SpvSelectionControlMaskNone, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"Flatten", SpvSelectionControlFlattenMask, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"DontFlatten",
-     SpvSelectionControlDontFlattenMask,
-     0,
-     {SPV_OPERAND_TYPE_NONE}},
-};
-
-static const spv_operand_desc_t loopControlEntries[] = {
-    {"None", SpvLoopControlMaskNone, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"Unroll", SpvLoopControlUnrollMask, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"DontUnroll", SpvLoopControlDontUnrollMask, 0, {SPV_OPERAND_TYPE_NONE}},
-};
-
-static const spv_operand_desc_t functionControlEntries[] = {
-    {"None", SpvFunctionControlMaskNone, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"Inline", SpvFunctionControlInlineMask, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"DontInline",
-     SpvFunctionControlDontInlineMask,
-     0,
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Pure", SpvFunctionControlPureMask, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"Const", SpvFunctionControlConstMask, 0, {SPV_OPERAND_TYPE_NONE}},
-};
-
-static const spv_operand_desc_t memorySemanticsEntries[] = {
-    // "Relaxed" should be a synonym for "None".
-    // Put the Relaxed entry first so that the disassembler
-    // will prefer to emit "Relaxed".
-    {"Relaxed", SpvMemorySemanticsMaskNone, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"None", SpvMemorySemanticsMaskNone, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"SequentiallyConsistent",
-     SpvMemorySemanticsSequentiallyConsistentMask,
-     0,
-     {SPV_OPERAND_TYPE_NONE}},
-    {"Acquire", SpvMemorySemanticsAcquireMask, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"Release", SpvMemorySemanticsReleaseMask, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"AcquireRelease",
-     SpvMemorySemanticsAcquireReleaseMask,
-     0,
-     {SPV_OPERAND_TYPE_NONE}},
-    {"UniformMemory",
-     SpvMemorySemanticsUniformMemoryMask,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"SubgroupMemory",
-     SpvMemorySemanticsSubgroupMemoryMask,
-     0,
-     {SPV_OPERAND_TYPE_NONE}},
-    {"WorkgroupMemory",
-     SpvMemorySemanticsWorkgroupMemoryMask,
-     0,
-     {SPV_OPERAND_TYPE_NONE}},
-    {"CrossWorkgroupMemory",
-     SpvMemorySemanticsCrossWorkgroupMemoryMask,
-     0,
-     {SPV_OPERAND_TYPE_NONE}},
-    {"AtomicCounterMemory",
-     SpvMemorySemanticsAtomicCounterMemoryMask,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityAtomicStorage),
-     {SPV_OPERAND_TYPE_NONE}},
-    {
-        "ImageMemory",
-        SpvMemorySemanticsImageMemoryMask,
-        0,
-        {SPV_OPERAND_TYPE_NONE},
-    },
-};
-
-static const spv_operand_desc_t memoryAccessEntries[] = {
-    {"None", SpvMemoryAccessMaskNone, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"Volatile", SpvMemoryAccessVolatileMask, 0, {SPV_OPERAND_TYPE_NONE}},
-    {
-        "Aligned",
-        SpvMemoryAccessAlignedMask,
-        0,
-        {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE},
-    },
-    {"Nontemporal", SpvMemoryAccessNontemporalMask, 0, {SPV_OPERAND_TYPE_NONE}},
-};
-
-static const spv_operand_desc_t scopeEntries[] = {
-    {"CrossDevice", SpvScopeCrossDevice, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"Device", SpvScopeDevice, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"Workgroup", SpvScopeWorkgroup, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"Subgroup", SpvScopeSubgroup, 0, {SPV_OPERAND_TYPE_NONE}},
-    {
-        "Invocation", SpvScopeInvocation, 0, {SPV_OPERAND_TYPE_NONE},
-    },
-};
-
-static const spv_operand_desc_t groupOperationEntries[] = {
-    {"Reduce",
-     SpvGroupOperationReduce,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"InclusiveScan",
-     SpvGroupOperationInclusiveScan,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"ExclusiveScan",
-     SpvGroupOperationExclusiveScan,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-};
-
-static const spv_operand_desc_t kernelKernelEnqueueFlagssEntries[] = {
-    {"NoWait",
-     SpvKernelEnqueueFlagsNoWait,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"WaitKernel",
-     SpvKernelEnqueueFlagsWaitKernel,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-    {"WaitWorkGroup",
-     SpvKernelEnqueueFlagsWaitWorkGroup,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-};
-
-static const spv_operand_desc_t kernelProfilingInfoEntries[] = {
-    {"None", SpvKernelProfilingInfoMaskNone, 0, {SPV_OPERAND_TYPE_NONE}},
-    {"CmdExecTime",
-     SpvKernelProfilingInfoCmdExecTimeMask,
-     SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
-     {SPV_OPERAND_TYPE_NONE}},
-};
-
-// A macro for defining a capability that doesn't depend on another capability.
-#define CASE(NAME)                                           \
-  {                                                          \
-    #NAME, SpvCapability##NAME, 0, { SPV_OPERAND_TYPE_NONE } \
-  }
-
-// A macro for defining a capability that depends on another.
-#define CASE_CAP(NAME, CAP)                                                   \
-  {                                                                           \
-    #NAME, SpvCapability##NAME, SPV_CAPABILITY_AS_MASK(SpvCapability##CAP), { \
-      SPV_OPERAND_TYPE_NONE                                                   \
-    }                                                                         \
-  }
-
-// clang-format off
-static const spv_operand_desc_t capabilityInfoEntries[] = {
-    CASE(Matrix),
-    CASE_CAP(Shader, Matrix),
-    CASE_CAP(Geometry, Shader),
-    CASE_CAP(Tessellation, Shader),
-    CASE(Addresses),
-    CASE(Linkage),
-    CASE(Kernel),
-    CASE_CAP(Vector16, Kernel),
-    CASE_CAP(Float16Buffer, Kernel),
-    CASE(Float16),
-    CASE(Float64),
-    CASE(Int64),
-    CASE_CAP(Int64Atomics, Int64),
-    CASE_CAP(ImageBasic, Kernel),
-    CASE_CAP(ImageReadWrite, Kernel),
-    CASE_CAP(ImageMipmap, Kernel),
-    // Value 16 intentionally missing.
-    CASE_CAP(Pipes, Kernel),
-    CASE(Groups),
-    CASE_CAP(DeviceEnqueue, Kernel),
-    CASE_CAP(LiteralSampler, Kernel),
-    CASE_CAP(AtomicStorage, Shader),
-    CASE(Int16),
-    CASE_CAP(TessellationPointSize, Tessellation),
-    CASE_CAP(GeometryPointSize, Geometry),
-    CASE_CAP(ImageGatherExtended, Shader),
-    // Value 26 intentionally missing.
-    CASE_CAP(StorageImageMultisample, Shader),
-    CASE_CAP(UniformBufferArrayDynamicIndexing, Shader),
-    CASE_CAP(SampledImageArrayDynamicIndexing, Shader),
-    CASE_CAP(StorageBufferArrayDynamicIndexing, Shader),
-    CASE_CAP(StorageImageArrayDynamicIndexing, Shader),
-    CASE_CAP(ClipDistance, Shader),
-    CASE_CAP(CullDistance, Shader),
-    CASE_CAP(ImageCubeArray, SampledCubeArray),
-    CASE_CAP(SampleRateShading, Shader),
-    CASE_CAP(ImageRect, SampledRect),
-    CASE_CAP(SampledRect, Shader),
-    CASE_CAP(GenericPointer, Addresses),
-    CASE_CAP(Int8, Kernel),
-    CASE_CAP(InputAttachment, Shader),
-    CASE_CAP(SparseResidency, Shader),
-    CASE_CAP(MinLod, Shader),
-    CASE_CAP(Sampled1D, Shader),
-    CASE_CAP(Image1D, Sampled1D),
-    CASE_CAP(SampledCubeArray, Shader),
-    CASE_CAP(SampledBuffer, Shader),
-    CASE_CAP(ImageBuffer, SampledBuffer),
-    CASE_CAP(ImageMSArray, Shader),
-    CASE_CAP(StorageImageExtendedFormats, Shader),
-    CASE_CAP(ImageQuery, Shader),
-    CASE_CAP(DerivativeControl, Shader),
-    CASE_CAP(InterpolationFunction, Shader),
-    CASE_CAP(TransformFeedback, Shader),
-    CASE_CAP(GeometryStreams, Geometry),
-    CASE_CAP(StorageImageReadWithoutFormat, Shader),
-    CASE_CAP(StorageImageWriteWithoutFormat, Shader),
-    CASE_CAP(MultiViewport, Geometry),
-};
-// clang-format on
-#undef CASE
-#undef CASE_CAP
-
 // Evaluates to the number of elements of array A.
 // If we could use constexpr, then we could make this a template function.
 // If the source arrays were std::array, then we could have used
 // std::array::size.
 #define ARRAY_SIZE(A) (static_cast<uint32_t>(sizeof(A) / sizeof(A[0])))
 
-static const spv_operand_desc_group_t opcodeEntryTypes[] = {
-    // TODO(dneto): Reformat this table.
-    {SPV_OPERAND_TYPE_SOURCE_LANGUAGE, ARRAY_SIZE(sourceLanguageEntries),
-     sourceLanguageEntries},
-    {SPV_OPERAND_TYPE_EXECUTION_MODEL, ARRAY_SIZE(executionModelEntries),
-     executionModelEntries},
-    {SPV_OPERAND_TYPE_ADDRESSING_MODEL, ARRAY_SIZE(addressingModelEntries),
-     addressingModelEntries},
-    {SPV_OPERAND_TYPE_MEMORY_MODEL, ARRAY_SIZE(memoryModelEntries),
-     memoryModelEntries},
-    {SPV_OPERAND_TYPE_EXECUTION_MODE, ARRAY_SIZE(executionModeEntries),
-     executionModeEntries},
-    {SPV_OPERAND_TYPE_STORAGE_CLASS, ARRAY_SIZE(storageClassEntries),
-     storageClassEntries},
-    {SPV_OPERAND_TYPE_DIMENSIONALITY, ARRAY_SIZE(dimensionalityEntries),
-     dimensionalityEntries},
-    {SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE,
-     ARRAY_SIZE(samplerAddressingModeEntries), samplerAddressingModeEntries},
-    {SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE, ARRAY_SIZE(samplerFilterModeEntries),
-     samplerFilterModeEntries},
-    {SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT,
-     ARRAY_SIZE(samplerImageFormatEntries), samplerImageFormatEntries},
-    {SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER, ARRAY_SIZE(imageChannelOrderEntries),
-     imageChannelOrderEntries},
-    {SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE,
-     ARRAY_SIZE(imageChannelDataTypeEntries), imageChannelDataTypeEntries},
-    {SPV_OPERAND_TYPE_IMAGE, ARRAY_SIZE(imageOperandEntries),
-     imageOperandEntries},
-    {SPV_OPERAND_TYPE_OPTIONAL_IMAGE,  // Same as *_IMAGE
-     ARRAY_SIZE(imageOperandEntries), imageOperandEntries},
-    {SPV_OPERAND_TYPE_FP_FAST_MATH_MODE, ARRAY_SIZE(fpFastMathModeEntries),
-     fpFastMathModeEntries},
-    {SPV_OPERAND_TYPE_FP_ROUNDING_MODE, ARRAY_SIZE(fpRoundingModeEntries),
-     fpRoundingModeEntries},
-    {SPV_OPERAND_TYPE_LINKAGE_TYPE, ARRAY_SIZE(linkageTypeEntries),
-     linkageTypeEntries},
-    {SPV_OPERAND_TYPE_ACCESS_QUALIFIER, ARRAY_SIZE(accessQualifierEntries),
-     accessQualifierEntries},
-    {SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER,  // Same as *_ACCESS_QUALIFIER
-     ARRAY_SIZE(accessQualifierEntries), accessQualifierEntries},
-    {SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
-     ARRAY_SIZE(functionParameterAttributeEntries),
-     functionParameterAttributeEntries},
-    {SPV_OPERAND_TYPE_DECORATION, ARRAY_SIZE(decorationEntries),
-     decorationEntries},
-    {SPV_OPERAND_TYPE_BUILT_IN, ARRAY_SIZE(builtInEntries), builtInEntries},
-    {SPV_OPERAND_TYPE_SELECTION_CONTROL, ARRAY_SIZE(selectionControlEntries),
-     selectionControlEntries},
-    {SPV_OPERAND_TYPE_LOOP_CONTROL, ARRAY_SIZE(loopControlEntries),
-     loopControlEntries},
-    {SPV_OPERAND_TYPE_FUNCTION_CONTROL, ARRAY_SIZE(functionControlEntries),
-     functionControlEntries},
-    {SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, ARRAY_SIZE(memorySemanticsEntries),
-     memorySemanticsEntries},
-    {SPV_OPERAND_TYPE_MEMORY_ACCESS, ARRAY_SIZE(memoryAccessEntries),
-     memoryAccessEntries},
-    {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,  // Same as *_MEMORY_ACCESS
-     ARRAY_SIZE(memoryAccessEntries), memoryAccessEntries},
-    {SPV_OPERAND_TYPE_SCOPE_ID, ARRAY_SIZE(scopeEntries), scopeEntries},
-    {SPV_OPERAND_TYPE_GROUP_OPERATION, ARRAY_SIZE(groupOperationEntries),
-     groupOperationEntries},
-    {SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS,
-     ARRAY_SIZE(kernelKernelEnqueueFlagssEntries),
-     kernelKernelEnqueueFlagssEntries},
-    {SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO,
-     ARRAY_SIZE(kernelProfilingInfoEntries), kernelProfilingInfoEntries},
-    {SPV_OPERAND_TYPE_CAPABILITY, ARRAY_SIZE(capabilityInfoEntries),
-     capabilityInfoEntries},
-};
+// Pull in operand info tables automatically generated from JSON grammar.
+#include "operand.kinds.inc"
 
 spv_result_t spvOperandTableGet(spv_operand_table* pOperandTable) {
   if (!pOperandTable) return SPV_ERROR_INVALID_POINTER;
 
-  static const spv_operand_table_t table = {ARRAY_SIZE(opcodeEntryTypes),
-                                            opcodeEntryTypes};
+  static const spv_operand_table_t table = {
+      ARRAY_SIZE(pygen_variable_OperandInfoTable),
+      pygen_variable_OperandInfoTable};
 
   *pOperandTable = &table;
 
@@ -1178,7 +133,6 @@
     case SPV_OPERAND_TYPE_MEMORY_MODEL:
       return "memory model";
     case SPV_OPERAND_TYPE_EXECUTION_MODE:
-    case SPV_OPERAND_TYPE_OPTIONAL_EXECUTION_MODE:
       return "execution mode";
     case SPV_OPERAND_TYPE_STORAGE_CLASS:
       return "storage class";
@@ -1312,10 +266,6 @@
                       {SPV_OPERAND_TYPE_OPTIONAL_ID,
                        SPV_OPERAND_TYPE_LITERAL_INTEGER, type});
       return true;
-    case SPV_OPERAND_TYPE_VARIABLE_EXECUTION_MODE:
-      pattern->insert(pattern->begin(),
-                      {SPV_OPERAND_TYPE_OPTIONAL_EXECUTION_MODE, type});
-      return true;
     default:
       break;
   }
diff --git a/source/spirv.core.grammar.json b/source/spirv.core.grammar.json
new file mode 100644
index 0000000..972be4f
--- /dev/null
+++ b/source/spirv.core.grammar.json
@@ -0,0 +1,5104 @@
+{
+  "copyright" : [
+    "Copyright (c) 2014-2016 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."
+  ],
+  "magic_number" : "0x07230203",
+  "major_version" : 1,
+  "minor_version" : 0,
+  "revision" : 4,
+  "instructions" : [
+    {
+      "opname" : "OpNop",
+      "opcode" : 0
+    },
+    {
+      "opname" : "OpUndef",
+      "opcode" : 1,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpSourceContinued",
+      "opcode" : 2,
+      "operands" : [
+        { "kind" : "LiteralString", "name" : "'Continued Source'" }
+      ]
+    },
+    {
+      "opname" : "OpSource",
+      "opcode" : 3,
+      "operands" : [
+        { "kind" : "SourceLanguage" },
+        { "kind" : "LiteralInteger",                     "name" : "'Version'" },
+        { "kind" : "IdRef",          "quantifier" : "?", "name" : "'File'" },
+        { "kind" : "LiteralString",  "quantifier" : "?", "name" : "'Source'" }
+      ]
+    },
+    {
+      "opname" : "OpSourceExtension",
+      "opcode" : 4,
+      "operands" : [
+        { "kind" : "LiteralString", "name" : "'Extension'" }
+      ]
+    },
+    {
+      "opname" : "OpName",
+      "opcode" : 5,
+      "operands" : [
+        { "kind" : "IdRef",         "name" : "'Target'" },
+        { "kind" : "LiteralString", "name" : "'Name'" }
+      ]
+    },
+    {
+      "opname" : "OpMemberName",
+      "opcode" : 6,
+      "operands" : [
+        { "kind" : "IdRef",          "name" : "'Type'" },
+        { "kind" : "LiteralInteger", "name" : "'Member'" },
+        { "kind" : "LiteralString",  "name" : "'Name'" }
+      ]
+    },
+    {
+      "opname" : "OpString",
+      "opcode" : 7,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "LiteralString", "name" : "'String'" }
+      ]
+    },
+    {
+      "opname" : "OpLine",
+      "opcode" : 8,
+      "operands" : [
+        { "kind" : "IdRef",          "name" : "'File'" },
+        { "kind" : "LiteralInteger", "name" : "'Line'" },
+        { "kind" : "LiteralInteger", "name" : "'Column'" }
+      ]
+    },
+    {
+      "opname" : "OpExtension",
+      "opcode" : 10,
+      "operands" : [
+        { "kind" : "LiteralString", "name" : "'Name'" }
+      ]
+    },
+    {
+      "opname" : "OpExtInstImport",
+      "opcode" : 11,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "LiteralString", "name" : "'Name'" }
+      ]
+    },
+    {
+      "opname" : "OpExtInst",
+      "opcode" : 12,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                                     "name" : "'Set'" },
+        { "kind" : "LiteralExtInstInteger",                     "name" : "'Instruction'" },
+        { "kind" : "IdRef",                 "quantifier" : "*", "name" : "'Operand 1', +\n'Operand 2', +\n..." }
+      ]
+    },
+    {
+      "opname" : "OpMemoryModel",
+      "opcode" : 14,
+      "operands" : [
+        { "kind" : "AddressingModel" },
+        { "kind" : "MemoryModel" }
+      ]
+    },
+    {
+      "opname" : "OpEntryPoint",
+      "opcode" : 15,
+      "operands" : [
+        { "kind" : "ExecutionModel" },
+        { "kind" : "IdRef",                              "name" : "'Entry Point'" },
+        { "kind" : "LiteralString",                      "name" : "'Name'" },
+        { "kind" : "IdRef",          "quantifier" : "*", "name" : "'Interface'" }
+      ]
+    },
+    {
+      "opname" : "OpExecutionMode",
+      "opcode" : 16,
+      "operands" : [
+        { "kind" : "IdRef",         "name" : "'Entry Point'" },
+        { "kind" : "ExecutionMode", "name" : "'Mode'" }
+      ]
+    },
+    {
+      "opname" : "OpCapability",
+      "opcode" : 17,
+      "operands" : [
+        { "kind" : "Capability", "name" : "'Capability'" }
+      ]
+    },
+    {
+      "opname" : "OpTypeVoid",
+      "opcode" : 19,
+      "operands" : [
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpTypeBool",
+      "opcode" : 20,
+      "operands" : [
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpTypeInt",
+      "opcode" : 21,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "LiteralInteger", "name" : "'Width'" },
+        { "kind" : "LiteralInteger", "name" : "'Signedness'" }
+      ]
+    },
+    {
+      "opname" : "OpTypeFloat",
+      "opcode" : 22,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "LiteralInteger", "name" : "'Width'" }
+      ]
+    },
+    {
+      "opname" : "OpTypeVector",
+      "opcode" : 23,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",          "name" : "'Component Type'" },
+        { "kind" : "LiteralInteger", "name" : "'Component Count'" }
+      ]
+    },
+    {
+      "opname" : "OpTypeMatrix",
+      "opcode" : 24,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",          "name" : "'Column Type'" },
+        { "kind" : "LiteralInteger", "name" : "'Column Count'" }
+      ],
+      "capabilities" : [ "Matrix" ]
+    },
+    {
+      "opname" : "OpTypeImage",
+      "opcode" : 25,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                               "name" : "'Sampled Type'" },
+        { "kind" : "Dim" },
+        { "kind" : "LiteralInteger",                      "name" : "'Depth'" },
+        { "kind" : "LiteralInteger",                      "name" : "'Arrayed'" },
+        { "kind" : "LiteralInteger",                      "name" : "'MS'" },
+        { "kind" : "LiteralInteger",                      "name" : "'Sampled'" },
+        { "kind" : "ImageFormat" },
+        { "kind" : "AccessQualifier", "quantifier" : "?" }
+      ]
+    },
+    {
+      "opname" : "OpTypeSampler",
+      "opcode" : 26,
+      "operands" : [
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpTypeSampledImage",
+      "opcode" : 27,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",    "name" : "'Image Type'" }
+      ]
+    },
+    {
+      "opname" : "OpTypeArray",
+      "opcode" : 28,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",    "name" : "'Element Type'" },
+        { "kind" : "IdRef",    "name" : "'Length'" }
+      ]
+    },
+    {
+      "opname" : "OpTypeRuntimeArray",
+      "opcode" : 29,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",    "name" : "'Element Type'" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpTypeStruct",
+      "opcode" : 30,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",    "quantifier" : "*", "name" : "'Member 0 type', +\n'member 1 type', +\n..." }
+      ]
+    },
+    {
+      "opname" : "OpTypeOpaque",
+      "opcode" : 31,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "LiteralString", "name" : "The name of the opaque type." }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpTypePointer",
+      "opcode" : 32,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "StorageClass" },
+        { "kind" : "IdRef",        "name" : "'Type'" }
+      ]
+    },
+    {
+      "opname" : "OpTypeFunction",
+      "opcode" : 33,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                        "name" : "'Return Type'" },
+        { "kind" : "IdRef",    "quantifier" : "*", "name" : "'Parameter 0 Type', +\n'Parameter 1 Type', +\n..." }
+      ]
+    },
+    {
+      "opname" : "OpTypeEvent",
+      "opcode" : 34,
+      "operands" : [
+        { "kind" : "IdResult" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpTypeDeviceEvent",
+      "opcode" : 35,
+      "operands" : [
+        { "kind" : "IdResult" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpTypeReserveId",
+      "opcode" : 36,
+      "operands" : [
+        { "kind" : "IdResult" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpTypeQueue",
+      "opcode" : 37,
+      "operands" : [
+        { "kind" : "IdResult" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpTypePipe",
+      "opcode" : 38,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "AccessQualifier", "name" : "'Qualifier'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpTypeForwardPointer",
+      "opcode" : 39,
+      "operands" : [
+        { "kind" : "IdRef",        "name" : "'Pointer Type'" },
+        { "kind" : "StorageClass" }
+      ],
+      "capabilities" : [ "Addresses" ]
+    },
+    {
+      "opname" : "OpConstantTrue",
+      "opcode" : 41,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpConstantFalse",
+      "opcode" : 42,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpConstant",
+      "opcode" : 43,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "LiteralContextDependentNumber", "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpConstantComposite",
+      "opcode" : 44,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "quantifier" : "*", "name" : "'Constituents'" }
+      ]
+    },
+    {
+      "opname" : "OpConstantSampler",
+      "opcode" : 45,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "SamplerAddressingMode" },
+        { "kind" : "LiteralInteger",        "name" : "'Param'" },
+        { "kind" : "SamplerFilterMode" }
+      ],
+      "capabilities" : [ "LiteralSampler" ]
+    },
+    {
+      "opname" : "OpConstantNull",
+      "opcode" : 46,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpSpecConstantTrue",
+      "opcode" : 48,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpSpecConstantFalse",
+      "opcode" : 49,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpSpecConstant",
+      "opcode" : 50,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "LiteralContextDependentNumber", "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpSpecConstantComposite",
+      "opcode" : 51,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "quantifier" : "*", "name" : "'Constituents'" }
+      ]
+    },
+    {
+      "opname" : "OpSpecConstantOp",
+      "opcode" : 52,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "LiteralSpecConstantOpInteger", "name" : "'Opcode'" }
+      ]
+    },
+    {
+      "opname" : "OpFunction",
+      "opcode" : 54,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "FunctionControl" },
+        { "kind" : "IdRef",           "name" : "'Function Type'" }
+      ]
+    },
+    {
+      "opname" : "OpFunctionParameter",
+      "opcode" : 55,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpFunctionEnd",
+      "opcode" : 56
+    },
+    {
+      "opname" : "OpFunctionCall",
+      "opcode" : 57,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                            "name" : "'Function'" },
+        { "kind" : "IdRef",        "quantifier" : "*", "name" : "'Argument 0', +\n'Argument 1', +\n..." }
+      ]
+    },
+    {
+      "opname" : "OpVariable",
+      "opcode" : 59,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "StorageClass" },
+        { "kind" : "IdRef",        "quantifier" : "?", "name" : "'Initializer'" }
+      ]
+    },
+    {
+      "opname" : "OpImageTexelPointer",
+      "opcode" : 60,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Image'" },
+        { "kind" : "IdRef",        "name" : "'Coordinate'" },
+        { "kind" : "IdRef",        "name" : "'Sample'" }
+      ]
+    },
+    {
+      "opname" : "OpLoad",
+      "opcode" : 61,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                            "name" : "'Pointer'" },
+        { "kind" : "MemoryAccess", "quantifier" : "?" }
+      ]
+    },
+    {
+      "opname" : "OpStore",
+      "opcode" : 62,
+      "operands" : [
+        { "kind" : "IdRef",                            "name" : "'Pointer'" },
+        { "kind" : "IdRef",                            "name" : "'Object'" },
+        { "kind" : "MemoryAccess", "quantifier" : "?" }
+      ]
+    },
+    {
+      "opname" : "OpCopyMemory",
+      "opcode" : 63,
+      "operands" : [
+        { "kind" : "IdRef",                            "name" : "'Target'" },
+        { "kind" : "IdRef",                            "name" : "'Source'" },
+        { "kind" : "MemoryAccess", "quantifier" : "?" }
+      ]
+    },
+    {
+      "opname" : "OpCopyMemorySized",
+      "opcode" : 64,
+      "operands" : [
+        { "kind" : "IdRef",                            "name" : "'Target'" },
+        { "kind" : "IdRef",                            "name" : "'Source'" },
+        { "kind" : "IdRef",                            "name" : "'Size'" },
+        { "kind" : "MemoryAccess", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "Addresses" ]
+    },
+    {
+      "opname" : "OpAccessChain",
+      "opcode" : 65,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                            "name" : "'Base'" },
+        { "kind" : "IdRef",        "quantifier" : "*", "name" : "'Indexes'" }
+      ]
+    },
+    {
+      "opname" : "OpInBoundsAccessChain",
+      "opcode" : 66,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                            "name" : "'Base'" },
+        { "kind" : "IdRef",        "quantifier" : "*", "name" : "'Indexes'" }
+      ]
+    },
+    {
+      "opname" : "OpPtrAccessChain",
+      "opcode" : 67,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                            "name" : "'Base'" },
+        { "kind" : "IdRef",                            "name" : "'Element'" },
+        { "kind" : "IdRef",        "quantifier" : "*", "name" : "'Indexes'" }
+      ],
+      "capabilities" : [ "Addresses" ]
+    },
+    {
+      "opname" : "OpArrayLength",
+      "opcode" : 68,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",          "name" : "'Structure'" },
+        { "kind" : "LiteralInteger", "name" : "'Array member'" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpGenericPtrMemSemantics",
+      "opcode" : 69,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pointer'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpInBoundsPtrAccessChain",
+      "opcode" : 70,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                            "name" : "'Base'" },
+        { "kind" : "IdRef",                            "name" : "'Element'" },
+        { "kind" : "IdRef",        "quantifier" : "*", "name" : "'Indexes'" }
+      ],
+      "capabilities" : [ "Addresses" ]
+    },
+    {
+      "opname" : "OpDecorate",
+      "opcode" : 71,
+      "operands" : [
+        { "kind" : "IdRef",      "name" : "'Target'" },
+        { "kind" : "Decoration" }
+      ]
+    },
+    {
+      "opname" : "OpMemberDecorate",
+      "opcode" : 72,
+      "operands" : [
+        { "kind" : "IdRef",          "name" : "'Structure Type'" },
+        { "kind" : "LiteralInteger", "name" : "'Member'" },
+        { "kind" : "Decoration" }
+      ]
+    },
+    {
+      "opname" : "OpDecorationGroup",
+      "opcode" : 73,
+      "operands" : [
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpGroupDecorate",
+      "opcode" : 74,
+      "operands" : [
+        { "kind" : "IdRef",                     "name" : "'Decoration Group'" },
+        { "kind" : "IdRef", "quantifier" : "*", "name" : "'Targets'" }
+      ]
+    },
+    {
+      "opname" : "OpGroupMemberDecorate",
+      "opcode" : 75,
+      "operands" : [
+        { "kind" : "IdRef",                                       "name" : "'Decoration Group'" },
+        { "kind" : "PairIdRefLiteralInteger", "quantifier" : "*", "name" : "'Targets'" }
+      ]
+    },
+    {
+      "opname" : "OpVectorExtractDynamic",
+      "opcode" : 77,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Vector'" },
+        { "kind" : "IdRef",        "name" : "'Index'" }
+      ]
+    },
+    {
+      "opname" : "OpVectorInsertDynamic",
+      "opcode" : 78,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Vector'" },
+        { "kind" : "IdRef",        "name" : "'Component'" },
+        { "kind" : "IdRef",        "name" : "'Index'" }
+      ]
+    },
+    {
+      "opname" : "OpVectorShuffle",
+      "opcode" : 79,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                              "name" : "'Vector 1'" },
+        { "kind" : "IdRef",                              "name" : "'Vector 2'" },
+        { "kind" : "LiteralInteger", "quantifier" : "*", "name" : "'Components'" }
+      ]
+    },
+    {
+      "opname" : "OpCompositeConstruct",
+      "opcode" : 80,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "quantifier" : "*", "name" : "'Constituents'" }
+      ]
+    },
+    {
+      "opname" : "OpCompositeExtract",
+      "opcode" : 81,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                              "name" : "'Composite'" },
+        { "kind" : "LiteralInteger", "quantifier" : "*", "name" : "'Indexes'" }
+      ]
+    },
+    {
+      "opname" : "OpCompositeInsert",
+      "opcode" : 82,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                              "name" : "'Object'" },
+        { "kind" : "IdRef",                              "name" : "'Composite'" },
+        { "kind" : "LiteralInteger", "quantifier" : "*", "name" : "'Indexes'" }
+      ]
+    },
+    {
+      "opname" : "OpCopyObject",
+      "opcode" : 83,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand'" }
+      ]
+    },
+    {
+      "opname" : "OpTranspose",
+      "opcode" : 84,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Matrix'" }
+      ],
+      "capabilities" : [ "Matrix" ]
+    },
+    {
+      "opname" : "OpSampledImage",
+      "opcode" : 86,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Image'" },
+        { "kind" : "IdRef",        "name" : "'Sampler'" }
+      ]
+    },
+    {
+      "opname" : "OpImageSampleImplicitLod",
+      "opcode" : 87,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpImageSampleExplicitLod",
+      "opcode" : 88,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",         "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",         "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands" }
+      ]
+    },
+    {
+      "opname" : "OpImageSampleDrefImplicitLod",
+      "opcode" : 89,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "IdRef",                             "name" : "'D~ref~'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpImageSampleDrefExplicitLod",
+      "opcode" : 90,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",         "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",         "name" : "'Coordinate'" },
+        { "kind" : "IdRef",         "name" : "'D~ref~'" },
+        { "kind" : "ImageOperands" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpImageSampleProjImplicitLod",
+      "opcode" : 91,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpImageSampleProjExplicitLod",
+      "opcode" : 92,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",         "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",         "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpImageSampleProjDrefImplicitLod",
+      "opcode" : 93,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "IdRef",                             "name" : "'D~ref~'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpImageSampleProjDrefExplicitLod",
+      "opcode" : 94,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",         "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",         "name" : "'Coordinate'" },
+        { "kind" : "IdRef",         "name" : "'D~ref~'" },
+        { "kind" : "ImageOperands" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpImageFetch",
+      "opcode" : 95,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ]
+    },
+    {
+      "opname" : "OpImageGather",
+      "opcode" : 96,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "IdRef",                             "name" : "'Component'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpImageDrefGather",
+      "opcode" : 97,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "IdRef",                             "name" : "'D~ref~'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpImageRead",
+      "opcode" : 98,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ]
+    },
+    {
+      "opname" : "OpImageWrite",
+      "opcode" : 99,
+      "operands" : [
+        { "kind" : "IdRef",                             "name" : "'Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "IdRef",                             "name" : "'Texel'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ]
+    },
+    {
+      "opname" : "OpImage",
+      "opcode" : 100,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Sampled Image'" }
+      ]
+    },
+    {
+      "opname" : "OpImageQueryFormat",
+      "opcode" : 101,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Image'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpImageQueryOrder",
+      "opcode" : 102,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Image'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpImageQuerySizeLod",
+      "opcode" : 103,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Image'" },
+        { "kind" : "IdRef",        "name" : "'Level of Detail'" }
+      ],
+      "capabilities" : [ "Kernel", "ImageQuery" ]
+    },
+    {
+      "opname" : "OpImageQuerySize",
+      "opcode" : 104,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Image'" }
+      ],
+      "capabilities" : [ "Kernel", "ImageQuery" ]
+    },
+    {
+      "opname" : "OpImageQueryLod",
+      "opcode" : 105,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Image'" },
+        { "kind" : "IdRef",        "name" : "'Coordinate'" }
+      ],
+      "capabilities" : [ "ImageQuery" ]
+    },
+    {
+      "opname" : "OpImageQueryLevels",
+      "opcode" : 106,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Image'" }
+      ],
+      "capabilities" : [ "Kernel", "ImageQuery" ]
+    },
+    {
+      "opname" : "OpImageQuerySamples",
+      "opcode" : 107,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Image'" }
+      ],
+      "capabilities" : [ "Kernel", "ImageQuery" ]
+    },
+    {
+      "opname" : "OpConvertFToU",
+      "opcode" : 109,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Float Value'" }
+      ]
+    },
+    {
+      "opname" : "OpConvertFToS",
+      "opcode" : 110,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Float Value'" }
+      ]
+    },
+    {
+      "opname" : "OpConvertSToF",
+      "opcode" : 111,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Signed Value'" }
+      ]
+    },
+    {
+      "opname" : "OpConvertUToF",
+      "opcode" : 112,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Unsigned Value'" }
+      ]
+    },
+    {
+      "opname" : "OpUConvert",
+      "opcode" : 113,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Unsigned Value'" }
+      ]
+    },
+    {
+      "opname" : "OpSConvert",
+      "opcode" : 114,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Signed Value'" }
+      ]
+    },
+    {
+      "opname" : "OpFConvert",
+      "opcode" : 115,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Float Value'" }
+      ]
+    },
+    {
+      "opname" : "OpQuantizeToF16",
+      "opcode" : 116,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpConvertPtrToU",
+      "opcode" : 117,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pointer'" }
+      ],
+      "capabilities" : [ "Addresses" ]
+    },
+    {
+      "opname" : "OpSatConvertSToU",
+      "opcode" : 118,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Signed Value'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpSatConvertUToS",
+      "opcode" : 119,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Unsigned Value'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpConvertUToPtr",
+      "opcode" : 120,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Integer Value'" }
+      ],
+      "capabilities" : [ "Addresses" ]
+    },
+    {
+      "opname" : "OpPtrCastToGeneric",
+      "opcode" : 121,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pointer'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpGenericCastToPtr",
+      "opcode" : 122,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pointer'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpGenericCastToPtrExplicit",
+      "opcode" : 123,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pointer'" },
+        { "kind" : "StorageClass", "name" : "'Storage'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpBitcast",
+      "opcode" : 124,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand'" }
+      ]
+    },
+    {
+      "opname" : "OpSNegate",
+      "opcode" : 126,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand'" }
+      ]
+    },
+    {
+      "opname" : "OpFNegate",
+      "opcode" : 127,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand'" }
+      ]
+    },
+    {
+      "opname" : "OpIAdd",
+      "opcode" : 128,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFAdd",
+      "opcode" : 129,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpISub",
+      "opcode" : 130,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFSub",
+      "opcode" : 131,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpIMul",
+      "opcode" : 132,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFMul",
+      "opcode" : 133,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpUDiv",
+      "opcode" : 134,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpSDiv",
+      "opcode" : 135,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFDiv",
+      "opcode" : 136,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpUMod",
+      "opcode" : 137,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpSRem",
+      "opcode" : 138,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpSMod",
+      "opcode" : 139,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFRem",
+      "opcode" : 140,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFMod",
+      "opcode" : 141,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpVectorTimesScalar",
+      "opcode" : 142,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Vector'" },
+        { "kind" : "IdRef",        "name" : "'Scalar'" }
+      ]
+    },
+    {
+      "opname" : "OpMatrixTimesScalar",
+      "opcode" : 143,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Matrix'" },
+        { "kind" : "IdRef",        "name" : "'Scalar'" }
+      ],
+      "capabilities" : [ "Matrix" ]
+    },
+    {
+      "opname" : "OpVectorTimesMatrix",
+      "opcode" : 144,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Vector'" },
+        { "kind" : "IdRef",        "name" : "'Matrix'" }
+      ],
+      "capabilities" : [ "Matrix" ]
+    },
+    {
+      "opname" : "OpMatrixTimesVector",
+      "opcode" : 145,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Matrix'" },
+        { "kind" : "IdRef",        "name" : "'Vector'" }
+      ],
+      "capabilities" : [ "Matrix" ]
+    },
+    {
+      "opname" : "OpMatrixTimesMatrix",
+      "opcode" : 146,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'LeftMatrix'" },
+        { "kind" : "IdRef",        "name" : "'RightMatrix'" }
+      ],
+      "capabilities" : [ "Matrix" ]
+    },
+    {
+      "opname" : "OpOuterProduct",
+      "opcode" : 147,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Vector 1'" },
+        { "kind" : "IdRef",        "name" : "'Vector 2'" }
+      ],
+      "capabilities" : [ "Matrix" ]
+    },
+    {
+      "opname" : "OpDot",
+      "opcode" : 148,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Vector 1'" },
+        { "kind" : "IdRef",        "name" : "'Vector 2'" }
+      ]
+    },
+    {
+      "opname" : "OpIAddCarry",
+      "opcode" : 149,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpISubBorrow",
+      "opcode" : 150,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpUMulExtended",
+      "opcode" : 151,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpSMulExtended",
+      "opcode" : 152,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpAny",
+      "opcode" : 154,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Vector'" }
+      ]
+    },
+    {
+      "opname" : "OpAll",
+      "opcode" : 155,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Vector'" }
+      ]
+    },
+    {
+      "opname" : "OpIsNan",
+      "opcode" : 156,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'x'" }
+      ]
+    },
+    {
+      "opname" : "OpIsInf",
+      "opcode" : 157,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'x'" }
+      ]
+    },
+    {
+      "opname" : "OpIsFinite",
+      "opcode" : 158,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'x'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpIsNormal",
+      "opcode" : 159,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'x'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpSignBitSet",
+      "opcode" : 160,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'x'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpLessOrGreater",
+      "opcode" : 161,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'x'" },
+        { "kind" : "IdRef",        "name" : "'y'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpOrdered",
+      "opcode" : 162,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'x'" },
+        { "kind" : "IdRef",        "name" : "'y'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpUnordered",
+      "opcode" : 163,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'x'" },
+        { "kind" : "IdRef",        "name" : "'y'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpLogicalEqual",
+      "opcode" : 164,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpLogicalNotEqual",
+      "opcode" : 165,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpLogicalOr",
+      "opcode" : 166,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpLogicalAnd",
+      "opcode" : 167,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpLogicalNot",
+      "opcode" : 168,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand'" }
+      ]
+    },
+    {
+      "opname" : "OpSelect",
+      "opcode" : 169,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Condition'" },
+        { "kind" : "IdRef",        "name" : "'Object 1'" },
+        { "kind" : "IdRef",        "name" : "'Object 2'" }
+      ]
+    },
+    {
+      "opname" : "OpIEqual",
+      "opcode" : 170,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpINotEqual",
+      "opcode" : 171,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpUGreaterThan",
+      "opcode" : 172,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpSGreaterThan",
+      "opcode" : 173,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpUGreaterThanEqual",
+      "opcode" : 174,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpSGreaterThanEqual",
+      "opcode" : 175,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpULessThan",
+      "opcode" : 176,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpSLessThan",
+      "opcode" : 177,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpULessThanEqual",
+      "opcode" : 178,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpSLessThanEqual",
+      "opcode" : 179,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFOrdEqual",
+      "opcode" : 180,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFUnordEqual",
+      "opcode" : 181,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFOrdNotEqual",
+      "opcode" : 182,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFUnordNotEqual",
+      "opcode" : 183,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFOrdLessThan",
+      "opcode" : 184,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFUnordLessThan",
+      "opcode" : 185,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFOrdGreaterThan",
+      "opcode" : 186,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFUnordGreaterThan",
+      "opcode" : 187,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFOrdLessThanEqual",
+      "opcode" : 188,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFUnordLessThanEqual",
+      "opcode" : 189,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFOrdGreaterThanEqual",
+      "opcode" : 190,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFUnordGreaterThanEqual",
+      "opcode" : 191,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpShiftRightLogical",
+      "opcode" : 194,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Base'" },
+        { "kind" : "IdRef",        "name" : "'Shift'" }
+      ]
+    },
+    {
+      "opname" : "OpShiftRightArithmetic",
+      "opcode" : 195,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Base'" },
+        { "kind" : "IdRef",        "name" : "'Shift'" }
+      ]
+    },
+    {
+      "opname" : "OpShiftLeftLogical",
+      "opcode" : 196,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Base'" },
+        { "kind" : "IdRef",        "name" : "'Shift'" }
+      ]
+    },
+    {
+      "opname" : "OpBitwiseOr",
+      "opcode" : 197,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpBitwiseXor",
+      "opcode" : 198,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpBitwiseAnd",
+      "opcode" : 199,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpNot",
+      "opcode" : 200,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand'" }
+      ]
+    },
+    {
+      "opname" : "OpBitFieldInsert",
+      "opcode" : 201,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Base'" },
+        { "kind" : "IdRef",        "name" : "'Insert'" },
+        { "kind" : "IdRef",        "name" : "'Offset'" },
+        { "kind" : "IdRef",        "name" : "'Count'" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpBitFieldSExtract",
+      "opcode" : 202,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Base'" },
+        { "kind" : "IdRef",        "name" : "'Offset'" },
+        { "kind" : "IdRef",        "name" : "'Count'" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpBitFieldUExtract",
+      "opcode" : 203,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Base'" },
+        { "kind" : "IdRef",        "name" : "'Offset'" },
+        { "kind" : "IdRef",        "name" : "'Count'" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpBitReverse",
+      "opcode" : 204,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Base'" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpBitCount",
+      "opcode" : 205,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Base'" }
+      ]
+    },
+    {
+      "opname" : "OpDPdx",
+      "opcode" : 207,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'P'" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpDPdy",
+      "opcode" : 208,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'P'" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpFwidth",
+      "opcode" : 209,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'P'" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpDPdxFine",
+      "opcode" : 210,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'P'" }
+      ],
+      "capabilities" : [ "DerivativeControl" ]
+    },
+    {
+      "opname" : "OpDPdyFine",
+      "opcode" : 211,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'P'" }
+      ],
+      "capabilities" : [ "DerivativeControl" ]
+    },
+    {
+      "opname" : "OpFwidthFine",
+      "opcode" : 212,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'P'" }
+      ],
+      "capabilities" : [ "DerivativeControl" ]
+    },
+    {
+      "opname" : "OpDPdxCoarse",
+      "opcode" : 213,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'P'" }
+      ],
+      "capabilities" : [ "DerivativeControl" ]
+    },
+    {
+      "opname" : "OpDPdyCoarse",
+      "opcode" : 214,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'P'" }
+      ],
+      "capabilities" : [ "DerivativeControl" ]
+    },
+    {
+      "opname" : "OpFwidthCoarse",
+      "opcode" : 215,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'P'" }
+      ],
+      "capabilities" : [ "DerivativeControl" ]
+    },
+    {
+      "opname" : "OpEmitVertex",
+      "opcode" : 218,
+      "capabilities" : [ "Geometry" ]
+    },
+    {
+      "opname" : "OpEndPrimitive",
+      "opcode" : 219,
+      "capabilities" : [ "Geometry" ]
+    },
+    {
+      "opname" : "OpEmitStreamVertex",
+      "opcode" : 220,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Stream'" }
+      ],
+      "capabilities" : [ "GeometryStreams" ]
+    },
+    {
+      "opname" : "OpEndStreamPrimitive",
+      "opcode" : 221,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Stream'" }
+      ],
+      "capabilities" : [ "GeometryStreams" ]
+    },
+    {
+      "opname" : "OpControlBarrier",
+      "opcode" : 224,
+      "operands" : [
+        { "kind" : "IdScope",           "name" : "'Execution'" },
+        { "kind" : "IdScope",           "name" : "'Memory'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" }
+      ]
+    },
+    {
+      "opname" : "OpMemoryBarrier",
+      "opcode" : 225,
+      "operands" : [
+        { "kind" : "IdScope",           "name" : "'Memory'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicLoad",
+      "opcode" : 227,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicStore",
+      "opcode" : 228,
+      "operands" : [
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicExchange",
+      "opcode" : 229,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicCompareExchange",
+      "opcode" : 230,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Equal'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Unequal'" },
+        { "kind" : "IdRef",             "name" : "'Value'" },
+        { "kind" : "IdRef",             "name" : "'Comparator'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicCompareExchangeWeak",
+      "opcode" : 231,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Equal'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Unequal'" },
+        { "kind" : "IdRef",             "name" : "'Value'" },
+        { "kind" : "IdRef",             "name" : "'Comparator'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpAtomicIIncrement",
+      "opcode" : 232,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicIDecrement",
+      "opcode" : 233,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicIAdd",
+      "opcode" : 234,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicISub",
+      "opcode" : 235,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicSMin",
+      "opcode" : 236,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicUMin",
+      "opcode" : 237,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicSMax",
+      "opcode" : 238,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicUMax",
+      "opcode" : 239,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicAnd",
+      "opcode" : 240,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicOr",
+      "opcode" : 241,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicXor",
+      "opcode" : 242,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpPhi",
+      "opcode" : 245,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "PairIdRefIdRef", "quantifier" : "*", "name" : "'Variable, Parent, ...'" }
+      ]
+    },
+    {
+      "opname" : "OpLoopMerge",
+      "opcode" : 246,
+      "operands" : [
+        { "kind" : "IdRef",       "name" : "'Merge Block'" },
+        { "kind" : "IdRef",       "name" : "'Continue Target'" },
+        { "kind" : "LoopControl" }
+      ]
+    },
+    {
+      "opname" : "OpSelectionMerge",
+      "opcode" : 247,
+      "operands" : [
+        { "kind" : "IdRef",            "name" : "'Merge Block'" },
+        { "kind" : "SelectionControl" }
+      ]
+    },
+    {
+      "opname" : "OpLabel",
+      "opcode" : 248,
+      "operands" : [
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpBranch",
+      "opcode" : 249,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Target Label'" }
+      ]
+    },
+    {
+      "opname" : "OpBranchConditional",
+      "opcode" : 250,
+      "operands" : [
+        { "kind" : "IdRef",                              "name" : "'Condition'" },
+        { "kind" : "IdRef",                              "name" : "'True Label'" },
+        { "kind" : "IdRef",                              "name" : "'False Label'" },
+        { "kind" : "LiteralInteger", "quantifier" : "*", "name" : "'Branch weights'" }
+      ]
+    },
+    {
+      "opname" : "OpSwitch",
+      "opcode" : 251,
+      "operands" : [
+        { "kind" : "IdRef",                                       "name" : "'Selector'" },
+        { "kind" : "IdRef",                                       "name" : "'Default'" },
+        { "kind" : "PairLiteralIntegerIdRef", "quantifier" : "*", "name" : "'Target'" }
+      ]
+    },
+    {
+      "opname" : "OpKill",
+      "opcode" : 252,
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpReturn",
+      "opcode" : 253
+    },
+    {
+      "opname" : "OpReturnValue",
+      "opcode" : 254,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpUnreachable",
+      "opcode" : 255
+    },
+    {
+      "opname" : "OpLifetimeStart",
+      "opcode" : 256,
+      "operands" : [
+        { "kind" : "IdRef",          "name" : "'Pointer'" },
+        { "kind" : "LiteralInteger", "name" : "'Size'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpLifetimeStop",
+      "opcode" : 257,
+      "operands" : [
+        { "kind" : "IdRef",          "name" : "'Pointer'" },
+        { "kind" : "LiteralInteger", "name" : "'Size'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpGroupAsyncCopy",
+      "opcode" : 259,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",      "name" : "'Execution'" },
+        { "kind" : "IdRef",        "name" : "'Destination'" },
+        { "kind" : "IdRef",        "name" : "'Source'" },
+        { "kind" : "IdRef",        "name" : "'Num Elements'" },
+        { "kind" : "IdRef",        "name" : "'Stride'" },
+        { "kind" : "IdRef",        "name" : "'Event'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpGroupWaitEvents",
+      "opcode" : 260,
+      "operands" : [
+        { "kind" : "IdScope", "name" : "'Execution'" },
+        { "kind" : "IdRef",   "name" : "'Num Events'" },
+        { "kind" : "IdRef",   "name" : "'Events List'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpGroupAll",
+      "opcode" : 261,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",      "name" : "'Execution'" },
+        { "kind" : "IdRef",        "name" : "'Predicate'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupAny",
+      "opcode" : 262,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",      "name" : "'Execution'" },
+        { "kind" : "IdRef",        "name" : "'Predicate'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupBroadcast",
+      "opcode" : 263,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",      "name" : "'Execution'" },
+        { "kind" : "IdRef",        "name" : "'Value'" },
+        { "kind" : "IdRef",        "name" : "'LocalId'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupIAdd",
+      "opcode" : 264,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "'X'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupFAdd",
+      "opcode" : 265,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "'X'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupFMin",
+      "opcode" : 266,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "X" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupUMin",
+      "opcode" : 267,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "'X'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupSMin",
+      "opcode" : 268,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "X" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupFMax",
+      "opcode" : 269,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "X" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupUMax",
+      "opcode" : 270,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "X" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupSMax",
+      "opcode" : 271,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "X" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpReadPipe",
+      "opcode" : 274,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pipe'" },
+        { "kind" : "IdRef",        "name" : "'Pointer'" },
+        { "kind" : "IdRef",        "name" : "'Packet Size'" },
+        { "kind" : "IdRef",        "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpWritePipe",
+      "opcode" : 275,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pipe'" },
+        { "kind" : "IdRef",        "name" : "'Pointer'" },
+        { "kind" : "IdRef",        "name" : "'Packet Size'" },
+        { "kind" : "IdRef",        "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpReservedReadPipe",
+      "opcode" : 276,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pipe'" },
+        { "kind" : "IdRef",        "name" : "'Reserve Id'" },
+        { "kind" : "IdRef",        "name" : "'Index'" },
+        { "kind" : "IdRef",        "name" : "'Pointer'" },
+        { "kind" : "IdRef",        "name" : "'Packet Size'" },
+        { "kind" : "IdRef",        "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpReservedWritePipe",
+      "opcode" : 277,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pipe'" },
+        { "kind" : "IdRef",        "name" : "'Reserve Id'" },
+        { "kind" : "IdRef",        "name" : "'Index'" },
+        { "kind" : "IdRef",        "name" : "'Pointer'" },
+        { "kind" : "IdRef",        "name" : "'Packet Size'" },
+        { "kind" : "IdRef",        "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpReserveReadPipePackets",
+      "opcode" : 278,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pipe'" },
+        { "kind" : "IdRef",        "name" : "'Num Packets'" },
+        { "kind" : "IdRef",        "name" : "'Packet Size'" },
+        { "kind" : "IdRef",        "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpReserveWritePipePackets",
+      "opcode" : 279,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pipe'" },
+        { "kind" : "IdRef",        "name" : "'Num Packets'" },
+        { "kind" : "IdRef",        "name" : "'Packet Size'" },
+        { "kind" : "IdRef",        "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpCommitReadPipe",
+      "opcode" : 280,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Pipe'" },
+        { "kind" : "IdRef", "name" : "'Reserve Id'" },
+        { "kind" : "IdRef", "name" : "'Packet Size'" },
+        { "kind" : "IdRef", "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpCommitWritePipe",
+      "opcode" : 281,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Pipe'" },
+        { "kind" : "IdRef", "name" : "'Reserve Id'" },
+        { "kind" : "IdRef", "name" : "'Packet Size'" },
+        { "kind" : "IdRef", "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpIsValidReserveId",
+      "opcode" : 282,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Reserve Id'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpGetNumPipePackets",
+      "opcode" : 283,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pipe'" },
+        { "kind" : "IdRef",        "name" : "'Packet Size'" },
+        { "kind" : "IdRef",        "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpGetMaxPipePackets",
+      "opcode" : 284,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pipe'" },
+        { "kind" : "IdRef",        "name" : "'Packet Size'" },
+        { "kind" : "IdRef",        "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpGroupReserveReadPipePackets",
+      "opcode" : 285,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",      "name" : "'Execution'" },
+        { "kind" : "IdRef",        "name" : "'Pipe'" },
+        { "kind" : "IdRef",        "name" : "'Num Packets'" },
+        { "kind" : "IdRef",        "name" : "'Packet Size'" },
+        { "kind" : "IdRef",        "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpGroupReserveWritePipePackets",
+      "opcode" : 286,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",      "name" : "'Execution'" },
+        { "kind" : "IdRef",        "name" : "'Pipe'" },
+        { "kind" : "IdRef",        "name" : "'Num Packets'" },
+        { "kind" : "IdRef",        "name" : "'Packet Size'" },
+        { "kind" : "IdRef",        "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpGroupCommitReadPipe",
+      "opcode" : 287,
+      "operands" : [
+        { "kind" : "IdScope", "name" : "'Execution'" },
+        { "kind" : "IdRef",   "name" : "'Pipe'" },
+        { "kind" : "IdRef",   "name" : "'Reserve Id'" },
+        { "kind" : "IdRef",   "name" : "'Packet Size'" },
+        { "kind" : "IdRef",   "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpGroupCommitWritePipe",
+      "opcode" : 288,
+      "operands" : [
+        { "kind" : "IdScope", "name" : "'Execution'" },
+        { "kind" : "IdRef",   "name" : "'Pipe'" },
+        { "kind" : "IdRef",   "name" : "'Reserve Id'" },
+        { "kind" : "IdRef",   "name" : "'Packet Size'" },
+        { "kind" : "IdRef",   "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpEnqueueMarker",
+      "opcode" : 291,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Queue'" },
+        { "kind" : "IdRef",        "name" : "'Num Events'" },
+        { "kind" : "IdRef",        "name" : "'Wait Events'" },
+        { "kind" : "IdRef",        "name" : "'Ret Event'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpEnqueueKernel",
+      "opcode" : 292,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                            "name" : "'Queue'" },
+        { "kind" : "IdRef",                            "name" : "'Flags'" },
+        { "kind" : "IdRef",                            "name" : "'ND Range'" },
+        { "kind" : "IdRef",                            "name" : "'Num Events'" },
+        { "kind" : "IdRef",                            "name" : "'Wait Events'" },
+        { "kind" : "IdRef",                            "name" : "'Ret Event'" },
+        { "kind" : "IdRef",                            "name" : "'Invoke'" },
+        { "kind" : "IdRef",                            "name" : "'Param'" },
+        { "kind" : "IdRef",                            "name" : "'Param Size'" },
+        { "kind" : "IdRef",                            "name" : "'Param Align'" },
+        { "kind" : "IdRef",        "quantifier" : "*", "name" : "'Local Size'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpGetKernelNDrangeSubGroupCount",
+      "opcode" : 293,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'ND Range'" },
+        { "kind" : "IdRef",        "name" : "'Invoke'" },
+        { "kind" : "IdRef",        "name" : "'Param'" },
+        { "kind" : "IdRef",        "name" : "'Param Size'" },
+        { "kind" : "IdRef",        "name" : "'Param Align'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpGetKernelNDrangeMaxSubGroupSize",
+      "opcode" : 294,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'ND Range'" },
+        { "kind" : "IdRef",        "name" : "'Invoke'" },
+        { "kind" : "IdRef",        "name" : "'Param'" },
+        { "kind" : "IdRef",        "name" : "'Param Size'" },
+        { "kind" : "IdRef",        "name" : "'Param Align'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpGetKernelWorkGroupSize",
+      "opcode" : 295,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Invoke'" },
+        { "kind" : "IdRef",        "name" : "'Param'" },
+        { "kind" : "IdRef",        "name" : "'Param Size'" },
+        { "kind" : "IdRef",        "name" : "'Param Align'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpGetKernelPreferredWorkGroupSizeMultiple",
+      "opcode" : 296,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Invoke'" },
+        { "kind" : "IdRef",        "name" : "'Param'" },
+        { "kind" : "IdRef",        "name" : "'Param Size'" },
+        { "kind" : "IdRef",        "name" : "'Param Align'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpRetainEvent",
+      "opcode" : 297,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Event'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpReleaseEvent",
+      "opcode" : 298,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Event'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpCreateUserEvent",
+      "opcode" : 299,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpIsValidEvent",
+      "opcode" : 300,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Event'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpSetUserEventStatus",
+      "opcode" : 301,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Event'" },
+        { "kind" : "IdRef", "name" : "'Status'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpCaptureEventProfilingInfo",
+      "opcode" : 302,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Event'" },
+        { "kind" : "IdRef", "name" : "'Profiling Info'" },
+        { "kind" : "IdRef", "name" : "'Value'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpGetDefaultQueue",
+      "opcode" : 303,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpBuildNDRange",
+      "opcode" : 304,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'GlobalWorkSize'" },
+        { "kind" : "IdRef",        "name" : "'LocalWorkSize'" },
+        { "kind" : "IdRef",        "name" : "'GlobalWorkOffset'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpImageSparseSampleImplicitLod",
+      "opcode" : 305,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseSampleExplicitLod",
+      "opcode" : 306,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",         "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",         "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseSampleDrefImplicitLod",
+      "opcode" : 307,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "IdRef",                             "name" : "'D~ref~'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseSampleDrefExplicitLod",
+      "opcode" : 308,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",         "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",         "name" : "'Coordinate'" },
+        { "kind" : "IdRef",         "name" : "'D~ref~'" },
+        { "kind" : "ImageOperands" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseSampleProjImplicitLod",
+      "opcode" : 309,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseSampleProjExplicitLod",
+      "opcode" : 310,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",         "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",         "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseSampleProjDrefImplicitLod",
+      "opcode" : 311,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "IdRef",                             "name" : "'D~ref~'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseSampleProjDrefExplicitLod",
+      "opcode" : 312,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",         "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",         "name" : "'Coordinate'" },
+        { "kind" : "IdRef",         "name" : "'D~ref~'" },
+        { "kind" : "ImageOperands" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseFetch",
+      "opcode" : 313,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseGather",
+      "opcode" : 314,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "IdRef",                             "name" : "'Component'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseDrefGather",
+      "opcode" : 315,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "IdRef",                             "name" : "'D~ref~'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseTexelsResident",
+      "opcode" : 316,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Resident Code'" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpNoLine",
+      "opcode" : 317
+    },
+    {
+      "opname" : "OpAtomicFlagTestAndSet",
+      "opcode" : 318,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpAtomicFlagClear",
+      "opcode" : 319,
+      "operands" : [
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpImageSparseRead",
+      "opcode" : 320,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    }
+  ],
+  "operand_kinds" : [
+    {
+      "category" : "BitEnum",
+      "kind" : "ImageOperands",
+      "enumerants" : [
+        {
+          "enumerant" : "None",
+          "value" : "0x0000"
+        },
+        {
+          "enumerant" : "Bias",
+          "value" : "0x0001",
+          "capabilities" : [ "Shader" ],
+          "parameters" : [
+            { "kind" : "IdRef" }
+          ]
+        },
+        {
+          "enumerant" : "Lod",
+          "value" : "0x0002",
+          "parameters" : [
+            { "kind" : "IdRef" }
+          ]
+        },
+        {
+          "enumerant" : "Grad",
+          "value" : "0x0004",
+          "parameters" : [
+            { "kind" : "IdRef" },
+            { "kind" : "IdRef" }
+          ]
+        },
+        {
+          "enumerant" : "ConstOffset",
+          "value" : "0x0008",
+          "parameters" : [
+            { "kind" : "IdRef" }
+          ]
+        },
+        {
+          "enumerant" : "Offset",
+          "value" : "0x0010",
+          "capabilities" : [ "ImageGatherExtended" ],
+          "parameters" : [
+            { "kind" : "IdRef" }
+          ]
+        },
+        {
+          "enumerant" : "ConstOffsets",
+          "value" : "0x0020",
+          "parameters" : [
+            { "kind" : "IdRef" }
+          ]
+        },
+        {
+          "enumerant" : "Sample",
+          "value" : "0x0040",
+          "parameters" : [
+            { "kind" : "IdRef" }
+          ]
+        },
+        {
+          "enumerant" : "MinLod",
+          "value" : "0x0080",
+          "capabilities" : [ "MinLod" ],
+          "parameters" : [
+            { "kind" : "IdRef" }
+          ]
+        }
+      ]
+    },
+    {
+      "category" : "BitEnum",
+      "kind" : "FPFastMathMode",
+      "enumerants" : [
+        {
+          "enumerant" : "None",
+          "value" : "0x0000"
+        },
+        {
+          "enumerant" : "NotNaN",
+          "value" : "0x0001",
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "NotInf",
+          "value" : "0x0002",
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "NSZ",
+          "value" : "0x0004",
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "AllowRecip",
+          "value" : "0x0008",
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Fast",
+          "value" : "0x0010",
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "BitEnum",
+      "kind" : "SelectionControl",
+      "enumerants" : [
+        {
+          "enumerant" : "None",
+          "value" : "0x0000"
+        },
+        {
+          "enumerant" : "Flatten",
+          "value" : "0x0001"
+        },
+        {
+          "enumerant" : "DontFlatten",
+          "value" : "0x0002"
+        }
+      ]
+    },
+    {
+      "category" : "BitEnum",
+      "kind" : "LoopControl",
+      "enumerants" : [
+        {
+          "enumerant" : "None",
+          "value" : "0x0000"
+        },
+        {
+          "enumerant" : "Unroll",
+          "value" : "0x0001"
+        },
+        {
+          "enumerant" : "DontUnroll",
+          "value" : "0x0002"
+        }
+      ]
+    },
+    {
+      "category" : "BitEnum",
+      "kind" : "FunctionControl",
+      "enumerants" : [
+        {
+          "enumerant" : "None",
+          "value" : "0x0000"
+        },
+        {
+          "enumerant" : "Inline",
+          "value" : "0x0001"
+        },
+        {
+          "enumerant" : "DontInline",
+          "value" : "0x0002"
+        },
+        {
+          "enumerant" : "Pure",
+          "value" : "0x0004"
+        },
+        {
+          "enumerant" : "Const",
+          "value" : "0x0008"
+        }
+      ]
+    },
+    {
+      "category" : "BitEnum",
+      "kind" : "MemorySemantics",
+      "enumerants" : [
+        {
+          "enumerant" : "Relaxed",
+          "value" : "0x0000"
+        },
+        {
+          "enumerant" : "None",
+          "value" : "0x0000"
+        },
+        {
+          "enumerant" : "SequentiallyConsistent",
+          "value" : "0x0010"
+        },
+        {
+          "enumerant" : "Acquire",
+          "value" : "0x0002"
+        },
+        {
+          "enumerant" : "Release",
+          "value" : "0x0004"
+        },
+        {
+          "enumerant" : "AcquireRelease",
+          "value" : "0x0008"
+        },
+        {
+          "enumerant" : "UniformMemory",
+          "value" : "0x0040",
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "SubgroupMemory",
+          "value" : "0x0080"
+        },
+        {
+          "enumerant" : "WorkgroupMemory",
+          "value" : "0x0100"
+        },
+        {
+          "enumerant" : "CrossWorkgroupMemory",
+          "value" : "0x0200"
+        },
+        {
+          "enumerant" : "AtomicCounterMemory",
+          "value" : "0x0400",
+          "capabilities" : [ "AtomicStorage" ]
+        },
+        {
+          "enumerant" : "ImageMemory",
+          "value" : "0x0800"
+        }
+      ]
+    },
+    {
+      "category" : "BitEnum",
+      "kind" : "MemoryAccess",
+      "enumerants" : [
+        {
+          "enumerant" : "None",
+          "value" : "0x0000"
+        },
+        {
+          "enumerant" : "Volatile",
+          "value" : "0x0001"
+        },
+        {
+          "enumerant" : "Aligned",
+          "value" : "0x0002",
+          "parameters" : [
+            { "kind" : "LiteralInteger" }
+          ]
+        },
+        {
+          "enumerant" : "Nontemporal",
+          "value" : "0x0004"
+        }
+      ]
+    },
+    {
+      "category" : "BitEnum",
+      "kind" : "KernelProfilingInfo",
+      "enumerants" : [
+        {
+          "enumerant" : "None",
+          "value" : "0x0000"
+        },
+        {
+          "enumerant" : "CmdExecTime",
+          "value" : "0x0001",
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "SourceLanguage",
+      "enumerants" : [
+        {
+          "enumerant" : "Unknown",
+          "value" : 0
+        },
+        {
+          "enumerant" : "ESSL",
+          "value" : 1
+        },
+        {
+          "enumerant" : "GLSL",
+          "value" : 2
+        },
+        {
+          "enumerant" : "OpenCL_C",
+          "value" : 3
+        },
+        {
+          "enumerant" : "OpenCL_CPP",
+          "value" : 4
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "ExecutionModel",
+      "enumerants" : [
+        {
+          "enumerant" : "Vertex",
+          "value" : 0,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "TessellationControl",
+          "value" : 1,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "TessellationEvaluation",
+          "value" : 2,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "Geometry",
+          "value" : 3,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "Fragment",
+          "value" : 4,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "GLCompute",
+          "value" : 5,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Kernel",
+          "value" : 6,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "AddressingModel",
+      "enumerants" : [
+        {
+          "enumerant" : "Logical",
+          "value" : 0
+        },
+        {
+          "enumerant" : "Physical32",
+          "value" : 1,
+          "capabilities" : [ "Addresses" ]
+        },
+        {
+          "enumerant" : "Physical64",
+          "value" : 2,
+          "capabilities" : [ "Addresses" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "MemoryModel",
+      "enumerants" : [
+        {
+          "enumerant" : "Simple",
+          "value" : 0,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "GLSL450",
+          "value" : 1,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "OpenCL",
+          "value" : 2,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "ExecutionMode",
+      "enumerants" : [
+        {
+          "enumerant" : "Invocations",
+          "value" : 0,
+          "capabilities" : [ "Geometry" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Number of <<Invocation,invocations>>'" }
+          ]
+        },
+        {
+          "enumerant" : "SpacingEqual",
+          "value" : 1,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "SpacingFractionalEven",
+          "value" : 2,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "SpacingFractionalOdd",
+          "value" : 3,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "VertexOrderCw",
+          "value" : 4,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "VertexOrderCcw",
+          "value" : 5,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "PixelCenterInteger",
+          "value" : 6,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "OriginUpperLeft",
+          "value" : 7,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "OriginLowerLeft",
+          "value" : 8,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "EarlyFragmentTests",
+          "value" : 9,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "PointMode",
+          "value" : 10,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "Xfb",
+          "value" : 11,
+          "capabilities" : [ "TransformFeedback" ]
+        },
+        {
+          "enumerant" : "DepthReplacing",
+          "value" : 12,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "DepthGreater",
+          "value" : 14,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "DepthLess",
+          "value" : 15,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "DepthUnchanged",
+          "value" : 16,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "LocalSize",
+          "value" : 17,
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'x size'" },
+            { "kind" : "LiteralInteger", "name" : "'y size'" },
+            { "kind" : "LiteralInteger", "name" : "'z size'" }
+          ]
+        },
+        {
+          "enumerant" : "LocalSizeHint",
+          "value" : 18,
+          "capabilities" : [ "Kernel" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'x size'" },
+            { "kind" : "LiteralInteger", "name" : "'y size'" },
+            { "kind" : "LiteralInteger", "name" : "'z size'" }
+          ]
+        },
+        {
+          "enumerant" : "InputPoints",
+          "value" : 19,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "InputLines",
+          "value" : 20,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "InputLinesAdjacency",
+          "value" : 21,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "Triangles",
+          "value" : 22,
+          "capabilities" : [ "Geometry", "Tessellation" ]
+        },
+        {
+          "enumerant" : "InputTrianglesAdjacency",
+          "value" : 23,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "Quads",
+          "value" : 24,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "Isolines",
+          "value" : 25,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "OutputVertices",
+          "value" : 26,
+          "capabilities" : [ "Geometry", "Tessellation" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Vertex count'" }
+          ]
+        },
+        {
+          "enumerant" : "OutputPoints",
+          "value" : 27,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "OutputLineStrip",
+          "value" : 28,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "OutputTriangleStrip",
+          "value" : 29,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "VecTypeHint",
+          "value" : 30,
+          "capabilities" : [ "Kernel" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Vector type'" }
+          ]
+        },
+        {
+          "enumerant" : "ContractionOff",
+          "value" : 31,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "StorageClass",
+      "enumerants" : [
+        {
+          "enumerant" : "UniformConstant",
+          "value" : 0
+        },
+        {
+          "enumerant" : "Input",
+          "value" : 1,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Uniform",
+          "value" : 2,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Output",
+          "value" : 3,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Workgroup",
+          "value" : 4
+        },
+        {
+          "enumerant" : "CrossWorkgroup",
+          "value" : 5
+        },
+        {
+          "enumerant" : "Private",
+          "value" : 6,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Function",
+          "value" : 7
+        },
+        {
+          "enumerant" : "Generic",
+          "value" : 8,
+          "capabilities" : [ "GenericPointer" ]
+        },
+        {
+          "enumerant" : "PushConstant",
+          "value" : 9,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "AtomicCounter",
+          "value" : 10,
+          "capabilities" : [ "AtomicStorage" ]
+        },
+        {
+          "enumerant" : "Image",
+          "value" : 11
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "Dim",
+      "enumerants" : [
+        {
+          "enumerant" : "1D",
+          "value" : 0,
+          "capabilities" : [ "Sampled1D" ]
+        },
+        {
+          "enumerant" : "2D",
+          "value" : 1
+        },
+        {
+          "enumerant" : "3D",
+          "value" : 2
+        },
+        {
+          "enumerant" : "Cube",
+          "value" : 3,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rect",
+          "value" : 4,
+          "capabilities" : [ "SampledRect" ]
+        },
+        {
+          "enumerant" : "Buffer",
+          "value" : 5,
+          "capabilities" : [ "SampledBuffer" ]
+        },
+        {
+          "enumerant" : "SubpassData",
+          "value" : 6,
+          "capabilities" : [ "InputAttachment" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "SamplerAddressingMode",
+      "enumerants" : [
+        {
+          "enumerant" : "None",
+          "value" : 0,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "ClampToEdge",
+          "value" : 1,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Clamp",
+          "value" : 2,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Repeat",
+          "value" : 3,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "RepeatMirrored",
+          "value" : 4,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "SamplerFilterMode",
+      "enumerants" : [
+        {
+          "enumerant" : "Nearest",
+          "value" : 0,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Linear",
+          "value" : 1,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "ImageFormat",
+      "enumerants" : [
+        {
+          "enumerant" : "Unknown",
+          "value" : 0
+        },
+        {
+          "enumerant" : "Rgba32f",
+          "value" : 1,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rgba16f",
+          "value" : 2,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "R32f",
+          "value" : 3,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rgba8",
+          "value" : 4,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rgba8Snorm",
+          "value" : 5,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rg32f",
+          "value" : 6,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rg16f",
+          "value" : 7,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "R11fG11fB10f",
+          "value" : 8,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "R16f",
+          "value" : 9,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rgba16",
+          "value" : 10,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rgb10A2",
+          "value" : 11,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rg16",
+          "value" : 12,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rg8",
+          "value" : 13,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "R16",
+          "value" : 14,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "R8",
+          "value" : 15,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rgba16Snorm",
+          "value" : 16,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rg16Snorm",
+          "value" : 17,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rg8Snorm",
+          "value" : 18,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "R16Snorm",
+          "value" : 19,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "R8Snorm",
+          "value" : 20,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rgba32i",
+          "value" : 21,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rgba16i",
+          "value" : 22,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rgba8i",
+          "value" : 23,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "R32i",
+          "value" : 24,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rg32i",
+          "value" : 25,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rg16i",
+          "value" : 26,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rg8i",
+          "value" : 27,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "R16i",
+          "value" : 28,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "R8i",
+          "value" : 29,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rgba32ui",
+          "value" : 30,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rgba16ui",
+          "value" : 31,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rgba8ui",
+          "value" : 32,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "R32ui",
+          "value" : 33,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rgb10a2ui",
+          "value" : 34,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rg32ui",
+          "value" : 35,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rg16ui",
+          "value" : 36,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rg8ui",
+          "value" : 37,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "R16ui",
+          "value" : 38,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "R8ui",
+          "value" : 39,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "ImageChannelOrder",
+      "enumerants" : [
+        {
+          "enumerant" : "R",
+          "value" : 0,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "A",
+          "value" : 1,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "RG",
+          "value" : 2,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "RA",
+          "value" : 3,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "RGB",
+          "value" : 4,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "RGBA",
+          "value" : 5,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "BGRA",
+          "value" : 6,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "ARGB",
+          "value" : 7,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Intensity",
+          "value" : 8,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Luminance",
+          "value" : 9,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Rx",
+          "value" : 10,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "RGx",
+          "value" : 11,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "RGBx",
+          "value" : 12,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Depth",
+          "value" : 13,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "DepthStencil",
+          "value" : 14,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "sRGB",
+          "value" : 15,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "sRGBx",
+          "value" : 16,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "sRGBA",
+          "value" : 17,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "sBGRA",
+          "value" : 18,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "ImageChannelDataType",
+      "enumerants" : [
+        {
+          "enumerant" : "SnormInt8",
+          "value" : 0,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "SnormInt16",
+          "value" : 1,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "UnormInt8",
+          "value" : 2,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "UnormInt16",
+          "value" : 3,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "UnormShort565",
+          "value" : 4,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "UnormShort555",
+          "value" : 5,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "UnormInt101010",
+          "value" : 6,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "SignedInt8",
+          "value" : 7,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "SignedInt16",
+          "value" : 8,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "SignedInt32",
+          "value" : 9,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "UnsignedInt8",
+          "value" : 10,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "UnsignedInt16",
+          "value" : 11,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "UnsignedInt32",
+          "value" : 12,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "HalfFloat",
+          "value" : 13,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Float",
+          "value" : 14,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "UnormInt24",
+          "value" : 15,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "UnormInt101010_2",
+          "value" : 16,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "FPRoundingMode",
+      "enumerants" : [
+        {
+          "enumerant" : "RTE",
+          "value" : 0,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "RTZ",
+          "value" : 1,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "RTP",
+          "value" : 2,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "RTN",
+          "value" : 3,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "LinkageType",
+      "enumerants" : [
+        {
+          "enumerant" : "Export",
+          "value" : 0,
+          "capabilities" : [ "Linkage" ]
+        },
+        {
+          "enumerant" : "Import",
+          "value" : 1,
+          "capabilities" : [ "Linkage" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "AccessQualifier",
+      "enumerants" : [
+        {
+          "enumerant" : "ReadOnly",
+          "value" : 0,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "WriteOnly",
+          "value" : 1,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "ReadWrite",
+          "value" : 2,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "FunctionParameterAttribute",
+      "enumerants" : [
+        {
+          "enumerant" : "Zext",
+          "value" : 0,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Sext",
+          "value" : 1,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "ByVal",
+          "value" : 2,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Sret",
+          "value" : 3,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "NoAlias",
+          "value" : 4,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "NoCapture",
+          "value" : 5,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "NoWrite",
+          "value" : 6,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "NoReadWrite",
+          "value" : 7,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "Decoration",
+      "enumerants" : [
+        {
+          "enumerant" : "RelaxedPrecision",
+          "value" : 0,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "SpecId",
+          "value" : 1,
+          "capabilities" : [ "Shader" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Specialization Constant ID'" }
+          ]
+        },
+        {
+          "enumerant" : "Block",
+          "value" : 2,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "BufferBlock",
+          "value" : 3,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "RowMajor",
+          "value" : 4,
+          "capabilities" : [ "Matrix" ]
+        },
+        {
+          "enumerant" : "ColMajor",
+          "value" : 5,
+          "capabilities" : [ "Matrix" ]
+        },
+        {
+          "enumerant" : "ArrayStride",
+          "value" : 6,
+          "capabilities" : [ "Shader" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Array Stride'" }
+          ]
+        },
+        {
+          "enumerant" : "MatrixStride",
+          "value" : 7,
+          "capabilities" : [ "Matrix" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Matrix Stride'" }
+          ]
+        },
+        {
+          "enumerant" : "GLSLShared",
+          "value" : 8,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "GLSLPacked",
+          "value" : 9,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "CPacked",
+          "value" : 10,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "BuiltIn",
+          "value" : 11,
+          "parameters" : [
+            { "kind" : "BuiltIn" }
+          ]
+        },
+        {
+          "enumerant" : "NoPerspective",
+          "value" : 13,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Flat",
+          "value" : 14,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Patch",
+          "value" : 15,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "Centroid",
+          "value" : 16,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Sample",
+          "value" : 17,
+          "capabilities" : [ "SampleRateShading" ]
+        },
+        {
+          "enumerant" : "Invariant",
+          "value" : 18,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Restrict",
+          "value" : 19
+        },
+        {
+          "enumerant" : "Aliased",
+          "value" : 20
+        },
+        {
+          "enumerant" : "Volatile",
+          "value" : 21
+        },
+        {
+          "enumerant" : "Constant",
+          "value" : 22,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Coherent",
+          "value" : 23
+        },
+        {
+          "enumerant" : "NonWritable",
+          "value" : 24
+        },
+        {
+          "enumerant" : "NonReadable",
+          "value" : 25
+        },
+        {
+          "enumerant" : "Uniform",
+          "value" : 26,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "SaturatedConversion",
+          "value" : 28,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Stream",
+          "value" : 29,
+          "capabilities" : [ "GeometryStreams" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Stream Number'" }
+          ]
+        },
+        {
+          "enumerant" : "Location",
+          "value" : 30,
+          "capabilities" : [ "Shader" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Location'" }
+          ]
+        },
+        {
+          "enumerant" : "Component",
+          "value" : 31,
+          "capabilities" : [ "Shader" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Component'" }
+          ]
+        },
+        {
+          "enumerant" : "Index",
+          "value" : 32,
+          "capabilities" : [ "Shader" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Index'" }
+          ]
+        },
+        {
+          "enumerant" : "Binding",
+          "value" : 33,
+          "capabilities" : [ "Shader" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Binding Point'" }
+          ]
+        },
+        {
+          "enumerant" : "DescriptorSet",
+          "value" : 34,
+          "capabilities" : [ "Shader" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Descriptor Set'" }
+          ]
+        },
+        {
+          "enumerant" : "Offset",
+          "value" : 35,
+          "capabilities" : [ "Shader" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Byte Offset'" }
+          ]
+        },
+        {
+          "enumerant" : "XfbBuffer",
+          "value" : 36,
+          "capabilities" : [ "TransformFeedback" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'XFB Buffer Number'" }
+          ]
+        },
+        {
+          "enumerant" : "XfbStride",
+          "value" : 37,
+          "capabilities" : [ "TransformFeedback" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'XFB Stride'" }
+          ]
+        },
+        {
+          "enumerant" : "FuncParamAttr",
+          "value" : 38,
+          "capabilities" : [ "Kernel" ],
+          "parameters" : [
+            { "kind" : "FunctionParameterAttribute", "name" : "'Function Parameter Attribute'" }
+          ]
+        },
+        {
+          "enumerant" : "FPRoundingMode",
+          "value" : 39,
+          "capabilities" : [ "Kernel" ],
+          "parameters" : [
+            { "kind" : "FPRoundingMode", "name" : "'Floating-Point Rounding Mode'" }
+          ]
+        },
+        {
+          "enumerant" : "FPFastMathMode",
+          "value" : 40,
+          "capabilities" : [ "Kernel" ],
+          "parameters" : [
+            { "kind" : "FPFastMathMode", "name" : "'Fast-Math Mode'" }
+          ]
+        },
+        {
+          "enumerant" : "LinkageAttributes",
+          "value" : 41,
+          "capabilities" : [ "Linkage" ],
+          "parameters" : [
+            { "kind" : "LiteralString", "name" : "'Name'" },
+            { "kind" : "LinkageType",   "name" : "'Linkage Type'" }
+          ]
+        },
+        {
+          "enumerant" : "NoContraction",
+          "value" : 42,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "InputAttachmentIndex",
+          "value" : 43,
+          "capabilities" : [ "InputAttachment" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Attachment Index'" }
+          ]
+        },
+        {
+          "enumerant" : "Alignment",
+          "value" : 44,
+          "capabilities" : [ "Kernel" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Alignment'" }
+          ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "BuiltIn",
+      "enumerants" : [
+        {
+          "enumerant" : "Position",
+          "value" : 0,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "PointSize",
+          "value" : 1,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "ClipDistance",
+          "value" : 3,
+          "capabilities" : [ "ClipDistance" ]
+        },
+        {
+          "enumerant" : "CullDistance",
+          "value" : 4,
+          "capabilities" : [ "CullDistance" ]
+        },
+        {
+          "enumerant" : "VertexId",
+          "value" : 5,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "InstanceId",
+          "value" : 6,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "PrimitiveId",
+          "value" : 7,
+          "capabilities" : [ "Geometry", "Tessellation" ]
+        },
+        {
+          "enumerant" : "InvocationId",
+          "value" : 8,
+          "capabilities" : [ "Geometry", "Tessellation" ]
+        },
+        {
+          "enumerant" : "Layer",
+          "value" : 9,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "ViewportIndex",
+          "value" : 10,
+          "capabilities" : [ "MultiViewport" ]
+        },
+        {
+          "enumerant" : "TessLevelOuter",
+          "value" : 11,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "TessLevelInner",
+          "value" : 12,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "TessCoord",
+          "value" : 13,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "PatchVertices",
+          "value" : 14,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "FragCoord",
+          "value" : 15,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "PointCoord",
+          "value" : 16,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "FrontFacing",
+          "value" : 17,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "SampleId",
+          "value" : 18,
+          "capabilities" : [ "SampleRateShading" ]
+        },
+        {
+          "enumerant" : "SamplePosition",
+          "value" : 19,
+          "capabilities" : [ "SampleRateShading" ]
+        },
+        {
+          "enumerant" : "SampleMask",
+          "value" : 20,
+          "capabilities" : [ "SampleRateShading" ]
+        },
+        {
+          "enumerant" : "FragDepth",
+          "value" : 22,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "HelperInvocation",
+          "value" : 23,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "NumWorkgroups",
+          "value" : 24
+        },
+        {
+          "enumerant" : "WorkgroupSize",
+          "value" : 25
+        },
+        {
+          "enumerant" : "WorkgroupId",
+          "value" : 26
+        },
+        {
+          "enumerant" : "LocalInvocationId",
+          "value" : 27
+        },
+        {
+          "enumerant" : "GlobalInvocationId",
+          "value" : 28
+        },
+        {
+          "enumerant" : "LocalInvocationIndex",
+          "value" : 29
+        },
+        {
+          "enumerant" : "WorkDim",
+          "value" : 30,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "GlobalSize",
+          "value" : 31,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "EnqueuedWorkgroupSize",
+          "value" : 32,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "GlobalOffset",
+          "value" : 33,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "GlobalLinearId",
+          "value" : 34,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "SubgroupSize",
+          "value" : 36,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "SubgroupMaxSize",
+          "value" : 37,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "NumSubgroups",
+          "value" : 38,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "NumEnqueuedSubgroups",
+          "value" : 39,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "SubgroupId",
+          "value" : 40,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "SubgroupLocalInvocationId",
+          "value" : 41,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "VertexIndex",
+          "value" : 42,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "InstanceIndex",
+          "value" : 43,
+          "capabilities" : [ "Shader" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "Scope",
+      "enumerants" : [
+        {
+          "enumerant" : "CrossDevice",
+          "value" : 0
+        },
+        {
+          "enumerant" : "Device",
+          "value" : 1
+        },
+        {
+          "enumerant" : "Workgroup",
+          "value" : 2
+        },
+        {
+          "enumerant" : "Subgroup",
+          "value" : 3
+        },
+        {
+          "enumerant" : "Invocation",
+          "value" : 4
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "GroupOperation",
+      "enumerants" : [
+        {
+          "enumerant" : "Reduce",
+          "value" : 0,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "InclusiveScan",
+          "value" : 1,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "ExclusiveScan",
+          "value" : 2,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "KernelEnqueueFlags",
+      "enumerants" : [
+        {
+          "enumerant" : "NoWait",
+          "value" : 0,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "WaitKernel",
+          "value" : 1,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "WaitWorkGroup",
+          "value" : 2,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "Capability",
+      "enumerants" : [
+        {
+          "enumerant" : "Matrix",
+          "value" : 0
+        },
+        {
+          "enumerant" : "Shader",
+          "value" : 1,
+          "capabilities" : [ "Matrix" ]
+        },
+        {
+          "enumerant" : "Geometry",
+          "value" : 2,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Tessellation",
+          "value" : 3,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Addresses",
+          "value" : 4
+        },
+        {
+          "enumerant" : "Linkage",
+          "value" : 5
+        },
+        {
+          "enumerant" : "Kernel",
+          "value" : 6
+        },
+        {
+          "enumerant" : "Vector16",
+          "value" : 7,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Float16Buffer",
+          "value" : 8,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Float16",
+          "value" : 9
+        },
+        {
+          "enumerant" : "Float64",
+          "value" : 10
+        },
+        {
+          "enumerant" : "Int64",
+          "value" : 11
+        },
+        {
+          "enumerant" : "Int64Atomics",
+          "value" : 12,
+          "capabilities" : [ "Int64" ]
+        },
+        {
+          "enumerant" : "ImageBasic",
+          "value" : 13,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "ImageReadWrite",
+          "value" : 14,
+          "capabilities" : [ "ImageBasic" ]
+        },
+        {
+          "enumerant" : "ImageMipmap",
+          "value" : 15,
+          "capabilities" : [ "ImageBasic" ]
+        },
+        {
+          "enumerant" : "Pipes",
+          "value" : 17,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Groups",
+          "value" : 18
+        },
+        {
+          "enumerant" : "DeviceEnqueue",
+          "value" : 19,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "LiteralSampler",
+          "value" : 20,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "AtomicStorage",
+          "value" : 21,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Int16",
+          "value" : 22
+        },
+        {
+          "enumerant" : "TessellationPointSize",
+          "value" : 23,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "GeometryPointSize",
+          "value" : 24,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "ImageGatherExtended",
+          "value" : 25,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "StorageImageMultisample",
+          "value" : 27,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "UniformBufferArrayDynamicIndexing",
+          "value" : 28,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "SampledImageArrayDynamicIndexing",
+          "value" : 29,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "StorageBufferArrayDynamicIndexing",
+          "value" : 30,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "StorageImageArrayDynamicIndexing",
+          "value" : 31,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "ClipDistance",
+          "value" : 32,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "CullDistance",
+          "value" : 33,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "ImageCubeArray",
+          "value" : 34,
+          "capabilities" : [ "SampledCubeArray" ]
+        },
+        {
+          "enumerant" : "SampleRateShading",
+          "value" : 35,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "ImageRect",
+          "value" : 36,
+          "capabilities" : [ "SampledRect" ]
+        },
+        {
+          "enumerant" : "SampledRect",
+          "value" : 37,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "GenericPointer",
+          "value" : 38,
+          "capabilities" : [ "Addresses" ]
+        },
+        {
+          "enumerant" : "Int8",
+          "value" : 39,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "InputAttachment",
+          "value" : 40,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "SparseResidency",
+          "value" : 41,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "MinLod",
+          "value" : 42,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Sampled1D",
+          "value" : 43,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Image1D",
+          "value" : 44,
+          "capabilities" : [ "Sampled1D" ]
+        },
+        {
+          "enumerant" : "SampledCubeArray",
+          "value" : 45,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "SampledBuffer",
+          "value" : 46,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "ImageBuffer",
+          "value" : 47,
+          "capabilities" : [ "SampledBuffer" ]
+        },
+        {
+          "enumerant" : "ImageMSArray",
+          "value" : 48,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "StorageImageExtendedFormats",
+          "value" : 49,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "ImageQuery",
+          "value" : 50,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "DerivativeControl",
+          "value" : 51,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "InterpolationFunction",
+          "value" : 52,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "TransformFeedback",
+          "value" : 53,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "GeometryStreams",
+          "value" : 54,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "StorageImageReadWithoutFormat",
+          "value" : 55,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "StorageImageWriteWithoutFormat",
+          "value" : 56,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "MultiViewport",
+          "value" : 57,
+          "capabilities" : [ "Geometry" ]
+        }
+      ]
+    },
+    {
+      "category" : "Id",
+      "kind" : "IdResultType",
+      "doc" : "Reference to an <id> representing the result's type of the enclosing instruction"
+    },
+    {
+      "category" : "Id",
+      "kind" : "IdResult",
+      "doc" : "Definition of an <id> representing the result of the enclosing instruction"
+    },
+    {
+      "category" : "Id",
+      "kind" : "IdMemorySemantics",
+      "doc" : "Reference to an <id> representing a 32-bit integer that is a mask from the MemorySemantics operand kind"
+    },
+    {
+      "category" : "Id",
+      "kind" : "IdScope",
+      "doc" : "Reference to an <id> representing a 32-bit integer that is a mask from the Scope operand kind"
+    },
+    {
+      "category" : "Id",
+      "kind" : "IdRef",
+      "doc" : "Reference to an <id>"
+    },
+    {
+      "category" : "Literal",
+      "kind" : "LiteralInteger",
+      "doc" : "An integer consuming one or more words"
+    },
+    {
+      "category" : "Literal",
+      "kind" : "LiteralString",
+      "doc" : "A null-terminated stream of characters consuming an integral number of words"
+    },
+    {
+      "category" : "Literal",
+      "kind" : "LiteralContextDependentNumber",
+      "doc" : "A literal number whose size and format are determined by a previous operand in the enclosing instruction"
+    },
+    {
+      "category" : "Literal",
+      "kind" : "LiteralExtInstInteger",
+      "doc" : "A 32-bit unsigned integer indicating which instruction to use and determining the layout of following operands (for OpExtInst)"
+    },
+    {
+      "category" : "Literal",
+      "kind" : "LiteralSpecConstantOpInteger",
+      "doc" : "An opcode indicating the operation to be performed and determining the layout of following operands (for OpSpecConstantOp)"
+    },
+    {
+      "category" : "Composite",
+      "kind" : "PairLiteralIntegerIdRef",
+      "bases" : [ "LiteralInteger", "IdRef" ]
+    },
+    {
+      "category" : "Composite",
+      "kind" : "PairIdRefLiteralInteger",
+      "bases" : [ "IdRef", "LiteralInteger" ]
+    },
+    {
+      "category" : "Composite",
+      "kind" : "PairIdRefIdRef",
+      "bases" : [ "IdRef", "IdRef" ]
+    }
+  ]
+}
diff --git a/source/spirv_constant.h b/source/spirv_constant.h
index 3ade7cc..a53ce0d 100644
--- a/source/spirv_constant.h
+++ b/source/spirv_constant.h
@@ -28,6 +28,7 @@
 #define LIBSPIRV_SPIRV_CONSTANT_H_
 
 #include "spirv-tools/libspirv.h"
+#include "spirv/spirv.h"
 
 // Version number macros.
 
@@ -40,6 +41,9 @@
 // Returns the minor version extracted from a version header word.
 #define SPV_SPIRV_VERSION_MINOR_PART(WORD) ((uint32_t(WORD) >> 8) & 0xff)
 
+// Returns the version number for the given SPIR-V target environment.
+uint32_t spvVersionForTargetEnv(spv_target_env env);
+
 // Header indices
 
 #define SPV_INDEX_MAGIC_NUMBER 0u
diff --git a/source/spirv_definition.h b/source/spirv_definition.h
index 65d2d54..088ae96 100644
--- a/source/spirv_definition.h
+++ b/source/spirv_definition.h
@@ -31,6 +31,8 @@
 
 #include "spirv-tools/libspirv.h"
 
+#define spvIsInBitfield(value, bitfield) ((value) == ((value)&bitfield))
+
 // A bit mask representing a set of capabilities.
 // Currently there are 57 distinct capabilities, so 64 bits
 // should be enough.
diff --git a/source/spirv_operands.h b/source/spirv_operands.h
deleted file mode 100644
index ed8c7e5..0000000
--- a/source/spirv_operands.h
+++ /dev/null
@@ -1,97 +0,0 @@
-//
-// Copyright (C) 2014-2016 LunarG, Inc.
-//
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-//
-//    Redistributions of source code must retain the above copyright
-//    notice, this list of conditions and the following disclaimer.
-//
-//    Redistributions in binary form must reproduce the above
-//    copyright notice, this list of conditions and the following
-//    disclaimer in the documentation and/or other materials provided
-//    with the distribution.
-//
-//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
-//    contributors may be used to endorse or promote products derived
-//    from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-
-//
-// Author: John Kessenich, LunarG
-//
-
-// The contents of this file were extracted from the SPIR-V spec-generating
-// code.
-
-#ifndef LIBSPIRV_SPIRV_OPERANDS_H_
-#define LIBSPIRV_SPIRV_OPERANDS_H_
-
-// Classify the kinds of logical operands of an instruction.
-enum OperandClass {
-  OperandNone,
-  OperandId,
-  OperandOptionalId,
-  OperandVariableIds,
-  OperandOptionalLiteral,
-  OperandOptionalLiteralString,
-  OperandVariableLiterals,
-  OperandVariableIdLiteral,
-  OperandVariableLiteralId,  // zero or more pairs of (Literal, Id)
-  OperandLiteralNumber,
-  OperandLiteralString,
-  OperandSource,
-  OperandExecutionModel,
-  OperandAddressing,
-  OperandMemory,
-  OperandExecutionMode,
-  OperandStorage,
-  OperandDimensionality,
-  OperandSamplerAddressingMode,
-  OperandSamplerFilterMode,
-  OperandSamplerImageFormat,
-  OperandImageChannelOrder,
-  OperandImageChannelDataType,
-  OperandImageOperands,
-  OperandOptionalImageOperands,
-  OperandFPFastMath,
-  OperandFPRoundingMode,
-  OperandLinkageType,
-  OperandAccessQualifier,
-  OperandOptionalAccessQualifier,
-  OperandFuncParamAttr,
-  OperandDecoration,
-  OperandBuiltIn,
-  OperandSelect,
-  OperandLoop,
-  OperandFunction,
-  OperandMemorySemantics,
-  OperandMemoryAccess,
-  OperandOptionalMemoryAccess,
-  OperandScope,
-  OperandGroupOperation,
-  OperandKernelEnqueueFlags,
-  OperandKernelProfilingInfo,
-  OperandCapability,
-
-  OperandOpcode,
-
-  OperandCount
-};
-
-#endif  // LIBSPIRV_SPIRV_OPERANDS_H_
diff --git a/test/Version.cpp b/source/spirv_target_env.cpp
similarity index 63%
rename from test/Version.cpp
rename to source/spirv_target_env.cpp
index 23ac42c..e9e1a1d 100644
--- a/test/Version.cpp
+++ b/source/spirv_target_env.cpp
@@ -1,4 +1,4 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
+// Copyright (c) 2015-2016 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
@@ -24,16 +24,32 @@
 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 // MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
 
-#include "gmock/gmock.h"
+#include <assert.h>
 
-#include "UnitSPIRV.h"
+#include "spirv-tools/libspirv.h"
+#include "spirv_constant.h"
 
-namespace {
-
-TEST(LibspirvMacros, Version) {
-  EXPECT_EQ(1, SPV_SPIRV_VERSION_MAJOR);
-  EXPECT_EQ(0, SPV_SPIRV_VERSION_MINOR);
-  EXPECT_EQ(3, SPV_SPIRV_VERSION_REVISION);
+const char* spvTargetEnvDescription(spv_target_env env) {
+  switch (env) {
+    case SPV_ENV_UNIVERSAL_1_0:
+      return "SPIR-V 1.0";
+    case SPV_ENV_VULKAN_1_0:
+      return "SPIR-V 1.0 (under Vulkan 1.0 semantics)";
+    default:
+      break;
+  }
+  assert(0 && "Unhandled SPIR-V target environment");
+  return "";
 }
 
-}  // anonymous namespace
+uint32_t spvVersionForTargetEnv(spv_target_env env) {
+  switch (env) {
+    case SPV_ENV_UNIVERSAL_1_0:
+    case SPV_ENV_VULKAN_1_0:
+      return SPV_SPIRV_VERSION_WORD(1, 0);
+    default:
+      break;
+  }
+  assert(0 && "Unhandled SPIR-V target environment");
+  return SPV_SPIRV_VERSION_WORD(0, 0);
+}
diff --git a/source/syntax_tables.patch b/source/syntax_tables.patch
deleted file mode 100644
index e2ab8f9..0000000
--- a/source/syntax_tables.patch
+++ /dev/null
@@ -1,500 +0,0 @@
-diff --git a/tools/spirv/CMakeLists.txt b/tools/spirv/CMakeLists.txt
-index af51f86..5775510 100644
---- a/tools/spirv/CMakeLists.txt
-+++ b/tools/spirv/CMakeLists.txt
-@@ -12,6 +12,7 @@ include_directories(../..)
- 
- set(SOURCES
-     main.cpp
-+    assembler_table.cpp
-     disassemble.cpp
-     header.cpp
-     doc.cpp
-diff --git a/tools/spirv/OclDoc.cpp b/tools/spirv/OclDoc.cpp
-index 1f25221..ff2c7c6 100644
---- a/tools/spirv/OclDoc.cpp
-+++ b/tools/spirv/OclDoc.cpp
-@@ -28,11 +28,14 @@
- #include "headers/spirv.hpp"
- #include "headers/OpenCL.std.h"
- 
--#include "doc.h"
- #include "OclDoc.h"
- 
-+#include "assembler_table.h"
-+#include "doc.h"
-+
- #include <stdio.h>
- #include <string.h>
-+#include <cassert>
- #include <algorithm>
- #include <map>
- 
-@@ -2187,4 +2190,31 @@ void PrintOclCommonDoc()
-     PrintOclDoc(SPIROpenCLCommonVersion);
- }
- 
-+void PrintOclInstructionsTable(std::ostream& out) {
-+  ParameterizeBuiltins(SPIROpenCLCommonVersion);
-+
-+  out << R"(
-+// OpenCL extended instructions table, one instruction per line.
-+// All instructions have a result type and a result ID.
-+// Fields in this file are:
-+//  - name
-+//  - extended instruction index
-+//  - EmptyList, or List of operand classes.
-+)";
-+  for (int i = 0; i < OclExtInstCeiling; ++i) {
-+    const BuiltInFunctionParameters& inst = BuiltInDesc[i];
-+    // Skip gaps in the enum space, if any.
-+    if (0 == strcmp("unknown", inst.opName)) continue;
-+    assert(inst.hasType());
-+    assert(inst.hasResult());
-+    out << "ExtInst(" << inst.opName << ", " << i << ", ";
-+    std::vector<OperandClassInfo> classes_info;
-+    for (const auto& operand_class : inst.operands.classes()) {
-+      classes_info.push_back({operand_class, false /* not optional */});
-+    }
-+    PrintOperandClasses(classes_info, out);
-+    out << ")" << std::endl;
-+  }
-+}
-+
- };  // end namespace spv
-diff --git a/tools/spirv/OclDoc.h b/tools/spirv/OclDoc.h
-index 8568880..7cf8a31 100644
---- a/tools/spirv/OclDoc.h
-+++ b/tools/spirv/OclDoc.h
-@@ -35,6 +35,8 @@
- #include <map>
- #include "headers/spirv.hpp"
- 
-+#include "doc.h"
-+
- namespace spv {
- 
- void OclGetDebugNames(const char** names);
-@@ -189,6 +191,8 @@ public:
-     int getImageType(int op) { return Type[op]; }
-     AccessQualifier getAccessQualifier(int op) { return accessQualifier[op]; }
- 
-+    const std::vector<OperandClass>& classes() const  { return opClass; }
-+
- protected:
-     std::vector<OperandClass> opClass;
-     std::vector<const char*> desc;
-@@ -307,4 +311,7 @@ protected:
- // Print out the OpenCL common (all spec revisions) documentation.
- void PrintOclCommonDoc();
- 
-+// Prints the OpenCL instructions table, for consumption by SPIR-V Tools.
-+void PrintOclInstructionsTable(std::ostream& out);
-+
- };  // end namespace spv
-diff --git a/tools/spirv/assembler_table.cpp b/tools/spirv/assembler_table.cpp
-new file mode 100644
-index 0000000..8dd8fa1
---- /dev/null
-+++ b/tools/spirv/assembler_table.cpp
-@@ -0,0 +1,229 @@
-+// Copyright (c) 2015-2016 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 "assembler_table.h"
-+
-+#include <cassert>
-+#include <cstring>
-+#include <sstream>
-+
-+#include "doc.h"
-+
-+namespace spv {
-+
-+namespace {
-+
-+// Returns true if the given instruction can vary in width.
-+bool IsVariableLength(const InstructionParameters& inst) {
-+  const OperandParameters& operands = inst.operands;
-+  for (int i = 0; i < operands.getNum() ; i++) {
-+    switch (operands.getClass(i)) {
-+      case spv::OperandVariableIds:
-+      case spv::OperandOptionalLiteral:
-+      case spv::OperandOptionalLiteralString:
-+      case spv::OperandVariableLiterals:
-+      case spv::OperandVariableIdLiteral:
-+      case spv::OperandVariableLiteralId:
-+      case spv::OperandLiteralString:
-+        return true;
-+      default:
-+        break;
-+    }
-+    if (operands.isOptional(i)) return true;
-+  }
-+  return false;
-+}
-+
-+// Returns a string for the given operand class, or nullptr if it's invalid.
-+const char* GetOperandClassString(OperandClass operandClass) {
-+  switch (operandClass) {
-+#define CASE(X) case X: return #X;
-+    CASE(OperandNone)
-+    CASE(OperandId)
-+    CASE(OperandVariableIds)
-+    CASE(OperandOptionalLiteral)
-+    CASE(OperandOptionalLiteralString)
-+    CASE(OperandVariableLiterals)
-+    CASE(OperandVariableIdLiteral)
-+    CASE(OperandVariableLiteralId)
-+    CASE(OperandLiteralNumber)
-+    CASE(OperandLiteralString)
-+    CASE(OperandSource)
-+    CASE(OperandExecutionModel)
-+    CASE(OperandAddressing)
-+    CASE(OperandMemory)
-+    CASE(OperandExecutionMode)
-+    CASE(OperandStorage)
-+    CASE(OperandDimensionality)
-+    CASE(OperandSamplerAddressingMode)
-+    CASE(OperandSamplerFilterMode)
-+    CASE(OperandSamplerImageFormat)
-+    CASE(OperandImageChannelOrder)
-+    CASE(OperandImageChannelDataType)
-+    CASE(OperandImageOperands)
-+    CASE(OperandFPFastMath)
-+    CASE(OperandFPRoundingMode)
-+    CASE(OperandLinkageType)
-+    CASE(OperandAccessQualifier)
-+    CASE(OperandFuncParamAttr)
-+    CASE(OperandDecoration)
-+    CASE(OperandBuiltIn)
-+    CASE(OperandSelect)
-+    CASE(OperandLoop)
-+    CASE(OperandFunction)
-+    CASE(OperandMemorySemantics)
-+    CASE(OperandMemoryAccess)
-+    CASE(OperandScope)
-+    CASE(OperandGroupOperation)
-+    CASE(OperandKernelEnqueueFlags)
-+    CASE(OperandKernelProfilingInfo)
-+    CASE(OperandCapability)
-+    CASE(OperandOpcode)
-+#undef CASE
-+
-+    case OperandCount:
-+    default:
-+      break;
-+  }
-+  return nullptr;
-+}
-+} // anonymous namespace
-+
-+// Prints a listing of the operand kinds for the given instruction.
-+// If the list is empty, then emit just "EmptyList",
-+// otherwise the output looks like a call to the "List" macro.
-+void PrintOperandClasses(const std::vector<OperandClassInfo>& classes, std::ostream& out) {
-+  std::stringstream contents;
-+  int numPrinted = 0;
-+  for (auto class_info : classes) {
-+    if (const char* name = GetOperandClassString(class_info.value)) {
-+      if (numPrinted) contents << ", ";
-+      switch (class_info.value) {
-+        case OperandId:
-+        case OperandImageOperands:
-+        case OperandLiteralString:
-+        case OperandMemoryAccess:
-+        case OperandAccessQualifier:
-+          if (class_info.is_optional) {
-+            contents << "OperandOptional" << (name + strlen("Operand"));
-+          } else {
-+            contents << name;
-+          }
-+          break;
-+        default:
-+          contents << name;
-+          break;
-+      }
-+      numPrinted++;
-+      if (class_info.value == OperandImageOperands) {
-+        // There are Id and/or VariableIds after this.  Skip them
-+        // because the bits in an OperandImageOperands determine
-+        // exactly the number of Ids required to follow.
-+        break;
-+      }
-+    }
-+  }
-+
-+  if (numPrinted)
-+    out << "List(" << contents.str() << ")";
-+  else
-+    out << "EmptyList";
-+}
-+}  // namespace spv
-+
-+namespace spv {
-+
-+// Prints a listing of the operand kinds for the given instruction.
-+// If the list is empty, then emit just "EmptyList",
-+// otherwise the output looks like a call to the "List" macro.
-+void PrintOperandClassesForInstruction(const InstructionParameters& inst,
-+                                       std::ostream& out) {
-+  std::vector<OperandClassInfo> result;
-+
-+  const OperandParameters& operands = inst.operands;
-+  for (int i = 0; i < operands.getNum(); i++) {
-+    result.push_back({operands.getClass(i), operands.isOptional(i)});
-+  }
-+  PrintOperandClasses(result, out);
-+}
-+
-+// Prints the table entry for the given instruction with the given opcode.
-+void PrintInstructionDesc(int opcode, const InstructionParameters& inst, std::ostream& out) {
-+  const char* name = OpcodeString(opcode);
-+  // There can be gaps in the listing.
-+  // All valid operations have a name beginning with "Op".
-+  if (strlen(name) > 2 && name[0] == 'O' && name[1] == 'p') {
-+    out << "Instruction("
-+        << name + 2 << ", "; // Skip the "Op" part.
-+    out << (inst.hasResult() ? 1 : 0) << ", ";
-+    out << (inst.hasType() ? 1 : 0) << ", ";
-+    out << inst.operands.getNum() << ", ";
-+
-+    // Emit the capability, if any.
-+    // The SPIR-V tools doesn't handle the concept of depending on more than
-+    // one capability.  So call it out separately.  Currently the biggest case
-+    // is 2.  This is a big hack.
-+    out << inst.capabilities.size() << ", ";
-+    assert(inst.capabilities.size() < 3);
-+    if (inst.capabilities.size() == 1) {
-+      out << "Capability(" << CapabilityString(inst.capabilities[0]) << "), ";
-+    } else if (inst.capabilities.size() == 2) {
-+      out << "Capability2(" << CapabilityString(inst.capabilities[0]) << ","
-+          << CapabilityString(inst.capabilities[1]) << "), ";
-+    } else {
-+      out << "Capability(None), ";
-+    }
-+
-+    out << (IsVariableLength(inst) ? 1 : 0) << ", ";
-+    PrintOperandClassesForInstruction(inst, out);
-+    out << ")" << std::endl;
-+  }
-+}
-+
-+void PrintAssemblerTable(std::ostream& out) {
-+  out << "// Instruction fields are:\n"
-+      << "//    name - skips the \"Op\" prefix\n"
-+      << "//    {0|1} - whether the instruction generates a result Id\n"
-+      << "//    {0|1} - whether the instruction encodes the type of the result Id\n"
-+      << "//    numLogicalOperands - does not include result id or type id\n"
-+      << "//    numCapabilities - we only handle 0 or 1 required capabilities\n"
-+      << "//    Capability(<capability-name>) - capability required to use this instruction. Might be None.\n"
-+      << "//       There can be Capability2(a,b) for dependence on two capabilities.\n"
-+      << "//    {0|1} - whether the instruction is variable number of logical operands\n"
-+      << "//    EmptyList or List(...) - list of classes of logical operands\n"
-+      << "// Example use:\n"
-+      << "// #define EmptyList {}\n"
-+      << "// #define List(...) {__VA_ARGS__}\n"
-+      << "// #define Capability(C) Capability##C\n"
-+      << "// #define CapabilityNone -1\n"
-+      << "// #define Instruction(Name,HasResult,HasType,NumLogicalOperands,CapabiltyRequired,IsVariable,LogicalArgsList)\n";
-+
-+  for (int i = 0; i < spv::OpcodeCeiling ; i++ ) {
-+    PrintInstructionDesc(i, InstructionDesc[i], out);
-+  }
-+}
-+
-+}
-diff --git a/tools/spirv/assembler_table.h b/tools/spirv/assembler_table.h
-new file mode 100644
-index 0000000..16ea384
---- /dev/null
-+++ b/tools/spirv/assembler_table.h
-@@ -0,0 +1,55 @@
-+// Copyright (c) 2015-2016 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.
-+
-+#pragma once
-+#ifndef ASSEMBLER_TABLE_H
-+#define ASSEMBLER_TABLE_H
-+
-+#include <iostream>
-+#include <vector>
-+
-+#include "doc.h"
-+
-+namespace spv {
-+
-+    // Relevant facts about an operand class value.
-+    struct OperandClassInfo {
-+      OperandClass value;
-+      bool is_optional;
-+    };
-+
-+    // Prints the tables used to define the structure of instructions.
-+    // Assumes that parameterization has already occurred
-+    void PrintAssemblerTable(std::ostream& out);
-+
-+    // Prints a listing of the operand kinds.
-+    // If the list is empty, then emit just "EmptyList",
-+    // otherwise the output looks like a call to the "List" macro.
-+    void PrintOperandClasses(const std::vector<OperandClassInfo>& classes, std::ostream& out);
-+
-+};  // end namespace spv
-+
-+#endif // ASSEMBLER_TABLE_H
-diff --git a/tools/spirv/doc.h b/tools/spirv/doc.h
-index 4c11d3b..6e1718a 100644
---- a/tools/spirv/doc.h
-+++ b/tools/spirv/doc.h
-@@ -32,6 +32,9 @@
- //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- //POSSIBILITY OF SUCH DAMAGE.
- 
-+#ifndef DOC_H_
-+#define DOC_H_
-+
- //
- // Author: John Kessenich, LunarG
- //
-@@ -81,6 +84,7 @@ const char* KernelEnqueueFlagsString(int);
- const char* KernelProfilingInfoString(int);
- const char* CapabilityString(int);
- const char* OpcodeString(int);
-+const char* OperandClassString(int);
- 
- // For grouping opcodes into subsections
- enum OpcodeClass {
-@@ -157,6 +161,10 @@ enum OperandClass {
- 
-     OperandOpcode,
- 
-+    // The operand class enum is not part of the spec, so
-+    // it should come after OperandOpcode.
-+    OperandOperandClass,
-+
-     OperandCount
- };
- 
-@@ -259,3 +267,5 @@ const char* AccessQualifierString(int attr);
- void PrintOperands(const OperandParameters& operands, int reservedOperands);
- 
- };  // end namespace spv
-+
-+#endif // DOC_H_
-diff --git a/tools/spirv/main.cpp b/tools/spirv/main.cpp
-index d7312f9..e1413bb 100644
---- a/tools/spirv/main.cpp
-+++ b/tools/spirv/main.cpp
-@@ -46,6 +46,7 @@ namespace spv {
- #include "headers/OpenCL.std.h"
- 
- // This tool's includes
-+#include "assembler_table.h"
- #include "disassemble.h"
- #include "header.h"
- #include "doc.h"
-@@ -65,6 +66,8 @@ enum TOptions {
-     EOptionDisassemble                = 0x004,
-     EOptionPrintHeader                = 0x008,
-     EOptionPrintOclBuiltinsAsciidoc   = 0x010,
-+    EOptionPrintAssemblerTable        = 0x020,
-+    EOptionPrintOclInstructionsTable  = 0x040,
- };
- 
- std::string Filename;
-@@ -86,9 +89,11 @@ void Usage()
-            "  -H print header in all supported languages to files in current directory\n"
-            "  -p print documentation\n"
-            "  -s [version] prints the SPIR-V extended instructions documentation\n"
--           "      'CL12': OpenCL 1.2 extended instructions documentation\n"
--           "      'CL20': OpenCL 2.0 extended instructions documentation\n"
--           "      'CL21': OpenCL 2.1 extended instructions documentation\n"
-+           "      'OpenCL': OpenCL 1.2, 2.0, 2.1 extended instructions documentation\n"
-+           "      'GLSL': GLSL extended instructions documentation\n"
-+           "  -a print table for the assembler\n"
-+           "  -C print OpenCL instructions for the assembler\n"
-+           "     This is incompatibile with -s OpenCL\n"
-            );
- }
- 
-@@ -155,6 +160,12 @@ bool ProcessArguments(int argc, char* argv[])
-                 }
-                 return true;
-             }
-+            case 'a':
-+                Options |= EOptionPrintAssemblerTable;
-+                break;
-+            case 'C':
-+                Options |= EOptionPrintOclInstructionsTable;
-+                break;
-             default:
-                 return false;
-             }
-@@ -162,6 +173,9 @@ bool ProcessArguments(int argc, char* argv[])
-             Filename = std::string(argv[0]);
-         }
-     }
-+    if ((Options & EOptionPrintOclBuiltinsAsciidoc) &&
-+        (Options & EOptionPrintOclInstructionsTable))
-+      return false;
- 
-     return true;
- }
-@@ -220,5 +234,11 @@ int main(int argc, char* argv[])
-     if (Options & EOptionPrintHeader)
-         spv::PrintHeader(Language, std::cout);
- 
-+    if (Options & EOptionPrintAssemblerTable)
-+        spv::PrintAssemblerTable(std::cout);
-+
-+    if (Options & EOptionPrintOclInstructionsTable)
-+        spv::PrintOclInstructionsTable(std::cout);
-+
-     return 0;
- }
diff --git a/source/table.cpp b/source/table.cpp
index 1a32f2d..3fa5c58 100644
--- a/source/table.cpp
+++ b/source/table.cpp
@@ -28,7 +28,15 @@
 
 #include <cstdlib>
 
-spv_context spvContextCreate() {
+spv_context spvContextCreate(spv_target_env env) {
+  switch (env) {
+    case SPV_ENV_UNIVERSAL_1_0:
+    case SPV_ENV_VULKAN_1_0:
+      break;
+    default:
+      return nullptr;
+  }
+
   spv_opcode_table opcode_table;
   spv_operand_table operand_table;
   spv_ext_inst_table ext_inst_table;
@@ -37,11 +45,7 @@
   spvOperandTableGet(&operand_table);
   spvExtInstTableGet(&ext_inst_table);
 
-  return new spv_context_t{opcode_table, operand_table, ext_inst_table};
+  return new spv_context_t{env, opcode_table, operand_table, ext_inst_table};
 }
 
-void spvContextDestroy(spv_context context) {
-  ::free(context->opcode_table->entries);
-  delete context->opcode_table;
-  delete context;
-}
+void spvContextDestroy(spv_context context) { delete context; }
diff --git a/source/table.h b/source/table.h
index 9e427dd..93270df 100644
--- a/source/table.h
+++ b/source/table.h
@@ -28,8 +28,8 @@
 #define LIBSPIRV_TABLE_H_
 
 #include "spirv-tools/libspirv.h"
+#include "spirv/spirv.h"
 #include "spirv_definition.h"
-#include "spirv_operands.h"
 
 typedef struct spv_opcode_desc_t {
   const char* name;
@@ -43,9 +43,6 @@
   spv_operand_type_t operandTypes[16];  // TODO: Smaller/larger?
   const bool hasResult;  // Does the instruction have a result ID operand?
   const bool hasType;    // Does the instruction have a type ID operand?
-  // The operand class for each logical argument.  This does *not* include
-  // the result Id or type ID.  The list is terminated by SPV_OPERAND_TYPE_NONE.
-  const OperandClass operandClass[16];
 } spv_opcode_desc_t;
 
 typedef struct spv_operand_desc_t {
@@ -78,7 +75,7 @@
 
 typedef struct spv_opcode_table_t {
   const uint32_t count;
-  spv_opcode_desc_t* entries;
+  const spv_opcode_desc_t* entries;
 } spv_opcode_table_t;
 
 typedef struct spv_operand_table_t {
@@ -100,6 +97,7 @@
 typedef const spv_ext_inst_table_t* spv_ext_inst_table;
 
 struct spv_context_t {
+  const spv_target_env target_env;
   const spv_opcode_table opcode_table;
   const spv_operand_table operand_table;
   const spv_ext_inst_table ext_inst_table;
diff --git a/source/text.cpp b/source/text.cpp
index ee90689..7d1d756 100644
--- a/source/text.cpp
+++ b/source/text.cpp
@@ -653,22 +653,18 @@
 
 enum { kAssemblerVersion = 0 };
 
-/// @brief Populate a binary stream's words with this generator's header.
-///
-/// @param[in,out] words the array of words
-/// @param[in] bound the upper ID bound
-///
-/// @return result code
-spv_result_t SetHeader(uint32_t* words, const uint32_t bound) {
-  if (!words) return SPV_ERROR_INVALID_BINARY;
+// Populates a binary stream's |header|. The target environment is specified via
+// |env| and Id bound is via |bound|.
+spv_result_t SetHeader(spv_target_env env, const uint32_t bound,
+                       uint32_t* header) {
+  if (!header) return SPV_ERROR_INVALID_BINARY;
 
-  words[SPV_INDEX_MAGIC_NUMBER] = SpvMagicNumber;
-  words[SPV_INDEX_VERSION_NUMBER] =
-      SPV_SPIRV_VERSION_WORD(SPV_SPIRV_VERSION_MAJOR, SPV_SPIRV_VERSION_MINOR);
-  words[SPV_INDEX_GENERATOR_NUMBER] =
+  header[SPV_INDEX_MAGIC_NUMBER] = SpvMagicNumber;
+  header[SPV_INDEX_VERSION_NUMBER] = spvVersionForTargetEnv(env);
+  header[SPV_INDEX_GENERATOR_NUMBER] =
       SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_ASSEMBLER, kAssemblerVersion);
-  words[SPV_INDEX_BOUND] = bound;
-  words[SPV_INDEX_SCHEMA] = 0;  // NOTE: Reserved
+  header[SPV_INDEX_BOUND] = bound;
+  header[SPV_INDEX_SCHEMA] = 0;  // NOTE: Reserved
 
   return SPV_SUCCESS;
 }
@@ -721,7 +717,8 @@
     currentIndex += inst.words.size();
   }
 
-  if (auto error = SetHeader(data, context.getBound())) return error;
+  if (auto error = SetHeader(grammar.target_env(), context.getBound(), data))
+    return error;
 
   spv_binary binary = new spv_binary_t();
   if (!binary) {
diff --git a/source/text_handler.cpp b/source/text_handler.cpp
index cc4a42b..3803465 100644
--- a/source/text_handler.cpp
+++ b/source/text_handler.cpp
@@ -90,6 +90,7 @@
       return advance(text, position);
     case ' ':
     case '\t':
+    case '\r':
       position->column++;
       position->index++;
       return advance(text, position);
@@ -137,6 +138,7 @@
         case ';':
         case '\t':
         case '\n':
+        case '\r':
           if (escaping || quoting) break;
         // Fall through.
         case '\0': {  // NOTE: End of word found!
diff --git a/source/validate.cpp b/source/validate.cpp
index e706541..ab4de21 100644
--- a/source/validate.cpp
+++ b/source/validate.cpp
@@ -128,7 +128,7 @@
 void ProcessIds(ValidationState_t& _, const spv_parsed_instruction_t& inst) {
   if (inst.result_id) {
     _.usedefs().AddDef(
-        {inst.result_id, inst.type_id, inst.opcode,
+        {inst.result_id, inst.type_id, static_cast<SpvOp>(inst.opcode),
          std::vector<uint32_t>(inst.words, inst.words + inst.num_words)});
   }
   for (auto op = inst.operands; op != inst.operands + inst.num_operands; ++op) {
@@ -140,7 +140,7 @@
                                 const spv_parsed_instruction_t* inst) {
   ValidationState_t& _ = *(reinterpret_cast<ValidationState_t*>(user_data));
   _.incrementInstructionCount();
-  if (inst->opcode == SpvOpEntryPoint)
+  if (static_cast<SpvOp>(inst->opcode) == SpvOpEntryPoint)
     _.entry_points().push_back(inst->words[2]);
 
   DebugInstructionPass(_, inst);
@@ -203,11 +203,12 @@
   uint64_t index = SPV_INDEX_INSTRUCTION;
   while (index < binary->wordCount) {
     uint16_t wordCount;
-    SpvOp opcode;
+    uint16_t opcode;
     spvOpcodeSplit(spvFixWord(binary->code[index], endian), &wordCount,
                    &opcode);
     spv_instruction_t inst;
-    spvInstructionCopy(&binary->code[index], opcode, wordCount, endian, &inst);
+    spvInstructionCopy(&binary->code[index], static_cast<SpvOp>(opcode),
+                       wordCount, endian, &inst);
     instructions.push_back(inst);
     index += wordCount;
   }
diff --git a/source/validate.h b/source/validate.h
index 5438924..77bf9c2 100644
--- a/source/validate.h
+++ b/source/validate.h
@@ -133,7 +133,7 @@
   // Returns the number of blocks in the current function being parsed
   size_t get_block_count() const;
 
-  // Retuns true if called after a function instruction but before the
+  // Returns true if called after a function instruction but before the
   // function end instruction
   bool in_function_body() const;
 
@@ -147,7 +147,7 @@
   // Parent module
   ValidationState_t& module_;
 
-  // Funciton IDs in a module
+  // Function IDs in a module
   std::vector<uint32_t> id_;
 
   // OpTypeFunction IDs of each of the id_ functions
@@ -216,7 +216,7 @@
   // Returns the function states
   Functions& get_functions();
 
-  // Retuns true if the called after a function instruction but before the
+  // Returns true if the called after a function instruction but before the
   // function end instruction
   bool in_function_body() const;
 
diff --git a/source/validate_cfg.cpp b/source/validate_cfg.cpp
index 50dc2b6..0f8e980 100644
--- a/source/validate_cfg.cpp
+++ b/source/validate_cfg.cpp
@@ -33,25 +33,24 @@
 spv_result_t CfgPass(ValidationState_t& _,
                      const spv_parsed_instruction_t* inst) {
   if (_.getLayoutSection() == kLayoutFunctionDefinitions) {
-    SpvOp opcode = inst->opcode;
+    SpvOp opcode = static_cast<SpvOp>(inst->opcode);
     switch (opcode) {
-    case SpvOpLabel:
-      spvCheckReturn(_.get_functions().RegisterBlock(inst->result_id));
-      break;
-    case SpvOpBranch:
-    case SpvOpBranchConditional:
-    case SpvOpSwitch:
-    case SpvOpKill:
-    case SpvOpReturn:
-    case SpvOpReturnValue:
-    case SpvOpUnreachable:
-      spvCheckReturn(_.get_functions().RegisterBlockEnd());
-      break;
-    default:
-      break;
+      case SpvOpLabel:
+        spvCheckReturn(_.get_functions().RegisterBlock(inst->result_id));
+        break;
+      case SpvOpBranch:
+      case SpvOpBranchConditional:
+      case SpvOpSwitch:
+      case SpvOpKill:
+      case SpvOpReturn:
+      case SpvOpReturnValue:
+      case SpvOpUnreachable:
+        spvCheckReturn(_.get_functions().RegisterBlockEnd());
+        break;
+      default:
+        break;
     }
   }
   return SPV_SUCCESS;
 }
-
 }
diff --git a/source/validate_id.cpp b/source/validate_id.cpp
index 513f257..879af59 100644
--- a/source/validate_id.cpp
+++ b/source/validate_id.cpp
@@ -264,6 +264,26 @@
   return true;
 }
 
+// True if the integer constant is > 0. constWords are words of the
+// constant-defining instruction (either OpConstant or
+// OpSpecConstant). typeWords are the words of the constant's-type-defining
+// OpTypeInt.
+bool aboveZero(const std::vector<uint32_t>& constWords,
+               const std::vector<uint32_t>& typeWords) {
+  const uint32_t width = typeWords[2];
+  const bool is_signed = typeWords[3];
+  const uint32_t loWord = constWords[3];
+  if (width > 32) {
+    // The spec currently doesn't allow integers wider than 64 bits.
+    const uint32_t hiWord = constWords[4];  // Must exist, per spec.
+    if (is_signed && (hiWord >> 31)) return false;
+    return loWord | hiWord;
+  } else {
+    if (is_signed && (loWord >> 31)) return false;
+    return loWord > 0;
+  }
+}
+
 template <>
 bool idUsage::isValid<SpvOpTypeArray>(const spv_instruction_t* inst,
                                       const spv_opcode_desc) {
@@ -278,8 +298,7 @@
   }
   auto lengthIndex = 3;
   auto length = usedefs_.FindDef(inst->words[lengthIndex]);
-  if (!length.first || (SpvOpConstant != length.second.opcode &&
-                        SpvOpSpecConstant != length.second.opcode)) {
+  if (!length.first || !spvOpcodeIsConstant(length.second.opcode)) {
     DIAG(lengthIndex) << "OpTypeArray Length <id> '" << inst->words[lengthIndex]
                       << "' is not a scalar constant type.";
     return false;
@@ -294,27 +313,23 @@
                       << "' is not a constant integer type.";
     return false;
   }
-  if (4 == constInst.size()) {
-    spvCheck(1 > constInst[3], DIAG(lengthIndex)
-                                   << "OpTypeArray Length <id> '"
-                                   << inst->words[lengthIndex]
-                                   << "' value must be at least 1.";
-             return false);
-  } else if (5 == constInst.size()) {
-    uint64_t value = constInst[3] | ((uint64_t)constInst[4]) << 32;
-    bool signedness = constResultType.second.words[3] != 0;
-    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);
+
+  switch (length.second.opcode) {
+    case SpvOpSpecConstant:
+    case SpvOpConstant:
+      if (aboveZero(length.second.words, constResultType.second.words)) break;
+    // Else fall through!
+    case SpvOpConstantNull: {
+      DIAG(lengthIndex) << "OpTypeArray Length <id> '"
+                        << inst->words[lengthIndex]
+                        << "' default value must be at least 1.";
+      return false;
     }
+    case SpvOpSpecConstantOp:
+      // Assume it's OK, rather than try to evaluate the operation.
+      break;
+    default:
+      assert(0 && "bug in spvOpcodeIsConstant() or result type isn't int");
   }
   return true;
 }
@@ -618,10 +633,10 @@
 // nullability transitively.
 bool IsTypeNullable(const std::vector<uint32_t>& instruction,
                     const UseDefTracker& usedefs) {
-  SpvOp opcode;
+  uint16_t opcode;
   uint16_t word_count;
   spvOpcodeSplit(instruction[0], &word_count, &opcode);
-  switch (opcode) {
+  switch (static_cast<SpvOp>(opcode)) {
     case SpvOpTypeBool:
     case SpvOpTypeInt:
     case SpvOpTypeFloat:
diff --git a/source/validate_instruction.cpp b/source/validate_instruction.cpp
index 87e1998..8ecb715 100644
--- a/source/validate_instruction.cpp
+++ b/source/validate_instruction.cpp
@@ -83,10 +83,11 @@
 spv_result_t CapCheck(ValidationState_t& _,
                       const spv_parsed_instruction_t* inst) {
   spv_opcode_desc opcode_desc;
-  if (SPV_SUCCESS == _.grammar().lookupOpcode(inst->opcode, &opcode_desc) &&
+  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+  if (SPV_SUCCESS == _.grammar().lookupOpcode(opcode, &opcode_desc) &&
       !_.HasAnyOf(opcode_desc->capabilities))
     return _.diag(SPV_ERROR_INVALID_CAPABILITY)
-           << "Opcode " << spvOpcodeString(inst->opcode)
+           << "Opcode " << spvOpcodeString(opcode)
            << " requires one of these capabilities: "
            << ToString(opcode_desc->capabilities, _.grammar());
   for (int i = 0; i < inst->num_operands; ++i) {
@@ -99,7 +100,7 @@
           const auto caps =
               RequiredCapabilities(_.grammar(), operand.type, mask_bit);
           if (!_.HasAnyOf(caps)) {
-            return CapabilityError(_, i + 1, inst->opcode,
+            return CapabilityError(_, i + 1, opcode,
                                    ToString(caps, _.grammar()));
           }
         }
@@ -108,8 +109,7 @@
       // Check the operand word as a whole.
       const auto caps = RequiredCapabilities(_.grammar(), operand.type, word);
       if (!_.HasAnyOf(caps)) {
-        return CapabilityError(_, i + 1, inst->opcode,
-                               ToString(caps, _.grammar()));
+        return CapabilityError(_, i + 1, opcode, ToString(caps, _.grammar()));
       }
     }
   }
@@ -118,10 +118,11 @@
 
 spv_result_t InstructionPass(ValidationState_t& _,
                              const spv_parsed_instruction_t* inst) {
-  if (inst->opcode == SpvOpCapability)
+  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+  if (opcode == SpvOpCapability)
     _.registerCapability(
         static_cast<SpvCapability>(inst->words[inst->operands[0].offset]));
-  if (inst->opcode == SpvOpVariable) {
+  if (opcode == SpvOpVariable) {
     const auto storage_class =
         static_cast<SpvStorageClass>(inst->words[inst->operands[2].offset]);
     if (storage_class == SpvStorageClassGeneric)
diff --git a/source/validate_layout.cpp b/source/validate_layout.cpp
index 24d2a43..2bb6db2 100644
--- a/source/validate_layout.cpp
+++ b/source/validate_layout.cpp
@@ -103,7 +103,7 @@
         }
         if (_.get_functions().get_block_count() != 0) {
           return _.diag(SPV_ERROR_INVALID_LAYOUT)
-                 << "Function parameters must only appear immediatly after the "
+                 << "Function parameters must only appear immediately after the "
                     "function definition";
         }
         spvCheckReturn(_.get_functions().RegisterFunctionParameter(
@@ -182,7 +182,7 @@
 // Performs logical layout validation. See Section 2.4
 spv_result_t ModuleLayoutPass(ValidationState_t& _,
                               const spv_parsed_instruction_t* inst) {
-  SpvOp opcode = inst->opcode;
+  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
 
   switch (_.getLayoutSection()) {
     case kLayoutCapabilities:
diff --git a/source/validate_ssa.cpp b/source/validate_ssa.cpp
index 88c10f8..38250bf 100644
--- a/source/validate_ssa.cpp
+++ b/source/validate_ssa.cpp
@@ -32,7 +32,7 @@
 using libspirv::ValidationState_t;
 
 namespace {
-// This funciton takes the opcode of an instruction and returns
+// This function takes the opcode of an instruction and returns
 // a function object that will return true if the index
 // of the operand can be forwarad declared. This function will
 // used in the SSA validation stage of the pipeline
@@ -95,11 +95,11 @@
 //
 // TODO(umar): Use dominators to correctly validate SSA. For example, the result
 // id from a 'then' block cannot dominate its usage in the 'else' block. This
-// is not yet performed by this funciton.
+// is not yet performed by this function.
 spv_result_t SsaPass(ValidationState_t& _,
                      const spv_parsed_instruction_t* inst) {
   auto can_have_forward_declared_ids =
-      getCanBeForwardDeclaredFunction(inst->opcode);
+      getCanBeForwardDeclaredFunction(static_cast<SpvOp>(inst->opcode));
 
   for (unsigned i = 0; i < inst->num_operands; i++) {
     const spv_parsed_operand_t& operand = inst->operands[i];
diff --git a/test/BinaryParse.cpp b/test/BinaryParse.cpp
index d6df8e7..9cd5bc9 100644
--- a/test/BinaryParse.cpp
+++ b/test/BinaryParse.cpp
@@ -28,10 +28,10 @@
 #include <string>
 #include <vector>
 
-#include "gmock/gmock.h"
-
 #include "TestFixture.h"
 #include "UnitSPIRV.h"
+#include "gmock/gmock.h"
+#include "spirv/OpenCL.std.h"
 
 // Returns true if two spv_parsed_operand_t values are equal.
 // To use this operator, this definition must appear in the same namespace
@@ -60,7 +60,7 @@
 struct ParsedInstruction {
   explicit ParsedInstruction(const spv_parsed_instruction_t& inst)
       : words(inst.words, inst.words + inst.num_words),
-        opcode(inst.opcode),
+        opcode(static_cast<SpvOp>(inst.opcode)),
         ext_inst_type(inst.ext_inst_type),
         type_id(inst.type_id),
         result_id(inst.result_id),
@@ -463,7 +463,7 @@
          "Module has incomplete header: only 3 words instead of 5"},
         {kHeaderForBound1, 4,
          "Module has incomplete header: only 4 words instead of 5"},
-    }),);
+    }), );
 
 // A binary parser diagnostic test case where a vector of words is
 // provided.  We'll use this to express cases that can't be created
@@ -696,7 +696,7 @@
              MakeInstruction(SpvOpConstant, {1, 2, 42}),
          }),
          "Type Id 1 is not a scalar numeric type"},
-    }),);
+    }), );
 
 // A binary parser diagnostic case generated from an assembly text input.
 struct AssemblyDiagnosticCase {
@@ -766,6 +766,6 @@
          "Invalid image operand: 511 has invalid mask component 256"},
         {"OpSelectionMerge %1 !7",
          "Invalid selection control operand: 7 has invalid mask component 4"},
-    }),);
+    }), );
 
 }  // anonymous namespace
diff --git a/test/BinaryToText.cpp b/test/BinaryToText.cpp
index cb4f6ad..bfb8887 100644
--- a/test/BinaryToText.cpp
+++ b/test/BinaryToText.cpp
@@ -30,8 +30,8 @@
 
 #include "gmock/gmock.h"
 
-#include "source/spirv_constant.h"
 #include "TestFixture.h"
+#include "source/spirv_constant.h"
 
 using ::testing::Eq;
 using ::testing::HasSubstr;
@@ -41,7 +41,7 @@
 namespace {
 class BinaryToText : public ::testing::Test {
  public:
-  BinaryToText() : context(spvContextCreate()) {}
+  BinaryToText() : context(spvContextCreate(SPV_ENV_UNIVERSAL_1_0)) {}
   ~BinaryToText() { spvContextDestroy(context); }
 
   virtual void SetUp() {
@@ -203,7 +203,7 @@
          "%2 = OpTypeVector %1 4",
          spvtest::MakeInstruction(SpvOpConstant, {2, 3, 999}),
          "Type Id 2 is not a scalar numeric type"},
-    }),);
+    }), );
 
 INSTANTIATE_TEST_CASE_P(
     InvalidIdsCheckedDuringLiteralCaseParsing, BinaryToTextFail,
@@ -219,7 +219,7 @@
         {"%1 = OpTypeFloat 32\n%2 = OpConstant %1 1.5",
          spvtest::MakeInstruction(SpvOpSwitch, {2, 3, 4, 5}),
          "Invalid OpSwitch: selector id 2 is not a scalar integer"},
-    }),);
+    }), );
 
 TEST_F(TextToBinaryTest, OneInstruction) {
   const std::string input = "OpSource OpenCL_C 12\n";
@@ -275,7 +275,7 @@
         "OpDecorate %1 FPFastMathMode NotNaN|NotInf\n",
         "OpDecorate %1 FPFastMathMode NSZ|AllowRecip\n",
         "OpDecorate %1 FPFastMathMode NotNaN|NotInf|NSZ|AllowRecip|Fast\n",
-    }),);
+    }), );
 
 INSTANTIATE_TEST_CASE_P(LoopControlMasks, RoundTripInstructionsTest,
                         ::testing::ValuesIn(std::vector<std::string>{
@@ -283,7 +283,7 @@
                             "OpLoopMerge %1 %2 Unroll\n",
                             "OpLoopMerge %1 %2 DontUnroll\n",
                             "OpLoopMerge %1 %2 Unroll|DontUnroll\n",
-                        }),);
+                        }), );
 
 INSTANTIATE_TEST_CASE_P(SelectionControlMasks, RoundTripInstructionsTest,
                         ::testing::ValuesIn(std::vector<std::string>{
@@ -291,7 +291,7 @@
                             "OpSelectionMerge %1 Flatten\n",
                             "OpSelectionMerge %1 DontFlatten\n",
                             "OpSelectionMerge %1 Flatten|DontFlatten\n",
-                        }),);
+                        }), );
 
 // clang-format off
 INSTANTIATE_TEST_CASE_P(
@@ -421,8 +421,6 @@
               Eq(SPV_SUCCESS));
   EXPECT_EQ(nullptr, diagnostic);
 
-  EXPECT_EQ(1, SPV_SPIRV_VERSION_MAJOR);
-  EXPECT_EQ(0, SPV_SPIRV_VERSION_MINOR);
   EXPECT_THAT(decoded_text->str, HasSubstr("Version: 1.0\n"))
       << EncodeAndDecodeSuccessfully("");
   spvTextDestroy(decoded_text);
@@ -474,6 +472,6 @@
                              "Khronos Glslang Reference Front End; 1"},
                             {9, 18, "Unknown(9); 18"},
                             {65535, 32767, "Unknown(65535); 32767"},
-                        }),);
+                        }), );
 
 }  // anonymous namespace
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 481f6ca..078febd 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -88,7 +88,6 @@
       ${CMAKE_CURRENT_SOURCE_DIR}/Validate.SSA.cpp
       ${CMAKE_CURRENT_SOURCE_DIR}/ValidateID.cpp
       ${CMAKE_CURRENT_SOURCE_DIR}/ValidationState.cpp
-      ${CMAKE_CURRENT_SOURCE_DIR}/Version.cpp
       ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
 
     add_executable(UnitSPIRV ${TEST_SOURCES})
diff --git a/test/Comment.cpp b/test/Comment.cpp
index e94c56a..7b9b94f 100644
--- a/test/Comment.cpp
+++ b/test/Comment.cpp
@@ -38,7 +38,7 @@
 
 TEST_F(TextToBinaryTest, Whitespace) {
   std::string input = R"(
-; I'm a proud comment at the begining of the file
+; I'm a proud comment at the beginning of the file
 ; I hide:   OpCapability Shader
             OpMemoryModel Logical Simple ; comment after instruction
 ;;;;;;;; many ;'s
diff --git a/test/ExtInst.OpenCL.std.cpp b/test/ExtInst.OpenCL.std.cpp
index 051b3ed..1140678 100644
--- a/test/ExtInst.OpenCL.std.cpp
+++ b/test/ExtInst.OpenCL.std.cpp
@@ -28,6 +28,7 @@
 
 #include <gmock/gmock.h>
 #include "TestFixture.h"
+#include "spirv/OpenCL.std.h"
 
 namespace {
 
@@ -330,7 +331,7 @@
 INSTANTIATE_TEST_CASE_P(
     OpenCLMiscPrintf, ExtInstOpenCLStdRoundTripTest,
     ::testing::ValuesIn(std::vector<InstructionCase>({
-      // Printf is interesting becuase it takes a variable number of arguments.
+      // Printf is interesting because it takes a variable number of arguments.
       // Start with zero optional arguments.
       {PREFIX, "%4", {4}},
       {PREFIX, "%4 %5", {4, 5}},
diff --git a/test/ExtInstGLSLstd450.cpp b/test/ExtInstGLSLstd450.cpp
index 2035854..8f4039a 100644
--- a/test/ExtInstGLSLstd450.cpp
+++ b/test/ExtInstGLSLstd450.cpp
@@ -28,6 +28,7 @@
 #include <vector>
 
 #include "UnitSPIRV.h"
+#include "spirv/GLSL.std.450.h"
 
 namespace {
 
@@ -49,7 +50,7 @@
 using ExtInstGLSLstd450RoundTripTest = ::testing::TestWithParam<ExtInstContext>;
 
 TEST_P(ExtInstGLSLstd450RoundTripTest, ParameterizedExtInst) {
-  spv_context context = spvContextCreate();
+  spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_0);
   const std::string spirv = R"(
 OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
@@ -94,8 +95,9 @@
   EXPECT_NE(binary->code + binary->wordCount,
             std::search(binary->code, binary->code + binary->wordCount,
                         expected_contains.begin(), expected_contains.end()))
-      << "Cannot find\n" << spvtest::WordVector(expected_contains).str()
-      << "in\n" << spvtest::WordVector(*binary).str();
+      << "Cannot find\n"
+      << spvtest::WordVector(expected_contains).str() << "in\n"
+      << spvtest::WordVector(*binary).str();
 
   // Check round trip gives the same text.
   spv_text output_text = nullptr;
@@ -205,6 +207,6 @@
         {"NMin", "%5 %5", 79, 7, {5, 5}},
         {"NMax", "%5 %5", 80, 7, {5, 5}},
         {"NClamp", "%5 %5 %5", 81, 8, {5, 5, 5}},
-    })),);
+    })), );
 
 }  // anonymous namespace
diff --git a/test/OpcodeRequiresCapabilities.cpp b/test/OpcodeRequiresCapabilities.cpp
index ff80964..c23fb5c 100644
--- a/test/OpcodeRequiresCapabilities.cpp
+++ b/test/OpcodeRequiresCapabilities.cpp
@@ -37,8 +37,7 @@
                0,
                {},
                false,
-               false,
-               {}}) {}
+               false}) {}
 
   virtual void SetUp() {}
 
@@ -65,10 +64,10 @@
                       SpvCapabilityClipDistance,
                       // Transformfeedback has value 53,
                       // and is the last capability.
-                      SpvCapabilityTransformFeedback),);
+                      SpvCapabilityTransformFeedback), );
 
 TEST(OpcodeRequiresCapability, None) {
-  spv_opcode_desc_t entry = {nullptr, (SpvOp)0, 0, 0, {}, false, false, {}};
+  spv_opcode_desc_t entry = {nullptr, (SpvOp)0, 0, 0, {}, false, false};
   ASSERT_EQ(0, spvOpcodeRequiresCapabilities(&entry));
 }
 
@@ -133,6 +132,6 @@
         ExpectedOpCodeCapabilities{SpvOpFunction, 0},
         ExpectedOpCodeCapabilities{SpvOpConvertFToS, 0},
         ExpectedOpCodeCapabilities{SpvOpEmitStreamVertex,
-                                   mask(SpvCapabilityGeometryStreams)}),);
+                                   mask(SpvCapabilityGeometryStreams)}), );
 
 }  // anonymous namespace
diff --git a/test/OpcodeSplit.cpp b/test/OpcodeSplit.cpp
index 2e6a8ae..976708c 100644
--- a/test/OpcodeSplit.cpp
+++ b/test/OpcodeSplit.cpp
@@ -31,7 +31,7 @@
 TEST(OpcodeSplit, Default) {
   uint32_t word = spvOpcodeMake(42, (SpvOp)23);
   uint16_t wordCount = 0;
-  SpvOp opcode;
+  uint16_t opcode;
   spvOpcodeSplit(word, &wordCount, &opcode);
   ASSERT_EQ(42, wordCount);
   ASSERT_EQ(23, opcode);
diff --git a/test/OperandCapabilities.cpp b/test/OperandCapabilities.cpp
index 684ec02..c3c84db 100644
--- a/test/OperandCapabilities.cpp
+++ b/test/OperandCapabilities.cpp
@@ -570,8 +570,8 @@
         CASE0(CAPABILITY, CapabilityInt64),
         CASE1(CAPABILITY, CapabilityInt64Atomics, Int64),
         CASE1(CAPABILITY, CapabilityImageBasic, Kernel),
-        CASE1(CAPABILITY, CapabilityImageReadWrite, Kernel),
-        CASE1(CAPABILITY, CapabilityImageMipmap, Kernel),
+        CASE1(CAPABILITY, CapabilityImageReadWrite, ImageBasic),
+        CASE1(CAPABILITY, CapabilityImageMipmap, ImageBasic),
         // Value 16 intentionally missing.
         CASE1(CAPABILITY, CapabilityPipes, Kernel),
         CASE0(CAPABILITY, CapabilityGroups),
diff --git a/test/OperandPattern.cpp b/test/OperandPattern.cpp
index a67c35f..f377469 100644
--- a/test/OperandPattern.cpp
+++ b/test/OperandPattern.cpp
@@ -189,9 +189,6 @@
               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
   EXPECT_THAT(spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_ID}),
               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
-  EXPECT_THAT(spvAlternatePatternFollowingImmediate(
-                  {SPV_OPERAND_TYPE_VARIABLE_EXECUTION_MODE}),
-              Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
 }
 
 TEST(AlternatePatternFollowingImmediate, SingleResultId) {
@@ -206,8 +203,7 @@
       spvAlternatePatternFollowingImmediate(
           {SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER,
            SPV_OPERAND_TYPE_CAPABILITY, SPV_OPERAND_TYPE_LOOP_CONTROL,
-           SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID,
-           SPV_OPERAND_TYPE_VARIABLE_EXECUTION_MODE}),
+           SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID}),
       Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
 }
 
diff --git a/test/TestFixture.h b/test/TestFixture.h
index 77f51a2..c3edd32 100644
--- a/test/TestFixture.h
+++ b/test/TestFixture.h
@@ -43,7 +43,7 @@
   const SpirvVector::size_type kFirstInstruction = 5;
 
   TextToBinaryTestBase()
-      : context(spvContextCreate()),
+      : context(spvContextCreate(SPV_ENV_UNIVERSAL_1_0)),
         diagnostic(nullptr),
         text(),
         binary(nullptr) {
@@ -66,8 +66,8 @@
   // Compiles SPIR-V text in the given assembly syntax format, asserting
   // compilation success. Returns the compiled code.
   SpirvVector CompileSuccessfully(const std::string& txt) {
-    spv_result_t status = spvTextToBinary(context, txt.c_str(), txt.size(),
-                                          &binary, &diagnostic);
+    spv_result_t status =
+        spvTextToBinary(context, txt.c_str(), txt.size(), &binary, &diagnostic);
     EXPECT_EQ(SPV_SUCCESS, status) << txt;
     SpirvVector code_copy;
     if (status == SPV_SUCCESS) {
@@ -100,8 +100,8 @@
   std::string EncodeAndDecodeSuccessfully(const std::string& txt,
                                           uint32_t disassemble_options) {
     DestroyBinary();
-    spv_result_t error = spvTextToBinary(context, txt.c_str(), txt.size(),
-                                         &binary, &diagnostic);
+    spv_result_t error =
+        spvTextToBinary(context, txt.c_str(), txt.size(), &binary, &diagnostic);
     if (error) {
       spvDiagnosticPrint(diagnostic);
       spvDiagnosticDestroy(diagnostic);
diff --git a/test/TextAdvance.cpp b/test/TextAdvance.cpp
index 627d0d6..0f18530 100644
--- a/test/TextAdvance.cpp
+++ b/test/TextAdvance.cpp
@@ -96,4 +96,40 @@
   ASSERT_EQ(SPV_END_OF_STREAM, data.advance());
 }
 
+// Invokes AssemblyContext::advance() on text, asserts success, and returns
+// AssemblyContext::position().
+spv_position_t PositionAfterAdvance(const char* text) {
+  AutoText input(text);
+  AssemblyContext data(input, nullptr);
+  EXPECT_EQ(SPV_SUCCESS, data.advance());
+  return data.position();
+}
+
+TEST(TextAdvance, SkipOverCR) {
+  const auto pos = PositionAfterAdvance("\rWord");
+  EXPECT_EQ(1u, pos.column);
+  EXPECT_EQ(0u, pos.line);
+  EXPECT_EQ(1u, pos.index);
+}
+
+TEST(TextAdvance, SkipOverCRs) {
+  const auto pos = PositionAfterAdvance("\r\r\rWord");
+  EXPECT_EQ(3u, pos.column);
+  EXPECT_EQ(0u, pos.line);
+  EXPECT_EQ(3u, pos.index);
+}
+
+TEST(TextAdvance, SkipOverCRLF) {
+  const auto pos = PositionAfterAdvance("\r\nWord");
+  EXPECT_EQ(0u, pos.column);
+  EXPECT_EQ(1u, pos.line);
+  EXPECT_EQ(2u, pos.index);
+}
+
+TEST(TextAdvance, SkipOverCRLFs) {
+  const auto pos = PositionAfterAdvance("\r\n\r\nWord");
+  EXPECT_EQ(0u, pos.column);
+  EXPECT_EQ(2u, pos.line);
+  EXPECT_EQ(4u, pos.index);
+}
 }  // anonymous namespace
diff --git a/test/TextDestroy.cpp b/test/TextDestroy.cpp
index ef789ad..c721fdc 100644
--- a/test/TextDestroy.cpp
+++ b/test/TextDestroy.cpp
@@ -31,7 +31,7 @@
 TEST(TextDestroy, DestroyNull) { spvBinaryDestroy(nullptr); }
 
 TEST(TextDestroy, Default) {
-  spv_context context = spvContextCreate();
+  spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_0);
   char textStr[] = R"(
       OpSource OpenCL_C 12
       OpMemoryModel Physical64 OpenCL
diff --git a/test/TextToBinary.Extension.cpp b/test/TextToBinary.Extension.cpp
index 437736d..420f0d3 100644
--- a/test/TextToBinary.Extension.cpp
+++ b/test/TextToBinary.Extension.cpp
@@ -31,6 +31,8 @@
 
 #include "TestFixture.h"
 #include "gmock/gmock.h"
+#include "spirv/GLSL.std.450.h"
+#include "spirv/OpenCL.std.h"
 
 namespace {
 
diff --git a/test/TextToBinary.ModeSetting.cpp b/test/TextToBinary.ModeSetting.cpp
index b61644d..36a5bae 100644
--- a/test/TextToBinary.ModeSetting.cpp
+++ b/test/TextToBinary.ModeSetting.cpp
@@ -198,6 +198,12 @@
               Eq("Invalid execution mode 'xxyyzz'."));
 }
 
+TEST_F(OpExecutionModeTest, TooManyModes) {
+  EXPECT_THAT(CompileFailure("OpExecutionMode %1 Xfb PointMode"),
+              Eq("Expected <opcode> or <result-id> at the beginning of an "
+                 "instruction, found 'PointMode'."));
+}
+
 // Test OpCapability
 
 using OpCapabilityTest = spvtest::TextToBinaryTestBase<
diff --git a/test/TextToBinary.cpp b/test/TextToBinary.cpp
index a2e490a..812da40 100644
--- a/test/TextToBinary.cpp
+++ b/test/TextToBinary.cpp
@@ -25,6 +25,7 @@
 // MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
 
 #include <algorithm>
+#include <cstring>
 #include <utility>
 #include <vector>
 
@@ -45,6 +46,8 @@
 using spvtest::MakeInstruction;
 using spvtest::TextToBinaryTest;
 using testing::Eq;
+using testing::IsNull;
+using testing::NotNull;
 
 // An mask parsing test case.
 struct MaskCase {
@@ -56,7 +59,7 @@
 using GoodMaskParseTest = ::testing::TestWithParam<MaskCase>;
 
 TEST_P(GoodMaskParseTest, GoodMaskExpressions) {
-  spv_context context = spvContextCreate();
+  spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_0);
 
   uint32_t value;
   EXPECT_EQ(SPV_SUCCESS,
@@ -96,12 +99,12 @@
         {SPV_OPERAND_TYPE_FUNCTION_CONTROL, 4, "Pure"},
         {SPV_OPERAND_TYPE_FUNCTION_CONTROL, 8, "Const"},
         {SPV_OPERAND_TYPE_FUNCTION_CONTROL, 0xd, "Inline|Const|Pure"},
-    }),);
+    }), );
 
 using BadFPFastMathMaskParseTest = ::testing::TestWithParam<const char*>;
 
 TEST_P(BadFPFastMathMaskParseTest, BadMaskExpressions) {
-  spv_context context = spvContextCreate();
+  spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_0);
 
   uint32_t value;
   EXPECT_NE(SPV_SUCCESS,
@@ -116,7 +119,7 @@
                             nullptr, "", "NotValidEnum", "|", "NotInf|",
                             "|NotInf", "NotInf||NotNaN",
                             "Unroll"  // A good word, but for the wrong enum
-                        }),);
+                        }), );
 
 TEST_F(TextToBinaryTest, InvalidText) {
   ASSERT_EQ(SPV_ERROR_INVALID_TEXT,
@@ -192,6 +195,14 @@
   EXPECT_EQ(6u, diagnostic->position.column + 1);
 }
 
+TEST_F(TextToBinaryTest, CRLF) {
+  const std::string input =
+      "%i32 = OpTypeInt 32 1\r\n%c = OpConstant %i32 123\r\n";
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
+                              MakeInstruction(SpvOpConstant, {1, 2, 123})})));
+}
+
 using TextToBinaryFloatValueTest = spvtest::TextToBinaryTestBase<
     ::testing::TestWithParam<std::pair<std::string, uint32_t>>>;
 
@@ -220,7 +231,7 @@
         {"-2.5", 0xc0200000},
         {"!0xff800000", 0xff800000},  // -inf
         {"!0xff800001", 0xff800001},  // NaN
-    }),);
+    }), );
 
 using TextToBinaryHalfValueTest = spvtest::TextToBinaryTestBase<
     ::testing::TestWithParam<std::pair<std::string, uint32_t>>>;
@@ -252,7 +263,7 @@
         {"0x1.8p4", 0x00004e00},
         {"0x1.801p4", 0x00004e00},
         {"0x1.804p4", 0x00004e01},
-    }),);
+    }), );
 
 TEST(AssemblyContextParseNarrowSignedIntegers, Sample) {
   AssemblyContext context(AutoText(""), nullptr);
@@ -538,4 +549,22 @@
   spvDiagnosticDestroy(diag);
 }
 
+TEST(CreateContext, InvalidEnvironment) {
+  spv_target_env env;
+  std::memset(&env, 99, sizeof(env));
+  EXPECT_THAT(spvContextCreate(env), IsNull());
+}
+
+TEST(CreateContext, UniversalEnvironment) {
+  auto c = spvContextCreate(SPV_ENV_UNIVERSAL_1_0);
+  EXPECT_THAT(c, NotNull());
+  spvContextDestroy(c);
+}
+
+TEST(CreateContext, VulkanEnvironment) {
+  auto c = spvContextCreate(SPV_ENV_VULKAN_1_0);
+  EXPECT_THAT(c, NotNull());
+  spvContextDestroy(c);
+}
+
 }  // anonymous namespace
diff --git a/test/TextWordGet.cpp b/test/TextWordGet.cpp
index 7abfee5..651f850 100644
--- a/test/TextWordGet.cpp
+++ b/test/TextWordGet.cpp
@@ -245,4 +245,19 @@
   ASSERT_STREQ("word" BACKSLASH BACKSLASH, word.c_str());
 }
 
+TEST(TextWordGet, CRLF) {
+  AutoText input("abc\r\nd");
+  AssemblyContext data(input, nullptr);
+  std::string word;
+  spv_position_t pos = {};
+  ASSERT_EQ(SPV_SUCCESS, data.getWord(&word, &pos));
+  EXPECT_EQ(3u, pos.column);
+  EXPECT_STREQ("abc", word.c_str());
+  data.setPosition(pos);
+  data.advance();
+  ASSERT_EQ(SPV_SUCCESS, data.getWord(&word, &pos));
+  EXPECT_EQ(1u, pos.column);
+  EXPECT_STREQ("d", word.c_str());
+}
+
 }  // anonymous namespace
diff --git a/test/UnitSPIRV.h b/test/UnitSPIRV.h
index 49eb2e2..6e89284 100644
--- a/test/UnitSPIRV.h
+++ b/test/UnitSPIRV.h
@@ -199,7 +199,7 @@
 // each of which has a 4-byte UTF-8 encoding.
 inline std::string MakeLongUTF8String(size_t num_4_byte_chars) {
   // An example of a longest valid UTF-8 character.
-  // Be explicit about the character type becuase Microsoft compilers can
+  // Be explicit about the character type because Microsoft compilers can
   // otherwise interpret the character string as being over wide (16-bit)
   // characters.  Ideally, we would just use a C++11 UTF-8 string literal,
   // but we want to support older Microsoft compilers.
diff --git a/test/Validate.Layout.cpp b/test/Validate.Layout.cpp
index 74a078c..c680be1 100644
--- a/test/Validate.Layout.cpp
+++ b/test/Validate.Layout.cpp
@@ -302,7 +302,7 @@
 %funcl   = OpLabel
            OpNop
            OpBranch %next
-%func2p  = OpFunctionParameter %intt        ;FunctionParameter appears in a function but not immediatly afterwards
+%func2p  = OpFunctionParameter %intt        ;FunctionParameter appears in a function but not immediately afterwards
 %next    = OpLabel
            OpNop
            OpReturn
diff --git a/test/ValidateFixtures.cpp b/test/ValidateFixtures.cpp
index e51a580..1830895 100644
--- a/test/ValidateFixtures.cpp
+++ b/test/ValidateFixtures.cpp
@@ -26,8 +26,8 @@
 
 // Common validation fixtures for unit tests
 
-#include "UnitSPIRV.h"
 #include "ValidateFixtures.h"
+#include "UnitSPIRV.h"
 
 #include <functional>
 #include <tuple>
@@ -37,7 +37,9 @@
 
 template <typename T>
 ValidateBase<T>::ValidateBase()
-    : context_(spvContextCreate()), binary_(), diagnostic_() {}
+    : context_(spvContextCreate(SPV_ENV_UNIVERSAL_1_0)),
+      binary_(),
+      diagnostic_() {}
 
 template <typename T>
 ValidateBase<T>::~ValidateBase() {
diff --git a/test/ValidateID.cpp b/test/ValidateID.cpp
index 171ec97..808a90b 100644
--- a/test/ValidateID.cpp
+++ b/test/ValidateID.cpp
@@ -24,9 +24,10 @@
 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 // MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
 
+#include <sstream>
 #include <string>
 
-#include "UnitSPIRV.h"
+#include "TestFixture.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
@@ -36,6 +37,11 @@
 
 namespace {
 
+using ::testing::ValuesIn;
+using std::ostringstream;
+using std::string;
+using std::vector;
+
 class ValidateID : public ::testing::Test {
  public:
   virtual void TearDown() { spvBinaryDestroy(binary); }
@@ -69,16 +75,18 @@
      OpMemoryModel Physical64 OpenCL
 )";
 
+// TODO(dekimir): this can be removed by adding a method to ValidateID akin to
+// OpTypeArrayLengthTest::Val().
 #define CHECK(str, expected)                                                   \
   spv_diagnostic diagnostic;                                                   \
-  spv_context context = spvContextCreate();                                    \
+  spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_0);               \
   std::string shader = std::string(kGLSL450MemoryModel) + str;                 \
   spv_result_t error = spvTextToBinary(context, shader.c_str(), shader.size(), \
                                        &binary, &diagnostic);                  \
   if (error) {                                                                 \
     spvDiagnosticPrint(diagnostic);                                            \
     spvDiagnosticDestroy(diagnostic);                                          \
-    ASSERT_EQ(SPV_SUCCESS, error);                                             \
+    ASSERT_EQ(SPV_SUCCESS, error) << shader;                                   \
   }                                                                            \
   spv_result_t result = spvValidate(context, get_const_binary(), &diagnostic); \
   if (SPV_SUCCESS != result) {                                                 \
@@ -91,10 +99,10 @@
 #define CHECK_KERNEL(str, expected, bitness)                                   \
   ASSERT_TRUE(bitness == 32 || bitness == 64);                                 \
   spv_diagnostic diagnostic;                                                   \
-  spv_context context = spvContextCreate();                                    \
-  std::string kernel = std::string(bitness == 32 ?                             \
-                                   kOpenCLMemoryModel32 :                      \
-                                   kOpenCLMemoryModel64) + str;                \
+  spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_0);               \
+  std::string kernel = std::string(bitness == 32 ? kOpenCLMemoryModel32        \
+                                                 : kOpenCLMemoryModel64) +     \
+                       str;                                                    \
   spv_result_t error = spvTextToBinary(context, kernel.c_str(), kernel.size(), \
                                        &binary, &diagnostic);                  \
   if (error) {                                                                 \
@@ -371,6 +379,7 @@
 %3 = OpTypeArray %1 %2)";
   CHECK(spirv, SPV_SUCCESS);
 }
+
 TEST_F(ValidateID, OpTypeArrayElementTypeBad) {
   const char* spirv = R"(
 %1 = OpTypeInt 32 0
@@ -378,14 +387,117 @@
 %3 = OpTypeArray %2 %2)";
   CHECK(spirv, SPV_ERROR_INVALID_ID);
 }
-TEST_F(ValidateID, OpTypeArrayLengthBad) {
+
+// Signed or unsigned.
+enum Signed { kSigned, kUnsigned };
+
+// Creates an assembly snippet declaring OpTypeArray with the given length.
+string MakeArrayLength(const string& len, Signed isSigned, int width) {
+  ostringstream ss;
+  ss << kGLSL450MemoryModel;
+  ss << " %t = OpTypeInt " << width << (isSigned == kSigned ? " 1" : " 0")
+     << " %l = OpConstant %t " << len << " %a = OpTypeArray %t %l";
+  return ss.str();
+}
+
+// Tests OpTypeArray.  Parameter is the width (in bits) of the array-length's
+// type.
+class OpTypeArrayLengthTest
+    : public spvtest::TextToBinaryTestBase<::testing::TestWithParam<int>> {
+ protected:
+  OpTypeArrayLengthTest()
+      : position_(spv_position_t{0, 0, 0}),
+        diagnostic_(spvDiagnosticCreate(&position_, "")) {}
+
+  ~OpTypeArrayLengthTest() { spvDiagnosticDestroy(diagnostic_); }
+
+  // Runs spvValidate() on v, printing any errors via spvDiagnosticPrint().
+  spv_result_t Val(const SpirvVector& v) {
+    spv_const_binary_t cbinary{v.data(), v.size()};
+    const auto status = spvValidate(context, &cbinary, &diagnostic_);
+    if (status != SPV_SUCCESS) {
+      spvDiagnosticPrint(diagnostic_);
+    }
+    return status;
+  }
+
+ private:
+  spv_position_t position_;  // For creating diagnostic_.
+  spv_diagnostic diagnostic_;
+};
+
+TEST_P(OpTypeArrayLengthTest, LengthPositive) {
+  const int width = GetParam();
+  EXPECT_EQ(SPV_SUCCESS,
+            Val(CompileSuccessfully(MakeArrayLength("1", kSigned, width))));
+  EXPECT_EQ(SPV_SUCCESS,
+            Val(CompileSuccessfully(MakeArrayLength("1", kUnsigned, width))));
+  EXPECT_EQ(SPV_SUCCESS,
+            Val(CompileSuccessfully(MakeArrayLength("2", kSigned, width))));
+  EXPECT_EQ(SPV_SUCCESS,
+            Val(CompileSuccessfully(MakeArrayLength("2", kUnsigned, width))));
+  EXPECT_EQ(SPV_SUCCESS,
+            Val(CompileSuccessfully(MakeArrayLength("55", kSigned, width))));
+  EXPECT_EQ(SPV_SUCCESS,
+            Val(CompileSuccessfully(MakeArrayLength("55", kUnsigned, width))));
+  const string fpad(width / 4 - 1, 'F');
+  EXPECT_EQ(
+      SPV_SUCCESS,
+      Val(CompileSuccessfully(MakeArrayLength("0x7" + fpad, kSigned, width))));
+  EXPECT_EQ(SPV_SUCCESS, Val(CompileSuccessfully(
+                             MakeArrayLength("0xF" + fpad, kUnsigned, width))));
+}
+
+TEST_P(OpTypeArrayLengthTest, LengthZero) {
+  const int width = GetParam();
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            Val(CompileSuccessfully(MakeArrayLength("0", kSigned, width))));
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            Val(CompileSuccessfully(MakeArrayLength("0", kUnsigned, width))));
+}
+
+TEST_P(OpTypeArrayLengthTest, LengthNegative) {
+  const int width = GetParam();
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            Val(CompileSuccessfully(MakeArrayLength("-1", kSigned, width))));
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            Val(CompileSuccessfully(MakeArrayLength("-2", kSigned, width))));
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            Val(CompileSuccessfully(MakeArrayLength("-123", kSigned, width))));
+  const string neg_max = "0x8" + string(width / 4 - 1, '0');
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            Val(CompileSuccessfully(MakeArrayLength(neg_max, kSigned, width))));
+}
+
+INSTANTIATE_TEST_CASE_P(Widths, OpTypeArrayLengthTest,
+                        ValuesIn(vector<int>{8, 16, 32, 48, 64}));
+
+TEST_F(ValidateID, OpTypeArrayLengthNull) {
   const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpConstant %1 0
-%3 = OpTypeArray %1 %2)";
+%i32 = OpTypeInt 32 1
+%len = OpConstantNull %i32
+%ary = OpTypeArray %i32 %len)";
   CHECK(spirv, SPV_ERROR_INVALID_ID);
 }
 
+TEST_F(ValidateID, OpTypeArrayLengthSpecConst) {
+  const char* spirv = R"(
+%i32 = OpTypeInt 32 1
+%len = OpSpecConstant %i32 2
+%ary = OpTypeArray %i32 %len)";
+  CHECK(spirv, SPV_SUCCESS);
+}
+
+TEST_F(ValidateID, OpTypeArrayLengthSpecConstOp) {
+  const char* spirv = R"(
+%i32 = OpTypeInt 32 1
+%c1 = OpConstant %i32 1
+%c2 = OpConstant %i32 2
+%len = OpSpecConstantOp %i32 IAdd %c1 %c2
+%ary = OpTypeArray %i32 %len)";
+  CHECK(spirv, SPV_SUCCESS);
+}
+
 TEST_F(ValidateID, OpTypeRuntimeArrayGood) {
   const char* spirv = R"(
 %1 = OpTypeInt 32 0
diff --git a/test/ValidationState.cpp b/test/ValidationState.cpp
index e38516d..bbc4f60 100644
--- a/test/ValidationState.cpp
+++ b/test/ValidationState.cpp
@@ -42,7 +42,8 @@
 class ValidationStateTest : public testing::Test {
  public:
   ValidationStateTest()
-      : context_(spvContextCreate()), state_(&diag_, context_) {}
+      : context_(spvContextCreate(SPV_ENV_UNIVERSAL_1_0)),
+        state_(&diag_, context_) {}
 
  protected:
   spv_diagnostic diag_;
diff --git a/tools/as/as.cpp b/tools/as/as.cpp
index 8166d76..214dcc1 100644
--- a/tools/as/as.cpp
+++ b/tools/as/as.cpp
@@ -54,7 +54,7 @@
 
 const char kBuildVersion[] =
 #include "build-version.inc"
-;
+    ;
 
 int main(int argc, char** argv) {
   const char* inFile = nullptr;
@@ -88,8 +88,8 @@
           // Long options
           if (0 == strcmp(argv[argi], "--version")) {
             printf("%s\n", kBuildVersion);
-            printf("Target: SPIR-V %d.%d rev %d\n", SPV_SPIRV_VERSION_MAJOR,
-                   SPV_SPIRV_VERSION_MINOR, SPV_SPIRV_VERSION_REVISION);
+            printf("Target: %s\n",
+                   spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_0));
             return 0;
           }
           if (0 == strcmp(argv[argi], "--help")) {
@@ -129,7 +129,7 @@
 
   spv_binary binary;
   spv_diagnostic diagnostic = nullptr;
-  spv_context context = spvContextCreate();
+  spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_0);
   spv_result_t error = spvTextToBinary(context, contents.data(),
                                        contents.size(), &binary, &diagnostic);
   spvContextDestroy(context);
diff --git a/tools/dis/dis.cpp b/tools/dis/dis.cpp
index 1f12f50..b8221c9 100644
--- a/tools/dis/dis.cpp
+++ b/tools/dis/dis.cpp
@@ -61,7 +61,7 @@
 
 const char kBuildVersion[] =
 #include "build-version.inc"
-;
+    ;
 
 int main(int argc, char** argv) {
   const char* inFile = nullptr;
@@ -101,8 +101,8 @@
             return 0;
           } else if (0 == strcmp(argv[argi], "--version")) {
             printf("%s\n", kBuildVersion);
-            printf("Target: SPIR-V %d.%d rev %d\n", SPV_SPIRV_VERSION_MAJOR,
-                   SPV_SPIRV_VERSION_MINOR, SPV_SPIRV_VERSION_REVISION);
+            printf("Target: %s\n",
+                   spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_0));
             return 0;
           } else {
             print_usage(argv[0]);
@@ -174,12 +174,11 @@
   // into the output stream.
   // If the printing option is off, then save the text in memory, so
   // it can be emitted later in this function.
-  const bool print_to_stdout =
-      spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_PRINT, options);
+  const bool print_to_stdout = SPV_BINARY_TO_TEXT_OPTION_PRINT & options;
   spv_text text;
   spv_text* textOrNull = print_to_stdout ? nullptr : &text;
   spv_diagnostic diagnostic = nullptr;
-  spv_context context = spvContextCreate();
+  spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_0);
   spv_result_t error =
       spvBinaryToText(context, contents.data(), contents.size(), options,
                       textOrNull, &diagnostic);
diff --git a/tools/val/val.cpp b/tools/val/val.cpp
index 76220fa..f9e19a4 100644
--- a/tools/val/val.cpp
+++ b/tools/val/val.cpp
@@ -52,22 +52,26 @@
 
 const char kBuildVersion[] =
 #include "build-version.inc"
-;
+    ;
 
 int main(int argc, char** argv) {
   const char* inFile = nullptr;
+  spv_target_env target_env = SPV_ENV_UNIVERSAL_1_0;
 
   for (int argi = 1; argi < argc; ++argi) {
     const char* cur_arg = argv[argi];
     if ('-' == cur_arg[0]) {
       if (0 == strcmp(cur_arg, "--version")) {
         printf("%s\n", kBuildVersion);
-        printf("Target: SPIR-V %d.%d rev %d\n", SPV_SPIRV_VERSION_MAJOR,
-               SPV_SPIRV_VERSION_MINOR, SPV_SPIRV_VERSION_REVISION);
+        printf("Targets:\n  %s\n  %s\n",
+               spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_0),
+               spvTargetEnvDescription(SPV_ENV_VULKAN_1_0));
         return 0;
       } else if (0 == strcmp(cur_arg, "--help") || 0 == strcmp(cur_arg, "-h")) {
         print_usage(argv[0]);
         return 0;
+      } else if (0 == strcmp(cur_arg, "--vulkan")) {
+        target_env = SPV_ENV_VULKAN_1_0;
       } else if (0 == cur_arg[1]) {
         // Setting a filename of "-" to indicate stdin.
         if (!inFile) {
@@ -108,7 +112,7 @@
   spv_const_binary_t binary = {contents.data(), contents.size()};
 
   spv_diagnostic diagnostic = nullptr;
-  spv_context context = spvContextCreate();
+  spv_context context = spvContextCreate(target_env);
   spv_result_t error = spvValidate(context, &binary, &diagnostic);
   spvContextDestroy(context);
   if (error) {
diff --git a/utils/generate_grammar_tables.py b/utils/generate_grammar_tables.py
new file mode 100755
index 0000000..b5ab592
--- /dev/null
+++ b/utils/generate_grammar_tables.py
@@ -0,0 +1,402 @@
+#!/usr/bin/env python
+"""Generates various info tables from SPIR-V JSON grammar."""
+
+from __future__ import print_function
+
+import functools
+import json
+import os.path
+import re
+
+# Prefix for all C variables generated by this script.
+PYGEN_VARIABLE_PREFIX = 'pygen_variable'
+
+CAPABILITY_BIT_MAPPING = {}
+
+
+def make_path_to_file(f):
+    """Makes all ancestor directories to the given file, if they
+    don't yet exist.
+
+    Arguments:
+        f: The file whose ancestor directories are to be created.
+    """
+    dir = os.path.dirname(os.path.abspath(f))
+    if not os.path.isdir(dir):
+        os.makedirs(dir)
+
+
+def populate_capability_bit_mapping_dict(cap_dict):
+    """Populates CAPABILITY_BIT_MAPPING.
+
+    Arguments:
+      - cap_dict: a dict containing all capability names and values
+    """
+    assert cap_dict['category'] == 'ValueEnum'
+    assert cap_dict['kind'] == 'Capability'
+    for enumerant in cap_dict['enumerants']:
+        CAPABILITY_BIT_MAPPING[enumerant['enumerant']] = enumerant['value']
+
+
+def compose_capability_mask(caps):
+    """Returns a bit mask for a sequence of capabilities
+
+    Arguments:
+      - caps: a sequence of capability names
+
+    Returns:
+      a string containing the hexadecimal value of the bit mask
+    """
+    assert len(CAPABILITY_BIT_MAPPING) != 0
+    bits = [CAPABILITY_BIT_MAPPING[c] for c in caps]
+    caps_mask = functools.reduce(lambda m, b: m | (1 << b), bits, 0)
+    return '0x{:04x}'.format(caps_mask)
+
+
+def convert_operand_kind(operand_tuple):
+    """Returns the corresponding operand type used in spirv-tools for
+    the given operand kind and quantifier used in the JSON grammar.
+
+    Arguments:
+      - operand_tuple: a tuple of two elements:
+          - operand kind: used in the JSON grammar
+          - quantifier: '', '?', or '*'
+
+    Returns:
+      a string of the enumerant name in spv_operand_type_t
+    """
+    kind, quantifier = operand_tuple
+    # The following cases are where we differ between the JSON grammar and
+    # spirv-tools.
+    if kind == 'IdResultType':
+        kind = 'TypeId'
+    elif kind == 'IdResult':
+        kind = 'ResultId'
+    elif kind == 'IdMemorySemantics' or kind == 'MemorySemantics':
+        kind = 'MemorySemanticsId'
+    elif kind == 'IdScope' or kind == 'Scope':
+        kind = 'ScopeId'
+    elif kind == 'IdRef':
+        kind = 'Id'
+
+    elif kind == 'ImageOperands':
+        kind = 'Image'
+    elif kind == 'Dim':
+        kind = 'Dimensionality'
+    elif kind == 'ImageFormat':
+        kind = 'SamplerImageFormat'
+    elif kind == 'KernelEnqueueFlags':
+        kind = 'KernelEnqFlags'
+
+    elif kind == 'LiteralExtInstInteger':
+        kind = 'ExtensionInstructionNumber'
+    elif kind == 'LiteralSpecConstantOpInteger':
+        kind = 'SpecConstantOpNumber'
+    elif kind == 'LiteralContextDependentNumber':
+        kind = 'TypedLiteralNumber'
+
+    elif kind == 'PairLiteralIntegerIdRef':
+        kind = 'LiteralIntegerId'
+    elif kind == 'PairIdRefLiteralInteger':
+        kind = 'IdLiteralInteger'
+    elif kind == 'PairIdRefIdRef':  # Used by OpPhi in the grammar
+        kind = 'Id'
+
+    if kind == 'FPRoundingMode':
+        kind = 'FpRoundingMode'
+    elif kind == 'FPFastMathMode':
+        kind = 'FpFastMathMode'
+
+    if quantifier == '?':
+        kind = 'Optional{}'.format(kind)
+    elif quantifier == '*':
+        kind = 'Variable{}'.format(kind)
+
+    return 'SPV_OPERAND_TYPE_{}'.format(
+        re.sub(r'([a-z])([A-Z])', r'\1_\2', kind).upper())
+
+
+class InstInitializer(object):
+    """Instances holds a SPIR-V instruction suitable for printing as
+    the initializer for spv_opcode_desc_t."""
+
+    def __init__(self, opname, caps, operands):
+        """Initialization.
+
+        Arguments:
+          - opname: opcode name (with the 'Op' prefix)
+          - caps: a sequence of capability names required by this opcode
+          - operands: a sequence of (operand-kind, operand-quantifier) tuples
+        """
+        assert opname.startswith('Op')
+        self.opname = opname[2:]  # Remove the "Op" prefix.
+        self.caps_mask = compose_capability_mask(caps)
+        self.operands = [convert_operand_kind(o) for o in operands]
+
+        operands = [o[0] for o in operands]
+        self.ref_type_id = 'IdResultType' in operands
+        self.def_result_id = 'IdResult' in operands
+
+    def __str__(self):
+        template = ['{{"{opname}"', 'SpvOp{opname}', '{caps_mask}',
+                    '{num_operands}', '{{{operands}}}',
+                    '{def_result_id}', '{ref_type_id}}}']
+        return ', '.join(template).format(
+            opname=self.opname,
+            caps_mask=self.caps_mask,
+            num_operands=len(self.operands),
+            operands=', '.join(self.operands),
+            def_result_id=(1 if self.def_result_id else 0),
+            ref_type_id=(1 if self.ref_type_id else 0))
+
+
+class ExtInstInitializer(object):
+    """Instances holds a SPIR-V extended instruction suitable for printing as
+    the initializer for spv_ext_inst_desc_t."""
+
+    def __init__(self, opname, opcode, caps, operands):
+        """Initialization.
+
+        Arguments:
+          - opname: opcode name
+          - opcode: enumerant value for this opcode
+          - caps: a sequence of capability names required by this opcode
+          - operands: a sequence of (operand-kind, operand-quantifier) tuples
+        """
+        self.opname = opname
+        self.opcode = opcode
+        self.caps_mask = compose_capability_mask(caps)
+        self.operands = [convert_operand_kind(o) for o in operands]
+        self.operands.append('SPV_OPERAND_TYPE_NONE')
+
+    def __str__(self):
+        template = ['{{"{opname}"', '{opcode}', '{caps_mask}',
+                    '{{{operands}}}}}']
+        return ', '.join(template).format(
+            opname=self.opname,
+            opcode=self.opcode,
+            caps_mask=self.caps_mask,
+            operands=', '.join(self.operands))
+
+
+def generate_instruction(inst, is_ext_inst):
+    """Returns the C initializer for the given SPIR-V instruction.
+
+    Arguments:
+      - inst: a dict containing information about a SPIR-V instruction
+      - is_ext_inst: a bool indicating whether |inst| is an extended
+                     instruction.
+
+    Returns:
+      a string containing the C initializer for spv_opcode_desc_t or
+      spv_ext_inst_desc_t
+    """
+    opname = inst.get('opname')
+    opcode = inst.get('opcode')
+    caps = inst.get('capabilities', [])
+    operands = inst.get('operands', {})
+    operands = [(o['kind'], o.get('quantifier', '')) for o in operands]
+
+    assert opname is not None
+
+    if is_ext_inst:
+        return str(ExtInstInitializer(opname, opcode, caps, operands))
+    else:
+        return str(InstInitializer(opname, caps, operands))
+
+
+def generate_instruction_table(inst_table, is_ext_inst):
+    """Returns the info table containing all SPIR-V instructions.
+
+    Arguments:
+      - inst_table: a dict containing all SPIR-V instructions.
+      - is_ext_inst: a bool indicating whether |inst_table| is for
+                     an extended instruction set.
+    """
+    return ',\n'.join([generate_instruction(inst, is_ext_inst)
+                       for inst in inst_table])
+
+
+class EnumerantInitializer(object):
+    """Prints an enumerant as the initializer for spv_operand_desc_t."""
+
+    def __init__(self, enumerant, value, caps, parameters):
+        """Initialization.
+
+        Arguments:
+          - enumerant: enumerant name
+          - value: enumerant value
+          - caps: a sequence of capability names required by this enumerant
+          - parameters: a sequence of (operand-kind, operand-quantifier) tuples
+        """
+        self.enumerant = enumerant
+        self.value = value
+        self.caps_mask = compose_capability_mask(caps)
+        self.parameters = [convert_operand_kind(p) for p in parameters]
+
+    def __str__(self):
+        template = ['{{"{enumerant}"', '{value}',
+                    '{caps_mask}', '{{{parameters}}}}}']
+        return ', '.join(template).format(
+            enumerant=self.enumerant,
+            value=self.value,
+            caps_mask=self.caps_mask,
+            parameters=', '.join(self.parameters))
+
+
+def generate_enum_operand_kind_entry(entry):
+    """Returns the C initializer for the given operand enum entry.
+
+    Arguments:
+      - entry: a dict containing information about an enum entry
+
+    Returns:
+      a string containing the C initializer for spv_operand_desc_t
+    """
+    enumerant = entry.get('enumerant')
+    value = entry.get('value')
+    caps = entry.get('capabilities', [])
+    params = entry.get('parameters', [])
+    params = [p.get('kind') for p in params]
+    params = zip(params, [''] * len(params))
+
+    assert enumerant is not None
+    assert value is not None
+
+    return str(EnumerantInitializer(enumerant, value, caps, params))
+
+
+def generate_enum_operand_kind(enum):
+    """Returns the C definition for the given operand kind."""
+    kind = enum.get('kind')
+    assert kind is not None
+
+    name = '{}_{}Entries'.format(PYGEN_VARIABLE_PREFIX, kind)
+    entries = ['  {}'.format(generate_enum_operand_kind_entry(e))
+               for e in enum.get('enumerants', [])]
+
+    template = ['static const spv_operand_desc_t {name}[] = {{',
+                '{entries}', '}};']
+    entries = '\n'.join(template).format(
+        name=name,
+        entries=',\n'.join(entries))
+
+    return kind, name, entries
+
+
+def generate_operand_kind_table(enums):
+    """Returns the info table containing all SPIR-V operand kinds."""
+    # We only need to output info tables for those operand kinds that are enums.
+    enums = [generate_enum_operand_kind(e)
+             for e in enums
+             if e.get('category') in ['ValueEnum', 'BitEnum']]
+    # We have three operand kinds that requires their optional counterpart to
+    # exist in the operand info table.
+    three_optional_enums = ['ImageOperands', 'AccessQualifier', 'MemoryAccess']
+    three_optional_enums = [e for e in enums if e[0] in three_optional_enums]
+    enums.extend(three_optional_enums)
+
+    enum_kinds, enum_names, enum_entries = zip(*enums)
+    # Mark the last three as optional ones.
+    enum_quantifiers = [''] * (len(enums) - 3) + ['?'] * 3
+    # And we don't want redefinition of them.
+    enum_entries = enum_entries[:-3]
+    enum_kinds = [convert_operand_kind(e)
+                  for e in zip(enum_kinds, enum_quantifiers)]
+    table_entries = zip(enum_kinds, enum_names, enum_names)
+    table_entries = ['  {{{}, ARRAY_SIZE({}), {}}}'.format(*e)
+                     for e in table_entries]
+
+    template = [
+        'static const spv_operand_desc_group_t {p}_OperandInfoTable[] = {{',
+        '{enums}', '}};']
+    table = '\n'.join(template).format(
+        p=PYGEN_VARIABLE_PREFIX, enums=',\n'.join(table_entries))
+
+    return '\n\n'.join(enum_entries + (table,))
+
+
+def main():
+    import argparse
+    parser = argparse.ArgumentParser(description='Generate SPIR-V info tables')
+    parser.add_argument('--spirv-core-grammar', metavar='<path>',
+                        type=str, required=True,
+                        help='input JSON grammar file for core SPIR-V '
+                        'instructions')
+    parser.add_argument('--extinst-glsl-grammar', metavar='<path>',
+                        type=str, required=False, default=None,
+                        help='input JSON grammar file for GLSL extended '
+                        'instruction set')
+    parser.add_argument('--extinst-opencl-grammar', metavar='<path>',
+                        type=str, required=False, default=None,
+                        help='input JSON grammar file for OpenGL extended '
+                        'instruction set')
+    parser.add_argument('--core-insts-output', metavar='<path>',
+                        type=str, required=False, default=None,
+                        help='output file for core SPIR-V instructions')
+    parser.add_argument('--glsl-insts-output', metavar='<path>',
+                        type=str, required=False, default=None,
+                        help='output file for GLSL extended instruction set')
+    parser.add_argument('--opencl-insts-output', metavar='<path>',
+                        type=str, required=False, default=None,
+                        help='output file for OpenCL extended instruction set')
+    parser.add_argument('--operand-kinds-output', metavar='<path>',
+                        type=str, required=False, default=None,
+                        help='output file for operand kinds')
+    args = parser.parse_args()
+
+    if (args.core_insts_output is None) != \
+            (args.operand_kinds_output is None):
+        print('error: --core-insts-output and --operand_kinds_output '
+              'should be specified together.')
+        exit(1)
+    if (args.glsl_insts_output is None) != \
+            (args.extinst_glsl_grammar is None):
+        print('error: --glsl-insts-output and --extinst-glsl-grammar '
+              'should be specified together.')
+        exit(1)
+    if (args.opencl_insts_output is None) != \
+            (args.extinst_opencl_grammar is None):
+        print('error: --opencl-insts-output and --extinst-opencl-grammar '
+              'should be specified together.')
+        exit(1)
+    if all([args.core_insts_output is None,
+            args.glsl_insts_output is None,
+            args.opencl_insts_output is None]):
+        print('error: at least one output should be specified.')
+        exit(1)
+
+    with open(args.spirv_core_grammar) as json_file:
+        grammar = json.loads(json_file.read())
+
+        # Get the dict for the Capability operand kind.
+        cap_dict = [o for o in grammar['operand_kinds']
+                    if o['kind'] == 'Capability']
+        assert len(cap_dict) == 1
+        populate_capability_bit_mapping_dict(cap_dict[0])
+
+        if args.core_insts_output is not None:
+            make_path_to_file(args.core_insts_output)
+            make_path_to_file(args.operand_kinds_output)
+            print(generate_instruction_table(grammar['instructions'], False),
+                  file=open(args.core_insts_output, 'w'))
+            print(generate_operand_kind_table(grammar['operand_kinds']),
+                  file=open(args.operand_kinds_output, 'w'))
+
+    if args.extinst_glsl_grammar is not None:
+        with open(args.extinst_glsl_grammar) as json_file:
+            grammar = json.loads(json_file.read())
+            make_path_to_file(args.glsl_insts_output)
+            print(generate_instruction_table(grammar['instructions'], True),
+                  file=open(args.glsl_insts_output, 'w'))
+
+    if args.extinst_opencl_grammar is not None:
+        with open(args.extinst_opencl_grammar) as json_file:
+            grammar = json.loads(json_file.read())
+            make_path_to_file(args.opencl_insts_output)
+            print(generate_instruction_table(grammar['instructions'], True),
+                  file=open(args.opencl_insts_output, 'w'))
+
+
+if __name__ == '__main__':
+    main()