/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2019-2026 Baldur Karlsson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

/******************************************************************************
 * Generated from Khronos SPIR-V machine-readable JSON grammar.
 *
 * Copyright: 2014-2024 The Khronos Group Inc.
 * License: MIT
 *
 * 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/
 ******************************************************************************/

#pragma once

// This file is autogenerated with gen_spirv_code.py - any changes will be overwritten next time
// that script is run.
// $ ./gen_spirv_code.py

// We need to disable clang-format since this file is programmatically generated
// clang-format off

#include <functional>
#include <set>
#include <stdint.h>
#include "api/replay/apidefs.h"
#include "api/replay/rdcstr.h"
#include "api/replay/rdcarray.h"
#include "api/replay/stringise.h"

#undef None
#undef CopyMemory
#undef MemoryBarrier

#include "spirv_common.h"
#include "spirv_gen.h"

namespace rdcspv
{

template<typename Type>
Type DecodeParam(const ConstIter &it, uint32_t &word);

template<>
inline uint32_t DecodeParam(const ConstIter &it, uint32_t &word)
{
  if(word >= it.size()) return 0;
  
  uint32_t ret = it.word(word);
  word += 1;
  return ret;
}

template<>
inline Capability DecodeParam(const ConstIter &it, uint32_t &word)
{
  if(word >= it.size()) return Capability::Invalid;
  
  Capability ret = Capability(word);
  word += 1;
  return ret;
}

template<>
inline Id DecodeParam<Id>(const ConstIter &it, uint32_t &word)
{
  if(word >= it.size()) return Id();
  
  Id ret = Id::fromWord(it.word(word));
  word += 1;
  return ret;
}

template<>
inline rdcstr DecodeParam<rdcstr>(const ConstIter &it, uint32_t &word)
{
  if(word >= it.size()) return "";
  
  rdcstr ret = (const char *)&it.word(word);
  word += uint32_t(ret.size() / 4) + 1;
  return ret;
}

template<typename Type>
rdcarray<Type> MultiParam(const ConstIter &it, uint32_t &word)
{
  rdcarray<Type> ret;
  while(word < it.size())
  {
    Type t = DecodeParam<Type>(it, word);
    ret.push_back(t);
  }
  return ret;
}

inline void EncodeParam(rdcarray<uint32_t> &words, const rdcstr &str)
{
  size_t i=0, remainingChars = str.size() + 1;
  while(remainingChars > 0)
  {
    uint32_t word = 0;
    for(size_t w=0; w < remainingChars && w < 4; w++)
      word |= uint32_t(str[i+w]) << (w*8);
    words.push_back(word);
    
    i += 4;
    if(remainingChars < 4)
      remainingChars = 0;
    else
      remainingChars -= 4;
  }
}

struct PairIdRefLiteralInteger { Id first; uint32_t second; };

struct PairIdRefIdRef { Id first, second; };


template<>
inline PairIdRefIdRef DecodeParam(const ConstIter &it, uint32_t &word)
{
  if(word >= it.size()) return {};
  
  PairIdRefIdRef ret = { Id::fromWord(it.word(word)), Id::fromWord(it.word(word+1)) };
  word += 2;
  return ret;
}

template<>
inline PairIdRefLiteralInteger DecodeParam(const ConstIter &it, uint32_t &word)
{
  if(word >= it.size()) return {};
  
  PairIdRefLiteralInteger ret = { Id::fromWord(it.word(word)), it.word(word+1) };
  word += 2;
  return ret;
}
template<>
inline ImageOperandsAndParamDatas DecodeParam(const ConstIter &it, uint32_t &word)
{
  if(word >= it.size()) return ImageOperandsAndParamDatas();

  ImageOperandsAndParamDatas ret((ImageOperands)it.word(word));
  word++;
  if(ret.flags & ImageOperands::Bias)
  {
    ret.bias = Id::fromWord(it.word(word));
    word += 1;
  }
  if(ret.flags & ImageOperands::Lod)
  {
    ret.lod = Id::fromWord(it.word(word));
    word += 1;
  }
  if(ret.flags & ImageOperands::Grad)
  {
    ret.grad.first = Id::fromWord(it.word(word+0));
    ret.grad.second = Id::fromWord(it.word(word+1));
    word += 2;
  }
  if(ret.flags & ImageOperands::ConstOffset)
  {
    ret.constOffset = Id::fromWord(it.word(word));
    word += 1;
  }
  if(ret.flags & ImageOperands::Offset)
  {
    ret.offset = Id::fromWord(it.word(word));
    word += 1;
  }
  if(ret.flags & ImageOperands::ConstOffsets)
  {
    ret.constOffsets = Id::fromWord(it.word(word));
    word += 1;
  }
  if(ret.flags & ImageOperands::Sample)
  {
    ret.sample = Id::fromWord(it.word(word));
    word += 1;
  }
  if(ret.flags & ImageOperands::MinLod)
  {
    ret.minLod = Id::fromWord(it.word(word));
    word += 1;
  }
  if(ret.flags & ImageOperands::MakeTexelAvailable)
  {
    ret.makeTexelAvailable = Id::fromWord(it.word(word));
    word += 1;
  }
  if(ret.flags & ImageOperands::MakeTexelVisible)
  {
    ret.makeTexelVisible = Id::fromWord(it.word(word));
    word += 1;
  }
  if(ret.flags & ImageOperands::Offsets)
  {
    ret.offsets = Id::fromWord(it.word(word));
    word += 1;
  }
  return ret;
}

inline void EncodeParam(rdcarray<uint32_t> &words, const ImageOperandsAndParamDatas &param)
{
  words.push_back((uint32_t)param.flags);
  if(param.flags & ImageOperands::Bias)
  {
    words.push_back(param.bias.value());
  }
  if(param.flags & ImageOperands::Lod)
  {
    words.push_back(param.lod.value());
  }
  if(param.flags & ImageOperands::Grad)
  {
    words.push_back(param.grad.first.value());
    words.push_back(param.grad.second.value());
  }
  if(param.flags & ImageOperands::ConstOffset)
  {
    words.push_back(param.constOffset.value());
  }
  if(param.flags & ImageOperands::Offset)
  {
    words.push_back(param.offset.value());
  }
  if(param.flags & ImageOperands::ConstOffsets)
  {
    words.push_back(param.constOffsets.value());
  }
  if(param.flags & ImageOperands::Sample)
  {
    words.push_back(param.sample.value());
  }
  if(param.flags & ImageOperands::MinLod)
  {
    words.push_back(param.minLod.value());
  }
  if(param.flags & ImageOperands::MakeTexelAvailable)
  {
    words.push_back(param.makeTexelAvailable.value());
  }
  if(param.flags & ImageOperands::MakeTexelVisible)
  {
    words.push_back(param.makeTexelVisible.value());
  }
  if(param.flags & ImageOperands::Offsets)
  {
    words.push_back(param.offsets.value());
  }
}

inline uint16_t ExtraWordCount(const ImageOperands imageOperands)
{
  switch(imageOperands)
  {
    case ImageOperands::Bias: return 1;
    case ImageOperands::Lod: return 1;
    case ImageOperands::Grad: return 2;
    case ImageOperands::ConstOffset: return 1;
    case ImageOperands::Offset: return 1;
    case ImageOperands::ConstOffsets: return 1;
    case ImageOperands::Sample: return 1;
    case ImageOperands::MinLod: return 1;
    case ImageOperands::MakeTexelAvailable: return 1;
    case ImageOperands::MakeTexelVisible: return 1;
    case ImageOperands::Offsets: return 1;
    default: break;
  }
  return 0;
}

inline uint16_t OptionalWordCount(const FPFastMathMode val) { return val != FPFastMathMode::None ? 1 : 0; }

inline uint16_t OptionalWordCount(const SelectionControl val) { return val != SelectionControl::None ? 1 : 0; }

template<>
inline LoopControlAndParamDatas DecodeParam(const ConstIter &it, uint32_t &word)
{
  if(word >= it.size()) return LoopControlAndParamDatas();

  LoopControlAndParamDatas ret((LoopControl)it.word(word));
  word++;
  if(ret.flags & LoopControl::DependencyLength)
  {
    ret.dependencyLength = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::MinIterations)
  {
    ret.minIterations = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::MaxIterations)
  {
    ret.maxIterations = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::IterationMultiple)
  {
    ret.iterationMultiple = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::PeelCount)
  {
    ret.peelCount = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::PartialCount)
  {
    ret.partialCount = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::InitiationIntervalALTERA)
  {
    ret.initiationIntervalALTERA = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::MaxConcurrencyALTERA)
  {
    ret.maxConcurrencyALTERA = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::DependencyArrayALTERA)
  {
    ret.dependencyArrayALTERA = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::PipelineEnableALTERA)
  {
    ret.pipelineEnableALTERA = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::LoopCoalesceALTERA)
  {
    ret.loopCoalesceALTERA = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::MaxInterleavingALTERA)
  {
    ret.maxInterleavingALTERA = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::SpeculatedIterationsALTERA)
  {
    ret.speculatedIterationsALTERA = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::LoopCountALTERA)
  {
    ret.loopCountALTERA = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::MaxReinvocationDelayALTERA)
  {
    ret.maxReinvocationDelayALTERA = (uint32_t)it.word(word);
    word += 1;
  }
  return ret;
}

inline void EncodeParam(rdcarray<uint32_t> &words, const LoopControlAndParamDatas &param)
{
  words.push_back((uint32_t)param.flags);
  if(param.flags & LoopControl::DependencyLength)
  {
    words.push_back((uint32_t)param.dependencyLength);
  }
  if(param.flags & LoopControl::MinIterations)
  {
    words.push_back((uint32_t)param.minIterations);
  }
  if(param.flags & LoopControl::MaxIterations)
  {
    words.push_back((uint32_t)param.maxIterations);
  }
  if(param.flags & LoopControl::IterationMultiple)
  {
    words.push_back((uint32_t)param.iterationMultiple);
  }
  if(param.flags & LoopControl::PeelCount)
  {
    words.push_back((uint32_t)param.peelCount);
  }
  if(param.flags & LoopControl::PartialCount)
  {
    words.push_back((uint32_t)param.partialCount);
  }
  if(param.flags & LoopControl::InitiationIntervalALTERA)
  {
    words.push_back((uint32_t)param.initiationIntervalALTERA);
  }
  if(param.flags & LoopControl::MaxConcurrencyALTERA)
  {
    words.push_back((uint32_t)param.maxConcurrencyALTERA);
  }
  if(param.flags & LoopControl::DependencyArrayALTERA)
  {
    words.push_back((uint32_t)param.dependencyArrayALTERA);
  }
  if(param.flags & LoopControl::PipelineEnableALTERA)
  {
    words.push_back((uint32_t)param.pipelineEnableALTERA);
  }
  if(param.flags & LoopControl::LoopCoalesceALTERA)
  {
    words.push_back((uint32_t)param.loopCoalesceALTERA);
  }
  if(param.flags & LoopControl::MaxInterleavingALTERA)
  {
    words.push_back((uint32_t)param.maxInterleavingALTERA);
  }
  if(param.flags & LoopControl::SpeculatedIterationsALTERA)
  {
    words.push_back((uint32_t)param.speculatedIterationsALTERA);
  }
  if(param.flags & LoopControl::LoopCountALTERA)
  {
    words.push_back((uint32_t)param.loopCountALTERA);
  }
  if(param.flags & LoopControl::MaxReinvocationDelayALTERA)
  {
    words.push_back((uint32_t)param.maxReinvocationDelayALTERA);
  }
}

inline uint16_t ExtraWordCount(const LoopControl loopControl)
{
  switch(loopControl)
  {
    case LoopControl::DependencyLength: return 1;
    case LoopControl::MinIterations: return 1;
    case LoopControl::MaxIterations: return 1;
    case LoopControl::IterationMultiple: return 1;
    case LoopControl::PeelCount: return 1;
    case LoopControl::PartialCount: return 1;
    case LoopControl::InitiationIntervalALTERA: return 1;
    case LoopControl::MaxConcurrencyALTERA: return 1;
    case LoopControl::DependencyArrayALTERA: return 1;
    case LoopControl::PipelineEnableALTERA: return 1;
    case LoopControl::LoopCoalesceALTERA: return 1;
    case LoopControl::MaxInterleavingALTERA: return 1;
    case LoopControl::SpeculatedIterationsALTERA: return 1;
    case LoopControl::LoopCountALTERA: return 1;
    case LoopControl::MaxReinvocationDelayALTERA: return 1;
    default: break;
  }
  return 0;
}

inline uint16_t OptionalWordCount(const FunctionControl val) { return val != FunctionControl::None ? 1 : 0; }

template<>
inline MemoryAccessAndParamDatas DecodeParam(const ConstIter &it, uint32_t &word)
{
  if(word >= it.size()) return MemoryAccessAndParamDatas();

  MemoryAccessAndParamDatas ret((MemoryAccess)it.word(word));
  word++;
  if(ret.flags & MemoryAccess::Aligned)
  {
    ret.aligned = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & MemoryAccess::MakePointerAvailable)
  {
    ret.makePointerAvailable = Id::fromWord(it.word(word));
    word += 1;
  }
  if(ret.flags & MemoryAccess::MakePointerVisible)
  {
    ret.makePointerVisible = Id::fromWord(it.word(word));
    word += 1;
  }
  if(ret.flags & MemoryAccess::AliasScopeINTELMask)
  {
    ret.aliasScopeINTELMask = Id::fromWord(it.word(word));
    word += 1;
  }
  if(ret.flags & MemoryAccess::NoAliasINTELMask)
  {
    ret.noAliasINTELMask = Id::fromWord(it.word(word));
    word += 1;
  }
  return ret;
}

inline void EncodeParam(rdcarray<uint32_t> &words, const MemoryAccessAndParamDatas &param)
{
  words.push_back((uint32_t)param.flags);
  if(param.flags & MemoryAccess::Aligned)
  {
    words.push_back((uint32_t)param.aligned);
  }
  if(param.flags & MemoryAccess::MakePointerAvailable)
  {
    words.push_back(param.makePointerAvailable.value());
  }
  if(param.flags & MemoryAccess::MakePointerVisible)
  {
    words.push_back(param.makePointerVisible.value());
  }
  if(param.flags & MemoryAccess::AliasScopeINTELMask)
  {
    words.push_back(param.aliasScopeINTELMask.value());
  }
  if(param.flags & MemoryAccess::NoAliasINTELMask)
  {
    words.push_back(param.noAliasINTELMask.value());
  }
}

inline uint16_t ExtraWordCount(const MemoryAccess memoryAccess)
{
  switch(memoryAccess)
  {
    case MemoryAccess::Aligned: return 1;
    case MemoryAccess::MakePointerAvailable: return 1;
    case MemoryAccess::MakePointerVisible: return 1;
    case MemoryAccess::AliasScopeINTELMask: return 1;
    case MemoryAccess::NoAliasINTELMask: return 1;
    default: break;
  }
  return 0;
}

inline uint16_t OptionalWordCount(const KernelProfilingInfo val) { return val != KernelProfilingInfo::None ? 1 : 0; }

inline uint16_t OptionalWordCount(const RayFlags val) { return val != RayFlags::NoneKHR ? 1 : 0; }

inline uint16_t OptionalWordCount(const RawAccessChainOperands val) { return val != RawAccessChainOperands::None ? 1 : 0; }

inline uint16_t OptionalWordCount(const SourceLanguage val) { return val != SourceLanguage::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const ExecutionModel val) { return val != ExecutionModel::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const AddressingModel val) { return val != AddressingModel::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const MemoryModel val) { return val != MemoryModel::Invalid ? 1 : 0; }

template<ExecutionMode val> struct ExecutionModeParam;

template<>
struct ExecutionModeParam<ExecutionMode::Invocations>
{
  uint32_t invocations;
  ExecutionModeParam(uint32_t invocationsParam) {  invocations = invocationsParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::Invocations);
    ret.invocations = invocations;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::LocalSize>
{
  LocalSizeParams localSize;
  ExecutionModeParam(uint32_t xsize, uint32_t ysize, uint32_t zsize) {  localSize.xsize = xsize; localSize.ysize = ysize; localSize.zsize = zsize; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::LocalSize);
    ret.localSize.xsize = localSize.xsize;
    ret.localSize.ysize = localSize.ysize;
    ret.localSize.zsize = localSize.zsize;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::LocalSizeHint>
{
  LocalSizeHintParams localSizeHint;
  ExecutionModeParam(uint32_t xsize, uint32_t ysize, uint32_t zsize) {  localSizeHint.xsize = xsize; localSizeHint.ysize = ysize; localSizeHint.zsize = zsize; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::LocalSizeHint);
    ret.localSizeHint.xsize = localSizeHint.xsize;
    ret.localSizeHint.ysize = localSizeHint.ysize;
    ret.localSizeHint.zsize = localSizeHint.zsize;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::OutputVertices>
{
  uint32_t outputVertices;
  ExecutionModeParam(uint32_t outputVerticesParam) {  outputVertices = outputVerticesParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::OutputVertices);
    ret.outputVertices = outputVertices;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::VecTypeHint>
{
  uint32_t vecTypeHint;
  ExecutionModeParam(uint32_t vecTypeHintParam) {  vecTypeHint = vecTypeHintParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::VecTypeHint);
    ret.vecTypeHint = vecTypeHint;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::SubgroupSize>
{
  uint32_t subgroupSize;
  ExecutionModeParam(uint32_t subgroupSizeParam) {  subgroupSize = subgroupSizeParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::SubgroupSize);
    ret.subgroupSize = subgroupSize;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::SubgroupsPerWorkgroup>
{
  uint32_t subgroupsPerWorkgroup;
  ExecutionModeParam(uint32_t subgroupsPerWorkgroupParam) {  subgroupsPerWorkgroup = subgroupsPerWorkgroupParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::SubgroupsPerWorkgroup);
    ret.subgroupsPerWorkgroup = subgroupsPerWorkgroup;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::SubgroupsPerWorkgroupId>
{
  Id subgroupsPerWorkgroupId;
  ExecutionModeParam(Id subgroupsPerWorkgroupIdParam) {  subgroupsPerWorkgroupId = subgroupsPerWorkgroupIdParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::SubgroupsPerWorkgroupId);
    ret.subgroupsPerWorkgroupId = subgroupsPerWorkgroupId;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::LocalSizeId>
{
  LocalSizeIdParams localSizeId;
  ExecutionModeParam(Id xsize, Id ysize, Id zsize) {  localSizeId.xsize = xsize; localSizeId.ysize = ysize; localSizeId.zsize = zsize; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::LocalSizeId);
    ret.localSizeId.xsize = localSizeId.xsize;
    ret.localSizeId.ysize = localSizeId.ysize;
    ret.localSizeId.zsize = localSizeId.zsize;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::LocalSizeHintId>
{
  LocalSizeHintIdParams localSizeHintId;
  ExecutionModeParam(Id xsizehint, Id ysizehint, Id zsizehint) {  localSizeHintId.xsizehint = xsizehint; localSizeHintId.ysizehint = ysizehint; localSizeHintId.zsizehint = zsizehint; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::LocalSizeHintId);
    ret.localSizeHintId.xsizehint = localSizeHintId.xsizehint;
    ret.localSizeHintId.ysizehint = localSizeHintId.ysizehint;
    ret.localSizeHintId.zsizehint = localSizeHintId.zsizehint;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::DenormPreserve>
{
  uint32_t denormPreserve;
  ExecutionModeParam(uint32_t denormPreserveParam) {  denormPreserve = denormPreserveParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::DenormPreserve);
    ret.denormPreserve = denormPreserve;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::DenormFlushToZero>
{
  uint32_t denormFlushToZero;
  ExecutionModeParam(uint32_t denormFlushToZeroParam) {  denormFlushToZero = denormFlushToZeroParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::DenormFlushToZero);
    ret.denormFlushToZero = denormFlushToZero;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::SignedZeroInfNanPreserve>
{
  uint32_t signedZeroInfNanPreserve;
  ExecutionModeParam(uint32_t signedZeroInfNanPreserveParam) {  signedZeroInfNanPreserve = signedZeroInfNanPreserveParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::SignedZeroInfNanPreserve);
    ret.signedZeroInfNanPreserve = signedZeroInfNanPreserve;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::RoundingModeRTE>
{
  uint32_t roundingModeRTE;
  ExecutionModeParam(uint32_t roundingModeRTEParam) {  roundingModeRTE = roundingModeRTEParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::RoundingModeRTE);
    ret.roundingModeRTE = roundingModeRTE;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::RoundingModeRTZ>
{
  uint32_t roundingModeRTZ;
  ExecutionModeParam(uint32_t roundingModeRTZParam) {  roundingModeRTZ = roundingModeRTZParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::RoundingModeRTZ);
    ret.roundingModeRTZ = roundingModeRTZ;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::TileShadingRateQCOM>
{
  TileShadingRateQCOMParams tileShadingRateQCOM;
  ExecutionModeParam(uint32_t xrate, uint32_t yrate, uint32_t zrate) {  tileShadingRateQCOM.xrate = xrate; tileShadingRateQCOM.yrate = yrate; tileShadingRateQCOM.zrate = zrate; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::TileShadingRateQCOM);
    ret.tileShadingRateQCOM.xrate = tileShadingRateQCOM.xrate;
    ret.tileShadingRateQCOM.yrate = tileShadingRateQCOM.yrate;
    ret.tileShadingRateQCOM.zrate = tileShadingRateQCOM.zrate;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::IsApiEntryAMDX>
{
  Id isApiEntryAMDX;
  ExecutionModeParam(Id isApiEntryAMDXParam) {  isApiEntryAMDX = isApiEntryAMDXParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::IsApiEntryAMDX);
    ret.isApiEntryAMDX = isApiEntryAMDX;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::MaxNodeRecursionAMDX>
{
  Id maxNodeRecursionAMDX;
  ExecutionModeParam(Id maxNodeRecursionAMDXParam) {  maxNodeRecursionAMDX = maxNodeRecursionAMDXParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::MaxNodeRecursionAMDX);
    ret.maxNodeRecursionAMDX = maxNodeRecursionAMDX;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::StaticNumWorkgroupsAMDX>
{
  StaticNumWorkgroupsAMDXParams staticNumWorkgroupsAMDX;
  ExecutionModeParam(Id xsize, Id ysize, Id zsize) {  staticNumWorkgroupsAMDX.xsize = xsize; staticNumWorkgroupsAMDX.ysize = ysize; staticNumWorkgroupsAMDX.zsize = zsize; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::StaticNumWorkgroupsAMDX);
    ret.staticNumWorkgroupsAMDX.xsize = staticNumWorkgroupsAMDX.xsize;
    ret.staticNumWorkgroupsAMDX.ysize = staticNumWorkgroupsAMDX.ysize;
    ret.staticNumWorkgroupsAMDX.zsize = staticNumWorkgroupsAMDX.zsize;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::ShaderIndexAMDX>
{
  Id shaderIndexAMDX;
  ExecutionModeParam(Id shaderIndexAMDXParam) {  shaderIndexAMDX = shaderIndexAMDXParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::ShaderIndexAMDX);
    ret.shaderIndexAMDX = shaderIndexAMDX;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::MaxNumWorkgroupsAMDX>
{
  MaxNumWorkgroupsAMDXParams maxNumWorkgroupsAMDX;
  ExecutionModeParam(Id xsize, Id ysize, Id zsize) {  maxNumWorkgroupsAMDX.xsize = xsize; maxNumWorkgroupsAMDX.ysize = ysize; maxNumWorkgroupsAMDX.zsize = zsize; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::MaxNumWorkgroupsAMDX);
    ret.maxNumWorkgroupsAMDX.xsize = maxNumWorkgroupsAMDX.xsize;
    ret.maxNumWorkgroupsAMDX.ysize = maxNumWorkgroupsAMDX.ysize;
    ret.maxNumWorkgroupsAMDX.zsize = maxNumWorkgroupsAMDX.zsize;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::SharesInputWithAMDX>
{
  SharesInputWithAMDXParams sharesInputWithAMDX;
  ExecutionModeParam(Id nodeName, Id shaderIndex) {  sharesInputWithAMDX.nodeName = nodeName; sharesInputWithAMDX.shaderIndex = shaderIndex; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::SharesInputWithAMDX);
    ret.sharesInputWithAMDX.nodeName = sharesInputWithAMDX.nodeName;
    ret.sharesInputWithAMDX.shaderIndex = sharesInputWithAMDX.shaderIndex;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::OutputPrimitivesEXT>
{
  uint32_t outputPrimitivesEXT;
  ExecutionModeParam(uint32_t outputPrimitivesEXTParam) {  outputPrimitivesEXT = outputPrimitivesEXTParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::OutputPrimitivesEXT);
    ret.outputPrimitivesEXT = outputPrimitivesEXT;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::SharedLocalMemorySizeINTEL>
{
  uint32_t sharedLocalMemorySizeINTEL;
  ExecutionModeParam(uint32_t sharedLocalMemorySizeINTELParam) {  sharedLocalMemorySizeINTEL = sharedLocalMemorySizeINTELParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::SharedLocalMemorySizeINTEL);
    ret.sharedLocalMemorySizeINTEL = sharedLocalMemorySizeINTEL;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::RoundingModeRTPINTEL>
{
  uint32_t roundingModeRTPINTEL;
  ExecutionModeParam(uint32_t roundingModeRTPINTELParam) {  roundingModeRTPINTEL = roundingModeRTPINTELParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::RoundingModeRTPINTEL);
    ret.roundingModeRTPINTEL = roundingModeRTPINTEL;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::RoundingModeRTNINTEL>
{
  uint32_t roundingModeRTNINTEL;
  ExecutionModeParam(uint32_t roundingModeRTNINTELParam) {  roundingModeRTNINTEL = roundingModeRTNINTELParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::RoundingModeRTNINTEL);
    ret.roundingModeRTNINTEL = roundingModeRTNINTEL;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::FloatingPointModeALTINTEL>
{
  uint32_t floatingPointModeALTINTEL;
  ExecutionModeParam(uint32_t floatingPointModeALTINTELParam) {  floatingPointModeALTINTEL = floatingPointModeALTINTELParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::FloatingPointModeALTINTEL);
    ret.floatingPointModeALTINTEL = floatingPointModeALTINTEL;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::FloatingPointModeIEEEINTEL>
{
  uint32_t floatingPointModeIEEEINTEL;
  ExecutionModeParam(uint32_t floatingPointModeIEEEINTELParam) {  floatingPointModeIEEEINTEL = floatingPointModeIEEEINTELParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::FloatingPointModeIEEEINTEL);
    ret.floatingPointModeIEEEINTEL = floatingPointModeIEEEINTEL;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::MaxWorkgroupSizeINTEL>
{
  MaxWorkgroupSizeINTELParams maxWorkgroupSizeINTEL;
  ExecutionModeParam(uint32_t max_x_size, uint32_t max_y_size, uint32_t max_z_size) {  maxWorkgroupSizeINTEL.max_x_size = max_x_size; maxWorkgroupSizeINTEL.max_y_size = max_y_size; maxWorkgroupSizeINTEL.max_z_size = max_z_size; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::MaxWorkgroupSizeINTEL);
    ret.maxWorkgroupSizeINTEL.max_x_size = maxWorkgroupSizeINTEL.max_x_size;
    ret.maxWorkgroupSizeINTEL.max_y_size = maxWorkgroupSizeINTEL.max_y_size;
    ret.maxWorkgroupSizeINTEL.max_z_size = maxWorkgroupSizeINTEL.max_z_size;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::MaxWorkDimINTEL>
{
  uint32_t maxWorkDimINTEL;
  ExecutionModeParam(uint32_t maxWorkDimINTELParam) {  maxWorkDimINTEL = maxWorkDimINTELParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::MaxWorkDimINTEL);
    ret.maxWorkDimINTEL = maxWorkDimINTEL;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::NumSIMDWorkitemsINTEL>
{
  uint32_t numSIMDWorkitemsINTEL;
  ExecutionModeParam(uint32_t numSIMDWorkitemsINTELParam) {  numSIMDWorkitemsINTEL = numSIMDWorkitemsINTELParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::NumSIMDWorkitemsINTEL);
    ret.numSIMDWorkitemsINTEL = numSIMDWorkitemsINTEL;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::SchedulerTargetFmaxMhzINTEL>
{
  uint32_t schedulerTargetFmaxMhzINTEL;
  ExecutionModeParam(uint32_t schedulerTargetFmaxMhzINTELParam) {  schedulerTargetFmaxMhzINTEL = schedulerTargetFmaxMhzINTELParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::SchedulerTargetFmaxMhzINTEL);
    ret.schedulerTargetFmaxMhzINTEL = schedulerTargetFmaxMhzINTEL;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::FPFastMathDefault>
{
  FPFastMathDefaultParams fPFastMathDefault;
  ExecutionModeParam(Id targetType, Id fastMathMode) {  fPFastMathDefault.targetType = targetType; fPFastMathDefault.fastMathMode = fastMathMode; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::FPFastMathDefault);
    ret.fPFastMathDefault.targetType = fPFastMathDefault.targetType;
    ret.fPFastMathDefault.fastMathMode = fPFastMathDefault.fastMathMode;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::StreamingInterfaceINTEL>
{
  uint32_t streamingInterfaceINTEL;
  ExecutionModeParam(uint32_t streamingInterfaceINTELParam) {  streamingInterfaceINTEL = streamingInterfaceINTELParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::StreamingInterfaceINTEL);
    ret.streamingInterfaceINTEL = streamingInterfaceINTEL;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::RegisterMapInterfaceINTEL>
{
  uint32_t registerMapInterfaceINTEL;
  ExecutionModeParam(uint32_t registerMapInterfaceINTELParam) {  registerMapInterfaceINTEL = registerMapInterfaceINTELParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::RegisterMapInterfaceINTEL);
    ret.registerMapInterfaceINTEL = registerMapInterfaceINTEL;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::NamedBarrierCountINTEL>
{
  uint32_t namedBarrierCountINTEL;
  ExecutionModeParam(uint32_t namedBarrierCountINTELParam) {  namedBarrierCountINTEL = namedBarrierCountINTELParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::NamedBarrierCountINTEL);
    ret.namedBarrierCountINTEL = namedBarrierCountINTEL;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::MaximumRegistersINTEL>
{
  uint32_t maximumRegistersINTEL;
  ExecutionModeParam(uint32_t maximumRegistersINTELParam) {  maximumRegistersINTEL = maximumRegistersINTELParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::MaximumRegistersINTEL);
    ret.maximumRegistersINTEL = maximumRegistersINTEL;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::MaximumRegistersIdINTEL>
{
  Id maximumRegistersIdINTEL;
  ExecutionModeParam(Id maximumRegistersIdINTELParam) {  maximumRegistersIdINTEL = maximumRegistersIdINTELParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::MaximumRegistersIdINTEL);
    ret.maximumRegistersIdINTEL = maximumRegistersIdINTEL;
    return ret;
  }
};

template<>
struct ExecutionModeParam<ExecutionMode::NamedMaximumRegistersINTEL>
{
  NamedMaximumNumberOfRegisters namedMaximumRegistersINTEL;
  ExecutionModeParam(NamedMaximumNumberOfRegisters namedMaximumRegistersINTELParam) {  namedMaximumRegistersINTEL = namedMaximumRegistersINTELParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::NamedMaximumRegistersINTEL);
    ret.namedMaximumRegistersINTEL = namedMaximumRegistersINTEL;
    return ret;
  }
};



template<>
inline ExecutionModeAndParamData DecodeParam(const ConstIter &it, uint32_t &word)
{
  if(word >= it.size()) return ExecutionModeAndParamData();

  ExecutionModeAndParamData ret((ExecutionMode)it.word(word));
  word++;
  switch(ret.value)
  {
    case ExecutionMode::Invocations:
      ret.invocations = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::LocalSize:
      ret.localSize.xsize = (uint32_t)it.word(word+0);
      ret.localSize.ysize = (uint32_t)it.word(word+1);
      ret.localSize.zsize = (uint32_t)it.word(word+2);
      word += 3;
      break;
    case ExecutionMode::LocalSizeHint:
      ret.localSizeHint.xsize = (uint32_t)it.word(word+0);
      ret.localSizeHint.ysize = (uint32_t)it.word(word+1);
      ret.localSizeHint.zsize = (uint32_t)it.word(word+2);
      word += 3;
      break;
    case ExecutionMode::OutputVertices:
      ret.outputVertices = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::VecTypeHint:
      ret.vecTypeHint = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::SubgroupSize:
      ret.subgroupSize = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::SubgroupsPerWorkgroup:
      ret.subgroupsPerWorkgroup = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::SubgroupsPerWorkgroupId:
      ret.subgroupsPerWorkgroupId = Id::fromWord(it.word(word));
      word += 1;
      break;
    case ExecutionMode::LocalSizeId:
      ret.localSizeId.xsize = Id::fromWord(it.word(word+0));
      ret.localSizeId.ysize = Id::fromWord(it.word(word+1));
      ret.localSizeId.zsize = Id::fromWord(it.word(word+2));
      word += 3;
      break;
    case ExecutionMode::LocalSizeHintId:
      ret.localSizeHintId.xsizehint = Id::fromWord(it.word(word+0));
      ret.localSizeHintId.ysizehint = Id::fromWord(it.word(word+1));
      ret.localSizeHintId.zsizehint = Id::fromWord(it.word(word+2));
      word += 3;
      break;
    case ExecutionMode::DenormPreserve:
      ret.denormPreserve = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::DenormFlushToZero:
      ret.denormFlushToZero = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::SignedZeroInfNanPreserve:
      ret.signedZeroInfNanPreserve = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::RoundingModeRTE:
      ret.roundingModeRTE = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::RoundingModeRTZ:
      ret.roundingModeRTZ = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::TileShadingRateQCOM:
      ret.tileShadingRateQCOM.xrate = (uint32_t)it.word(word+0);
      ret.tileShadingRateQCOM.yrate = (uint32_t)it.word(word+1);
      ret.tileShadingRateQCOM.zrate = (uint32_t)it.word(word+2);
      word += 3;
      break;
    case ExecutionMode::IsApiEntryAMDX:
      ret.isApiEntryAMDX = Id::fromWord(it.word(word));
      word += 1;
      break;
    case ExecutionMode::MaxNodeRecursionAMDX:
      ret.maxNodeRecursionAMDX = Id::fromWord(it.word(word));
      word += 1;
      break;
    case ExecutionMode::StaticNumWorkgroupsAMDX:
      ret.staticNumWorkgroupsAMDX.xsize = Id::fromWord(it.word(word+0));
      ret.staticNumWorkgroupsAMDX.ysize = Id::fromWord(it.word(word+1));
      ret.staticNumWorkgroupsAMDX.zsize = Id::fromWord(it.word(word+2));
      word += 3;
      break;
    case ExecutionMode::ShaderIndexAMDX:
      ret.shaderIndexAMDX = Id::fromWord(it.word(word));
      word += 1;
      break;
    case ExecutionMode::MaxNumWorkgroupsAMDX:
      ret.maxNumWorkgroupsAMDX.xsize = Id::fromWord(it.word(word+0));
      ret.maxNumWorkgroupsAMDX.ysize = Id::fromWord(it.word(word+1));
      ret.maxNumWorkgroupsAMDX.zsize = Id::fromWord(it.word(word+2));
      word += 3;
      break;
    case ExecutionMode::SharesInputWithAMDX:
      ret.sharesInputWithAMDX.nodeName = Id::fromWord(it.word(word+0));
      ret.sharesInputWithAMDX.shaderIndex = Id::fromWord(it.word(word+1));
      word += 2;
      break;
    case ExecutionMode::OutputPrimitivesEXT:
      ret.outputPrimitivesEXT = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::SharedLocalMemorySizeINTEL:
      ret.sharedLocalMemorySizeINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::RoundingModeRTPINTEL:
      ret.roundingModeRTPINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::RoundingModeRTNINTEL:
      ret.roundingModeRTNINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::FloatingPointModeALTINTEL:
      ret.floatingPointModeALTINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::FloatingPointModeIEEEINTEL:
      ret.floatingPointModeIEEEINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::MaxWorkgroupSizeINTEL:
      ret.maxWorkgroupSizeINTEL.max_x_size = (uint32_t)it.word(word+0);
      ret.maxWorkgroupSizeINTEL.max_y_size = (uint32_t)it.word(word+1);
      ret.maxWorkgroupSizeINTEL.max_z_size = (uint32_t)it.word(word+2);
      word += 3;
      break;
    case ExecutionMode::MaxWorkDimINTEL:
      ret.maxWorkDimINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::NumSIMDWorkitemsINTEL:
      ret.numSIMDWorkitemsINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::SchedulerTargetFmaxMhzINTEL:
      ret.schedulerTargetFmaxMhzINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::FPFastMathDefault:
      ret.fPFastMathDefault.targetType = Id::fromWord(it.word(word+0));
      ret.fPFastMathDefault.fastMathMode = Id::fromWord(it.word(word+1));
      word += 2;
      break;
    case ExecutionMode::StreamingInterfaceINTEL:
      ret.streamingInterfaceINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::RegisterMapInterfaceINTEL:
      ret.registerMapInterfaceINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::NamedBarrierCountINTEL:
      ret.namedBarrierCountINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::MaximumRegistersINTEL:
      ret.maximumRegistersINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case ExecutionMode::MaximumRegistersIdINTEL:
      ret.maximumRegistersIdINTEL = Id::fromWord(it.word(word));
      word += 1;
      break;
    case ExecutionMode::NamedMaximumRegistersINTEL:
      ret.namedMaximumRegistersINTEL = (NamedMaximumNumberOfRegisters)it.word(word);
      word += 1;
      break;
    default: break;
  }
  return ret;
}

inline void EncodeParam(rdcarray<uint32_t> &words, const ExecutionModeAndParamData &param)
{
  words.push_back((uint32_t)param.value);
  switch(param.value)
  {
    case ExecutionMode::Invocations:
      words.push_back((uint32_t)param.invocations);
      break;
    case ExecutionMode::LocalSize:
      words.push_back((uint32_t)param.localSize.xsize);
      words.push_back((uint32_t)param.localSize.ysize);
      words.push_back((uint32_t)param.localSize.zsize);
      break;
    case ExecutionMode::LocalSizeHint:
      words.push_back((uint32_t)param.localSizeHint.xsize);
      words.push_back((uint32_t)param.localSizeHint.ysize);
      words.push_back((uint32_t)param.localSizeHint.zsize);
      break;
    case ExecutionMode::OutputVertices:
      words.push_back((uint32_t)param.outputVertices);
      break;
    case ExecutionMode::VecTypeHint:
      words.push_back((uint32_t)param.vecTypeHint);
      break;
    case ExecutionMode::SubgroupSize:
      words.push_back((uint32_t)param.subgroupSize);
      break;
    case ExecutionMode::SubgroupsPerWorkgroup:
      words.push_back((uint32_t)param.subgroupsPerWorkgroup);
      break;
    case ExecutionMode::SubgroupsPerWorkgroupId:
      words.push_back(param.subgroupsPerWorkgroupId.value());
      break;
    case ExecutionMode::LocalSizeId:
      words.push_back(param.localSizeId.xsize.value());
      words.push_back(param.localSizeId.ysize.value());
      words.push_back(param.localSizeId.zsize.value());
      break;
    case ExecutionMode::LocalSizeHintId:
      words.push_back(param.localSizeHintId.xsizehint.value());
      words.push_back(param.localSizeHintId.ysizehint.value());
      words.push_back(param.localSizeHintId.zsizehint.value());
      break;
    case ExecutionMode::DenormPreserve:
      words.push_back((uint32_t)param.denormPreserve);
      break;
    case ExecutionMode::DenormFlushToZero:
      words.push_back((uint32_t)param.denormFlushToZero);
      break;
    case ExecutionMode::SignedZeroInfNanPreserve:
      words.push_back((uint32_t)param.signedZeroInfNanPreserve);
      break;
    case ExecutionMode::RoundingModeRTE:
      words.push_back((uint32_t)param.roundingModeRTE);
      break;
    case ExecutionMode::RoundingModeRTZ:
      words.push_back((uint32_t)param.roundingModeRTZ);
      break;
    case ExecutionMode::TileShadingRateQCOM:
      words.push_back((uint32_t)param.tileShadingRateQCOM.xrate);
      words.push_back((uint32_t)param.tileShadingRateQCOM.yrate);
      words.push_back((uint32_t)param.tileShadingRateQCOM.zrate);
      break;
    case ExecutionMode::IsApiEntryAMDX:
      words.push_back(param.isApiEntryAMDX.value());
      break;
    case ExecutionMode::MaxNodeRecursionAMDX:
      words.push_back(param.maxNodeRecursionAMDX.value());
      break;
    case ExecutionMode::StaticNumWorkgroupsAMDX:
      words.push_back(param.staticNumWorkgroupsAMDX.xsize.value());
      words.push_back(param.staticNumWorkgroupsAMDX.ysize.value());
      words.push_back(param.staticNumWorkgroupsAMDX.zsize.value());
      break;
    case ExecutionMode::ShaderIndexAMDX:
      words.push_back(param.shaderIndexAMDX.value());
      break;
    case ExecutionMode::MaxNumWorkgroupsAMDX:
      words.push_back(param.maxNumWorkgroupsAMDX.xsize.value());
      words.push_back(param.maxNumWorkgroupsAMDX.ysize.value());
      words.push_back(param.maxNumWorkgroupsAMDX.zsize.value());
      break;
    case ExecutionMode::SharesInputWithAMDX:
      words.push_back(param.sharesInputWithAMDX.nodeName.value());
      words.push_back(param.sharesInputWithAMDX.shaderIndex.value());
      break;
    case ExecutionMode::OutputPrimitivesEXT:
      words.push_back((uint32_t)param.outputPrimitivesEXT);
      break;
    case ExecutionMode::SharedLocalMemorySizeINTEL:
      words.push_back((uint32_t)param.sharedLocalMemorySizeINTEL);
      break;
    case ExecutionMode::RoundingModeRTPINTEL:
      words.push_back((uint32_t)param.roundingModeRTPINTEL);
      break;
    case ExecutionMode::RoundingModeRTNINTEL:
      words.push_back((uint32_t)param.roundingModeRTNINTEL);
      break;
    case ExecutionMode::FloatingPointModeALTINTEL:
      words.push_back((uint32_t)param.floatingPointModeALTINTEL);
      break;
    case ExecutionMode::FloatingPointModeIEEEINTEL:
      words.push_back((uint32_t)param.floatingPointModeIEEEINTEL);
      break;
    case ExecutionMode::MaxWorkgroupSizeINTEL:
      words.push_back((uint32_t)param.maxWorkgroupSizeINTEL.max_x_size);
      words.push_back((uint32_t)param.maxWorkgroupSizeINTEL.max_y_size);
      words.push_back((uint32_t)param.maxWorkgroupSizeINTEL.max_z_size);
      break;
    case ExecutionMode::MaxWorkDimINTEL:
      words.push_back((uint32_t)param.maxWorkDimINTEL);
      break;
    case ExecutionMode::NumSIMDWorkitemsINTEL:
      words.push_back((uint32_t)param.numSIMDWorkitemsINTEL);
      break;
    case ExecutionMode::SchedulerTargetFmaxMhzINTEL:
      words.push_back((uint32_t)param.schedulerTargetFmaxMhzINTEL);
      break;
    case ExecutionMode::FPFastMathDefault:
      words.push_back(param.fPFastMathDefault.targetType.value());
      words.push_back(param.fPFastMathDefault.fastMathMode.value());
      break;
    case ExecutionMode::StreamingInterfaceINTEL:
      words.push_back((uint32_t)param.streamingInterfaceINTEL);
      break;
    case ExecutionMode::RegisterMapInterfaceINTEL:
      words.push_back((uint32_t)param.registerMapInterfaceINTEL);
      break;
    case ExecutionMode::NamedBarrierCountINTEL:
      words.push_back((uint32_t)param.namedBarrierCountINTEL);
      break;
    case ExecutionMode::MaximumRegistersINTEL:
      words.push_back((uint32_t)param.maximumRegistersINTEL);
      break;
    case ExecutionMode::MaximumRegistersIdINTEL:
      words.push_back(param.maximumRegistersIdINTEL.value());
      break;
    case ExecutionMode::NamedMaximumRegistersINTEL:
      words.push_back((uint32_t)param.namedMaximumRegistersINTEL);
      break;
    default: break;
  }
}

inline uint16_t ExtraWordCount(const ExecutionMode executionMode)
{
  switch(executionMode)
  {
    case ExecutionMode::Invocations: return 1;
    case ExecutionMode::LocalSize: return 3;
    case ExecutionMode::LocalSizeHint: return 3;
    case ExecutionMode::OutputVertices: return 1;
    case ExecutionMode::VecTypeHint: return 1;
    case ExecutionMode::SubgroupSize: return 1;
    case ExecutionMode::SubgroupsPerWorkgroup: return 1;
    case ExecutionMode::SubgroupsPerWorkgroupId: return 1;
    case ExecutionMode::LocalSizeId: return 3;
    case ExecutionMode::LocalSizeHintId: return 3;
    case ExecutionMode::DenormPreserve: return 1;
    case ExecutionMode::DenormFlushToZero: return 1;
    case ExecutionMode::SignedZeroInfNanPreserve: return 1;
    case ExecutionMode::RoundingModeRTE: return 1;
    case ExecutionMode::RoundingModeRTZ: return 1;
    case ExecutionMode::TileShadingRateQCOM: return 3;
    case ExecutionMode::IsApiEntryAMDX: return 1;
    case ExecutionMode::MaxNodeRecursionAMDX: return 1;
    case ExecutionMode::StaticNumWorkgroupsAMDX: return 3;
    case ExecutionMode::ShaderIndexAMDX: return 1;
    case ExecutionMode::MaxNumWorkgroupsAMDX: return 3;
    case ExecutionMode::SharesInputWithAMDX: return 2;
    case ExecutionMode::OutputPrimitivesEXT: return 1;
    case ExecutionMode::SharedLocalMemorySizeINTEL: return 1;
    case ExecutionMode::RoundingModeRTPINTEL: return 1;
    case ExecutionMode::RoundingModeRTNINTEL: return 1;
    case ExecutionMode::FloatingPointModeALTINTEL: return 1;
    case ExecutionMode::FloatingPointModeIEEEINTEL: return 1;
    case ExecutionMode::MaxWorkgroupSizeINTEL: return 3;
    case ExecutionMode::MaxWorkDimINTEL: return 1;
    case ExecutionMode::NumSIMDWorkitemsINTEL: return 1;
    case ExecutionMode::SchedulerTargetFmaxMhzINTEL: return 1;
    case ExecutionMode::FPFastMathDefault: return 2;
    case ExecutionMode::StreamingInterfaceINTEL: return 1;
    case ExecutionMode::RegisterMapInterfaceINTEL: return 1;
    case ExecutionMode::NamedBarrierCountINTEL: return 1;
    case ExecutionMode::MaximumRegistersINTEL: return 1;
    case ExecutionMode::MaximumRegistersIdINTEL: return 1;
    case ExecutionMode::NamedMaximumRegistersINTEL: return 1;
    default: break;
  }
  return 0;
}

inline uint16_t OptionalWordCount(const StorageClass val) { return val != StorageClass::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const Dim val) { return val != Dim::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const SamplerAddressingMode val) { return val != SamplerAddressingMode::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const SamplerFilterMode val) { return val != SamplerFilterMode::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const ImageFormat val) { return val != ImageFormat::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const ImageChannelOrder val) { return val != ImageChannelOrder::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const ImageChannelDataType val) { return val != ImageChannelDataType::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const FPRoundingMode val) { return val != FPRoundingMode::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const FPDenormMode val) { return val != FPDenormMode::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const QuantizationModes val) { return val != QuantizationModes::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const FPOperationMode val) { return val != FPOperationMode::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const OverflowModes val) { return val != OverflowModes::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const LinkageType val) { return val != LinkageType::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const AccessQualifier val) { return val != AccessQualifier::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const HostAccessQualifier val) { return val != HostAccessQualifier::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const FunctionParameterAttribute val) { return val != FunctionParameterAttribute::Invalid ? 1 : 0; }

template<Decoration val> struct DecorationParam;

template<>
struct DecorationParam<Decoration::SpecId>
{
  uint32_t specId;
  DecorationParam(uint32_t specIdParam) {  specId = specIdParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::SpecId);
    ret.specId = specId;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::ArrayStride>
{
  uint32_t arrayStride;
  DecorationParam(uint32_t arrayStrideParam) {  arrayStride = arrayStrideParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::ArrayStride);
    ret.arrayStride = arrayStride;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::MatrixStride>
{
  uint32_t matrixStride;
  DecorationParam(uint32_t matrixStrideParam) {  matrixStride = matrixStrideParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::MatrixStride);
    ret.matrixStride = matrixStride;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::BuiltIn>
{
  BuiltIn builtIn;
  DecorationParam(BuiltIn builtInParam) {  builtIn = builtInParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::BuiltIn);
    ret.builtIn = builtIn;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::UniformId>
{
  IdScope uniformId;
  DecorationParam(IdScope uniformIdParam) {  uniformId = uniformIdParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::UniformId);
    ret.uniformId = uniformId;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::Stream>
{
  uint32_t stream;
  DecorationParam(uint32_t streamParam) {  stream = streamParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::Stream);
    ret.stream = stream;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::Location>
{
  uint32_t location;
  DecorationParam(uint32_t locationParam) {  location = locationParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::Location);
    ret.location = location;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::Component>
{
  uint32_t component;
  DecorationParam(uint32_t componentParam) {  component = componentParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::Component);
    ret.component = component;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::Index>
{
  uint32_t index;
  DecorationParam(uint32_t indexParam) {  index = indexParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::Index);
    ret.index = index;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::Binding>
{
  uint32_t binding;
  DecorationParam(uint32_t bindingParam) {  binding = bindingParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::Binding);
    ret.binding = binding;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::DescriptorSet>
{
  uint32_t descriptorSet;
  DecorationParam(uint32_t descriptorSetParam) {  descriptorSet = descriptorSetParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::DescriptorSet);
    ret.descriptorSet = descriptorSet;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::Offset>
{
  uint32_t offset;
  DecorationParam(uint32_t offsetParam) {  offset = offsetParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::Offset);
    ret.offset = offset;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::XfbBuffer>
{
  uint32_t xfbBuffer;
  DecorationParam(uint32_t xfbBufferParam) {  xfbBuffer = xfbBufferParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::XfbBuffer);
    ret.xfbBuffer = xfbBuffer;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::XfbStride>
{
  uint32_t xfbStride;
  DecorationParam(uint32_t xfbStrideParam) {  xfbStride = xfbStrideParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::XfbStride);
    ret.xfbStride = xfbStride;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::FuncParamAttr>
{
  FunctionParameterAttribute funcParamAttr;
  DecorationParam(FunctionParameterAttribute funcParamAttrParam) {  funcParamAttr = funcParamAttrParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::FuncParamAttr);
    ret.funcParamAttr = funcParamAttr;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::FPRoundingMode>
{
  FPRoundingMode fPRoundingMode;
  DecorationParam(FPRoundingMode fPRoundingModeParam) {  fPRoundingMode = fPRoundingModeParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::FPRoundingMode);
    ret.fPRoundingMode = fPRoundingMode;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::FPFastMathMode>
{
  FPFastMathMode fPFastMathMode;
  DecorationParam(FPFastMathMode fPFastMathModeParam) {  fPFastMathMode = fPFastMathModeParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::FPFastMathMode);
    ret.fPFastMathMode = fPFastMathMode;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::InputAttachmentIndex>
{
  uint32_t inputAttachmentIndex;
  DecorationParam(uint32_t inputAttachmentIndexParam) {  inputAttachmentIndex = inputAttachmentIndexParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::InputAttachmentIndex);
    ret.inputAttachmentIndex = inputAttachmentIndex;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::Alignment>
{
  uint32_t alignment;
  DecorationParam(uint32_t alignmentParam) {  alignment = alignmentParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::Alignment);
    ret.alignment = alignment;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::MaxByteOffset>
{
  uint32_t maxByteOffset;
  DecorationParam(uint32_t maxByteOffsetParam) {  maxByteOffset = maxByteOffsetParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::MaxByteOffset);
    ret.maxByteOffset = maxByteOffset;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::AlignmentId>
{
  Id alignmentId;
  DecorationParam(Id alignmentIdParam) {  alignmentId = alignmentIdParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::AlignmentId);
    ret.alignmentId = alignmentId;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::MaxByteOffsetId>
{
  Id maxByteOffsetId;
  DecorationParam(Id maxByteOffsetIdParam) {  maxByteOffsetId = maxByteOffsetIdParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::MaxByteOffsetId);
    ret.maxByteOffsetId = maxByteOffsetId;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::NodeSharesPayloadLimitsWithAMDX>
{
  Id nodeSharesPayloadLimitsWithAMDX;
  DecorationParam(Id nodeSharesPayloadLimitsWithAMDXParam) {  nodeSharesPayloadLimitsWithAMDX = nodeSharesPayloadLimitsWithAMDXParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::NodeSharesPayloadLimitsWithAMDX);
    ret.nodeSharesPayloadLimitsWithAMDX = nodeSharesPayloadLimitsWithAMDX;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::NodeMaxPayloadsAMDX>
{
  Id nodeMaxPayloadsAMDX;
  DecorationParam(Id nodeMaxPayloadsAMDXParam) {  nodeMaxPayloadsAMDX = nodeMaxPayloadsAMDXParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::NodeMaxPayloadsAMDX);
    ret.nodeMaxPayloadsAMDX = nodeMaxPayloadsAMDX;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::PayloadNodeNameAMDX>
{
  Id payloadNodeNameAMDX;
  DecorationParam(Id payloadNodeNameAMDXParam) {  payloadNodeNameAMDX = payloadNodeNameAMDXParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::PayloadNodeNameAMDX);
    ret.payloadNodeNameAMDX = payloadNodeNameAMDX;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::PayloadNodeBaseIndexAMDX>
{
  Id payloadNodeBaseIndexAMDX;
  DecorationParam(Id payloadNodeBaseIndexAMDXParam) {  payloadNodeBaseIndexAMDX = payloadNodeBaseIndexAMDXParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::PayloadNodeBaseIndexAMDX);
    ret.payloadNodeBaseIndexAMDX = payloadNodeBaseIndexAMDX;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::PayloadNodeArraySizeAMDX>
{
  Id payloadNodeArraySizeAMDX;
  DecorationParam(Id payloadNodeArraySizeAMDXParam) {  payloadNodeArraySizeAMDX = payloadNodeArraySizeAMDXParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::PayloadNodeArraySizeAMDX);
    ret.payloadNodeArraySizeAMDX = payloadNodeArraySizeAMDX;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::ArrayStrideIdEXT>
{
  Id arrayStrideIdEXT;
  DecorationParam(Id arrayStrideIdEXTParam) {  arrayStrideIdEXT = arrayStrideIdEXTParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::ArrayStrideIdEXT);
    ret.arrayStrideIdEXT = arrayStrideIdEXT;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::OffsetIdEXT>
{
  Id offsetIdEXT;
  DecorationParam(Id offsetIdEXTParam) {  offsetIdEXT = offsetIdEXTParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::OffsetIdEXT);
    ret.offsetIdEXT = offsetIdEXT;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::SecondaryViewportRelativeNV>
{
  uint32_t secondaryViewportRelativeNV;
  DecorationParam(uint32_t secondaryViewportRelativeNVParam) {  secondaryViewportRelativeNV = secondaryViewportRelativeNVParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::SecondaryViewportRelativeNV);
    ret.secondaryViewportRelativeNV = secondaryViewportRelativeNV;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::MemberOffsetNV>
{
  uint32_t memberOffsetNV;
  DecorationParam(uint32_t memberOffsetNVParam) {  memberOffsetNV = memberOffsetNVParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::MemberOffsetNV);
    ret.memberOffsetNV = memberOffsetNV;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::BankNV>
{
  uint32_t bankNV;
  DecorationParam(uint32_t bankNVParam) {  bankNV = bankNVParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::BankNV);
    ret.bankNV = bankNV;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::SIMTCallINTEL>
{
  uint32_t sIMTCallINTEL;
  DecorationParam(uint32_t sIMTCallINTELParam) {  sIMTCallINTEL = sIMTCallINTELParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::SIMTCallINTEL);
    ret.sIMTCallINTEL = sIMTCallINTEL;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::FuncParamIOKindINTEL>
{
  uint32_t funcParamIOKindINTEL;
  DecorationParam(uint32_t funcParamIOKindINTELParam) {  funcParamIOKindINTEL = funcParamIOKindINTELParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::FuncParamIOKindINTEL);
    ret.funcParamIOKindINTEL = funcParamIOKindINTEL;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::GlobalVariableOffsetINTEL>
{
  uint32_t globalVariableOffsetINTEL;
  DecorationParam(uint32_t globalVariableOffsetINTELParam) {  globalVariableOffsetINTEL = globalVariableOffsetINTELParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::GlobalVariableOffsetINTEL);
    ret.globalVariableOffsetINTEL = globalVariableOffsetINTEL;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::CounterBuffer>
{
  Id counterBuffer;
  DecorationParam(Id counterBufferParam) {  counterBuffer = counterBufferParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::CounterBuffer);
    ret.counterBuffer = counterBuffer;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::FunctionRoundingModeINTEL>
{
  FunctionRoundingModeINTELParams functionRoundingModeINTEL;
  DecorationParam(uint32_t targetWidth, FPRoundingMode fPRoundingMode) {  functionRoundingModeINTEL.targetWidth = targetWidth; functionRoundingModeINTEL.fPRoundingMode = fPRoundingMode; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::FunctionRoundingModeINTEL);
    ret.functionRoundingModeINTEL.targetWidth = functionRoundingModeINTEL.targetWidth;
    ret.functionRoundingModeINTEL.fPRoundingMode = functionRoundingModeINTEL.fPRoundingMode;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::FunctionDenormModeINTEL>
{
  FunctionDenormModeINTELParams functionDenormModeINTEL;
  DecorationParam(uint32_t targetWidth, FPDenormMode fPDenormMode) {  functionDenormModeINTEL.targetWidth = targetWidth; functionDenormModeINTEL.fPDenormMode = fPDenormMode; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::FunctionDenormModeINTEL);
    ret.functionDenormModeINTEL.targetWidth = functionDenormModeINTEL.targetWidth;
    ret.functionDenormModeINTEL.fPDenormMode = functionDenormModeINTEL.fPDenormMode;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::NumbanksALTERA>
{
  uint32_t numbanksALTERA;
  DecorationParam(uint32_t numbanksALTERAParam) {  numbanksALTERA = numbanksALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::NumbanksALTERA);
    ret.numbanksALTERA = numbanksALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::BankwidthALTERA>
{
  uint32_t bankwidthALTERA;
  DecorationParam(uint32_t bankwidthALTERAParam) {  bankwidthALTERA = bankwidthALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::BankwidthALTERA);
    ret.bankwidthALTERA = bankwidthALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::MaxPrivateCopiesALTERA>
{
  uint32_t maxPrivateCopiesALTERA;
  DecorationParam(uint32_t maxPrivateCopiesALTERAParam) {  maxPrivateCopiesALTERA = maxPrivateCopiesALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::MaxPrivateCopiesALTERA);
    ret.maxPrivateCopiesALTERA = maxPrivateCopiesALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::MaxReplicatesALTERA>
{
  uint32_t maxReplicatesALTERA;
  DecorationParam(uint32_t maxReplicatesALTERAParam) {  maxReplicatesALTERA = maxReplicatesALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::MaxReplicatesALTERA);
    ret.maxReplicatesALTERA = maxReplicatesALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::BankBitsALTERA>
{
  uint32_t bankBitsALTERA;
  DecorationParam(uint32_t bankBitsALTERAParam) {  bankBitsALTERA = bankBitsALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::BankBitsALTERA);
    ret.bankBitsALTERA = bankBitsALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::ForcePow2DepthALTERA>
{
  uint32_t forcePow2DepthALTERA;
  DecorationParam(uint32_t forcePow2DepthALTERAParam) {  forcePow2DepthALTERA = forcePow2DepthALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::ForcePow2DepthALTERA);
    ret.forcePow2DepthALTERA = forcePow2DepthALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::StridesizeALTERA>
{
  uint32_t stridesizeALTERA;
  DecorationParam(uint32_t stridesizeALTERAParam) {  stridesizeALTERA = stridesizeALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::StridesizeALTERA);
    ret.stridesizeALTERA = stridesizeALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::WordsizeALTERA>
{
  uint32_t wordsizeALTERA;
  DecorationParam(uint32_t wordsizeALTERAParam) {  wordsizeALTERA = wordsizeALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::WordsizeALTERA);
    ret.wordsizeALTERA = wordsizeALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::CacheSizeALTERA>
{
  uint32_t cacheSizeALTERA;
  DecorationParam(uint32_t cacheSizeALTERAParam) {  cacheSizeALTERA = cacheSizeALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::CacheSizeALTERA);
    ret.cacheSizeALTERA = cacheSizeALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::PrefetchALTERA>
{
  uint32_t prefetchALTERA;
  DecorationParam(uint32_t prefetchALTERAParam) {  prefetchALTERA = prefetchALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::PrefetchALTERA);
    ret.prefetchALTERA = prefetchALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::MathOpDSPModeALTERA>
{
  MathOpDSPModeALTERAParams mathOpDSPModeALTERA;
  DecorationParam(uint32_t mode, uint32_t propagate) {  mathOpDSPModeALTERA.mode = mode; mathOpDSPModeALTERA.propagate = propagate; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::MathOpDSPModeALTERA);
    ret.mathOpDSPModeALTERA.mode = mathOpDSPModeALTERA.mode;
    ret.mathOpDSPModeALTERA.propagate = mathOpDSPModeALTERA.propagate;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::AliasScopeINTEL>
{
  Id aliasScopeINTEL;
  DecorationParam(Id aliasScopeINTELParam) {  aliasScopeINTEL = aliasScopeINTELParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::AliasScopeINTEL);
    ret.aliasScopeINTEL = aliasScopeINTEL;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::NoAliasINTEL>
{
  Id noAliasINTEL;
  DecorationParam(Id noAliasINTELParam) {  noAliasINTEL = noAliasINTELParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::NoAliasINTEL);
    ret.noAliasINTEL = noAliasINTEL;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::InitiationIntervalALTERA>
{
  uint32_t initiationIntervalALTERA;
  DecorationParam(uint32_t initiationIntervalALTERAParam) {  initiationIntervalALTERA = initiationIntervalALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::InitiationIntervalALTERA);
    ret.initiationIntervalALTERA = initiationIntervalALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::MaxConcurrencyALTERA>
{
  uint32_t maxConcurrencyALTERA;
  DecorationParam(uint32_t maxConcurrencyALTERAParam) {  maxConcurrencyALTERA = maxConcurrencyALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::MaxConcurrencyALTERA);
    ret.maxConcurrencyALTERA = maxConcurrencyALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::PipelineEnableALTERA>
{
  uint32_t pipelineEnableALTERA;
  DecorationParam(uint32_t pipelineEnableALTERAParam) {  pipelineEnableALTERA = pipelineEnableALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::PipelineEnableALTERA);
    ret.pipelineEnableALTERA = pipelineEnableALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::BufferLocationALTERA>
{
  uint32_t bufferLocationALTERA;
  DecorationParam(uint32_t bufferLocationALTERAParam) {  bufferLocationALTERA = bufferLocationALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::BufferLocationALTERA);
    ret.bufferLocationALTERA = bufferLocationALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::IOPipeStorageALTERA>
{
  uint32_t iOPipeStorageALTERA;
  DecorationParam(uint32_t iOPipeStorageALTERAParam) {  iOPipeStorageALTERA = iOPipeStorageALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::IOPipeStorageALTERA);
    ret.iOPipeStorageALTERA = iOPipeStorageALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::FunctionFloatingPointModeINTEL>
{
  FunctionFloatingPointModeINTELParams functionFloatingPointModeINTEL;
  DecorationParam(uint32_t targetWidth, FPOperationMode fPOperationMode) {  functionFloatingPointModeINTEL.targetWidth = targetWidth; functionFloatingPointModeINTEL.fPOperationMode = fPOperationMode; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::FunctionFloatingPointModeINTEL);
    ret.functionFloatingPointModeINTEL.targetWidth = functionFloatingPointModeINTEL.targetWidth;
    ret.functionFloatingPointModeINTEL.fPOperationMode = functionFloatingPointModeINTEL.fPOperationMode;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::FPMaxErrorDecorationINTEL>
{
  float fPMaxErrorDecorationINTEL;
  DecorationParam(float fPMaxErrorDecorationINTELParam) {  fPMaxErrorDecorationINTEL = fPMaxErrorDecorationINTELParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::FPMaxErrorDecorationINTEL);
    ret.fPMaxErrorDecorationINTEL = fPMaxErrorDecorationINTEL;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::LatencyControlLabelALTERA>
{
  uint32_t latencyControlLabelALTERA;
  DecorationParam(uint32_t latencyControlLabelALTERAParam) {  latencyControlLabelALTERA = latencyControlLabelALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::LatencyControlLabelALTERA);
    ret.latencyControlLabelALTERA = latencyControlLabelALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::LatencyControlConstraintALTERA>
{
  LatencyControlConstraintALTERAParams latencyControlConstraintALTERA;
  DecorationParam(uint32_t relativeTo, uint32_t controlType, uint32_t relativeCycle) {  latencyControlConstraintALTERA.relativeTo = relativeTo; latencyControlConstraintALTERA.controlType = controlType; latencyControlConstraintALTERA.relativeCycle = relativeCycle; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::LatencyControlConstraintALTERA);
    ret.latencyControlConstraintALTERA.relativeTo = latencyControlConstraintALTERA.relativeTo;
    ret.latencyControlConstraintALTERA.controlType = latencyControlConstraintALTERA.controlType;
    ret.latencyControlConstraintALTERA.relativeCycle = latencyControlConstraintALTERA.relativeCycle;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::MMHostInterfaceAddressWidthALTERA>
{
  uint32_t mMHostInterfaceAddressWidthALTERA;
  DecorationParam(uint32_t mMHostInterfaceAddressWidthALTERAParam) {  mMHostInterfaceAddressWidthALTERA = mMHostInterfaceAddressWidthALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::MMHostInterfaceAddressWidthALTERA);
    ret.mMHostInterfaceAddressWidthALTERA = mMHostInterfaceAddressWidthALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::MMHostInterfaceDataWidthALTERA>
{
  uint32_t mMHostInterfaceDataWidthALTERA;
  DecorationParam(uint32_t mMHostInterfaceDataWidthALTERAParam) {  mMHostInterfaceDataWidthALTERA = mMHostInterfaceDataWidthALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::MMHostInterfaceDataWidthALTERA);
    ret.mMHostInterfaceDataWidthALTERA = mMHostInterfaceDataWidthALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::MMHostInterfaceLatencyALTERA>
{
  uint32_t mMHostInterfaceLatencyALTERA;
  DecorationParam(uint32_t mMHostInterfaceLatencyALTERAParam) {  mMHostInterfaceLatencyALTERA = mMHostInterfaceLatencyALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::MMHostInterfaceLatencyALTERA);
    ret.mMHostInterfaceLatencyALTERA = mMHostInterfaceLatencyALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::MMHostInterfaceReadWriteModeALTERA>
{
  AccessQualifier mMHostInterfaceReadWriteModeALTERA;
  DecorationParam(AccessQualifier mMHostInterfaceReadWriteModeALTERAParam) {  mMHostInterfaceReadWriteModeALTERA = mMHostInterfaceReadWriteModeALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::MMHostInterfaceReadWriteModeALTERA);
    ret.mMHostInterfaceReadWriteModeALTERA = mMHostInterfaceReadWriteModeALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::MMHostInterfaceMaxBurstALTERA>
{
  uint32_t mMHostInterfaceMaxBurstALTERA;
  DecorationParam(uint32_t mMHostInterfaceMaxBurstALTERAParam) {  mMHostInterfaceMaxBurstALTERA = mMHostInterfaceMaxBurstALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::MMHostInterfaceMaxBurstALTERA);
    ret.mMHostInterfaceMaxBurstALTERA = mMHostInterfaceMaxBurstALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::MMHostInterfaceWaitRequestALTERA>
{
  uint32_t mMHostInterfaceWaitRequestALTERA;
  DecorationParam(uint32_t mMHostInterfaceWaitRequestALTERAParam) {  mMHostInterfaceWaitRequestALTERA = mMHostInterfaceWaitRequestALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::MMHostInterfaceWaitRequestALTERA);
    ret.mMHostInterfaceWaitRequestALTERA = mMHostInterfaceWaitRequestALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::InitModeALTERA>
{
  InitializationModeQualifier initModeALTERA;
  DecorationParam(InitializationModeQualifier initModeALTERAParam) {  initModeALTERA = initModeALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::InitModeALTERA);
    ret.initModeALTERA = initModeALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::ImplementInRegisterMapALTERA>
{
  uint32_t implementInRegisterMapALTERA;
  DecorationParam(uint32_t implementInRegisterMapALTERAParam) {  implementInRegisterMapALTERA = implementInRegisterMapALTERAParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::ImplementInRegisterMapALTERA);
    ret.implementInRegisterMapALTERA = implementInRegisterMapALTERA;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::ConditionalINTEL>
{
  Id conditionalINTEL;
  DecorationParam(Id conditionalINTELParam) {  conditionalINTEL = conditionalINTELParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::ConditionalINTEL);
    ret.conditionalINTEL = conditionalINTEL;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::CacheControlLoadINTEL>
{
  CacheControlLoadINTELParams cacheControlLoadINTEL;
  DecorationParam(uint32_t cacheLevel, LoadCacheControl cacheControl) {  cacheControlLoadINTEL.cacheLevel = cacheLevel; cacheControlLoadINTEL.cacheControl = cacheControl; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::CacheControlLoadINTEL);
    ret.cacheControlLoadINTEL.cacheLevel = cacheControlLoadINTEL.cacheLevel;
    ret.cacheControlLoadINTEL.cacheControl = cacheControlLoadINTEL.cacheControl;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::CacheControlStoreINTEL>
{
  CacheControlStoreINTELParams cacheControlStoreINTEL;
  DecorationParam(uint32_t cacheLevel, StoreCacheControl cacheControl) {  cacheControlStoreINTEL.cacheLevel = cacheLevel; cacheControlStoreINTEL.cacheControl = cacheControl; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::CacheControlStoreINTEL);
    ret.cacheControlStoreINTEL.cacheLevel = cacheControlStoreINTEL.cacheLevel;
    ret.cacheControlStoreINTEL.cacheControl = cacheControlStoreINTEL.cacheControl;
    return ret;
  }
};



template<>
inline DecorationAndParamData DecodeParam(const ConstIter &it, uint32_t &word)
{
  if(word >= it.size()) return DecorationAndParamData();

  DecorationAndParamData ret((Decoration)it.word(word));
  word++;
  switch(ret.value)
  {
    case Decoration::SpecId:
      ret.specId = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::ArrayStride:
      ret.arrayStride = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::MatrixStride:
      ret.matrixStride = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::BuiltIn:
      ret.builtIn = (BuiltIn)it.word(word);
      word += 1;
      break;
    case Decoration::UniformId:
      ret.uniformId = Id::fromWord(it.word(word));
      word += 1;
      break;
    case Decoration::Stream:
      ret.stream = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::Location:
      ret.location = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::Component:
      ret.component = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::Index:
      ret.index = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::Binding:
      ret.binding = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::DescriptorSet:
      ret.descriptorSet = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::Offset:
      ret.offset = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::XfbBuffer:
      ret.xfbBuffer = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::XfbStride:
      ret.xfbStride = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::FuncParamAttr:
      ret.funcParamAttr = (FunctionParameterAttribute)it.word(word);
      word += 1;
      break;
    case Decoration::FPRoundingMode:
      ret.fPRoundingMode = (FPRoundingMode)it.word(word);
      word += 1;
      break;
    case Decoration::FPFastMathMode:
      ret.fPFastMathMode = (FPFastMathMode)it.word(word);
      word += 1;
      break;
    case Decoration::InputAttachmentIndex:
      ret.inputAttachmentIndex = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::Alignment:
      ret.alignment = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::MaxByteOffset:
      ret.maxByteOffset = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::AlignmentId:
      ret.alignmentId = Id::fromWord(it.word(word));
      word += 1;
      break;
    case Decoration::MaxByteOffsetId:
      ret.maxByteOffsetId = Id::fromWord(it.word(word));
      word += 1;
      break;
    case Decoration::NodeSharesPayloadLimitsWithAMDX:
      ret.nodeSharesPayloadLimitsWithAMDX = Id::fromWord(it.word(word));
      word += 1;
      break;
    case Decoration::NodeMaxPayloadsAMDX:
      ret.nodeMaxPayloadsAMDX = Id::fromWord(it.word(word));
      word += 1;
      break;
    case Decoration::PayloadNodeNameAMDX:
      ret.payloadNodeNameAMDX = Id::fromWord(it.word(word));
      word += 1;
      break;
    case Decoration::PayloadNodeBaseIndexAMDX:
      ret.payloadNodeBaseIndexAMDX = Id::fromWord(it.word(word));
      word += 1;
      break;
    case Decoration::PayloadNodeArraySizeAMDX:
      ret.payloadNodeArraySizeAMDX = Id::fromWord(it.word(word));
      word += 1;
      break;
    case Decoration::ArrayStrideIdEXT:
      ret.arrayStrideIdEXT = Id::fromWord(it.word(word));
      word += 1;
      break;
    case Decoration::OffsetIdEXT:
      ret.offsetIdEXT = Id::fromWord(it.word(word));
      word += 1;
      break;
    case Decoration::SecondaryViewportRelativeNV:
      ret.secondaryViewportRelativeNV = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::MemberOffsetNV:
      ret.memberOffsetNV = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::BankNV:
      ret.bankNV = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::SIMTCallINTEL:
      ret.sIMTCallINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::FuncParamIOKindINTEL:
      ret.funcParamIOKindINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::GlobalVariableOffsetINTEL:
      ret.globalVariableOffsetINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::CounterBuffer:
      ret.counterBuffer = Id::fromWord(it.word(word));
      word += 1;
      break;
    case Decoration::FunctionRoundingModeINTEL:
      ret.functionRoundingModeINTEL.targetWidth = (uint32_t)it.word(word+0);
      ret.functionRoundingModeINTEL.fPRoundingMode = (FPRoundingMode)it.word(word+1);
      word += 2;
      break;
    case Decoration::FunctionDenormModeINTEL:
      ret.functionDenormModeINTEL.targetWidth = (uint32_t)it.word(word+0);
      ret.functionDenormModeINTEL.fPDenormMode = (FPDenormMode)it.word(word+1);
      word += 2;
      break;
    case Decoration::NumbanksALTERA:
      ret.numbanksALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::BankwidthALTERA:
      ret.bankwidthALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::MaxPrivateCopiesALTERA:
      ret.maxPrivateCopiesALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::MaxReplicatesALTERA:
      ret.maxReplicatesALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::BankBitsALTERA:
      ret.bankBitsALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::ForcePow2DepthALTERA:
      ret.forcePow2DepthALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::StridesizeALTERA:
      ret.stridesizeALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::WordsizeALTERA:
      ret.wordsizeALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::CacheSizeALTERA:
      ret.cacheSizeALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::PrefetchALTERA:
      ret.prefetchALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::MathOpDSPModeALTERA:
      ret.mathOpDSPModeALTERA.mode = (uint32_t)it.word(word+0);
      ret.mathOpDSPModeALTERA.propagate = (uint32_t)it.word(word+1);
      word += 2;
      break;
    case Decoration::AliasScopeINTEL:
      ret.aliasScopeINTEL = Id::fromWord(it.word(word));
      word += 1;
      break;
    case Decoration::NoAliasINTEL:
      ret.noAliasINTEL = Id::fromWord(it.word(word));
      word += 1;
      break;
    case Decoration::InitiationIntervalALTERA:
      ret.initiationIntervalALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::MaxConcurrencyALTERA:
      ret.maxConcurrencyALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::PipelineEnableALTERA:
      ret.pipelineEnableALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::BufferLocationALTERA:
      ret.bufferLocationALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::IOPipeStorageALTERA:
      ret.iOPipeStorageALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::FunctionFloatingPointModeINTEL:
      ret.functionFloatingPointModeINTEL.targetWidth = (uint32_t)it.word(word+0);
      ret.functionFloatingPointModeINTEL.fPOperationMode = (FPOperationMode)it.word(word+1);
      word += 2;
      break;
    case Decoration::FPMaxErrorDecorationINTEL:
      ret.fPMaxErrorDecorationINTEL = (float)it.word(word);
      word += 1;
      break;
    case Decoration::LatencyControlLabelALTERA:
      ret.latencyControlLabelALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::LatencyControlConstraintALTERA:
      ret.latencyControlConstraintALTERA.relativeTo = (uint32_t)it.word(word+0);
      ret.latencyControlConstraintALTERA.controlType = (uint32_t)it.word(word+1);
      ret.latencyControlConstraintALTERA.relativeCycle = (uint32_t)it.word(word+2);
      word += 3;
      break;
    case Decoration::MMHostInterfaceAddressWidthALTERA:
      ret.mMHostInterfaceAddressWidthALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::MMHostInterfaceDataWidthALTERA:
      ret.mMHostInterfaceDataWidthALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::MMHostInterfaceLatencyALTERA:
      ret.mMHostInterfaceLatencyALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::MMHostInterfaceReadWriteModeALTERA:
      ret.mMHostInterfaceReadWriteModeALTERA = (AccessQualifier)it.word(word);
      word += 1;
      break;
    case Decoration::MMHostInterfaceMaxBurstALTERA:
      ret.mMHostInterfaceMaxBurstALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::MMHostInterfaceWaitRequestALTERA:
      ret.mMHostInterfaceWaitRequestALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::InitModeALTERA:
      ret.initModeALTERA = (InitializationModeQualifier)it.word(word);
      word += 1;
      break;
    case Decoration::ImplementInRegisterMapALTERA:
      ret.implementInRegisterMapALTERA = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::ConditionalINTEL:
      ret.conditionalINTEL = Id::fromWord(it.word(word));
      word += 1;
      break;
    case Decoration::CacheControlLoadINTEL:
      ret.cacheControlLoadINTEL.cacheLevel = (uint32_t)it.word(word+0);
      ret.cacheControlLoadINTEL.cacheControl = (LoadCacheControl)it.word(word+1);
      word += 2;
      break;
    case Decoration::CacheControlStoreINTEL:
      ret.cacheControlStoreINTEL.cacheLevel = (uint32_t)it.word(word+0);
      ret.cacheControlStoreINTEL.cacheControl = (StoreCacheControl)it.word(word+1);
      word += 2;
      break;
    default: break;
  }
  return ret;
}

inline void EncodeParam(rdcarray<uint32_t> &words, const DecorationAndParamData &param)
{
  words.push_back((uint32_t)param.value);
  switch(param.value)
  {
    case Decoration::SpecId:
      words.push_back((uint32_t)param.specId);
      break;
    case Decoration::ArrayStride:
      words.push_back((uint32_t)param.arrayStride);
      break;
    case Decoration::MatrixStride:
      words.push_back((uint32_t)param.matrixStride);
      break;
    case Decoration::BuiltIn:
      words.push_back((uint32_t)param.builtIn);
      break;
    case Decoration::UniformId:
      words.push_back(param.uniformId.value());
      break;
    case Decoration::Stream:
      words.push_back((uint32_t)param.stream);
      break;
    case Decoration::Location:
      words.push_back((uint32_t)param.location);
      break;
    case Decoration::Component:
      words.push_back((uint32_t)param.component);
      break;
    case Decoration::Index:
      words.push_back((uint32_t)param.index);
      break;
    case Decoration::Binding:
      words.push_back((uint32_t)param.binding);
      break;
    case Decoration::DescriptorSet:
      words.push_back((uint32_t)param.descriptorSet);
      break;
    case Decoration::Offset:
      words.push_back((uint32_t)param.offset);
      break;
    case Decoration::XfbBuffer:
      words.push_back((uint32_t)param.xfbBuffer);
      break;
    case Decoration::XfbStride:
      words.push_back((uint32_t)param.xfbStride);
      break;
    case Decoration::FuncParamAttr:
      words.push_back((uint32_t)param.funcParamAttr);
      break;
    case Decoration::FPRoundingMode:
      words.push_back((uint32_t)param.fPRoundingMode);
      break;
    case Decoration::FPFastMathMode:
      words.push_back((uint32_t)param.fPFastMathMode);
      break;
    case Decoration::InputAttachmentIndex:
      words.push_back((uint32_t)param.inputAttachmentIndex);
      break;
    case Decoration::Alignment:
      words.push_back((uint32_t)param.alignment);
      break;
    case Decoration::MaxByteOffset:
      words.push_back((uint32_t)param.maxByteOffset);
      break;
    case Decoration::AlignmentId:
      words.push_back(param.alignmentId.value());
      break;
    case Decoration::MaxByteOffsetId:
      words.push_back(param.maxByteOffsetId.value());
      break;
    case Decoration::NodeSharesPayloadLimitsWithAMDX:
      words.push_back(param.nodeSharesPayloadLimitsWithAMDX.value());
      break;
    case Decoration::NodeMaxPayloadsAMDX:
      words.push_back(param.nodeMaxPayloadsAMDX.value());
      break;
    case Decoration::PayloadNodeNameAMDX:
      words.push_back(param.payloadNodeNameAMDX.value());
      break;
    case Decoration::PayloadNodeBaseIndexAMDX:
      words.push_back(param.payloadNodeBaseIndexAMDX.value());
      break;
    case Decoration::PayloadNodeArraySizeAMDX:
      words.push_back(param.payloadNodeArraySizeAMDX.value());
      break;
    case Decoration::ArrayStrideIdEXT:
      words.push_back(param.arrayStrideIdEXT.value());
      break;
    case Decoration::OffsetIdEXT:
      words.push_back(param.offsetIdEXT.value());
      break;
    case Decoration::SecondaryViewportRelativeNV:
      words.push_back((uint32_t)param.secondaryViewportRelativeNV);
      break;
    case Decoration::MemberOffsetNV:
      words.push_back((uint32_t)param.memberOffsetNV);
      break;
    case Decoration::BankNV:
      words.push_back((uint32_t)param.bankNV);
      break;
    case Decoration::SIMTCallINTEL:
      words.push_back((uint32_t)param.sIMTCallINTEL);
      break;
    case Decoration::FuncParamIOKindINTEL:
      words.push_back((uint32_t)param.funcParamIOKindINTEL);
      break;
    case Decoration::GlobalVariableOffsetINTEL:
      words.push_back((uint32_t)param.globalVariableOffsetINTEL);
      break;
    case Decoration::CounterBuffer:
      words.push_back(param.counterBuffer.value());
      break;
    case Decoration::FunctionRoundingModeINTEL:
      words.push_back((uint32_t)param.functionRoundingModeINTEL.targetWidth);
      words.push_back((uint32_t)param.functionRoundingModeINTEL.fPRoundingMode);
      break;
    case Decoration::FunctionDenormModeINTEL:
      words.push_back((uint32_t)param.functionDenormModeINTEL.targetWidth);
      words.push_back((uint32_t)param.functionDenormModeINTEL.fPDenormMode);
      break;
    case Decoration::NumbanksALTERA:
      words.push_back((uint32_t)param.numbanksALTERA);
      break;
    case Decoration::BankwidthALTERA:
      words.push_back((uint32_t)param.bankwidthALTERA);
      break;
    case Decoration::MaxPrivateCopiesALTERA:
      words.push_back((uint32_t)param.maxPrivateCopiesALTERA);
      break;
    case Decoration::MaxReplicatesALTERA:
      words.push_back((uint32_t)param.maxReplicatesALTERA);
      break;
    case Decoration::BankBitsALTERA:
      words.push_back((uint32_t)param.bankBitsALTERA);
      break;
    case Decoration::ForcePow2DepthALTERA:
      words.push_back((uint32_t)param.forcePow2DepthALTERA);
      break;
    case Decoration::StridesizeALTERA:
      words.push_back((uint32_t)param.stridesizeALTERA);
      break;
    case Decoration::WordsizeALTERA:
      words.push_back((uint32_t)param.wordsizeALTERA);
      break;
    case Decoration::CacheSizeALTERA:
      words.push_back((uint32_t)param.cacheSizeALTERA);
      break;
    case Decoration::PrefetchALTERA:
      words.push_back((uint32_t)param.prefetchALTERA);
      break;
    case Decoration::MathOpDSPModeALTERA:
      words.push_back((uint32_t)param.mathOpDSPModeALTERA.mode);
      words.push_back((uint32_t)param.mathOpDSPModeALTERA.propagate);
      break;
    case Decoration::AliasScopeINTEL:
      words.push_back(param.aliasScopeINTEL.value());
      break;
    case Decoration::NoAliasINTEL:
      words.push_back(param.noAliasINTEL.value());
      break;
    case Decoration::InitiationIntervalALTERA:
      words.push_back((uint32_t)param.initiationIntervalALTERA);
      break;
    case Decoration::MaxConcurrencyALTERA:
      words.push_back((uint32_t)param.maxConcurrencyALTERA);
      break;
    case Decoration::PipelineEnableALTERA:
      words.push_back((uint32_t)param.pipelineEnableALTERA);
      break;
    case Decoration::BufferLocationALTERA:
      words.push_back((uint32_t)param.bufferLocationALTERA);
      break;
    case Decoration::IOPipeStorageALTERA:
      words.push_back((uint32_t)param.iOPipeStorageALTERA);
      break;
    case Decoration::FunctionFloatingPointModeINTEL:
      words.push_back((uint32_t)param.functionFloatingPointModeINTEL.targetWidth);
      words.push_back((uint32_t)param.functionFloatingPointModeINTEL.fPOperationMode);
      break;
    case Decoration::FPMaxErrorDecorationINTEL:
      words.push_back((uint32_t)param.fPMaxErrorDecorationINTEL);
      break;
    case Decoration::LatencyControlLabelALTERA:
      words.push_back((uint32_t)param.latencyControlLabelALTERA);
      break;
    case Decoration::LatencyControlConstraintALTERA:
      words.push_back((uint32_t)param.latencyControlConstraintALTERA.relativeTo);
      words.push_back((uint32_t)param.latencyControlConstraintALTERA.controlType);
      words.push_back((uint32_t)param.latencyControlConstraintALTERA.relativeCycle);
      break;
    case Decoration::MMHostInterfaceAddressWidthALTERA:
      words.push_back((uint32_t)param.mMHostInterfaceAddressWidthALTERA);
      break;
    case Decoration::MMHostInterfaceDataWidthALTERA:
      words.push_back((uint32_t)param.mMHostInterfaceDataWidthALTERA);
      break;
    case Decoration::MMHostInterfaceLatencyALTERA:
      words.push_back((uint32_t)param.mMHostInterfaceLatencyALTERA);
      break;
    case Decoration::MMHostInterfaceReadWriteModeALTERA:
      words.push_back((uint32_t)param.mMHostInterfaceReadWriteModeALTERA);
      break;
    case Decoration::MMHostInterfaceMaxBurstALTERA:
      words.push_back((uint32_t)param.mMHostInterfaceMaxBurstALTERA);
      break;
    case Decoration::MMHostInterfaceWaitRequestALTERA:
      words.push_back((uint32_t)param.mMHostInterfaceWaitRequestALTERA);
      break;
    case Decoration::InitModeALTERA:
      words.push_back((uint32_t)param.initModeALTERA);
      break;
    case Decoration::ImplementInRegisterMapALTERA:
      words.push_back((uint32_t)param.implementInRegisterMapALTERA);
      break;
    case Decoration::ConditionalINTEL:
      words.push_back(param.conditionalINTEL.value());
      break;
    case Decoration::CacheControlLoadINTEL:
      words.push_back((uint32_t)param.cacheControlLoadINTEL.cacheLevel);
      words.push_back((uint32_t)param.cacheControlLoadINTEL.cacheControl);
      break;
    case Decoration::CacheControlStoreINTEL:
      words.push_back((uint32_t)param.cacheControlStoreINTEL.cacheLevel);
      words.push_back((uint32_t)param.cacheControlStoreINTEL.cacheControl);
      break;
    default: break;
  }
}

inline uint16_t ExtraWordCount(const Decoration decoration)
{
  switch(decoration)
  {
    case Decoration::SpecId: return 1;
    case Decoration::ArrayStride: return 1;
    case Decoration::MatrixStride: return 1;
    case Decoration::BuiltIn: return 1;
    case Decoration::UniformId: return 1;
    case Decoration::Stream: return 1;
    case Decoration::Location: return 1;
    case Decoration::Component: return 1;
    case Decoration::Index: return 1;
    case Decoration::Binding: return 1;
    case Decoration::DescriptorSet: return 1;
    case Decoration::Offset: return 1;
    case Decoration::XfbBuffer: return 1;
    case Decoration::XfbStride: return 1;
    case Decoration::FuncParamAttr: return 1;
    case Decoration::FPRoundingMode: return 1;
    case Decoration::FPFastMathMode: return 1;
    case Decoration::InputAttachmentIndex: return 1;
    case Decoration::Alignment: return 1;
    case Decoration::MaxByteOffset: return 1;
    case Decoration::AlignmentId: return 1;
    case Decoration::MaxByteOffsetId: return 1;
    case Decoration::NodeSharesPayloadLimitsWithAMDX: return 1;
    case Decoration::NodeMaxPayloadsAMDX: return 1;
    case Decoration::PayloadNodeNameAMDX: return 1;
    case Decoration::PayloadNodeBaseIndexAMDX: return 1;
    case Decoration::PayloadNodeArraySizeAMDX: return 1;
    case Decoration::ArrayStrideIdEXT: return 1;
    case Decoration::OffsetIdEXT: return 1;
    case Decoration::SecondaryViewportRelativeNV: return 1;
    case Decoration::MemberOffsetNV: return 1;
    case Decoration::BankNV: return 1;
    case Decoration::SIMTCallINTEL: return 1;
    case Decoration::FuncParamIOKindINTEL: return 1;
    case Decoration::GlobalVariableOffsetINTEL: return 1;
    case Decoration::CounterBuffer: return 1;
    case Decoration::FunctionRoundingModeINTEL: return 2;
    case Decoration::FunctionDenormModeINTEL: return 2;
    case Decoration::NumbanksALTERA: return 1;
    case Decoration::BankwidthALTERA: return 1;
    case Decoration::MaxPrivateCopiesALTERA: return 1;
    case Decoration::MaxReplicatesALTERA: return 1;
    case Decoration::BankBitsALTERA: return 1;
    case Decoration::ForcePow2DepthALTERA: return 1;
    case Decoration::StridesizeALTERA: return 1;
    case Decoration::WordsizeALTERA: return 1;
    case Decoration::CacheSizeALTERA: return 1;
    case Decoration::PrefetchALTERA: return 1;
    case Decoration::MathOpDSPModeALTERA: return 2;
    case Decoration::AliasScopeINTEL: return 1;
    case Decoration::NoAliasINTEL: return 1;
    case Decoration::InitiationIntervalALTERA: return 1;
    case Decoration::MaxConcurrencyALTERA: return 1;
    case Decoration::PipelineEnableALTERA: return 1;
    case Decoration::BufferLocationALTERA: return 1;
    case Decoration::IOPipeStorageALTERA: return 1;
    case Decoration::FunctionFloatingPointModeINTEL: return 2;
    case Decoration::FPMaxErrorDecorationINTEL: return 1;
    case Decoration::LatencyControlLabelALTERA: return 1;
    case Decoration::LatencyControlConstraintALTERA: return 3;
    case Decoration::MMHostInterfaceAddressWidthALTERA: return 1;
    case Decoration::MMHostInterfaceDataWidthALTERA: return 1;
    case Decoration::MMHostInterfaceLatencyALTERA: return 1;
    case Decoration::MMHostInterfaceReadWriteModeALTERA: return 1;
    case Decoration::MMHostInterfaceMaxBurstALTERA: return 1;
    case Decoration::MMHostInterfaceWaitRequestALTERA: return 1;
    case Decoration::InitModeALTERA: return 1;
    case Decoration::ImplementInRegisterMapALTERA: return 1;
    case Decoration::ConditionalINTEL: return 1;
    case Decoration::CacheControlLoadINTEL: return 2;
    case Decoration::CacheControlStoreINTEL: return 2;
    default: break;
  }
  return 0;
}

inline uint16_t OptionalWordCount(const BuiltIn val) { return val != BuiltIn::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const Scope val) { return val != Scope::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const GroupOperation val) { return val != GroupOperation::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const KernelEnqueueFlags val) { return val != KernelEnqueueFlags::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const Capability val) { return val != Capability::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const RayQueryIntersection val) { return val != RayQueryIntersection::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const RayQueryCommittedIntersectionType val) { return val != RayQueryCommittedIntersectionType::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const RayQueryCandidateIntersectionType val) { return val != RayQueryCandidateIntersectionType::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const PackedVectorFormat val) { return val != PackedVectorFormat::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const CooperativeMatrixOperands val) { return val != CooperativeMatrixOperands::NoneKHR ? 1 : 0; }

inline uint16_t OptionalWordCount(const CooperativeMatrixLayout val) { return val != CooperativeMatrixLayout::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const CooperativeMatrixUse val) { return val != CooperativeMatrixUse::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const TensorClampMode val) { return val != TensorClampMode::Invalid ? 1 : 0; }

template<>
inline TensorAddressingOperandsAndParamDatas DecodeParam(const ConstIter &it, uint32_t &word)
{
  if(word >= it.size()) return TensorAddressingOperandsAndParamDatas();

  TensorAddressingOperandsAndParamDatas ret((TensorAddressingOperands)it.word(word));
  word++;
  if(ret.flags & TensorAddressingOperands::TensorView)
  {
    ret.tensorView = Id::fromWord(it.word(word));
    word += 1;
  }
  if(ret.flags & TensorAddressingOperands::DecodeFunc)
  {
    ret.decodeFunc = Id::fromWord(it.word(word));
    word += 1;
  }
  return ret;
}

inline void EncodeParam(rdcarray<uint32_t> &words, const TensorAddressingOperandsAndParamDatas &param)
{
  words.push_back((uint32_t)param.flags);
  if(param.flags & TensorAddressingOperands::TensorView)
  {
    words.push_back(param.tensorView.value());
  }
  if(param.flags & TensorAddressingOperands::DecodeFunc)
  {
    words.push_back(param.decodeFunc.value());
  }
}

inline uint16_t ExtraWordCount(const TensorAddressingOperands tensorAddressingOperands)
{
  switch(tensorAddressingOperands)
  {
    case TensorAddressingOperands::TensorView: return 1;
    case TensorAddressingOperands::DecodeFunc: return 1;
    default: break;
  }
  return 0;
}

inline uint16_t OptionalWordCount(const InitializationModeQualifier val) { return val != InitializationModeQualifier::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const LoadCacheControl val) { return val != LoadCacheControl::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const StoreCacheControl val) { return val != StoreCacheControl::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const NamedMaximumNumberOfRegisters val) { return val != NamedMaximumNumberOfRegisters::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const MatrixMultiplyAccumulateOperands val) { return val != MatrixMultiplyAccumulateOperands::None ? 1 : 0; }

inline uint16_t OptionalWordCount(const FPEncoding val) { return val != FPEncoding::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const CooperativeVectorMatrixLayout val) { return val != CooperativeVectorMatrixLayout::Invalid ? 1 : 0; }

inline uint16_t OptionalWordCount(const ComponentType val) { return val != ComponentType::Invalid ? 1 : 0; }

template<>
inline TensorOperandsAndParamDatas DecodeParam(const ConstIter &it, uint32_t &word)
{
  if(word >= it.size()) return TensorOperandsAndParamDatas();

  TensorOperandsAndParamDatas ret((TensorOperands)it.word(word));
  word++;
  if(ret.flags & TensorOperands::OutOfBoundsValueARM)
  {
    ret.outOfBoundsValueARM = Id::fromWord(it.word(word));
    word += 1;
  }
  if(ret.flags & TensorOperands::MakeElementAvailableARM)
  {
    ret.makeElementAvailableARM = Id::fromWord(it.word(word));
    word += 1;
  }
  if(ret.flags & TensorOperands::MakeElementVisibleARM)
  {
    ret.makeElementVisibleARM = Id::fromWord(it.word(word));
    word += 1;
  }
  return ret;
}

inline void EncodeParam(rdcarray<uint32_t> &words, const TensorOperandsAndParamDatas &param)
{
  words.push_back((uint32_t)param.flags);
  if(param.flags & TensorOperands::OutOfBoundsValueARM)
  {
    words.push_back(param.outOfBoundsValueARM.value());
  }
  if(param.flags & TensorOperands::MakeElementAvailableARM)
  {
    words.push_back(param.makeElementAvailableARM.value());
  }
  if(param.flags & TensorOperands::MakeElementVisibleARM)
  {
    words.push_back(param.makeElementVisibleARM.value());
  }
}

inline uint16_t ExtraWordCount(const TensorOperands tensorOperands)
{
  switch(tensorOperands)
  {
    case TensorOperands::OutOfBoundsValueARM: return 1;
    case TensorOperands::MakeElementAvailableARM: return 1;
    case TensorOperands::MakeElementVisibleARM: return 1;
    default: break;
  }
  return 0;
}


inline uint16_t ExtraWordCount(const rdcstr &val)
{
  return uint16_t(val.size() / 4);
}

inline uint16_t OptionalWordCount(const rdcstr &val)
{
  if(val.empty()) return 0;
  return uint16_t(val.size() / 4) + 1;
}

inline uint16_t OptionalWordCount(const Id &val)
{
  return val != Id() ? 1 : 0;
}

inline uint16_t OptionalWordCount(const PairIdRefLiteralInteger &val)
{
  return val.first != Id() ? 2 : 0;
}

inline uint16_t OptionalWordCount(const PairIdRefIdRef &val)
{
  return val.first != Id() ? 2 : 0;
}

template<typename Type>
uint16_t MultiWordCount(const rdcarray<Type> &multiParams)
{
  uint16_t ret = 0;
  for(size_t i=0; i < multiParams.size(); i++)
    ret += sizeof(multiParams[i])/sizeof(uint32_t);
  return ret;
}

struct OpNop
{
  OpNop(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpNop()
      : op(Op::Nop)
      , wordCount(FixedWordSize)
  {
    // no operands
  }

  static constexpr Op OpCode = Op::Nop;
  static constexpr uint16_t FixedWordSize = 1U;
  Op op;
  uint16_t wordCount;
  // no operands
};

struct OpUndef
{
  OpUndef(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpUndef(IdResultType resultType, IdResult result)
      : op(Op::Undef)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
  }

  static constexpr Op OpCode = Op::Undef;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
};

struct OpSourceContinued
{
  OpSourceContinued(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    word = 1;
    this->continuedSource = DecodeParam<rdcstr>(it, word);
  }
  OpSourceContinued(rdcstr continuedSource)
      : op(Op::SourceContinued)
      , wordCount(MinWordSize + ExtraWordCount(continuedSource))
  {
    this->continuedSource = continuedSource;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    EncodeParam(words, continuedSource);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::SourceContinued;
  static constexpr uint16_t MinWordSize = 2U;
  Op op;
  uint16_t wordCount;
  rdcstr continuedSource;
};

struct OpSource
{
  OpSource(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->sourceLanguage = (SourceLanguage)it.word(1);
    this->version = (uint32_t)it.word(2);
    this->file = (it.size() > 3) ? Id::fromWord(it.word(3)) : Id();
    word = 4;
    this->source = DecodeParam<rdcstr>(it, word);
  }
  OpSource(SourceLanguage sourceLanguage, uint32_t version, Id file = Id(), rdcstr source = "")
      : op(Op::Source)
      , wordCount(MinWordSize + OptionalWordCount(source))
  {
    this->sourceLanguage = sourceLanguage;
    this->version = version;
    this->file = file;
    this->source = source;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back((uint32_t)sourceLanguage);
    words.push_back((uint32_t)version);
    if(file != Id()) words.push_back(file.value());
    EncodeParam(words, source);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::Source;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  SourceLanguage sourceLanguage;
  uint32_t version;
  Id file;
  rdcstr source;

  bool HasFile() const { return wordCount > 3; }
  bool HasSource() const { return wordCount > 4; }
};

struct OpSourceExtension
{
  OpSourceExtension(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    word = 1;
    this->extension = DecodeParam<rdcstr>(it, word);
  }
  OpSourceExtension(rdcstr extension)
      : op(Op::SourceExtension)
      , wordCount(MinWordSize + ExtraWordCount(extension))
  {
    this->extension = extension;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    EncodeParam(words, extension);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::SourceExtension;
  static constexpr uint16_t MinWordSize = 2U;
  Op op;
  uint16_t wordCount;
  rdcstr extension;
};

struct OpName
{
  OpName(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->target = Id::fromWord(it.word(1));
    word = 2;
    this->name = DecodeParam<rdcstr>(it, word);
  }
  OpName(Id target, rdcstr name)
      : op(Op::Name)
      , wordCount(MinWordSize + ExtraWordCount(name))
  {
    this->target = target;
    this->name = name;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(target.value());
    EncodeParam(words, name);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::Name;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id target;
  rdcstr name;
};

struct OpMemberName
{
  OpMemberName(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->type = Id::fromWord(it.word(1));
    this->member = (uint32_t)it.word(2);
    word = 3;
    this->name = DecodeParam<rdcstr>(it, word);
  }
  OpMemberName(Id type, uint32_t member, rdcstr name)
      : op(Op::MemberName)
      , wordCount(MinWordSize + ExtraWordCount(name))
  {
    this->type = type;
    this->member = member;
    this->name = name;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(type.value());
    words.push_back((uint32_t)member);
    EncodeParam(words, name);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::MemberName;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  Id type;
  uint32_t member;
  rdcstr name;
};

struct OpString
{
  OpString(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->result = Id::fromWord(it.word(1));
    word = 2;
    this->string = DecodeParam<rdcstr>(it, word);
  }
  OpString(IdResult result, rdcstr string)
      : op(Op::String)
      , wordCount(MinWordSize + ExtraWordCount(string))
  {
    this->result = result;
    this->string = string;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(result.value());
    EncodeParam(words, string);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::String;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  rdcstr string;
};

struct OpLine
{
  OpLine(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpLine(Id file, uint32_t line, uint32_t column)
      : op(Op::Line)
      , wordCount(FixedWordSize)
  {
    this->file = file;
    this->line = line;
    this->column = column;
  }

  static constexpr Op OpCode = Op::Line;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  Id file;
  uint32_t line;
  uint32_t column;
};

struct OpExtension
{
  OpExtension(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    word = 1;
    this->name = DecodeParam<rdcstr>(it, word);
  }
  OpExtension(rdcstr name)
      : op(Op::Extension)
      , wordCount(MinWordSize + ExtraWordCount(name))
  {
    this->name = name;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    EncodeParam(words, name);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::Extension;
  static constexpr uint16_t MinWordSize = 2U;
  Op op;
  uint16_t wordCount;
  rdcstr name;
};

struct OpExtInstImport
{
  OpExtInstImport(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->result = Id::fromWord(it.word(1));
    word = 2;
    this->name = DecodeParam<rdcstr>(it, word);
  }
  OpExtInstImport(IdResult result, rdcstr name)
      : op(Op::ExtInstImport)
      , wordCount(MinWordSize + ExtraWordCount(name))
  {
    this->result = result;
    this->name = name;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(result.value());
    EncodeParam(words, name);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ExtInstImport;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  rdcstr name;
};

struct OpExtInst; // has operands with variable sizes

struct OpMemoryModel
{
  OpMemoryModel(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpMemoryModel(AddressingModel addressingModel, MemoryModel memoryModel)
      : op(Op::MemoryModel)
      , wordCount(FixedWordSize)
  {
    this->addressingModel = addressingModel;
    this->memoryModel = memoryModel;
  }

  static constexpr Op OpCode = Op::MemoryModel;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  AddressingModel addressingModel;
  MemoryModel memoryModel;
};

struct OpEntryPoint
{
  OpEntryPoint(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->executionModel = (ExecutionModel)it.word(1);
    this->entryPoint = Id::fromWord(it.word(2));
    word = 3;
    this->name = DecodeParam<rdcstr>(it, word);
    this->iface = MultiParam<Id>(it, word);
  }
  OpEntryPoint(ExecutionModel executionModel, Id entryPoint, rdcstr name, const rdcarray<Id> &iface = {})
      : op(Op::EntryPoint)
      , wordCount(MinWordSize + ExtraWordCount(name) + MultiWordCount(iface))
  {
    this->executionModel = executionModel;
    this->entryPoint = entryPoint;
    this->name = name;
    this->iface = iface;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back((uint32_t)executionModel);
    words.push_back(entryPoint.value());
    EncodeParam(words, name);
    for(size_t i=0; i < iface.size(); i++)
    {
      words.push_back(iface[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::EntryPoint;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  ExecutionModel executionModel;
  Id entryPoint;
  rdcstr name;
  rdcarray<Id> iface;
};

struct OpExecutionMode
{
  OpExecutionMode(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->entryPoint = Id::fromWord(it.word(1));
    word = 2;
    this->mode = DecodeParam<ExecutionModeAndParamData>(it, word);
  }
  OpExecutionMode(Id entryPoint, ExecutionModeAndParamData mode)
      : op(Op::ExecutionMode)
      , wordCount(MinWordSize + ExtraWordCount(mode))
  {
    this->entryPoint = entryPoint;
    this->mode = mode;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(entryPoint.value());
    EncodeParam(words, mode);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ExecutionMode;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id entryPoint;
  ExecutionModeAndParamData mode;
};

struct OpCapability
{
  OpCapability(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpCapability(Capability capability)
      : op(Op::Capability)
      , wordCount(FixedWordSize)
  {
    this->capability = capability;
  }

  static constexpr Op OpCode = Op::Capability;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  Capability capability;
};

struct OpTypeVoid
{
  OpTypeVoid(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeVoid(IdResult result)
      : op(Op::TypeVoid)
      , wordCount(FixedWordSize)
  {
    this->result = result;
  }

  static constexpr Op OpCode = Op::TypeVoid;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  IdResult result;
};

struct OpTypeBool
{
  OpTypeBool(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeBool(IdResult result)
      : op(Op::TypeBool)
      , wordCount(FixedWordSize)
  {
    this->result = result;
  }

  static constexpr Op OpCode = Op::TypeBool;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  IdResult result;
};

struct OpTypeInt
{
  OpTypeInt(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeInt(IdResult result, uint32_t width, uint32_t signedness)
      : op(Op::TypeInt)
      , wordCount(FixedWordSize)
  {
    this->result = result;
    this->width = width;
    this->signedness = signedness;
  }

  static constexpr Op OpCode = Op::TypeInt;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  uint32_t width;
  uint32_t signedness;
};

struct OpTypeFloat
{
  OpTypeFloat(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->result = Id::fromWord(it.word(1));
    this->width = (uint32_t)it.word(2);
    this->floatingPointEncoding = (it.size() > 3) ? (FPEncoding)it.word(3) : FPEncoding::Invalid;
  }
  OpTypeFloat(IdResult result, uint32_t width, FPEncoding floatingPointEncoding = FPEncoding::Invalid)
      : op(Op::TypeFloat)
      , wordCount(MinWordSize + OptionalWordCount(floatingPointEncoding))
  {
    this->result = result;
    this->width = width;
    this->floatingPointEncoding = floatingPointEncoding;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(result.value());
    words.push_back((uint32_t)width);
    if(floatingPointEncoding != FPEncoding::Invalid) words.push_back((uint32_t)floatingPointEncoding);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::TypeFloat;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  uint32_t width;
  FPEncoding floatingPointEncoding;

  bool HasFloatingPointEncoding() const { return wordCount > 3; }
};

struct OpTypeVector
{
  OpTypeVector(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeVector(IdResult result, Id componentType, uint32_t componentCount)
      : op(Op::TypeVector)
      , wordCount(FixedWordSize)
  {
    this->result = result;
    this->componentType = componentType;
    this->componentCount = componentCount;
  }

  static constexpr Op OpCode = Op::TypeVector;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  Id componentType;
  uint32_t componentCount;
};

struct OpTypeMatrix
{
  OpTypeMatrix(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeMatrix(IdResult result, Id columnType, uint32_t columnCount)
      : op(Op::TypeMatrix)
      , wordCount(FixedWordSize)
  {
    this->result = result;
    this->columnType = columnType;
    this->columnCount = columnCount;
  }

  static constexpr Op OpCode = Op::TypeMatrix;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  Id columnType;
  uint32_t columnCount;
};

struct OpTypeImage
{
  OpTypeImage(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->result = Id::fromWord(it.word(1));
    this->sampledType = Id::fromWord(it.word(2));
    this->dim = (Dim)it.word(3);
    this->depth = (uint32_t)it.word(4);
    this->arrayed = (uint32_t)it.word(5);
    this->mS = (uint32_t)it.word(6);
    this->sampled = (uint32_t)it.word(7);
    this->imageFormat = (ImageFormat)it.word(8);
    this->accessQualifier = (it.size() > 9) ? (AccessQualifier)it.word(9) : AccessQualifier::Invalid;
  }
  OpTypeImage(IdResult result, Id sampledType, Dim dim, uint32_t depth, uint32_t arrayed, uint32_t mS, uint32_t sampled, ImageFormat imageFormat, AccessQualifier accessQualifier = AccessQualifier::Invalid)
      : op(Op::TypeImage)
      , wordCount(MinWordSize + OptionalWordCount(accessQualifier))
  {
    this->result = result;
    this->sampledType = sampledType;
    this->dim = dim;
    this->depth = depth;
    this->arrayed = arrayed;
    this->mS = mS;
    this->sampled = sampled;
    this->imageFormat = imageFormat;
    this->accessQualifier = accessQualifier;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(result.value());
    words.push_back(sampledType.value());
    words.push_back((uint32_t)dim);
    words.push_back((uint32_t)depth);
    words.push_back((uint32_t)arrayed);
    words.push_back((uint32_t)mS);
    words.push_back((uint32_t)sampled);
    words.push_back((uint32_t)imageFormat);
    if(accessQualifier != AccessQualifier::Invalid) words.push_back((uint32_t)accessQualifier);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::TypeImage;
  static constexpr uint16_t MinWordSize = 9U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  Id sampledType;
  Dim dim;
  uint32_t depth;
  uint32_t arrayed;
  uint32_t mS;
  uint32_t sampled;
  ImageFormat imageFormat;
  AccessQualifier accessQualifier;

  bool HasAccessQualifier() const { return wordCount > 9; }
};

struct OpTypeSampler
{
  OpTypeSampler(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeSampler(IdResult result)
      : op(Op::TypeSampler)
      , wordCount(FixedWordSize)
  {
    this->result = result;
  }

  static constexpr Op OpCode = Op::TypeSampler;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  IdResult result;
};

struct OpTypeSampledImage
{
  OpTypeSampledImage(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeSampledImage(IdResult result, Id imageType)
      : op(Op::TypeSampledImage)
      , wordCount(FixedWordSize)
  {
    this->result = result;
    this->imageType = imageType;
  }

  static constexpr Op OpCode = Op::TypeSampledImage;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  Id imageType;
};

struct OpTypeArray
{
  OpTypeArray(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeArray(IdResult result, Id elementType, Id length)
      : op(Op::TypeArray)
      , wordCount(FixedWordSize)
  {
    this->result = result;
    this->elementType = elementType;
    this->length = length;
  }

  static constexpr Op OpCode = Op::TypeArray;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  Id elementType;
  Id length;
};

struct OpTypeRuntimeArray
{
  OpTypeRuntimeArray(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeRuntimeArray(IdResult result, Id elementType)
      : op(Op::TypeRuntimeArray)
      , wordCount(FixedWordSize)
  {
    this->result = result;
    this->elementType = elementType;
  }

  static constexpr Op OpCode = Op::TypeRuntimeArray;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  Id elementType;
};

struct OpTypeStruct
{
  OpTypeStruct(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->result = Id::fromWord(it.word(1));
    word = 2;
    this->members = MultiParam<Id>(it, word);
  }
  OpTypeStruct(IdResult result, const rdcarray<Id> &members = {})
      : op(Op::TypeStruct)
      , wordCount(MinWordSize + MultiWordCount(members))
  {
    this->result = result;
    this->members = members;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(result.value());
    for(size_t i=0; i < members.size(); i++)
    {
      words.push_back(members[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::TypeStruct;
  static constexpr uint16_t MinWordSize = 2U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  rdcarray<Id> members;
};

struct OpTypeOpaque
{
  OpTypeOpaque(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->result = Id::fromWord(it.word(1));
    word = 2;
    this->thenameoftheopaquetype = DecodeParam<rdcstr>(it, word);
  }
  OpTypeOpaque(IdResult result, rdcstr thenameoftheopaquetype)
      : op(Op::TypeOpaque)
      , wordCount(MinWordSize + ExtraWordCount(thenameoftheopaquetype))
  {
    this->result = result;
    this->thenameoftheopaquetype = thenameoftheopaquetype;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(result.value());
    EncodeParam(words, thenameoftheopaquetype);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::TypeOpaque;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  rdcstr thenameoftheopaquetype;
};

struct OpTypePointer
{
  OpTypePointer(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypePointer(IdResult result, StorageClass storageClass, Id type)
      : op(Op::TypePointer)
      , wordCount(FixedWordSize)
  {
    this->result = result;
    this->storageClass = storageClass;
    this->type = type;
  }

  static constexpr Op OpCode = Op::TypePointer;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  StorageClass storageClass;
  Id type;
};

struct OpTypeFunction
{
  OpTypeFunction(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->result = Id::fromWord(it.word(1));
    this->returnType = Id::fromWord(it.word(2));
    word = 3;
    this->parameters = MultiParam<Id>(it, word);
  }
  OpTypeFunction(IdResult result, Id returnType, const rdcarray<Id> &parameters = {})
      : op(Op::TypeFunction)
      , wordCount(MinWordSize + MultiWordCount(parameters))
  {
    this->result = result;
    this->returnType = returnType;
    this->parameters = parameters;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(result.value());
    words.push_back(returnType.value());
    for(size_t i=0; i < parameters.size(); i++)
    {
      words.push_back(parameters[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::TypeFunction;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  Id returnType;
  rdcarray<Id> parameters;
};

struct OpTypeEvent
{
  OpTypeEvent(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeEvent(IdResult result)
      : op(Op::TypeEvent)
      , wordCount(FixedWordSize)
  {
    this->result = result;
  }

  static constexpr Op OpCode = Op::TypeEvent;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  IdResult result;
};

struct OpTypeDeviceEvent
{
  OpTypeDeviceEvent(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeDeviceEvent(IdResult result)
      : op(Op::TypeDeviceEvent)
      , wordCount(FixedWordSize)
  {
    this->result = result;
  }

  static constexpr Op OpCode = Op::TypeDeviceEvent;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  IdResult result;
};

struct OpTypeReserveId
{
  OpTypeReserveId(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeReserveId(IdResult result)
      : op(Op::TypeReserveId)
      , wordCount(FixedWordSize)
  {
    this->result = result;
  }

  static constexpr Op OpCode = Op::TypeReserveId;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  IdResult result;
};

struct OpTypeQueue
{
  OpTypeQueue(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeQueue(IdResult result)
      : op(Op::TypeQueue)
      , wordCount(FixedWordSize)
  {
    this->result = result;
  }

  static constexpr Op OpCode = Op::TypeQueue;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  IdResult result;
};

struct OpTypePipe
{
  OpTypePipe(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypePipe(IdResult result, AccessQualifier qualifier)
      : op(Op::TypePipe)
      , wordCount(FixedWordSize)
  {
    this->result = result;
    this->qualifier = qualifier;
  }

  static constexpr Op OpCode = Op::TypePipe;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  AccessQualifier qualifier;
};

struct OpTypeForwardPointer
{
  OpTypeForwardPointer(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeForwardPointer(Id pointerType, StorageClass storageClass)
      : op(Op::TypeForwardPointer)
      , wordCount(FixedWordSize)
  {
    this->pointerType = pointerType;
    this->storageClass = storageClass;
  }

  static constexpr Op OpCode = Op::TypeForwardPointer;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id pointerType;
  StorageClass storageClass;
};

struct OpConstantTrue
{
  OpConstantTrue(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConstantTrue(IdResultType resultType, IdResult result)
      : op(Op::ConstantTrue)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
  }

  static constexpr Op OpCode = Op::ConstantTrue;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
};

struct OpConstantFalse
{
  OpConstantFalse(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConstantFalse(IdResultType resultType, IdResult result)
      : op(Op::ConstantFalse)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
  }

  static constexpr Op OpCode = Op::ConstantFalse;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
};

struct OpConstant; // has operands with variable sizes

struct OpConstantComposite
{
  OpConstantComposite(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    word = 3;
    this->constituents = MultiParam<Id>(it, word);
  }
  OpConstantComposite(IdResultType resultType, IdResult result, const rdcarray<Id> &constituents = {})
      : op(Op::ConstantComposite)
      , wordCount(MinWordSize + MultiWordCount(constituents))
  {
    this->resultType = resultType;
    this->result = result;
    this->constituents = constituents;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    for(size_t i=0; i < constituents.size(); i++)
    {
      words.push_back(constituents[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ConstantComposite;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  rdcarray<Id> constituents;
};

struct OpConstantSampler
{
  OpConstantSampler(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConstantSampler(IdResultType resultType, IdResult result, SamplerAddressingMode samplerAddressingMode, uint32_t param, SamplerFilterMode samplerFilterMode)
      : op(Op::ConstantSampler)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->samplerAddressingMode = samplerAddressingMode;
    this->param = param;
    this->samplerFilterMode = samplerFilterMode;
  }

  static constexpr Op OpCode = Op::ConstantSampler;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  SamplerAddressingMode samplerAddressingMode;
  uint32_t param;
  SamplerFilterMode samplerFilterMode;
};

struct OpConstantNull
{
  OpConstantNull(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConstantNull(IdResultType resultType, IdResult result)
      : op(Op::ConstantNull)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
  }

  static constexpr Op OpCode = Op::ConstantNull;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
};

struct OpSpecConstantTrue
{
  OpSpecConstantTrue(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSpecConstantTrue(IdResultType resultType, IdResult result)
      : op(Op::SpecConstantTrue)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
  }

  static constexpr Op OpCode = Op::SpecConstantTrue;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
};

struct OpSpecConstantFalse
{
  OpSpecConstantFalse(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSpecConstantFalse(IdResultType resultType, IdResult result)
      : op(Op::SpecConstantFalse)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
  }

  static constexpr Op OpCode = Op::SpecConstantFalse;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
};

struct OpSpecConstant; // has operands with variable sizes

struct OpSpecConstantComposite
{
  OpSpecConstantComposite(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    word = 3;
    this->constituents = MultiParam<Id>(it, word);
  }
  OpSpecConstantComposite(IdResultType resultType, IdResult result, const rdcarray<Id> &constituents = {})
      : op(Op::SpecConstantComposite)
      , wordCount(MinWordSize + MultiWordCount(constituents))
  {
    this->resultType = resultType;
    this->result = result;
    this->constituents = constituents;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    for(size_t i=0; i < constituents.size(); i++)
    {
      words.push_back(constituents[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::SpecConstantComposite;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  rdcarray<Id> constituents;
};

struct OpSpecConstantOp; // has operands with variable sizes

struct OpFunction
{
  OpFunction(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFunction(IdResultType resultType, IdResult result, FunctionControl functionControl, Id functionType)
      : op(Op::Function)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->functionControl = functionControl;
    this->functionType = functionType;
  }

  static constexpr Op OpCode = Op::Function;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  FunctionControl functionControl;
  Id functionType;
};

struct OpFunctionParameter
{
  OpFunctionParameter(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFunctionParameter(IdResultType resultType, IdResult result)
      : op(Op::FunctionParameter)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
  }

  static constexpr Op OpCode = Op::FunctionParameter;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
};

struct OpFunctionEnd
{
  OpFunctionEnd(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFunctionEnd()
      : op(Op::FunctionEnd)
      , wordCount(FixedWordSize)
  {
    // no operands
  }

  static constexpr Op OpCode = Op::FunctionEnd;
  static constexpr uint16_t FixedWordSize = 1U;
  Op op;
  uint16_t wordCount;
  // no operands
};

struct OpFunctionCall
{
  OpFunctionCall(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->function = Id::fromWord(it.word(3));
    word = 4;
    this->arguments = MultiParam<Id>(it, word);
  }
  OpFunctionCall(IdResultType resultType, IdResult result, Id function, const rdcarray<Id> &arguments = {})
      : op(Op::FunctionCall)
      , wordCount(MinWordSize + MultiWordCount(arguments))
  {
    this->resultType = resultType;
    this->result = result;
    this->function = function;
    this->arguments = arguments;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(function.value());
    for(size_t i=0; i < arguments.size(); i++)
    {
      words.push_back(arguments[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::FunctionCall;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id function;
  rdcarray<Id> arguments;
};

struct OpVariable
{
  OpVariable(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->storageClass = (StorageClass)it.word(3);
    this->initializer = (it.size() > 4) ? Id::fromWord(it.word(4)) : Id();
  }
  OpVariable(IdResultType resultType, IdResult result, StorageClass storageClass, Id initializer = Id())
      : op(Op::Variable)
      , wordCount(MinWordSize + OptionalWordCount(initializer))
  {
    this->resultType = resultType;
    this->result = result;
    this->storageClass = storageClass;
    this->initializer = initializer;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back((uint32_t)storageClass);
    if(initializer != Id()) words.push_back(initializer.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::Variable;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  StorageClass storageClass;
  Id initializer;

  bool HasInitializer() const { return wordCount > 4; }
};

struct OpImageTexelPointer
{
  OpImageTexelPointer(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpImageTexelPointer(IdResultType resultType, IdResult result, Id image, Id coordinate, Id sample)
      : op(Op::ImageTexelPointer)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->image = image;
    this->coordinate = coordinate;
    this->sample = sample;
  }

  static constexpr Op OpCode = Op::ImageTexelPointer;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id image;
  Id coordinate;
  Id sample;
};

struct OpLoad
{
  OpLoad(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->pointer = Id::fromWord(it.word(3));
    word = 4;
    this->memoryAccess = DecodeParam<MemoryAccessAndParamDatas>(it, word);
  }
  OpLoad(IdResultType resultType, IdResult result, Id pointer, MemoryAccessAndParamDatas memoryAccess = MemoryAccess::None)
      : op(Op::Load)
      , wordCount(MinWordSize + ExtraWordCount(memoryAccess))
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memoryAccess = memoryAccess;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(pointer.value());
    EncodeParam(words, memoryAccess);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::Load;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  MemoryAccessAndParamDatas memoryAccess;
};

struct OpStore
{
  OpStore(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->pointer = Id::fromWord(it.word(1));
    this->object = Id::fromWord(it.word(2));
    word = 3;
    this->memoryAccess = DecodeParam<MemoryAccessAndParamDatas>(it, word);
  }
  OpStore(Id pointer, Id object, MemoryAccessAndParamDatas memoryAccess = MemoryAccess::None)
      : op(Op::Store)
      , wordCount(MinWordSize + ExtraWordCount(memoryAccess))
  {
    this->pointer = pointer;
    this->object = object;
    this->memoryAccess = memoryAccess;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(pointer.value());
    words.push_back(object.value());
    EncodeParam(words, memoryAccess);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::Store;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id pointer;
  Id object;
  MemoryAccessAndParamDatas memoryAccess;
};

struct OpCopyMemory
{
  OpCopyMemory(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->target = Id::fromWord(it.word(1));
    this->source = Id::fromWord(it.word(2));
    word = 3;
    this->memoryAccess0 = DecodeParam<MemoryAccessAndParamDatas>(it, word);
    this->memoryAccess1 = DecodeParam<MemoryAccessAndParamDatas>(it, word);
  }
  OpCopyMemory(Id target, Id source, MemoryAccessAndParamDatas memoryAccess0 = MemoryAccess::None, MemoryAccessAndParamDatas memoryAccess1 = MemoryAccess::None)
      : op(Op::CopyMemory)
      , wordCount(MinWordSize + ExtraWordCount(memoryAccess0) + ExtraWordCount(memoryAccess1))
  {
    this->target = target;
    this->source = source;
    this->memoryAccess0 = memoryAccess0;
    this->memoryAccess1 = memoryAccess1;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(target.value());
    words.push_back(source.value());
    EncodeParam(words, memoryAccess0);
    EncodeParam(words, memoryAccess1);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::CopyMemory;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id target;
  Id source;
  MemoryAccessAndParamDatas memoryAccess0;
  MemoryAccessAndParamDatas memoryAccess1;
};

struct OpCopyMemorySized
{
  OpCopyMemorySized(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->target = Id::fromWord(it.word(1));
    this->source = Id::fromWord(it.word(2));
    this->size = Id::fromWord(it.word(3));
    word = 4;
    this->memoryAccess0 = DecodeParam<MemoryAccessAndParamDatas>(it, word);
    this->memoryAccess1 = DecodeParam<MemoryAccessAndParamDatas>(it, word);
  }
  OpCopyMemorySized(Id target, Id source, Id size, MemoryAccessAndParamDatas memoryAccess0 = MemoryAccess::None, MemoryAccessAndParamDatas memoryAccess1 = MemoryAccess::None)
      : op(Op::CopyMemorySized)
      , wordCount(MinWordSize + ExtraWordCount(memoryAccess0) + ExtraWordCount(memoryAccess1))
  {
    this->target = target;
    this->source = source;
    this->size = size;
    this->memoryAccess0 = memoryAccess0;
    this->memoryAccess1 = memoryAccess1;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(target.value());
    words.push_back(source.value());
    words.push_back(size.value());
    EncodeParam(words, memoryAccess0);
    EncodeParam(words, memoryAccess1);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::CopyMemorySized;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  Id target;
  Id source;
  Id size;
  MemoryAccessAndParamDatas memoryAccess0;
  MemoryAccessAndParamDatas memoryAccess1;
};

struct OpAccessChain
{
  OpAccessChain(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->base = Id::fromWord(it.word(3));
    word = 4;
    this->indexes = MultiParam<Id>(it, word);
  }
  OpAccessChain(IdResultType resultType, IdResult result, Id base, const rdcarray<Id> &indexes = {})
      : op(Op::AccessChain)
      , wordCount(MinWordSize + MultiWordCount(indexes))
  {
    this->resultType = resultType;
    this->result = result;
    this->base = base;
    this->indexes = indexes;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(base.value());
    for(size_t i=0; i < indexes.size(); i++)
    {
      words.push_back(indexes[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::AccessChain;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id base;
  rdcarray<Id> indexes;
};

struct OpInBoundsAccessChain
{
  OpInBoundsAccessChain(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->base = Id::fromWord(it.word(3));
    word = 4;
    this->indexes = MultiParam<Id>(it, word);
  }
  OpInBoundsAccessChain(IdResultType resultType, IdResult result, Id base, const rdcarray<Id> &indexes = {})
      : op(Op::InBoundsAccessChain)
      , wordCount(MinWordSize + MultiWordCount(indexes))
  {
    this->resultType = resultType;
    this->result = result;
    this->base = base;
    this->indexes = indexes;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(base.value());
    for(size_t i=0; i < indexes.size(); i++)
    {
      words.push_back(indexes[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::InBoundsAccessChain;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id base;
  rdcarray<Id> indexes;
};

struct OpPtrAccessChain
{
  OpPtrAccessChain(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->base = Id::fromWord(it.word(3));
    this->element = Id::fromWord(it.word(4));
    word = 5;
    this->indexes = MultiParam<Id>(it, word);
  }
  OpPtrAccessChain(IdResultType resultType, IdResult result, Id base, Id element, const rdcarray<Id> &indexes = {})
      : op(Op::PtrAccessChain)
      , wordCount(MinWordSize + MultiWordCount(indexes))
  {
    this->resultType = resultType;
    this->result = result;
    this->base = base;
    this->element = element;
    this->indexes = indexes;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(base.value());
    words.push_back(element.value());
    for(size_t i=0; i < indexes.size(); i++)
    {
      words.push_back(indexes[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::PtrAccessChain;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id base;
  Id element;
  rdcarray<Id> indexes;
};

struct OpArrayLength
{
  OpArrayLength(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpArrayLength(IdResultType resultType, IdResult result, Id structure, uint32_t arraymember)
      : op(Op::ArrayLength)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->structure = structure;
    this->arraymember = arraymember;
  }

  static constexpr Op OpCode = Op::ArrayLength;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id structure;
  uint32_t arraymember;
};

struct OpGenericPtrMemSemantics
{
  OpGenericPtrMemSemantics(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGenericPtrMemSemantics(IdResultType resultType, IdResult result, Id pointer)
      : op(Op::GenericPtrMemSemantics)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
  }

  static constexpr Op OpCode = Op::GenericPtrMemSemantics;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
};

struct OpInBoundsPtrAccessChain
{
  OpInBoundsPtrAccessChain(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->base = Id::fromWord(it.word(3));
    this->element = Id::fromWord(it.word(4));
    word = 5;
    this->indexes = MultiParam<Id>(it, word);
  }
  OpInBoundsPtrAccessChain(IdResultType resultType, IdResult result, Id base, Id element, const rdcarray<Id> &indexes = {})
      : op(Op::InBoundsPtrAccessChain)
      , wordCount(MinWordSize + MultiWordCount(indexes))
  {
    this->resultType = resultType;
    this->result = result;
    this->base = base;
    this->element = element;
    this->indexes = indexes;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(base.value());
    words.push_back(element.value());
    for(size_t i=0; i < indexes.size(); i++)
    {
      words.push_back(indexes[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::InBoundsPtrAccessChain;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id base;
  Id element;
  rdcarray<Id> indexes;
};

struct OpDecorate
{
  OpDecorate(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->target = Id::fromWord(it.word(1));
    word = 2;
    this->decoration = DecodeParam<DecorationAndParamData>(it, word);
  }
  OpDecorate(Id target, DecorationAndParamData decoration)
      : op(Op::Decorate)
      , wordCount(MinWordSize + ExtraWordCount(decoration))
  {
    this->target = target;
    this->decoration = decoration;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(target.value());
    EncodeParam(words, decoration);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::Decorate;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id target;
  DecorationAndParamData decoration;
};

struct OpMemberDecorate
{
  OpMemberDecorate(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->structureType = Id::fromWord(it.word(1));
    this->member = (uint32_t)it.word(2);
    word = 3;
    this->decoration = DecodeParam<DecorationAndParamData>(it, word);
  }
  OpMemberDecorate(Id structureType, uint32_t member, DecorationAndParamData decoration)
      : op(Op::MemberDecorate)
      , wordCount(MinWordSize + ExtraWordCount(decoration))
  {
    this->structureType = structureType;
    this->member = member;
    this->decoration = decoration;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(structureType.value());
    words.push_back((uint32_t)member);
    EncodeParam(words, decoration);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::MemberDecorate;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  Id structureType;
  uint32_t member;
  DecorationAndParamData decoration;
};

struct OpDecorationGroup
{
  OpDecorationGroup(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpDecorationGroup(IdResult result)
      : op(Op::DecorationGroup)
      , wordCount(FixedWordSize)
  {
    this->result = result;
  }

  static constexpr Op OpCode = Op::DecorationGroup;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  IdResult result;
};

struct OpGroupDecorate
{
  OpGroupDecorate(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->decorationGroup = Id::fromWord(it.word(1));
    word = 2;
    this->targets = MultiParam<Id>(it, word);
  }
  OpGroupDecorate(Id decorationGroup, const rdcarray<Id> &targets = {})
      : op(Op::GroupDecorate)
      , wordCount(MinWordSize + MultiWordCount(targets))
  {
    this->decorationGroup = decorationGroup;
    this->targets = targets;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(decorationGroup.value());
    for(size_t i=0; i < targets.size(); i++)
    {
      words.push_back(targets[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GroupDecorate;
  static constexpr uint16_t MinWordSize = 2U;
  Op op;
  uint16_t wordCount;
  Id decorationGroup;
  rdcarray<Id> targets;
};

struct OpGroupMemberDecorate
{
  OpGroupMemberDecorate(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->decorationGroup = Id::fromWord(it.word(1));
    word = 2;
    this->targets = MultiParam<PairIdRefLiteralInteger>(it, word);
  }
  OpGroupMemberDecorate(Id decorationGroup, const rdcarray<PairIdRefLiteralInteger> &targets = {})
      : op(Op::GroupMemberDecorate)
      , wordCount(MinWordSize + MultiWordCount(targets))
  {
    this->decorationGroup = decorationGroup;
    this->targets = targets;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(decorationGroup.value());
    for(size_t i=0; i < targets.size(); i++)
    {
      words.push_back(targets[i].first.value()); words.push_back((uint32_t)targets[i].second);
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GroupMemberDecorate;
  static constexpr uint16_t MinWordSize = 2U;
  Op op;
  uint16_t wordCount;
  Id decorationGroup;
  rdcarray<PairIdRefLiteralInteger> targets;
};

struct OpVectorExtractDynamic
{
  OpVectorExtractDynamic(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpVectorExtractDynamic(IdResultType resultType, IdResult result, Id vector, Id index)
      : op(Op::VectorExtractDynamic)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->vector = vector;
    this->index = index;
  }

  static constexpr Op OpCode = Op::VectorExtractDynamic;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id vector;
  Id index;
};

struct OpVectorInsertDynamic
{
  OpVectorInsertDynamic(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpVectorInsertDynamic(IdResultType resultType, IdResult result, Id vector, Id component, Id index)
      : op(Op::VectorInsertDynamic)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->vector = vector;
    this->component = component;
    this->index = index;
  }

  static constexpr Op OpCode = Op::VectorInsertDynamic;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id vector;
  Id component;
  Id index;
};

struct OpVectorShuffle
{
  OpVectorShuffle(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->vector1 = Id::fromWord(it.word(3));
    this->vector2 = Id::fromWord(it.word(4));
    word = 5;
    this->components = MultiParam<uint32_t>(it, word);
  }
  OpVectorShuffle(IdResultType resultType, IdResult result, Id vector1, Id vector2, const rdcarray<uint32_t> &components = {})
      : op(Op::VectorShuffle)
      , wordCount(MinWordSize + MultiWordCount(components))
  {
    this->resultType = resultType;
    this->result = result;
    this->vector1 = vector1;
    this->vector2 = vector2;
    this->components = components;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(vector1.value());
    words.push_back(vector2.value());
    for(size_t i=0; i < components.size(); i++)
    {
      words.push_back((uint32_t)components[i]);
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::VectorShuffle;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id vector1;
  Id vector2;
  rdcarray<uint32_t> components;
};

struct OpCompositeConstruct
{
  OpCompositeConstruct(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    word = 3;
    this->constituents = MultiParam<Id>(it, word);
  }
  OpCompositeConstruct(IdResultType resultType, IdResult result, const rdcarray<Id> &constituents = {})
      : op(Op::CompositeConstruct)
      , wordCount(MinWordSize + MultiWordCount(constituents))
  {
    this->resultType = resultType;
    this->result = result;
    this->constituents = constituents;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    for(size_t i=0; i < constituents.size(); i++)
    {
      words.push_back(constituents[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::CompositeConstruct;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  rdcarray<Id> constituents;
};

struct OpCompositeExtract
{
  OpCompositeExtract(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->composite = Id::fromWord(it.word(3));
    word = 4;
    this->indexes = MultiParam<uint32_t>(it, word);
  }
  OpCompositeExtract(IdResultType resultType, IdResult result, Id composite, const rdcarray<uint32_t> &indexes = {})
      : op(Op::CompositeExtract)
      , wordCount(MinWordSize + MultiWordCount(indexes))
  {
    this->resultType = resultType;
    this->result = result;
    this->composite = composite;
    this->indexes = indexes;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(composite.value());
    for(size_t i=0; i < indexes.size(); i++)
    {
      words.push_back((uint32_t)indexes[i]);
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::CompositeExtract;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id composite;
  rdcarray<uint32_t> indexes;
};

struct OpCompositeInsert
{
  OpCompositeInsert(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->object = Id::fromWord(it.word(3));
    this->composite = Id::fromWord(it.word(4));
    word = 5;
    this->indexes = MultiParam<uint32_t>(it, word);
  }
  OpCompositeInsert(IdResultType resultType, IdResult result, Id object, Id composite, const rdcarray<uint32_t> &indexes = {})
      : op(Op::CompositeInsert)
      , wordCount(MinWordSize + MultiWordCount(indexes))
  {
    this->resultType = resultType;
    this->result = result;
    this->object = object;
    this->composite = composite;
    this->indexes = indexes;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(object.value());
    words.push_back(composite.value());
    for(size_t i=0; i < indexes.size(); i++)
    {
      words.push_back((uint32_t)indexes[i]);
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::CompositeInsert;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id object;
  Id composite;
  rdcarray<uint32_t> indexes;
};

struct OpCopyObject
{
  OpCopyObject(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpCopyObject(IdResultType resultType, IdResult result, Id operand)
      : op(Op::CopyObject)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand = operand;
  }

  static constexpr Op OpCode = Op::CopyObject;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand;
};

struct OpTranspose
{
  OpTranspose(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTranspose(IdResultType resultType, IdResult result, Id matrix)
      : op(Op::Transpose)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->matrix = matrix;
  }

  static constexpr Op OpCode = Op::Transpose;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id matrix;
};

struct OpSampledImage
{
  OpSampledImage(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSampledImage(IdResultType resultType, IdResult result, Id image, Id sampler)
      : op(Op::SampledImage)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->image = image;
    this->sampler = sampler;
  }

  static constexpr Op OpCode = Op::SampledImage;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id image;
  Id sampler;
};

struct OpImageSampleImplicitLod
{
  OpImageSampleImplicitLod(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    word = 5;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSampleImplicitLod(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, ImageOperandsAndParamDatas imageOperands = ImageOperands::None)
      : op(Op::ImageSampleImplicitLod)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSampleImplicitLod;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageSampleExplicitLod
{
  OpImageSampleExplicitLod(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    word = 5;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSampleExplicitLod(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, ImageOperandsAndParamDatas imageOperands)
      : op(Op::ImageSampleExplicitLod)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSampleExplicitLod;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageSampleDrefImplicitLod
{
  OpImageSampleDrefImplicitLod(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    this->dref = Id::fromWord(it.word(5));
    word = 6;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSampleDrefImplicitLod(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, Id dref, ImageOperandsAndParamDatas imageOperands = ImageOperands::None)
      : op(Op::ImageSampleDrefImplicitLod)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->dref = dref;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    words.push_back(dref.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSampleDrefImplicitLod;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  Id dref;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageSampleDrefExplicitLod
{
  OpImageSampleDrefExplicitLod(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    this->dref = Id::fromWord(it.word(5));
    word = 6;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSampleDrefExplicitLod(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, Id dref, ImageOperandsAndParamDatas imageOperands)
      : op(Op::ImageSampleDrefExplicitLod)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->dref = dref;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    words.push_back(dref.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSampleDrefExplicitLod;
  static constexpr uint16_t MinWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  Id dref;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageSampleProjImplicitLod
{
  OpImageSampleProjImplicitLod(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    word = 5;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSampleProjImplicitLod(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, ImageOperandsAndParamDatas imageOperands = ImageOperands::None)
      : op(Op::ImageSampleProjImplicitLod)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSampleProjImplicitLod;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageSampleProjExplicitLod
{
  OpImageSampleProjExplicitLod(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    word = 5;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSampleProjExplicitLod(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, ImageOperandsAndParamDatas imageOperands)
      : op(Op::ImageSampleProjExplicitLod)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSampleProjExplicitLod;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageSampleProjDrefImplicitLod
{
  OpImageSampleProjDrefImplicitLod(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    this->dref = Id::fromWord(it.word(5));
    word = 6;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSampleProjDrefImplicitLod(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, Id dref, ImageOperandsAndParamDatas imageOperands = ImageOperands::None)
      : op(Op::ImageSampleProjDrefImplicitLod)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->dref = dref;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    words.push_back(dref.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSampleProjDrefImplicitLod;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  Id dref;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageSampleProjDrefExplicitLod
{
  OpImageSampleProjDrefExplicitLod(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    this->dref = Id::fromWord(it.word(5));
    word = 6;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSampleProjDrefExplicitLod(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, Id dref, ImageOperandsAndParamDatas imageOperands)
      : op(Op::ImageSampleProjDrefExplicitLod)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->dref = dref;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    words.push_back(dref.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSampleProjDrefExplicitLod;
  static constexpr uint16_t MinWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  Id dref;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageFetch
{
  OpImageFetch(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->image = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    word = 5;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageFetch(IdResultType resultType, IdResult result, Id image, Id coordinate, ImageOperandsAndParamDatas imageOperands = ImageOperands::None)
      : op(Op::ImageFetch)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->image = image;
    this->coordinate = coordinate;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(image.value());
    words.push_back(coordinate.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageFetch;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id image;
  Id coordinate;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageGather
{
  OpImageGather(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    this->component = Id::fromWord(it.word(5));
    word = 6;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageGather(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, Id component, ImageOperandsAndParamDatas imageOperands = ImageOperands::None)
      : op(Op::ImageGather)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->component = component;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    words.push_back(component.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageGather;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  Id component;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageDrefGather
{
  OpImageDrefGather(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    this->dref = Id::fromWord(it.word(5));
    word = 6;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageDrefGather(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, Id dref, ImageOperandsAndParamDatas imageOperands = ImageOperands::None)
      : op(Op::ImageDrefGather)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->dref = dref;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    words.push_back(dref.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageDrefGather;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  Id dref;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageRead
{
  OpImageRead(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->image = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    word = 5;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageRead(IdResultType resultType, IdResult result, Id image, Id coordinate, ImageOperandsAndParamDatas imageOperands = ImageOperands::None)
      : op(Op::ImageRead)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->image = image;
    this->coordinate = coordinate;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(image.value());
    words.push_back(coordinate.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageRead;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id image;
  Id coordinate;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageWrite
{
  OpImageWrite(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->image = Id::fromWord(it.word(1));
    this->coordinate = Id::fromWord(it.word(2));
    this->texel = Id::fromWord(it.word(3));
    word = 4;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageWrite(Id image, Id coordinate, Id texel, ImageOperandsAndParamDatas imageOperands = ImageOperands::None)
      : op(Op::ImageWrite)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->image = image;
    this->coordinate = coordinate;
    this->texel = texel;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(image.value());
    words.push_back(coordinate.value());
    words.push_back(texel.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageWrite;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  Id image;
  Id coordinate;
  Id texel;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImage
{
  OpImage(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpImage(IdResultType resultType, IdResult result, Id sampledImage)
      : op(Op::Image)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
  }

  static constexpr Op OpCode = Op::Image;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
};

struct OpImageQueryFormat
{
  OpImageQueryFormat(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpImageQueryFormat(IdResultType resultType, IdResult result, Id image)
      : op(Op::ImageQueryFormat)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->image = image;
  }

  static constexpr Op OpCode = Op::ImageQueryFormat;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id image;
};

struct OpImageQueryOrder
{
  OpImageQueryOrder(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpImageQueryOrder(IdResultType resultType, IdResult result, Id image)
      : op(Op::ImageQueryOrder)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->image = image;
  }

  static constexpr Op OpCode = Op::ImageQueryOrder;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id image;
};

struct OpImageQuerySizeLod
{
  OpImageQuerySizeLod(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpImageQuerySizeLod(IdResultType resultType, IdResult result, Id image, Id levelofDetail)
      : op(Op::ImageQuerySizeLod)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->image = image;
    this->levelofDetail = levelofDetail;
  }

  static constexpr Op OpCode = Op::ImageQuerySizeLod;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id image;
  Id levelofDetail;
};

struct OpImageQuerySize
{
  OpImageQuerySize(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpImageQuerySize(IdResultType resultType, IdResult result, Id image)
      : op(Op::ImageQuerySize)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->image = image;
  }

  static constexpr Op OpCode = Op::ImageQuerySize;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id image;
};

struct OpImageQueryLod
{
  OpImageQueryLod(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpImageQueryLod(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate)
      : op(Op::ImageQueryLod)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
  }

  static constexpr Op OpCode = Op::ImageQueryLod;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
};

struct OpImageQueryLevels
{
  OpImageQueryLevels(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpImageQueryLevels(IdResultType resultType, IdResult result, Id image)
      : op(Op::ImageQueryLevels)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->image = image;
  }

  static constexpr Op OpCode = Op::ImageQueryLevels;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id image;
};

struct OpImageQuerySamples
{
  OpImageQuerySamples(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpImageQuerySamples(IdResultType resultType, IdResult result, Id image)
      : op(Op::ImageQuerySamples)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->image = image;
  }

  static constexpr Op OpCode = Op::ImageQuerySamples;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id image;
};

struct OpConvertFToU
{
  OpConvertFToU(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConvertFToU(IdResultType resultType, IdResult result, Id floatValue)
      : op(Op::ConvertFToU)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->floatValue = floatValue;
  }

  static constexpr Op OpCode = Op::ConvertFToU;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id floatValue;
};

struct OpConvertFToS
{
  OpConvertFToS(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConvertFToS(IdResultType resultType, IdResult result, Id floatValue)
      : op(Op::ConvertFToS)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->floatValue = floatValue;
  }

  static constexpr Op OpCode = Op::ConvertFToS;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id floatValue;
};

struct OpConvertSToF
{
  OpConvertSToF(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConvertSToF(IdResultType resultType, IdResult result, Id signedValue)
      : op(Op::ConvertSToF)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->signedValue = signedValue;
  }

  static constexpr Op OpCode = Op::ConvertSToF;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id signedValue;
};

struct OpConvertUToF
{
  OpConvertUToF(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConvertUToF(IdResultType resultType, IdResult result, Id unsignedValue)
      : op(Op::ConvertUToF)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->unsignedValue = unsignedValue;
  }

  static constexpr Op OpCode = Op::ConvertUToF;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id unsignedValue;
};

struct OpUConvert
{
  OpUConvert(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpUConvert(IdResultType resultType, IdResult result, Id unsignedValue)
      : op(Op::UConvert)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->unsignedValue = unsignedValue;
  }

  static constexpr Op OpCode = Op::UConvert;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id unsignedValue;
};

struct OpSConvert
{
  OpSConvert(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSConvert(IdResultType resultType, IdResult result, Id signedValue)
      : op(Op::SConvert)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->signedValue = signedValue;
  }

  static constexpr Op OpCode = Op::SConvert;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id signedValue;
};

struct OpFConvert
{
  OpFConvert(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFConvert(IdResultType resultType, IdResult result, Id floatValue)
      : op(Op::FConvert)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->floatValue = floatValue;
  }

  static constexpr Op OpCode = Op::FConvert;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id floatValue;
};

struct OpQuantizeToF16
{
  OpQuantizeToF16(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpQuantizeToF16(IdResultType resultType, IdResult result, Id value)
      : op(Op::QuantizeToF16)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->value = value;
  }

  static constexpr Op OpCode = Op::QuantizeToF16;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id value;
};

struct OpConvertPtrToU
{
  OpConvertPtrToU(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConvertPtrToU(IdResultType resultType, IdResult result, Id pointer)
      : op(Op::ConvertPtrToU)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
  }

  static constexpr Op OpCode = Op::ConvertPtrToU;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
};

struct OpSatConvertSToU
{
  OpSatConvertSToU(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSatConvertSToU(IdResultType resultType, IdResult result, Id signedValue)
      : op(Op::SatConvertSToU)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->signedValue = signedValue;
  }

  static constexpr Op OpCode = Op::SatConvertSToU;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id signedValue;
};

struct OpSatConvertUToS
{
  OpSatConvertUToS(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSatConvertUToS(IdResultType resultType, IdResult result, Id unsignedValue)
      : op(Op::SatConvertUToS)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->unsignedValue = unsignedValue;
  }

  static constexpr Op OpCode = Op::SatConvertUToS;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id unsignedValue;
};

struct OpConvertUToPtr
{
  OpConvertUToPtr(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConvertUToPtr(IdResultType resultType, IdResult result, Id integerValue)
      : op(Op::ConvertUToPtr)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->integerValue = integerValue;
  }

  static constexpr Op OpCode = Op::ConvertUToPtr;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id integerValue;
};

struct OpPtrCastToGeneric
{
  OpPtrCastToGeneric(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpPtrCastToGeneric(IdResultType resultType, IdResult result, Id pointer)
      : op(Op::PtrCastToGeneric)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
  }

  static constexpr Op OpCode = Op::PtrCastToGeneric;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
};

struct OpGenericCastToPtr
{
  OpGenericCastToPtr(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGenericCastToPtr(IdResultType resultType, IdResult result, Id pointer)
      : op(Op::GenericCastToPtr)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
  }

  static constexpr Op OpCode = Op::GenericCastToPtr;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
};

struct OpGenericCastToPtrExplicit
{
  OpGenericCastToPtrExplicit(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGenericCastToPtrExplicit(IdResultType resultType, IdResult result, Id pointer, StorageClass storage)
      : op(Op::GenericCastToPtrExplicit)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->storage = storage;
  }

  static constexpr Op OpCode = Op::GenericCastToPtrExplicit;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  StorageClass storage;
};

struct OpBitcast
{
  OpBitcast(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpBitcast(IdResultType resultType, IdResult result, Id operand)
      : op(Op::Bitcast)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand = operand;
  }

  static constexpr Op OpCode = Op::Bitcast;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand;
};

struct OpSNegate
{
  OpSNegate(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSNegate(IdResultType resultType, IdResult result, Id operand)
      : op(Op::SNegate)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand = operand;
  }

  static constexpr Op OpCode = Op::SNegate;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand;
};

struct OpFNegate
{
  OpFNegate(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFNegate(IdResultType resultType, IdResult result, Id operand)
      : op(Op::FNegate)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand = operand;
  }

  static constexpr Op OpCode = Op::FNegate;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand;
};

struct OpIAdd
{
  OpIAdd(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpIAdd(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::IAdd)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::IAdd;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpFAdd
{
  OpFAdd(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFAdd(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::FAdd)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::FAdd;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpISub
{
  OpISub(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpISub(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::ISub)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::ISub;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpFSub
{
  OpFSub(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFSub(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::FSub)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::FSub;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpIMul
{
  OpIMul(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpIMul(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::IMul)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::IMul;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpFMul
{
  OpFMul(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFMul(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::FMul)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::FMul;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpUDiv
{
  OpUDiv(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpUDiv(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::UDiv)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::UDiv;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpSDiv
{
  OpSDiv(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSDiv(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::SDiv)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::SDiv;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpFDiv
{
  OpFDiv(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFDiv(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::FDiv)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::FDiv;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpUMod
{
  OpUMod(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpUMod(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::UMod)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::UMod;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpSRem
{
  OpSRem(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSRem(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::SRem)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::SRem;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpSMod
{
  OpSMod(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSMod(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::SMod)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::SMod;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpFRem
{
  OpFRem(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFRem(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::FRem)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::FRem;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpFMod
{
  OpFMod(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFMod(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::FMod)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::FMod;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpVectorTimesScalar
{
  OpVectorTimesScalar(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpVectorTimesScalar(IdResultType resultType, IdResult result, Id vector, Id scalar)
      : op(Op::VectorTimesScalar)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->vector = vector;
    this->scalar = scalar;
  }

  static constexpr Op OpCode = Op::VectorTimesScalar;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id vector;
  Id scalar;
};

struct OpMatrixTimesScalar
{
  OpMatrixTimesScalar(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpMatrixTimesScalar(IdResultType resultType, IdResult result, Id matrix, Id scalar)
      : op(Op::MatrixTimesScalar)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->matrix = matrix;
    this->scalar = scalar;
  }

  static constexpr Op OpCode = Op::MatrixTimesScalar;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id matrix;
  Id scalar;
};

struct OpVectorTimesMatrix
{
  OpVectorTimesMatrix(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpVectorTimesMatrix(IdResultType resultType, IdResult result, Id vector, Id matrix)
      : op(Op::VectorTimesMatrix)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->vector = vector;
    this->matrix = matrix;
  }

  static constexpr Op OpCode = Op::VectorTimesMatrix;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id vector;
  Id matrix;
};

struct OpMatrixTimesVector
{
  OpMatrixTimesVector(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpMatrixTimesVector(IdResultType resultType, IdResult result, Id matrix, Id vector)
      : op(Op::MatrixTimesVector)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->matrix = matrix;
    this->vector = vector;
  }

  static constexpr Op OpCode = Op::MatrixTimesVector;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id matrix;
  Id vector;
};

struct OpMatrixTimesMatrix
{
  OpMatrixTimesMatrix(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpMatrixTimesMatrix(IdResultType resultType, IdResult result, Id leftMatrix, Id rightMatrix)
      : op(Op::MatrixTimesMatrix)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->leftMatrix = leftMatrix;
    this->rightMatrix = rightMatrix;
  }

  static constexpr Op OpCode = Op::MatrixTimesMatrix;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id leftMatrix;
  Id rightMatrix;
};

struct OpOuterProduct
{
  OpOuterProduct(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpOuterProduct(IdResultType resultType, IdResult result, Id vector1, Id vector2)
      : op(Op::OuterProduct)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->vector1 = vector1;
    this->vector2 = vector2;
  }

  static constexpr Op OpCode = Op::OuterProduct;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id vector1;
  Id vector2;
};

struct OpDot
{
  OpDot(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpDot(IdResultType resultType, IdResult result, Id vector1, Id vector2)
      : op(Op::Dot)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->vector1 = vector1;
    this->vector2 = vector2;
  }

  static constexpr Op OpCode = Op::Dot;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id vector1;
  Id vector2;
};

struct OpIAddCarry
{
  OpIAddCarry(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpIAddCarry(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::IAddCarry)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::IAddCarry;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpISubBorrow
{
  OpISubBorrow(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpISubBorrow(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::ISubBorrow)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::ISubBorrow;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpUMulExtended
{
  OpUMulExtended(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpUMulExtended(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::UMulExtended)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::UMulExtended;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpSMulExtended
{
  OpSMulExtended(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSMulExtended(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::SMulExtended)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::SMulExtended;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpAny
{
  OpAny(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAny(IdResultType resultType, IdResult result, Id vector)
      : op(Op::Any)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->vector = vector;
  }

  static constexpr Op OpCode = Op::Any;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id vector;
};

struct OpAll
{
  OpAll(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAll(IdResultType resultType, IdResult result, Id vector)
      : op(Op::All)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->vector = vector;
  }

  static constexpr Op OpCode = Op::All;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id vector;
};

struct OpIsNan
{
  OpIsNan(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpIsNan(IdResultType resultType, IdResult result, Id x)
      : op(Op::IsNan)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->x = x;
  }

  static constexpr Op OpCode = Op::IsNan;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id x;
};

struct OpIsInf
{
  OpIsInf(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpIsInf(IdResultType resultType, IdResult result, Id x)
      : op(Op::IsInf)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->x = x;
  }

  static constexpr Op OpCode = Op::IsInf;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id x;
};

struct OpIsFinite
{
  OpIsFinite(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpIsFinite(IdResultType resultType, IdResult result, Id x)
      : op(Op::IsFinite)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->x = x;
  }

  static constexpr Op OpCode = Op::IsFinite;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id x;
};

struct OpIsNormal
{
  OpIsNormal(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpIsNormal(IdResultType resultType, IdResult result, Id x)
      : op(Op::IsNormal)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->x = x;
  }

  static constexpr Op OpCode = Op::IsNormal;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id x;
};

struct OpSignBitSet
{
  OpSignBitSet(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSignBitSet(IdResultType resultType, IdResult result, Id x)
      : op(Op::SignBitSet)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->x = x;
  }

  static constexpr Op OpCode = Op::SignBitSet;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id x;
};

struct OpLessOrGreater
{
  OpLessOrGreater(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpLessOrGreater(IdResultType resultType, IdResult result, Id x, Id y)
      : op(Op::LessOrGreater)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->x = x;
    this->y = y;
  }

  static constexpr Op OpCode = Op::LessOrGreater;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id x;
  Id y;
};

struct OpOrdered
{
  OpOrdered(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpOrdered(IdResultType resultType, IdResult result, Id x, Id y)
      : op(Op::Ordered)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->x = x;
    this->y = y;
  }

  static constexpr Op OpCode = Op::Ordered;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id x;
  Id y;
};

struct OpUnordered
{
  OpUnordered(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpUnordered(IdResultType resultType, IdResult result, Id x, Id y)
      : op(Op::Unordered)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->x = x;
    this->y = y;
  }

  static constexpr Op OpCode = Op::Unordered;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id x;
  Id y;
};

struct OpLogicalEqual
{
  OpLogicalEqual(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpLogicalEqual(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::LogicalEqual)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::LogicalEqual;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpLogicalNotEqual
{
  OpLogicalNotEqual(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpLogicalNotEqual(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::LogicalNotEqual)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::LogicalNotEqual;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpLogicalOr
{
  OpLogicalOr(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpLogicalOr(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::LogicalOr)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::LogicalOr;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpLogicalAnd
{
  OpLogicalAnd(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpLogicalAnd(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::LogicalAnd)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::LogicalAnd;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpLogicalNot
{
  OpLogicalNot(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpLogicalNot(IdResultType resultType, IdResult result, Id operand)
      : op(Op::LogicalNot)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand = operand;
  }

  static constexpr Op OpCode = Op::LogicalNot;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand;
};

struct OpSelect
{
  OpSelect(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSelect(IdResultType resultType, IdResult result, Id condition, Id object1, Id object2)
      : op(Op::Select)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->condition = condition;
    this->object1 = object1;
    this->object2 = object2;
  }

  static constexpr Op OpCode = Op::Select;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id condition;
  Id object1;
  Id object2;
};

struct OpIEqual
{
  OpIEqual(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpIEqual(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::IEqual)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::IEqual;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpINotEqual
{
  OpINotEqual(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpINotEqual(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::INotEqual)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::INotEqual;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpUGreaterThan
{
  OpUGreaterThan(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpUGreaterThan(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::UGreaterThan)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::UGreaterThan;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpSGreaterThan
{
  OpSGreaterThan(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSGreaterThan(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::SGreaterThan)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::SGreaterThan;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpUGreaterThanEqual
{
  OpUGreaterThanEqual(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpUGreaterThanEqual(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::UGreaterThanEqual)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::UGreaterThanEqual;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpSGreaterThanEqual
{
  OpSGreaterThanEqual(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSGreaterThanEqual(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::SGreaterThanEqual)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::SGreaterThanEqual;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpULessThan
{
  OpULessThan(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpULessThan(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::ULessThan)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::ULessThan;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpSLessThan
{
  OpSLessThan(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSLessThan(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::SLessThan)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::SLessThan;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpULessThanEqual
{
  OpULessThanEqual(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpULessThanEqual(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::ULessThanEqual)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::ULessThanEqual;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpSLessThanEqual
{
  OpSLessThanEqual(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSLessThanEqual(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::SLessThanEqual)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::SLessThanEqual;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpFOrdEqual
{
  OpFOrdEqual(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFOrdEqual(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::FOrdEqual)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::FOrdEqual;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpFUnordEqual
{
  OpFUnordEqual(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFUnordEqual(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::FUnordEqual)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::FUnordEqual;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpFOrdNotEqual
{
  OpFOrdNotEqual(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFOrdNotEqual(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::FOrdNotEqual)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::FOrdNotEqual;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpFUnordNotEqual
{
  OpFUnordNotEqual(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFUnordNotEqual(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::FUnordNotEqual)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::FUnordNotEqual;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpFOrdLessThan
{
  OpFOrdLessThan(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFOrdLessThan(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::FOrdLessThan)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::FOrdLessThan;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpFUnordLessThan
{
  OpFUnordLessThan(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFUnordLessThan(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::FUnordLessThan)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::FUnordLessThan;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpFOrdGreaterThan
{
  OpFOrdGreaterThan(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFOrdGreaterThan(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::FOrdGreaterThan)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::FOrdGreaterThan;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpFUnordGreaterThan
{
  OpFUnordGreaterThan(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFUnordGreaterThan(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::FUnordGreaterThan)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::FUnordGreaterThan;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpFOrdLessThanEqual
{
  OpFOrdLessThanEqual(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFOrdLessThanEqual(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::FOrdLessThanEqual)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::FOrdLessThanEqual;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpFUnordLessThanEqual
{
  OpFUnordLessThanEqual(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFUnordLessThanEqual(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::FUnordLessThanEqual)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::FUnordLessThanEqual;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpFOrdGreaterThanEqual
{
  OpFOrdGreaterThanEqual(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFOrdGreaterThanEqual(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::FOrdGreaterThanEqual)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::FOrdGreaterThanEqual;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpFUnordGreaterThanEqual
{
  OpFUnordGreaterThanEqual(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFUnordGreaterThanEqual(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::FUnordGreaterThanEqual)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::FUnordGreaterThanEqual;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpShiftRightLogical
{
  OpShiftRightLogical(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpShiftRightLogical(IdResultType resultType, IdResult result, Id base, Id shift)
      : op(Op::ShiftRightLogical)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->base = base;
    this->shift = shift;
  }

  static constexpr Op OpCode = Op::ShiftRightLogical;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id base;
  Id shift;
};

struct OpShiftRightArithmetic
{
  OpShiftRightArithmetic(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpShiftRightArithmetic(IdResultType resultType, IdResult result, Id base, Id shift)
      : op(Op::ShiftRightArithmetic)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->base = base;
    this->shift = shift;
  }

  static constexpr Op OpCode = Op::ShiftRightArithmetic;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id base;
  Id shift;
};

struct OpShiftLeftLogical
{
  OpShiftLeftLogical(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpShiftLeftLogical(IdResultType resultType, IdResult result, Id base, Id shift)
      : op(Op::ShiftLeftLogical)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->base = base;
    this->shift = shift;
  }

  static constexpr Op OpCode = Op::ShiftLeftLogical;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id base;
  Id shift;
};

struct OpBitwiseOr
{
  OpBitwiseOr(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpBitwiseOr(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::BitwiseOr)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::BitwiseOr;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpBitwiseXor
{
  OpBitwiseXor(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpBitwiseXor(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::BitwiseXor)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::BitwiseXor;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpBitwiseAnd
{
  OpBitwiseAnd(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpBitwiseAnd(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::BitwiseAnd)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::BitwiseAnd;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpNot
{
  OpNot(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpNot(IdResultType resultType, IdResult result, Id operand)
      : op(Op::Not)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand = operand;
  }

  static constexpr Op OpCode = Op::Not;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand;
};

struct OpBitFieldInsert
{
  OpBitFieldInsert(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpBitFieldInsert(IdResultType resultType, IdResult result, Id base, Id insert, Id offset, Id count)
      : op(Op::BitFieldInsert)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->base = base;
    this->insert = insert;
    this->offset = offset;
    this->count = count;
  }

  static constexpr Op OpCode = Op::BitFieldInsert;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id base;
  Id insert;
  Id offset;
  Id count;
};

struct OpBitFieldSExtract
{
  OpBitFieldSExtract(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpBitFieldSExtract(IdResultType resultType, IdResult result, Id base, Id offset, Id count)
      : op(Op::BitFieldSExtract)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->base = base;
    this->offset = offset;
    this->count = count;
  }

  static constexpr Op OpCode = Op::BitFieldSExtract;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id base;
  Id offset;
  Id count;
};

struct OpBitFieldUExtract
{
  OpBitFieldUExtract(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpBitFieldUExtract(IdResultType resultType, IdResult result, Id base, Id offset, Id count)
      : op(Op::BitFieldUExtract)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->base = base;
    this->offset = offset;
    this->count = count;
  }

  static constexpr Op OpCode = Op::BitFieldUExtract;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id base;
  Id offset;
  Id count;
};

struct OpBitReverse
{
  OpBitReverse(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpBitReverse(IdResultType resultType, IdResult result, Id base)
      : op(Op::BitReverse)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->base = base;
  }

  static constexpr Op OpCode = Op::BitReverse;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id base;
};

struct OpBitCount
{
  OpBitCount(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpBitCount(IdResultType resultType, IdResult result, Id base)
      : op(Op::BitCount)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->base = base;
  }

  static constexpr Op OpCode = Op::BitCount;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id base;
};

struct OpDPdx
{
  OpDPdx(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpDPdx(IdResultType resultType, IdResult result, Id p)
      : op(Op::DPdx)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->p = p;
  }

  static constexpr Op OpCode = Op::DPdx;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id p;
};

struct OpDPdy
{
  OpDPdy(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpDPdy(IdResultType resultType, IdResult result, Id p)
      : op(Op::DPdy)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->p = p;
  }

  static constexpr Op OpCode = Op::DPdy;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id p;
};

struct OpFwidth
{
  OpFwidth(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFwidth(IdResultType resultType, IdResult result, Id p)
      : op(Op::Fwidth)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->p = p;
  }

  static constexpr Op OpCode = Op::Fwidth;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id p;
};

struct OpDPdxFine
{
  OpDPdxFine(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpDPdxFine(IdResultType resultType, IdResult result, Id p)
      : op(Op::DPdxFine)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->p = p;
  }

  static constexpr Op OpCode = Op::DPdxFine;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id p;
};

struct OpDPdyFine
{
  OpDPdyFine(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpDPdyFine(IdResultType resultType, IdResult result, Id p)
      : op(Op::DPdyFine)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->p = p;
  }

  static constexpr Op OpCode = Op::DPdyFine;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id p;
};

struct OpFwidthFine
{
  OpFwidthFine(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFwidthFine(IdResultType resultType, IdResult result, Id p)
      : op(Op::FwidthFine)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->p = p;
  }

  static constexpr Op OpCode = Op::FwidthFine;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id p;
};

struct OpDPdxCoarse
{
  OpDPdxCoarse(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpDPdxCoarse(IdResultType resultType, IdResult result, Id p)
      : op(Op::DPdxCoarse)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->p = p;
  }

  static constexpr Op OpCode = Op::DPdxCoarse;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id p;
};

struct OpDPdyCoarse
{
  OpDPdyCoarse(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpDPdyCoarse(IdResultType resultType, IdResult result, Id p)
      : op(Op::DPdyCoarse)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->p = p;
  }

  static constexpr Op OpCode = Op::DPdyCoarse;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id p;
};

struct OpFwidthCoarse
{
  OpFwidthCoarse(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFwidthCoarse(IdResultType resultType, IdResult result, Id p)
      : op(Op::FwidthCoarse)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->p = p;
  }

  static constexpr Op OpCode = Op::FwidthCoarse;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id p;
};

struct OpEmitVertex
{
  OpEmitVertex(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpEmitVertex()
      : op(Op::EmitVertex)
      , wordCount(FixedWordSize)
  {
    // no operands
  }

  static constexpr Op OpCode = Op::EmitVertex;
  static constexpr uint16_t FixedWordSize = 1U;
  Op op;
  uint16_t wordCount;
  // no operands
};

struct OpEndPrimitive
{
  OpEndPrimitive(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpEndPrimitive()
      : op(Op::EndPrimitive)
      , wordCount(FixedWordSize)
  {
    // no operands
  }

  static constexpr Op OpCode = Op::EndPrimitive;
  static constexpr uint16_t FixedWordSize = 1U;
  Op op;
  uint16_t wordCount;
  // no operands
};

struct OpEmitStreamVertex
{
  OpEmitStreamVertex(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpEmitStreamVertex(Id stream)
      : op(Op::EmitStreamVertex)
      , wordCount(FixedWordSize)
  {
    this->stream = stream;
  }

  static constexpr Op OpCode = Op::EmitStreamVertex;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  Id stream;
};

struct OpEndStreamPrimitive
{
  OpEndStreamPrimitive(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpEndStreamPrimitive(Id stream)
      : op(Op::EndStreamPrimitive)
      , wordCount(FixedWordSize)
  {
    this->stream = stream;
  }

  static constexpr Op OpCode = Op::EndStreamPrimitive;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  Id stream;
};

struct OpControlBarrier
{
  OpControlBarrier(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpControlBarrier(IdScope execution, IdScope memory, IdMemorySemantics semantics)
      : op(Op::ControlBarrier)
      , wordCount(FixedWordSize)
  {
    this->execution = execution;
    this->memory = memory;
    this->semantics = semantics;
  }

  static constexpr Op OpCode = Op::ControlBarrier;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdScope execution;
  IdScope memory;
  IdMemorySemantics semantics;
};

struct OpMemoryBarrier
{
  OpMemoryBarrier(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpMemoryBarrier(IdScope memory, IdMemorySemantics semantics)
      : op(Op::MemoryBarrier)
      , wordCount(FixedWordSize)
  {
    this->memory = memory;
    this->semantics = semantics;
  }

  static constexpr Op OpCode = Op::MemoryBarrier;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdScope memory;
  IdMemorySemantics semantics;
};

struct OpAtomicLoad
{
  OpAtomicLoad(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicLoad(IdResultType resultType, IdResult result, Id pointer, IdScope memory, IdMemorySemantics semantics)
      : op(Op::AtomicLoad)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memory = memory;
    this->semantics = semantics;
  }

  static constexpr Op OpCode = Op::AtomicLoad;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  IdScope memory;
  IdMemorySemantics semantics;
};

struct OpAtomicStore
{
  OpAtomicStore(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicStore(Id pointer, IdScope memory, IdMemorySemantics semantics, Id value)
      : op(Op::AtomicStore)
      , wordCount(FixedWordSize)
  {
    this->pointer = pointer;
    this->memory = memory;
    this->semantics = semantics;
    this->value = value;
  }

  static constexpr Op OpCode = Op::AtomicStore;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  Id pointer;
  IdScope memory;
  IdMemorySemantics semantics;
  Id value;
};

struct OpAtomicExchange
{
  OpAtomicExchange(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicExchange(IdResultType resultType, IdResult result, Id pointer, IdScope memory, IdMemorySemantics semantics, Id value)
      : op(Op::AtomicExchange)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memory = memory;
    this->semantics = semantics;
    this->value = value;
  }

  static constexpr Op OpCode = Op::AtomicExchange;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  IdScope memory;
  IdMemorySemantics semantics;
  Id value;
};

struct OpAtomicCompareExchange
{
  OpAtomicCompareExchange(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicCompareExchange(IdResultType resultType, IdResult result, Id pointer, IdScope memory, IdMemorySemantics equal, IdMemorySemantics unequal, Id value, Id comparator)
      : op(Op::AtomicCompareExchange)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memory = memory;
    this->equal = equal;
    this->unequal = unequal;
    this->value = value;
    this->comparator = comparator;
  }

  static constexpr Op OpCode = Op::AtomicCompareExchange;
  static constexpr uint16_t FixedWordSize = 9U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  IdScope memory;
  IdMemorySemantics equal;
  IdMemorySemantics unequal;
  Id value;
  Id comparator;
};

struct OpAtomicCompareExchangeWeak
{
  OpAtomicCompareExchangeWeak(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicCompareExchangeWeak(IdResultType resultType, IdResult result, Id pointer, IdScope memory, IdMemorySemantics equal, IdMemorySemantics unequal, Id value, Id comparator)
      : op(Op::AtomicCompareExchangeWeak)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memory = memory;
    this->equal = equal;
    this->unequal = unequal;
    this->value = value;
    this->comparator = comparator;
  }

  static constexpr Op OpCode = Op::AtomicCompareExchangeWeak;
  static constexpr uint16_t FixedWordSize = 9U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  IdScope memory;
  IdMemorySemantics equal;
  IdMemorySemantics unequal;
  Id value;
  Id comparator;
};

struct OpAtomicIIncrement
{
  OpAtomicIIncrement(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicIIncrement(IdResultType resultType, IdResult result, Id pointer, IdScope memory, IdMemorySemantics semantics)
      : op(Op::AtomicIIncrement)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memory = memory;
    this->semantics = semantics;
  }

  static constexpr Op OpCode = Op::AtomicIIncrement;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  IdScope memory;
  IdMemorySemantics semantics;
};

struct OpAtomicIDecrement
{
  OpAtomicIDecrement(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicIDecrement(IdResultType resultType, IdResult result, Id pointer, IdScope memory, IdMemorySemantics semantics)
      : op(Op::AtomicIDecrement)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memory = memory;
    this->semantics = semantics;
  }

  static constexpr Op OpCode = Op::AtomicIDecrement;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  IdScope memory;
  IdMemorySemantics semantics;
};

struct OpAtomicIAdd
{
  OpAtomicIAdd(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicIAdd(IdResultType resultType, IdResult result, Id pointer, IdScope memory, IdMemorySemantics semantics, Id value)
      : op(Op::AtomicIAdd)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memory = memory;
    this->semantics = semantics;
    this->value = value;
  }

  static constexpr Op OpCode = Op::AtomicIAdd;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  IdScope memory;
  IdMemorySemantics semantics;
  Id value;
};

struct OpAtomicISub
{
  OpAtomicISub(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicISub(IdResultType resultType, IdResult result, Id pointer, IdScope memory, IdMemorySemantics semantics, Id value)
      : op(Op::AtomicISub)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memory = memory;
    this->semantics = semantics;
    this->value = value;
  }

  static constexpr Op OpCode = Op::AtomicISub;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  IdScope memory;
  IdMemorySemantics semantics;
  Id value;
};

struct OpAtomicSMin
{
  OpAtomicSMin(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicSMin(IdResultType resultType, IdResult result, Id pointer, IdScope memory, IdMemorySemantics semantics, Id value)
      : op(Op::AtomicSMin)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memory = memory;
    this->semantics = semantics;
    this->value = value;
  }

  static constexpr Op OpCode = Op::AtomicSMin;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  IdScope memory;
  IdMemorySemantics semantics;
  Id value;
};

struct OpAtomicUMin
{
  OpAtomicUMin(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicUMin(IdResultType resultType, IdResult result, Id pointer, IdScope memory, IdMemorySemantics semantics, Id value)
      : op(Op::AtomicUMin)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memory = memory;
    this->semantics = semantics;
    this->value = value;
  }

  static constexpr Op OpCode = Op::AtomicUMin;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  IdScope memory;
  IdMemorySemantics semantics;
  Id value;
};

struct OpAtomicSMax
{
  OpAtomicSMax(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicSMax(IdResultType resultType, IdResult result, Id pointer, IdScope memory, IdMemorySemantics semantics, Id value)
      : op(Op::AtomicSMax)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memory = memory;
    this->semantics = semantics;
    this->value = value;
  }

  static constexpr Op OpCode = Op::AtomicSMax;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  IdScope memory;
  IdMemorySemantics semantics;
  Id value;
};

struct OpAtomicUMax
{
  OpAtomicUMax(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicUMax(IdResultType resultType, IdResult result, Id pointer, IdScope memory, IdMemorySemantics semantics, Id value)
      : op(Op::AtomicUMax)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memory = memory;
    this->semantics = semantics;
    this->value = value;
  }

  static constexpr Op OpCode = Op::AtomicUMax;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  IdScope memory;
  IdMemorySemantics semantics;
  Id value;
};

struct OpAtomicAnd
{
  OpAtomicAnd(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicAnd(IdResultType resultType, IdResult result, Id pointer, IdScope memory, IdMemorySemantics semantics, Id value)
      : op(Op::AtomicAnd)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memory = memory;
    this->semantics = semantics;
    this->value = value;
  }

  static constexpr Op OpCode = Op::AtomicAnd;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  IdScope memory;
  IdMemorySemantics semantics;
  Id value;
};

struct OpAtomicOr
{
  OpAtomicOr(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicOr(IdResultType resultType, IdResult result, Id pointer, IdScope memory, IdMemorySemantics semantics, Id value)
      : op(Op::AtomicOr)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memory = memory;
    this->semantics = semantics;
    this->value = value;
  }

  static constexpr Op OpCode = Op::AtomicOr;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  IdScope memory;
  IdMemorySemantics semantics;
  Id value;
};

struct OpAtomicXor
{
  OpAtomicXor(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicXor(IdResultType resultType, IdResult result, Id pointer, IdScope memory, IdMemorySemantics semantics, Id value)
      : op(Op::AtomicXor)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memory = memory;
    this->semantics = semantics;
    this->value = value;
  }

  static constexpr Op OpCode = Op::AtomicXor;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  IdScope memory;
  IdMemorySemantics semantics;
  Id value;
};

struct OpPhi
{
  OpPhi(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    word = 3;
    this->parents = MultiParam<PairIdRefIdRef>(it, word);
  }
  OpPhi(IdResultType resultType, IdResult result, const rdcarray<PairIdRefIdRef> &parents = {})
      : op(Op::Phi)
      , wordCount(MinWordSize + MultiWordCount(parents))
  {
    this->resultType = resultType;
    this->result = result;
    this->parents = parents;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    for(size_t i=0; i < parents.size(); i++)
    {
      words.push_back(parents[i].first.value()); words.push_back(parents[i].second.value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::Phi;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  rdcarray<PairIdRefIdRef> parents;
};

struct OpLoopMerge
{
  OpLoopMerge(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->mergeBlock = Id::fromWord(it.word(1));
    this->continueTarget = Id::fromWord(it.word(2));
    word = 3;
    this->loopControl = DecodeParam<LoopControlAndParamDatas>(it, word);
  }
  OpLoopMerge(Id mergeBlock, Id continueTarget, LoopControlAndParamDatas loopControl)
      : op(Op::LoopMerge)
      , wordCount(MinWordSize + ExtraWordCount(loopControl))
  {
    this->mergeBlock = mergeBlock;
    this->continueTarget = continueTarget;
    this->loopControl = loopControl;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(mergeBlock.value());
    words.push_back(continueTarget.value());
    EncodeParam(words, loopControl);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::LoopMerge;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  Id mergeBlock;
  Id continueTarget;
  LoopControlAndParamDatas loopControl;
};

struct OpSelectionMerge
{
  OpSelectionMerge(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSelectionMerge(Id mergeBlock, SelectionControl selectionControl)
      : op(Op::SelectionMerge)
      , wordCount(FixedWordSize)
  {
    this->mergeBlock = mergeBlock;
    this->selectionControl = selectionControl;
  }

  static constexpr Op OpCode = Op::SelectionMerge;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id mergeBlock;
  SelectionControl selectionControl;
};

struct OpLabel
{
  OpLabel(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpLabel(IdResult result)
      : op(Op::Label)
      , wordCount(FixedWordSize)
  {
    this->result = result;
  }

  static constexpr Op OpCode = Op::Label;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  IdResult result;
};

struct OpBranch
{
  OpBranch(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpBranch(Id targetLabel)
      : op(Op::Branch)
      , wordCount(FixedWordSize)
  {
    this->targetLabel = targetLabel;
  }

  static constexpr Op OpCode = Op::Branch;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  Id targetLabel;
};

struct OpBranchConditional
{
  OpBranchConditional(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->condition = Id::fromWord(it.word(1));
    this->trueLabel = Id::fromWord(it.word(2));
    this->falseLabel = Id::fromWord(it.word(3));
    word = 4;
    this->branchweights = MultiParam<uint32_t>(it, word);
  }
  OpBranchConditional(Id condition, Id trueLabel, Id falseLabel, const rdcarray<uint32_t> &branchweights = {})
      : op(Op::BranchConditional)
      , wordCount(MinWordSize + MultiWordCount(branchweights))
  {
    this->condition = condition;
    this->trueLabel = trueLabel;
    this->falseLabel = falseLabel;
    this->branchweights = branchweights;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(condition.value());
    words.push_back(trueLabel.value());
    words.push_back(falseLabel.value());
    for(size_t i=0; i < branchweights.size(); i++)
    {
      words.push_back((uint32_t)branchweights[i]);
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::BranchConditional;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  Id condition;
  Id trueLabel;
  Id falseLabel;
  rdcarray<uint32_t> branchweights;
};

struct OpSwitch; // has operands with variable sizes

struct OpKill
{
  OpKill(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpKill()
      : op(Op::Kill)
      , wordCount(FixedWordSize)
  {
    // no operands
  }

  static constexpr Op OpCode = Op::Kill;
  static constexpr uint16_t FixedWordSize = 1U;
  Op op;
  uint16_t wordCount;
  // no operands
};

struct OpReturn
{
  OpReturn(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpReturn()
      : op(Op::Return)
      , wordCount(FixedWordSize)
  {
    // no operands
  }

  static constexpr Op OpCode = Op::Return;
  static constexpr uint16_t FixedWordSize = 1U;
  Op op;
  uint16_t wordCount;
  // no operands
};

struct OpReturnValue
{
  OpReturnValue(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpReturnValue(Id value)
      : op(Op::ReturnValue)
      , wordCount(FixedWordSize)
  {
    this->value = value;
  }

  static constexpr Op OpCode = Op::ReturnValue;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  Id value;
};

struct OpUnreachable
{
  OpUnreachable(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpUnreachable()
      : op(Op::Unreachable)
      , wordCount(FixedWordSize)
  {
    // no operands
  }

  static constexpr Op OpCode = Op::Unreachable;
  static constexpr uint16_t FixedWordSize = 1U;
  Op op;
  uint16_t wordCount;
  // no operands
};

struct OpLifetimeStart
{
  OpLifetimeStart(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpLifetimeStart(Id pointer, uint32_t size)
      : op(Op::LifetimeStart)
      , wordCount(FixedWordSize)
  {
    this->pointer = pointer;
    this->size = size;
  }

  static constexpr Op OpCode = Op::LifetimeStart;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id pointer;
  uint32_t size;
};

struct OpLifetimeStop
{
  OpLifetimeStop(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpLifetimeStop(Id pointer, uint32_t size)
      : op(Op::LifetimeStop)
      , wordCount(FixedWordSize)
  {
    this->pointer = pointer;
    this->size = size;
  }

  static constexpr Op OpCode = Op::LifetimeStop;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id pointer;
  uint32_t size;
};

struct OpGroupAsyncCopy
{
  OpGroupAsyncCopy(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupAsyncCopy(IdResultType resultType, IdResult result, IdScope execution, Id destination, Id source, Id numElements, Id stride, Id event)
      : op(Op::GroupAsyncCopy)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->destination = destination;
    this->source = source;
    this->numElements = numElements;
    this->stride = stride;
    this->event = event;
  }

  static constexpr Op OpCode = Op::GroupAsyncCopy;
  static constexpr uint16_t FixedWordSize = 9U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id destination;
  Id source;
  Id numElements;
  Id stride;
  Id event;
};

struct OpGroupWaitEvents
{
  OpGroupWaitEvents(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupWaitEvents(IdScope execution, Id numEvents, Id eventsList)
      : op(Op::GroupWaitEvents)
      , wordCount(FixedWordSize)
  {
    this->execution = execution;
    this->numEvents = numEvents;
    this->eventsList = eventsList;
  }

  static constexpr Op OpCode = Op::GroupWaitEvents;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdScope execution;
  Id numEvents;
  Id eventsList;
};

struct OpGroupAll
{
  OpGroupAll(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupAll(IdResultType resultType, IdResult result, IdScope execution, Id predicate)
      : op(Op::GroupAll)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->predicate = predicate;
  }

  static constexpr Op OpCode = Op::GroupAll;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id predicate;
};

struct OpGroupAny
{
  OpGroupAny(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupAny(IdResultType resultType, IdResult result, IdScope execution, Id predicate)
      : op(Op::GroupAny)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->predicate = predicate;
  }

  static constexpr Op OpCode = Op::GroupAny;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id predicate;
};

struct OpGroupBroadcast
{
  OpGroupBroadcast(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupBroadcast(IdResultType resultType, IdResult result, IdScope execution, Id value, Id localId)
      : op(Op::GroupBroadcast)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->value = value;
    this->localId = localId;
  }

  static constexpr Op OpCode = Op::GroupBroadcast;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id value;
  Id localId;
};

struct OpGroupIAdd
{
  OpGroupIAdd(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupIAdd(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupIAdd)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupIAdd;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupFAdd
{
  OpGroupFAdd(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupFAdd(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupFAdd)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupFAdd;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupFMin
{
  OpGroupFMin(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupFMin(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupFMin)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupFMin;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupUMin
{
  OpGroupUMin(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupUMin(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupUMin)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupUMin;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupSMin
{
  OpGroupSMin(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupSMin(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupSMin)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupSMin;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupFMax
{
  OpGroupFMax(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupFMax(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupFMax)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupFMax;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupUMax
{
  OpGroupUMax(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupUMax(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupUMax)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupUMax;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupSMax
{
  OpGroupSMax(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupSMax(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupSMax)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupSMax;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpReadPipe
{
  OpReadPipe(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpReadPipe(IdResultType resultType, IdResult result, Id pipe, Id pointer, Id packetSize, Id packetAlignment)
      : op(Op::ReadPipe)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pipe = pipe;
    this->pointer = pointer;
    this->packetSize = packetSize;
    this->packetAlignment = packetAlignment;
  }

  static constexpr Op OpCode = Op::ReadPipe;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pipe;
  Id pointer;
  Id packetSize;
  Id packetAlignment;
};

struct OpWritePipe
{
  OpWritePipe(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpWritePipe(IdResultType resultType, IdResult result, Id pipe, Id pointer, Id packetSize, Id packetAlignment)
      : op(Op::WritePipe)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pipe = pipe;
    this->pointer = pointer;
    this->packetSize = packetSize;
    this->packetAlignment = packetAlignment;
  }

  static constexpr Op OpCode = Op::WritePipe;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pipe;
  Id pointer;
  Id packetSize;
  Id packetAlignment;
};

struct OpReservedReadPipe
{
  OpReservedReadPipe(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpReservedReadPipe(IdResultType resultType, IdResult result, Id pipe, Id reserveId, Id index, Id pointer, Id packetSize, Id packetAlignment)
      : op(Op::ReservedReadPipe)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pipe = pipe;
    this->reserveId = reserveId;
    this->index = index;
    this->pointer = pointer;
    this->packetSize = packetSize;
    this->packetAlignment = packetAlignment;
  }

  static constexpr Op OpCode = Op::ReservedReadPipe;
  static constexpr uint16_t FixedWordSize = 9U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pipe;
  Id reserveId;
  Id index;
  Id pointer;
  Id packetSize;
  Id packetAlignment;
};

struct OpReservedWritePipe
{
  OpReservedWritePipe(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpReservedWritePipe(IdResultType resultType, IdResult result, Id pipe, Id reserveId, Id index, Id pointer, Id packetSize, Id packetAlignment)
      : op(Op::ReservedWritePipe)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pipe = pipe;
    this->reserveId = reserveId;
    this->index = index;
    this->pointer = pointer;
    this->packetSize = packetSize;
    this->packetAlignment = packetAlignment;
  }

  static constexpr Op OpCode = Op::ReservedWritePipe;
  static constexpr uint16_t FixedWordSize = 9U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pipe;
  Id reserveId;
  Id index;
  Id pointer;
  Id packetSize;
  Id packetAlignment;
};

struct OpReserveReadPipePackets
{
  OpReserveReadPipePackets(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpReserveReadPipePackets(IdResultType resultType, IdResult result, Id pipe, Id numPackets, Id packetSize, Id packetAlignment)
      : op(Op::ReserveReadPipePackets)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pipe = pipe;
    this->numPackets = numPackets;
    this->packetSize = packetSize;
    this->packetAlignment = packetAlignment;
  }

  static constexpr Op OpCode = Op::ReserveReadPipePackets;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pipe;
  Id numPackets;
  Id packetSize;
  Id packetAlignment;
};

struct OpReserveWritePipePackets
{
  OpReserveWritePipePackets(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpReserveWritePipePackets(IdResultType resultType, IdResult result, Id pipe, Id numPackets, Id packetSize, Id packetAlignment)
      : op(Op::ReserveWritePipePackets)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pipe = pipe;
    this->numPackets = numPackets;
    this->packetSize = packetSize;
    this->packetAlignment = packetAlignment;
  }

  static constexpr Op OpCode = Op::ReserveWritePipePackets;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pipe;
  Id numPackets;
  Id packetSize;
  Id packetAlignment;
};

struct OpCommitReadPipe
{
  OpCommitReadPipe(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpCommitReadPipe(Id pipe, Id reserveId, Id packetSize, Id packetAlignment)
      : op(Op::CommitReadPipe)
      , wordCount(FixedWordSize)
  {
    this->pipe = pipe;
    this->reserveId = reserveId;
    this->packetSize = packetSize;
    this->packetAlignment = packetAlignment;
  }

  static constexpr Op OpCode = Op::CommitReadPipe;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  Id pipe;
  Id reserveId;
  Id packetSize;
  Id packetAlignment;
};

struct OpCommitWritePipe
{
  OpCommitWritePipe(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpCommitWritePipe(Id pipe, Id reserveId, Id packetSize, Id packetAlignment)
      : op(Op::CommitWritePipe)
      , wordCount(FixedWordSize)
  {
    this->pipe = pipe;
    this->reserveId = reserveId;
    this->packetSize = packetSize;
    this->packetAlignment = packetAlignment;
  }

  static constexpr Op OpCode = Op::CommitWritePipe;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  Id pipe;
  Id reserveId;
  Id packetSize;
  Id packetAlignment;
};

struct OpIsValidReserveId
{
  OpIsValidReserveId(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpIsValidReserveId(IdResultType resultType, IdResult result, Id reserveId)
      : op(Op::IsValidReserveId)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->reserveId = reserveId;
  }

  static constexpr Op OpCode = Op::IsValidReserveId;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id reserveId;
};

struct OpGetNumPipePackets
{
  OpGetNumPipePackets(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGetNumPipePackets(IdResultType resultType, IdResult result, Id pipe, Id packetSize, Id packetAlignment)
      : op(Op::GetNumPipePackets)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pipe = pipe;
    this->packetSize = packetSize;
    this->packetAlignment = packetAlignment;
  }

  static constexpr Op OpCode = Op::GetNumPipePackets;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pipe;
  Id packetSize;
  Id packetAlignment;
};

struct OpGetMaxPipePackets
{
  OpGetMaxPipePackets(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGetMaxPipePackets(IdResultType resultType, IdResult result, Id pipe, Id packetSize, Id packetAlignment)
      : op(Op::GetMaxPipePackets)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pipe = pipe;
    this->packetSize = packetSize;
    this->packetAlignment = packetAlignment;
  }

  static constexpr Op OpCode = Op::GetMaxPipePackets;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pipe;
  Id packetSize;
  Id packetAlignment;
};

struct OpGroupReserveReadPipePackets
{
  OpGroupReserveReadPipePackets(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupReserveReadPipePackets(IdResultType resultType, IdResult result, IdScope execution, Id pipe, Id numPackets, Id packetSize, Id packetAlignment)
      : op(Op::GroupReserveReadPipePackets)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->pipe = pipe;
    this->numPackets = numPackets;
    this->packetSize = packetSize;
    this->packetAlignment = packetAlignment;
  }

  static constexpr Op OpCode = Op::GroupReserveReadPipePackets;
  static constexpr uint16_t FixedWordSize = 8U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id pipe;
  Id numPackets;
  Id packetSize;
  Id packetAlignment;
};

struct OpGroupReserveWritePipePackets
{
  OpGroupReserveWritePipePackets(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupReserveWritePipePackets(IdResultType resultType, IdResult result, IdScope execution, Id pipe, Id numPackets, Id packetSize, Id packetAlignment)
      : op(Op::GroupReserveWritePipePackets)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->pipe = pipe;
    this->numPackets = numPackets;
    this->packetSize = packetSize;
    this->packetAlignment = packetAlignment;
  }

  static constexpr Op OpCode = Op::GroupReserveWritePipePackets;
  static constexpr uint16_t FixedWordSize = 8U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id pipe;
  Id numPackets;
  Id packetSize;
  Id packetAlignment;
};

struct OpGroupCommitReadPipe
{
  OpGroupCommitReadPipe(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupCommitReadPipe(IdScope execution, Id pipe, Id reserveId, Id packetSize, Id packetAlignment)
      : op(Op::GroupCommitReadPipe)
      , wordCount(FixedWordSize)
  {
    this->execution = execution;
    this->pipe = pipe;
    this->reserveId = reserveId;
    this->packetSize = packetSize;
    this->packetAlignment = packetAlignment;
  }

  static constexpr Op OpCode = Op::GroupCommitReadPipe;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdScope execution;
  Id pipe;
  Id reserveId;
  Id packetSize;
  Id packetAlignment;
};

struct OpGroupCommitWritePipe
{
  OpGroupCommitWritePipe(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupCommitWritePipe(IdScope execution, Id pipe, Id reserveId, Id packetSize, Id packetAlignment)
      : op(Op::GroupCommitWritePipe)
      , wordCount(FixedWordSize)
  {
    this->execution = execution;
    this->pipe = pipe;
    this->reserveId = reserveId;
    this->packetSize = packetSize;
    this->packetAlignment = packetAlignment;
  }

  static constexpr Op OpCode = Op::GroupCommitWritePipe;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdScope execution;
  Id pipe;
  Id reserveId;
  Id packetSize;
  Id packetAlignment;
};

struct OpEnqueueMarker
{
  OpEnqueueMarker(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpEnqueueMarker(IdResultType resultType, IdResult result, Id queue, Id numEvents, Id waitEvents, Id retEvent)
      : op(Op::EnqueueMarker)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->queue = queue;
    this->numEvents = numEvents;
    this->waitEvents = waitEvents;
    this->retEvent = retEvent;
  }

  static constexpr Op OpCode = Op::EnqueueMarker;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id queue;
  Id numEvents;
  Id waitEvents;
  Id retEvent;
};

struct OpEnqueueKernel
{
  OpEnqueueKernel(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->queue = Id::fromWord(it.word(3));
    this->flags = Id::fromWord(it.word(4));
    this->nDRange = Id::fromWord(it.word(5));
    this->numEvents = Id::fromWord(it.word(6));
    this->waitEvents = Id::fromWord(it.word(7));
    this->retEvent = Id::fromWord(it.word(8));
    this->invoke = Id::fromWord(it.word(9));
    this->param = Id::fromWord(it.word(10));
    this->paramSize = Id::fromWord(it.word(11));
    this->paramAlign = Id::fromWord(it.word(12));
    word = 13;
    this->localSize = MultiParam<Id>(it, word);
  }
  OpEnqueueKernel(IdResultType resultType, IdResult result, Id queue, Id flags, Id nDRange, Id numEvents, Id waitEvents, Id retEvent, Id invoke, Id param, Id paramSize, Id paramAlign, const rdcarray<Id> &localSize = {})
      : op(Op::EnqueueKernel)
      , wordCount(MinWordSize + MultiWordCount(localSize))
  {
    this->resultType = resultType;
    this->result = result;
    this->queue = queue;
    this->flags = flags;
    this->nDRange = nDRange;
    this->numEvents = numEvents;
    this->waitEvents = waitEvents;
    this->retEvent = retEvent;
    this->invoke = invoke;
    this->param = param;
    this->paramSize = paramSize;
    this->paramAlign = paramAlign;
    this->localSize = localSize;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(queue.value());
    words.push_back(flags.value());
    words.push_back(nDRange.value());
    words.push_back(numEvents.value());
    words.push_back(waitEvents.value());
    words.push_back(retEvent.value());
    words.push_back(invoke.value());
    words.push_back(param.value());
    words.push_back(paramSize.value());
    words.push_back(paramAlign.value());
    for(size_t i=0; i < localSize.size(); i++)
    {
      words.push_back(localSize[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::EnqueueKernel;
  static constexpr uint16_t MinWordSize = 13U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id queue;
  Id flags;
  Id nDRange;
  Id numEvents;
  Id waitEvents;
  Id retEvent;
  Id invoke;
  Id param;
  Id paramSize;
  Id paramAlign;
  rdcarray<Id> localSize;
};

struct OpGetKernelNDrangeSubGroupCount
{
  OpGetKernelNDrangeSubGroupCount(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGetKernelNDrangeSubGroupCount(IdResultType resultType, IdResult result, Id nDRange, Id invoke, Id param, Id paramSize, Id paramAlign)
      : op(Op::GetKernelNDrangeSubGroupCount)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->nDRange = nDRange;
    this->invoke = invoke;
    this->param = param;
    this->paramSize = paramSize;
    this->paramAlign = paramAlign;
  }

  static constexpr Op OpCode = Op::GetKernelNDrangeSubGroupCount;
  static constexpr uint16_t FixedWordSize = 8U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id nDRange;
  Id invoke;
  Id param;
  Id paramSize;
  Id paramAlign;
};

struct OpGetKernelNDrangeMaxSubGroupSize
{
  OpGetKernelNDrangeMaxSubGroupSize(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGetKernelNDrangeMaxSubGroupSize(IdResultType resultType, IdResult result, Id nDRange, Id invoke, Id param, Id paramSize, Id paramAlign)
      : op(Op::GetKernelNDrangeMaxSubGroupSize)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->nDRange = nDRange;
    this->invoke = invoke;
    this->param = param;
    this->paramSize = paramSize;
    this->paramAlign = paramAlign;
  }

  static constexpr Op OpCode = Op::GetKernelNDrangeMaxSubGroupSize;
  static constexpr uint16_t FixedWordSize = 8U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id nDRange;
  Id invoke;
  Id param;
  Id paramSize;
  Id paramAlign;
};

struct OpGetKernelWorkGroupSize
{
  OpGetKernelWorkGroupSize(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGetKernelWorkGroupSize(IdResultType resultType, IdResult result, Id invoke, Id param, Id paramSize, Id paramAlign)
      : op(Op::GetKernelWorkGroupSize)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->invoke = invoke;
    this->param = param;
    this->paramSize = paramSize;
    this->paramAlign = paramAlign;
  }

  static constexpr Op OpCode = Op::GetKernelWorkGroupSize;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id invoke;
  Id param;
  Id paramSize;
  Id paramAlign;
};

struct OpGetKernelPreferredWorkGroupSizeMultiple
{
  OpGetKernelPreferredWorkGroupSizeMultiple(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGetKernelPreferredWorkGroupSizeMultiple(IdResultType resultType, IdResult result, Id invoke, Id param, Id paramSize, Id paramAlign)
      : op(Op::GetKernelPreferredWorkGroupSizeMultiple)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->invoke = invoke;
    this->param = param;
    this->paramSize = paramSize;
    this->paramAlign = paramAlign;
  }

  static constexpr Op OpCode = Op::GetKernelPreferredWorkGroupSizeMultiple;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id invoke;
  Id param;
  Id paramSize;
  Id paramAlign;
};

struct OpRetainEvent
{
  OpRetainEvent(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRetainEvent(Id event)
      : op(Op::RetainEvent)
      , wordCount(FixedWordSize)
  {
    this->event = event;
  }

  static constexpr Op OpCode = Op::RetainEvent;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  Id event;
};

struct OpReleaseEvent
{
  OpReleaseEvent(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpReleaseEvent(Id event)
      : op(Op::ReleaseEvent)
      , wordCount(FixedWordSize)
  {
    this->event = event;
  }

  static constexpr Op OpCode = Op::ReleaseEvent;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  Id event;
};

struct OpCreateUserEvent
{
  OpCreateUserEvent(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpCreateUserEvent(IdResultType resultType, IdResult result)
      : op(Op::CreateUserEvent)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
  }

  static constexpr Op OpCode = Op::CreateUserEvent;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
};

struct OpIsValidEvent
{
  OpIsValidEvent(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpIsValidEvent(IdResultType resultType, IdResult result, Id event)
      : op(Op::IsValidEvent)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->event = event;
  }

  static constexpr Op OpCode = Op::IsValidEvent;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id event;
};

struct OpSetUserEventStatus
{
  OpSetUserEventStatus(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSetUserEventStatus(Id event, Id status)
      : op(Op::SetUserEventStatus)
      , wordCount(FixedWordSize)
  {
    this->event = event;
    this->status = status;
  }

  static constexpr Op OpCode = Op::SetUserEventStatus;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id event;
  Id status;
};

struct OpCaptureEventProfilingInfo
{
  OpCaptureEventProfilingInfo(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpCaptureEventProfilingInfo(Id event, Id profilingInfo, Id value)
      : op(Op::CaptureEventProfilingInfo)
      , wordCount(FixedWordSize)
  {
    this->event = event;
    this->profilingInfo = profilingInfo;
    this->value = value;
  }

  static constexpr Op OpCode = Op::CaptureEventProfilingInfo;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  Id event;
  Id profilingInfo;
  Id value;
};

struct OpGetDefaultQueue
{
  OpGetDefaultQueue(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGetDefaultQueue(IdResultType resultType, IdResult result)
      : op(Op::GetDefaultQueue)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
  }

  static constexpr Op OpCode = Op::GetDefaultQueue;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
};

struct OpBuildNDRange
{
  OpBuildNDRange(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpBuildNDRange(IdResultType resultType, IdResult result, Id globalWorkSize, Id localWorkSize, Id globalWorkOffset)
      : op(Op::BuildNDRange)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->globalWorkSize = globalWorkSize;
    this->localWorkSize = localWorkSize;
    this->globalWorkOffset = globalWorkOffset;
  }

  static constexpr Op OpCode = Op::BuildNDRange;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id globalWorkSize;
  Id localWorkSize;
  Id globalWorkOffset;
};

struct OpImageSparseSampleImplicitLod
{
  OpImageSparseSampleImplicitLod(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    word = 5;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSparseSampleImplicitLod(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, ImageOperandsAndParamDatas imageOperands = ImageOperands::None)
      : op(Op::ImageSparseSampleImplicitLod)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSparseSampleImplicitLod;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageSparseSampleExplicitLod
{
  OpImageSparseSampleExplicitLod(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    word = 5;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSparseSampleExplicitLod(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, ImageOperandsAndParamDatas imageOperands)
      : op(Op::ImageSparseSampleExplicitLod)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSparseSampleExplicitLod;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageSparseSampleDrefImplicitLod
{
  OpImageSparseSampleDrefImplicitLod(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    this->dref = Id::fromWord(it.word(5));
    word = 6;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSparseSampleDrefImplicitLod(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, Id dref, ImageOperandsAndParamDatas imageOperands = ImageOperands::None)
      : op(Op::ImageSparseSampleDrefImplicitLod)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->dref = dref;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    words.push_back(dref.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSparseSampleDrefImplicitLod;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  Id dref;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageSparseSampleDrefExplicitLod
{
  OpImageSparseSampleDrefExplicitLod(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    this->dref = Id::fromWord(it.word(5));
    word = 6;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSparseSampleDrefExplicitLod(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, Id dref, ImageOperandsAndParamDatas imageOperands)
      : op(Op::ImageSparseSampleDrefExplicitLod)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->dref = dref;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    words.push_back(dref.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSparseSampleDrefExplicitLod;
  static constexpr uint16_t MinWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  Id dref;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageSparseSampleProjImplicitLod
{
  OpImageSparseSampleProjImplicitLod(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    word = 5;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSparseSampleProjImplicitLod(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, ImageOperandsAndParamDatas imageOperands = ImageOperands::None)
      : op(Op::ImageSparseSampleProjImplicitLod)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSparseSampleProjImplicitLod;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageSparseSampleProjExplicitLod
{
  OpImageSparseSampleProjExplicitLod(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    word = 5;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSparseSampleProjExplicitLod(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, ImageOperandsAndParamDatas imageOperands)
      : op(Op::ImageSparseSampleProjExplicitLod)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSparseSampleProjExplicitLod;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageSparseSampleProjDrefImplicitLod
{
  OpImageSparseSampleProjDrefImplicitLod(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    this->dref = Id::fromWord(it.word(5));
    word = 6;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSparseSampleProjDrefImplicitLod(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, Id dref, ImageOperandsAndParamDatas imageOperands = ImageOperands::None)
      : op(Op::ImageSparseSampleProjDrefImplicitLod)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->dref = dref;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    words.push_back(dref.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSparseSampleProjDrefImplicitLod;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  Id dref;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageSparseSampleProjDrefExplicitLod
{
  OpImageSparseSampleProjDrefExplicitLod(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    this->dref = Id::fromWord(it.word(5));
    word = 6;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSparseSampleProjDrefExplicitLod(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, Id dref, ImageOperandsAndParamDatas imageOperands)
      : op(Op::ImageSparseSampleProjDrefExplicitLod)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->dref = dref;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    words.push_back(dref.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSparseSampleProjDrefExplicitLod;
  static constexpr uint16_t MinWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  Id dref;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageSparseFetch
{
  OpImageSparseFetch(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->image = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    word = 5;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSparseFetch(IdResultType resultType, IdResult result, Id image, Id coordinate, ImageOperandsAndParamDatas imageOperands = ImageOperands::None)
      : op(Op::ImageSparseFetch)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->image = image;
    this->coordinate = coordinate;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(image.value());
    words.push_back(coordinate.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSparseFetch;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id image;
  Id coordinate;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageSparseGather
{
  OpImageSparseGather(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    this->component = Id::fromWord(it.word(5));
    word = 6;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSparseGather(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, Id component, ImageOperandsAndParamDatas imageOperands = ImageOperands::None)
      : op(Op::ImageSparseGather)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->component = component;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    words.push_back(component.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSparseGather;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  Id component;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageSparseDrefGather
{
  OpImageSparseDrefGather(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    this->dref = Id::fromWord(it.word(5));
    word = 6;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSparseDrefGather(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, Id dref, ImageOperandsAndParamDatas imageOperands = ImageOperands::None)
      : op(Op::ImageSparseDrefGather)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->dref = dref;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    words.push_back(dref.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSparseDrefGather;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  Id dref;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpImageSparseTexelsResident
{
  OpImageSparseTexelsResident(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpImageSparseTexelsResident(IdResultType resultType, IdResult result, Id residentCode)
      : op(Op::ImageSparseTexelsResident)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->residentCode = residentCode;
  }

  static constexpr Op OpCode = Op::ImageSparseTexelsResident;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id residentCode;
};

struct OpNoLine
{
  OpNoLine(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpNoLine()
      : op(Op::NoLine)
      , wordCount(FixedWordSize)
  {
    // no operands
  }

  static constexpr Op OpCode = Op::NoLine;
  static constexpr uint16_t FixedWordSize = 1U;
  Op op;
  uint16_t wordCount;
  // no operands
};

struct OpAtomicFlagTestAndSet
{
  OpAtomicFlagTestAndSet(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicFlagTestAndSet(IdResultType resultType, IdResult result, Id pointer, IdScope memory, IdMemorySemantics semantics)
      : op(Op::AtomicFlagTestAndSet)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memory = memory;
    this->semantics = semantics;
  }

  static constexpr Op OpCode = Op::AtomicFlagTestAndSet;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  IdScope memory;
  IdMemorySemantics semantics;
};

struct OpAtomicFlagClear
{
  OpAtomicFlagClear(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicFlagClear(Id pointer, IdScope memory, IdMemorySemantics semantics)
      : op(Op::AtomicFlagClear)
      , wordCount(FixedWordSize)
  {
    this->pointer = pointer;
    this->memory = memory;
    this->semantics = semantics;
  }

  static constexpr Op OpCode = Op::AtomicFlagClear;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  Id pointer;
  IdScope memory;
  IdMemorySemantics semantics;
};

struct OpImageSparseRead
{
  OpImageSparseRead(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->image = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    word = 5;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSparseRead(IdResultType resultType, IdResult result, Id image, Id coordinate, ImageOperandsAndParamDatas imageOperands = ImageOperands::None)
      : op(Op::ImageSparseRead)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->image = image;
    this->coordinate = coordinate;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(image.value());
    words.push_back(coordinate.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSparseRead;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id image;
  Id coordinate;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpSizeOf
{
  OpSizeOf(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSizeOf(IdResultType resultType, IdResult result, Id pointer)
      : op(Op::SizeOf)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
  }

  static constexpr Op OpCode = Op::SizeOf;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
};

struct OpTypePipeStorage
{
  OpTypePipeStorage(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypePipeStorage(IdResult result)
      : op(Op::TypePipeStorage)
      , wordCount(FixedWordSize)
  {
    this->result = result;
  }

  static constexpr Op OpCode = Op::TypePipeStorage;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  IdResult result;
};

struct OpConstantPipeStorage
{
  OpConstantPipeStorage(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConstantPipeStorage(IdResultType resultType, IdResult result, uint32_t packetSize, uint32_t packetAlignment, uint32_t capacity)
      : op(Op::ConstantPipeStorage)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->packetSize = packetSize;
    this->packetAlignment = packetAlignment;
    this->capacity = capacity;
  }

  static constexpr Op OpCode = Op::ConstantPipeStorage;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  uint32_t packetSize;
  uint32_t packetAlignment;
  uint32_t capacity;
};

struct OpCreatePipeFromPipeStorage
{
  OpCreatePipeFromPipeStorage(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpCreatePipeFromPipeStorage(IdResultType resultType, IdResult result, Id pipeStorage)
      : op(Op::CreatePipeFromPipeStorage)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pipeStorage = pipeStorage;
  }

  static constexpr Op OpCode = Op::CreatePipeFromPipeStorage;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pipeStorage;
};

struct OpGetKernelLocalSizeForSubgroupCount
{
  OpGetKernelLocalSizeForSubgroupCount(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGetKernelLocalSizeForSubgroupCount(IdResultType resultType, IdResult result, Id subgroupCount, Id invoke, Id param, Id paramSize, Id paramAlign)
      : op(Op::GetKernelLocalSizeForSubgroupCount)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->subgroupCount = subgroupCount;
    this->invoke = invoke;
    this->param = param;
    this->paramSize = paramSize;
    this->paramAlign = paramAlign;
  }

  static constexpr Op OpCode = Op::GetKernelLocalSizeForSubgroupCount;
  static constexpr uint16_t FixedWordSize = 8U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id subgroupCount;
  Id invoke;
  Id param;
  Id paramSize;
  Id paramAlign;
};

struct OpGetKernelMaxNumSubgroups
{
  OpGetKernelMaxNumSubgroups(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGetKernelMaxNumSubgroups(IdResultType resultType, IdResult result, Id invoke, Id param, Id paramSize, Id paramAlign)
      : op(Op::GetKernelMaxNumSubgroups)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->invoke = invoke;
    this->param = param;
    this->paramSize = paramSize;
    this->paramAlign = paramAlign;
  }

  static constexpr Op OpCode = Op::GetKernelMaxNumSubgroups;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id invoke;
  Id param;
  Id paramSize;
  Id paramAlign;
};

struct OpTypeNamedBarrier
{
  OpTypeNamedBarrier(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeNamedBarrier(IdResult result)
      : op(Op::TypeNamedBarrier)
      , wordCount(FixedWordSize)
  {
    this->result = result;
  }

  static constexpr Op OpCode = Op::TypeNamedBarrier;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  IdResult result;
};

struct OpNamedBarrierInitialize
{
  OpNamedBarrierInitialize(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpNamedBarrierInitialize(IdResultType resultType, IdResult result, Id subgroupCount)
      : op(Op::NamedBarrierInitialize)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->subgroupCount = subgroupCount;
  }

  static constexpr Op OpCode = Op::NamedBarrierInitialize;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id subgroupCount;
};

struct OpMemoryNamedBarrier
{
  OpMemoryNamedBarrier(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpMemoryNamedBarrier(Id namedBarrier, IdScope memory, IdMemorySemantics semantics)
      : op(Op::MemoryNamedBarrier)
      , wordCount(FixedWordSize)
  {
    this->namedBarrier = namedBarrier;
    this->memory = memory;
    this->semantics = semantics;
  }

  static constexpr Op OpCode = Op::MemoryNamedBarrier;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  Id namedBarrier;
  IdScope memory;
  IdMemorySemantics semantics;
};

struct OpModuleProcessed
{
  OpModuleProcessed(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    word = 1;
    this->process = DecodeParam<rdcstr>(it, word);
  }
  OpModuleProcessed(rdcstr process)
      : op(Op::ModuleProcessed)
      , wordCount(MinWordSize + ExtraWordCount(process))
  {
    this->process = process;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    EncodeParam(words, process);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ModuleProcessed;
  static constexpr uint16_t MinWordSize = 2U;
  Op op;
  uint16_t wordCount;
  rdcstr process;
};

struct OpExecutionModeId
{
  OpExecutionModeId(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->entryPoint = Id::fromWord(it.word(1));
    word = 2;
    this->mode = DecodeParam<ExecutionModeAndParamData>(it, word);
  }
  OpExecutionModeId(Id entryPoint, ExecutionModeAndParamData mode)
      : op(Op::ExecutionModeId)
      , wordCount(MinWordSize + ExtraWordCount(mode))
  {
    this->entryPoint = entryPoint;
    this->mode = mode;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(entryPoint.value());
    EncodeParam(words, mode);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ExecutionModeId;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id entryPoint;
  ExecutionModeAndParamData mode;
};

struct OpDecorateId
{
  OpDecorateId(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->target = Id::fromWord(it.word(1));
    word = 2;
    this->decoration = DecodeParam<DecorationAndParamData>(it, word);
  }
  OpDecorateId(Id target, DecorationAndParamData decoration)
      : op(Op::DecorateId)
      , wordCount(MinWordSize + ExtraWordCount(decoration))
  {
    this->target = target;
    this->decoration = decoration;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(target.value());
    EncodeParam(words, decoration);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::DecorateId;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id target;
  DecorationAndParamData decoration;
};

struct OpGroupNonUniformElect
{
  OpGroupNonUniformElect(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformElect(IdResultType resultType, IdResult result, IdScope execution)
      : op(Op::GroupNonUniformElect)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
  }

  static constexpr Op OpCode = Op::GroupNonUniformElect;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
};

struct OpGroupNonUniformAll
{
  OpGroupNonUniformAll(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformAll(IdResultType resultType, IdResult result, IdScope execution, Id predicate)
      : op(Op::GroupNonUniformAll)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->predicate = predicate;
  }

  static constexpr Op OpCode = Op::GroupNonUniformAll;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id predicate;
};

struct OpGroupNonUniformAny
{
  OpGroupNonUniformAny(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformAny(IdResultType resultType, IdResult result, IdScope execution, Id predicate)
      : op(Op::GroupNonUniformAny)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->predicate = predicate;
  }

  static constexpr Op OpCode = Op::GroupNonUniformAny;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id predicate;
};

struct OpGroupNonUniformAllEqual
{
  OpGroupNonUniformAllEqual(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformAllEqual(IdResultType resultType, IdResult result, IdScope execution, Id value)
      : op(Op::GroupNonUniformAllEqual)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->value = value;
  }

  static constexpr Op OpCode = Op::GroupNonUniformAllEqual;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id value;
};

struct OpGroupNonUniformBroadcast
{
  OpGroupNonUniformBroadcast(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformBroadcast(IdResultType resultType, IdResult result, IdScope execution, Id value, Id invocationId)
      : op(Op::GroupNonUniformBroadcast)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->value = value;
    this->invocationId = invocationId;
  }

  static constexpr Op OpCode = Op::GroupNonUniformBroadcast;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id value;
  Id invocationId;
};

struct OpGroupNonUniformBroadcastFirst
{
  OpGroupNonUniformBroadcastFirst(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformBroadcastFirst(IdResultType resultType, IdResult result, IdScope execution, Id value)
      : op(Op::GroupNonUniformBroadcastFirst)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->value = value;
  }

  static constexpr Op OpCode = Op::GroupNonUniformBroadcastFirst;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id value;
};

struct OpGroupNonUniformBallot
{
  OpGroupNonUniformBallot(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformBallot(IdResultType resultType, IdResult result, IdScope execution, Id predicate)
      : op(Op::GroupNonUniformBallot)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->predicate = predicate;
  }

  static constexpr Op OpCode = Op::GroupNonUniformBallot;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id predicate;
};

struct OpGroupNonUniformInverseBallot
{
  OpGroupNonUniformInverseBallot(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformInverseBallot(IdResultType resultType, IdResult result, IdScope execution, Id value)
      : op(Op::GroupNonUniformInverseBallot)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->value = value;
  }

  static constexpr Op OpCode = Op::GroupNonUniformInverseBallot;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id value;
};

struct OpGroupNonUniformBallotBitExtract
{
  OpGroupNonUniformBallotBitExtract(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformBallotBitExtract(IdResultType resultType, IdResult result, IdScope execution, Id value, Id index)
      : op(Op::GroupNonUniformBallotBitExtract)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->value = value;
    this->index = index;
  }

  static constexpr Op OpCode = Op::GroupNonUniformBallotBitExtract;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id value;
  Id index;
};

struct OpGroupNonUniformBallotBitCount
{
  OpGroupNonUniformBallotBitCount(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformBallotBitCount(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id value)
      : op(Op::GroupNonUniformBallotBitCount)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->value = value;
  }

  static constexpr Op OpCode = Op::GroupNonUniformBallotBitCount;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id value;
};

struct OpGroupNonUniformBallotFindLSB
{
  OpGroupNonUniformBallotFindLSB(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformBallotFindLSB(IdResultType resultType, IdResult result, IdScope execution, Id value)
      : op(Op::GroupNonUniformBallotFindLSB)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->value = value;
  }

  static constexpr Op OpCode = Op::GroupNonUniformBallotFindLSB;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id value;
};

struct OpGroupNonUniformBallotFindMSB
{
  OpGroupNonUniformBallotFindMSB(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformBallotFindMSB(IdResultType resultType, IdResult result, IdScope execution, Id value)
      : op(Op::GroupNonUniformBallotFindMSB)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->value = value;
  }

  static constexpr Op OpCode = Op::GroupNonUniformBallotFindMSB;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id value;
};

struct OpGroupNonUniformShuffle
{
  OpGroupNonUniformShuffle(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformShuffle(IdResultType resultType, IdResult result, IdScope execution, Id value, Id invocationId)
      : op(Op::GroupNonUniformShuffle)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->value = value;
    this->invocationId = invocationId;
  }

  static constexpr Op OpCode = Op::GroupNonUniformShuffle;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id value;
  Id invocationId;
};

struct OpGroupNonUniformShuffleXor
{
  OpGroupNonUniformShuffleXor(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformShuffleXor(IdResultType resultType, IdResult result, IdScope execution, Id value, Id mask)
      : op(Op::GroupNonUniformShuffleXor)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->value = value;
    this->mask = mask;
  }

  static constexpr Op OpCode = Op::GroupNonUniformShuffleXor;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id value;
  Id mask;
};

struct OpGroupNonUniformShuffleUp
{
  OpGroupNonUniformShuffleUp(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformShuffleUp(IdResultType resultType, IdResult result, IdScope execution, Id value, Id delta)
      : op(Op::GroupNonUniformShuffleUp)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->value = value;
    this->delta = delta;
  }

  static constexpr Op OpCode = Op::GroupNonUniformShuffleUp;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id value;
  Id delta;
};

struct OpGroupNonUniformShuffleDown
{
  OpGroupNonUniformShuffleDown(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformShuffleDown(IdResultType resultType, IdResult result, IdScope execution, Id value, Id delta)
      : op(Op::GroupNonUniformShuffleDown)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->value = value;
    this->delta = delta;
  }

  static constexpr Op OpCode = Op::GroupNonUniformShuffleDown;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id value;
  Id delta;
};

struct OpGroupNonUniformIAdd
{
  OpGroupNonUniformIAdd(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->execution = Id::fromWord(it.word(3));
    this->operation = (GroupOperation)it.word(4);
    this->value = Id::fromWord(it.word(5));
    this->clusterSize = (it.size() > 6) ? Id::fromWord(it.word(6)) : Id();
  }
  OpGroupNonUniformIAdd(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id value, Id clusterSize = Id())
      : op(Op::GroupNonUniformIAdd)
      , wordCount(MinWordSize + OptionalWordCount(clusterSize))
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->value = value;
    this->clusterSize = clusterSize;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(execution.value());
    words.push_back((uint32_t)operation);
    words.push_back(value.value());
    if(clusterSize != Id()) words.push_back(clusterSize.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GroupNonUniformIAdd;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id value;
  Id clusterSize;

  bool HasClusterSize() const { return wordCount > 6; }
};

struct OpGroupNonUniformFAdd
{
  OpGroupNonUniformFAdd(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->execution = Id::fromWord(it.word(3));
    this->operation = (GroupOperation)it.word(4);
    this->value = Id::fromWord(it.word(5));
    this->clusterSize = (it.size() > 6) ? Id::fromWord(it.word(6)) : Id();
  }
  OpGroupNonUniformFAdd(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id value, Id clusterSize = Id())
      : op(Op::GroupNonUniformFAdd)
      , wordCount(MinWordSize + OptionalWordCount(clusterSize))
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->value = value;
    this->clusterSize = clusterSize;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(execution.value());
    words.push_back((uint32_t)operation);
    words.push_back(value.value());
    if(clusterSize != Id()) words.push_back(clusterSize.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GroupNonUniformFAdd;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id value;
  Id clusterSize;

  bool HasClusterSize() const { return wordCount > 6; }
};

struct OpGroupNonUniformIMul
{
  OpGroupNonUniformIMul(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->execution = Id::fromWord(it.word(3));
    this->operation = (GroupOperation)it.word(4);
    this->value = Id::fromWord(it.word(5));
    this->clusterSize = (it.size() > 6) ? Id::fromWord(it.word(6)) : Id();
  }
  OpGroupNonUniformIMul(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id value, Id clusterSize = Id())
      : op(Op::GroupNonUniformIMul)
      , wordCount(MinWordSize + OptionalWordCount(clusterSize))
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->value = value;
    this->clusterSize = clusterSize;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(execution.value());
    words.push_back((uint32_t)operation);
    words.push_back(value.value());
    if(clusterSize != Id()) words.push_back(clusterSize.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GroupNonUniformIMul;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id value;
  Id clusterSize;

  bool HasClusterSize() const { return wordCount > 6; }
};

struct OpGroupNonUniformFMul
{
  OpGroupNonUniformFMul(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->execution = Id::fromWord(it.word(3));
    this->operation = (GroupOperation)it.word(4);
    this->value = Id::fromWord(it.word(5));
    this->clusterSize = (it.size() > 6) ? Id::fromWord(it.word(6)) : Id();
  }
  OpGroupNonUniformFMul(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id value, Id clusterSize = Id())
      : op(Op::GroupNonUniformFMul)
      , wordCount(MinWordSize + OptionalWordCount(clusterSize))
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->value = value;
    this->clusterSize = clusterSize;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(execution.value());
    words.push_back((uint32_t)operation);
    words.push_back(value.value());
    if(clusterSize != Id()) words.push_back(clusterSize.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GroupNonUniformFMul;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id value;
  Id clusterSize;

  bool HasClusterSize() const { return wordCount > 6; }
};

struct OpGroupNonUniformSMin
{
  OpGroupNonUniformSMin(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->execution = Id::fromWord(it.word(3));
    this->operation = (GroupOperation)it.word(4);
    this->value = Id::fromWord(it.word(5));
    this->clusterSize = (it.size() > 6) ? Id::fromWord(it.word(6)) : Id();
  }
  OpGroupNonUniformSMin(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id value, Id clusterSize = Id())
      : op(Op::GroupNonUniformSMin)
      , wordCount(MinWordSize + OptionalWordCount(clusterSize))
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->value = value;
    this->clusterSize = clusterSize;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(execution.value());
    words.push_back((uint32_t)operation);
    words.push_back(value.value());
    if(clusterSize != Id()) words.push_back(clusterSize.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GroupNonUniformSMin;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id value;
  Id clusterSize;

  bool HasClusterSize() const { return wordCount > 6; }
};

struct OpGroupNonUniformUMin
{
  OpGroupNonUniformUMin(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->execution = Id::fromWord(it.word(3));
    this->operation = (GroupOperation)it.word(4);
    this->value = Id::fromWord(it.word(5));
    this->clusterSize = (it.size() > 6) ? Id::fromWord(it.word(6)) : Id();
  }
  OpGroupNonUniformUMin(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id value, Id clusterSize = Id())
      : op(Op::GroupNonUniformUMin)
      , wordCount(MinWordSize + OptionalWordCount(clusterSize))
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->value = value;
    this->clusterSize = clusterSize;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(execution.value());
    words.push_back((uint32_t)operation);
    words.push_back(value.value());
    if(clusterSize != Id()) words.push_back(clusterSize.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GroupNonUniformUMin;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id value;
  Id clusterSize;

  bool HasClusterSize() const { return wordCount > 6; }
};

struct OpGroupNonUniformFMin
{
  OpGroupNonUniformFMin(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->execution = Id::fromWord(it.word(3));
    this->operation = (GroupOperation)it.word(4);
    this->value = Id::fromWord(it.word(5));
    this->clusterSize = (it.size() > 6) ? Id::fromWord(it.word(6)) : Id();
  }
  OpGroupNonUniformFMin(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id value, Id clusterSize = Id())
      : op(Op::GroupNonUniformFMin)
      , wordCount(MinWordSize + OptionalWordCount(clusterSize))
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->value = value;
    this->clusterSize = clusterSize;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(execution.value());
    words.push_back((uint32_t)operation);
    words.push_back(value.value());
    if(clusterSize != Id()) words.push_back(clusterSize.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GroupNonUniformFMin;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id value;
  Id clusterSize;

  bool HasClusterSize() const { return wordCount > 6; }
};

struct OpGroupNonUniformSMax
{
  OpGroupNonUniformSMax(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->execution = Id::fromWord(it.word(3));
    this->operation = (GroupOperation)it.word(4);
    this->value = Id::fromWord(it.word(5));
    this->clusterSize = (it.size() > 6) ? Id::fromWord(it.word(6)) : Id();
  }
  OpGroupNonUniformSMax(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id value, Id clusterSize = Id())
      : op(Op::GroupNonUniformSMax)
      , wordCount(MinWordSize + OptionalWordCount(clusterSize))
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->value = value;
    this->clusterSize = clusterSize;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(execution.value());
    words.push_back((uint32_t)operation);
    words.push_back(value.value());
    if(clusterSize != Id()) words.push_back(clusterSize.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GroupNonUniformSMax;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id value;
  Id clusterSize;

  bool HasClusterSize() const { return wordCount > 6; }
};

struct OpGroupNonUniformUMax
{
  OpGroupNonUniformUMax(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->execution = Id::fromWord(it.word(3));
    this->operation = (GroupOperation)it.word(4);
    this->value = Id::fromWord(it.word(5));
    this->clusterSize = (it.size() > 6) ? Id::fromWord(it.word(6)) : Id();
  }
  OpGroupNonUniformUMax(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id value, Id clusterSize = Id())
      : op(Op::GroupNonUniformUMax)
      , wordCount(MinWordSize + OptionalWordCount(clusterSize))
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->value = value;
    this->clusterSize = clusterSize;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(execution.value());
    words.push_back((uint32_t)operation);
    words.push_back(value.value());
    if(clusterSize != Id()) words.push_back(clusterSize.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GroupNonUniformUMax;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id value;
  Id clusterSize;

  bool HasClusterSize() const { return wordCount > 6; }
};

struct OpGroupNonUniformFMax
{
  OpGroupNonUniformFMax(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->execution = Id::fromWord(it.word(3));
    this->operation = (GroupOperation)it.word(4);
    this->value = Id::fromWord(it.word(5));
    this->clusterSize = (it.size() > 6) ? Id::fromWord(it.word(6)) : Id();
  }
  OpGroupNonUniformFMax(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id value, Id clusterSize = Id())
      : op(Op::GroupNonUniformFMax)
      , wordCount(MinWordSize + OptionalWordCount(clusterSize))
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->value = value;
    this->clusterSize = clusterSize;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(execution.value());
    words.push_back((uint32_t)operation);
    words.push_back(value.value());
    if(clusterSize != Id()) words.push_back(clusterSize.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GroupNonUniformFMax;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id value;
  Id clusterSize;

  bool HasClusterSize() const { return wordCount > 6; }
};

struct OpGroupNonUniformBitwiseAnd
{
  OpGroupNonUniformBitwiseAnd(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->execution = Id::fromWord(it.word(3));
    this->operation = (GroupOperation)it.word(4);
    this->value = Id::fromWord(it.word(5));
    this->clusterSize = (it.size() > 6) ? Id::fromWord(it.word(6)) : Id();
  }
  OpGroupNonUniformBitwiseAnd(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id value, Id clusterSize = Id())
      : op(Op::GroupNonUniformBitwiseAnd)
      , wordCount(MinWordSize + OptionalWordCount(clusterSize))
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->value = value;
    this->clusterSize = clusterSize;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(execution.value());
    words.push_back((uint32_t)operation);
    words.push_back(value.value());
    if(clusterSize != Id()) words.push_back(clusterSize.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GroupNonUniformBitwiseAnd;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id value;
  Id clusterSize;

  bool HasClusterSize() const { return wordCount > 6; }
};

struct OpGroupNonUniformBitwiseOr
{
  OpGroupNonUniformBitwiseOr(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->execution = Id::fromWord(it.word(3));
    this->operation = (GroupOperation)it.word(4);
    this->value = Id::fromWord(it.word(5));
    this->clusterSize = (it.size() > 6) ? Id::fromWord(it.word(6)) : Id();
  }
  OpGroupNonUniformBitwiseOr(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id value, Id clusterSize = Id())
      : op(Op::GroupNonUniformBitwiseOr)
      , wordCount(MinWordSize + OptionalWordCount(clusterSize))
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->value = value;
    this->clusterSize = clusterSize;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(execution.value());
    words.push_back((uint32_t)operation);
    words.push_back(value.value());
    if(clusterSize != Id()) words.push_back(clusterSize.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GroupNonUniformBitwiseOr;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id value;
  Id clusterSize;

  bool HasClusterSize() const { return wordCount > 6; }
};

struct OpGroupNonUniformBitwiseXor
{
  OpGroupNonUniformBitwiseXor(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->execution = Id::fromWord(it.word(3));
    this->operation = (GroupOperation)it.word(4);
    this->value = Id::fromWord(it.word(5));
    this->clusterSize = (it.size() > 6) ? Id::fromWord(it.word(6)) : Id();
  }
  OpGroupNonUniformBitwiseXor(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id value, Id clusterSize = Id())
      : op(Op::GroupNonUniformBitwiseXor)
      , wordCount(MinWordSize + OptionalWordCount(clusterSize))
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->value = value;
    this->clusterSize = clusterSize;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(execution.value());
    words.push_back((uint32_t)operation);
    words.push_back(value.value());
    if(clusterSize != Id()) words.push_back(clusterSize.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GroupNonUniformBitwiseXor;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id value;
  Id clusterSize;

  bool HasClusterSize() const { return wordCount > 6; }
};

struct OpGroupNonUniformLogicalAnd
{
  OpGroupNonUniformLogicalAnd(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->execution = Id::fromWord(it.word(3));
    this->operation = (GroupOperation)it.word(4);
    this->value = Id::fromWord(it.word(5));
    this->clusterSize = (it.size() > 6) ? Id::fromWord(it.word(6)) : Id();
  }
  OpGroupNonUniformLogicalAnd(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id value, Id clusterSize = Id())
      : op(Op::GroupNonUniformLogicalAnd)
      , wordCount(MinWordSize + OptionalWordCount(clusterSize))
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->value = value;
    this->clusterSize = clusterSize;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(execution.value());
    words.push_back((uint32_t)operation);
    words.push_back(value.value());
    if(clusterSize != Id()) words.push_back(clusterSize.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GroupNonUniformLogicalAnd;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id value;
  Id clusterSize;

  bool HasClusterSize() const { return wordCount > 6; }
};

struct OpGroupNonUniformLogicalOr
{
  OpGroupNonUniformLogicalOr(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->execution = Id::fromWord(it.word(3));
    this->operation = (GroupOperation)it.word(4);
    this->value = Id::fromWord(it.word(5));
    this->clusterSize = (it.size() > 6) ? Id::fromWord(it.word(6)) : Id();
  }
  OpGroupNonUniformLogicalOr(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id value, Id clusterSize = Id())
      : op(Op::GroupNonUniformLogicalOr)
      , wordCount(MinWordSize + OptionalWordCount(clusterSize))
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->value = value;
    this->clusterSize = clusterSize;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(execution.value());
    words.push_back((uint32_t)operation);
    words.push_back(value.value());
    if(clusterSize != Id()) words.push_back(clusterSize.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GroupNonUniformLogicalOr;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id value;
  Id clusterSize;

  bool HasClusterSize() const { return wordCount > 6; }
};

struct OpGroupNonUniformLogicalXor
{
  OpGroupNonUniformLogicalXor(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->execution = Id::fromWord(it.word(3));
    this->operation = (GroupOperation)it.word(4);
    this->value = Id::fromWord(it.word(5));
    this->clusterSize = (it.size() > 6) ? Id::fromWord(it.word(6)) : Id();
  }
  OpGroupNonUniformLogicalXor(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id value, Id clusterSize = Id())
      : op(Op::GroupNonUniformLogicalXor)
      , wordCount(MinWordSize + OptionalWordCount(clusterSize))
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->value = value;
    this->clusterSize = clusterSize;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(execution.value());
    words.push_back((uint32_t)operation);
    words.push_back(value.value());
    if(clusterSize != Id()) words.push_back(clusterSize.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GroupNonUniformLogicalXor;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id value;
  Id clusterSize;

  bool HasClusterSize() const { return wordCount > 6; }
};

struct OpGroupNonUniformQuadBroadcast
{
  OpGroupNonUniformQuadBroadcast(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformQuadBroadcast(IdResultType resultType, IdResult result, IdScope execution, Id value, Id index)
      : op(Op::GroupNonUniformQuadBroadcast)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->value = value;
    this->index = index;
  }

  static constexpr Op OpCode = Op::GroupNonUniformQuadBroadcast;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id value;
  Id index;
};

struct OpGroupNonUniformQuadSwap
{
  OpGroupNonUniformQuadSwap(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformQuadSwap(IdResultType resultType, IdResult result, IdScope execution, Id value, Id direction)
      : op(Op::GroupNonUniformQuadSwap)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->value = value;
    this->direction = direction;
  }

  static constexpr Op OpCode = Op::GroupNonUniformQuadSwap;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id value;
  Id direction;
};

struct OpCopyLogical
{
  OpCopyLogical(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpCopyLogical(IdResultType resultType, IdResult result, Id operand)
      : op(Op::CopyLogical)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand = operand;
  }

  static constexpr Op OpCode = Op::CopyLogical;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand;
};

struct OpPtrEqual
{
  OpPtrEqual(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpPtrEqual(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::PtrEqual)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::PtrEqual;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpPtrNotEqual
{
  OpPtrNotEqual(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpPtrNotEqual(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::PtrNotEqual)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::PtrNotEqual;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpPtrDiff
{
  OpPtrDiff(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpPtrDiff(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::PtrDiff)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::PtrDiff;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpColorAttachmentReadEXT
{
  OpColorAttachmentReadEXT(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->attachment = Id::fromWord(it.word(3));
    this->sample = (it.size() > 4) ? Id::fromWord(it.word(4)) : Id();
  }
  OpColorAttachmentReadEXT(IdResultType resultType, IdResult result, Id attachment, Id sample = Id())
      : op(Op::ColorAttachmentReadEXT)
      , wordCount(MinWordSize + OptionalWordCount(sample))
  {
    this->resultType = resultType;
    this->result = result;
    this->attachment = attachment;
    this->sample = sample;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(attachment.value());
    if(sample != Id()) words.push_back(sample.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ColorAttachmentReadEXT;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id attachment;
  Id sample;

  bool HasSample() const { return wordCount > 4; }
};

struct OpDepthAttachmentReadEXT
{
  OpDepthAttachmentReadEXT(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sample = (it.size() > 3) ? Id::fromWord(it.word(3)) : Id();
  }
  OpDepthAttachmentReadEXT(IdResultType resultType, IdResult result, Id sample = Id())
      : op(Op::DepthAttachmentReadEXT)
      , wordCount(MinWordSize + OptionalWordCount(sample))
  {
    this->resultType = resultType;
    this->result = result;
    this->sample = sample;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    if(sample != Id()) words.push_back(sample.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::DepthAttachmentReadEXT;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sample;

  bool HasSample() const { return wordCount > 3; }
};

struct OpStencilAttachmentReadEXT
{
  OpStencilAttachmentReadEXT(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sample = (it.size() > 3) ? Id::fromWord(it.word(3)) : Id();
  }
  OpStencilAttachmentReadEXT(IdResultType resultType, IdResult result, Id sample = Id())
      : op(Op::StencilAttachmentReadEXT)
      , wordCount(MinWordSize + OptionalWordCount(sample))
  {
    this->resultType = resultType;
    this->result = result;
    this->sample = sample;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    if(sample != Id()) words.push_back(sample.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::StencilAttachmentReadEXT;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sample;

  bool HasSample() const { return wordCount > 3; }
};

struct OpTypeTensorARM
{
  OpTypeTensorARM(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->result = Id::fromWord(it.word(1));
    this->elementType = Id::fromWord(it.word(2));
    this->rank = (it.size() > 3) ? Id::fromWord(it.word(3)) : Id();
    this->shape = (it.size() > 4) ? Id::fromWord(it.word(4)) : Id();
  }
  OpTypeTensorARM(IdResult result, Id elementType, Id rank = Id(), Id shape = Id())
      : op(Op::TypeTensorARM)
      , wordCount(MinWordSize + OptionalWordCount(rank) + OptionalWordCount(shape))
  {
    this->result = result;
    this->elementType = elementType;
    this->rank = rank;
    this->shape = shape;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(result.value());
    words.push_back(elementType.value());
    if(rank != Id()) words.push_back(rank.value());
    if(shape != Id()) words.push_back(shape.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::TypeTensorARM;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  Id elementType;
  Id rank;
  Id shape;

  bool HasRank() const { return wordCount > 3; }
  bool HasShape() const { return wordCount > 4; }
};

struct OpTensorReadARM
{
  OpTensorReadARM(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->tensor = Id::fromWord(it.word(3));
    this->coordinates = Id::fromWord(it.word(4));
    word = 5;
    this->tensorOperands = DecodeParam<TensorOperandsAndParamDatas>(it, word);
  }
  OpTensorReadARM(IdResultType resultType, IdResult result, Id tensor, Id coordinates, TensorOperandsAndParamDatas tensorOperands = TensorOperands::NoneARM)
      : op(Op::TensorReadARM)
      , wordCount(MinWordSize + ExtraWordCount(tensorOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->tensor = tensor;
    this->coordinates = coordinates;
    this->tensorOperands = tensorOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(tensor.value());
    words.push_back(coordinates.value());
    EncodeParam(words, tensorOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::TensorReadARM;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id tensor;
  Id coordinates;
  TensorOperandsAndParamDatas tensorOperands;
};

struct OpTensorWriteARM
{
  OpTensorWriteARM(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->tensor = Id::fromWord(it.word(1));
    this->coordinates = Id::fromWord(it.word(2));
    this->object = Id::fromWord(it.word(3));
    word = 4;
    this->tensorOperands = DecodeParam<TensorOperandsAndParamDatas>(it, word);
  }
  OpTensorWriteARM(Id tensor, Id coordinates, Id object, TensorOperandsAndParamDatas tensorOperands = TensorOperands::NoneARM)
      : op(Op::TensorWriteARM)
      , wordCount(MinWordSize + ExtraWordCount(tensorOperands))
  {
    this->tensor = tensor;
    this->coordinates = coordinates;
    this->object = object;
    this->tensorOperands = tensorOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(tensor.value());
    words.push_back(coordinates.value());
    words.push_back(object.value());
    EncodeParam(words, tensorOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::TensorWriteARM;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  Id tensor;
  Id coordinates;
  Id object;
  TensorOperandsAndParamDatas tensorOperands;
};

struct OpTensorQuerySizeARM
{
  OpTensorQuerySizeARM(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTensorQuerySizeARM(IdResultType resultType, IdResult result, Id tensor, Id dimension)
      : op(Op::TensorQuerySizeARM)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->tensor = tensor;
    this->dimension = dimension;
  }

  static constexpr Op OpCode = Op::TensorQuerySizeARM;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id tensor;
  Id dimension;
};

struct OpGraphConstantARM
{
  OpGraphConstantARM(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGraphConstantARM(IdResultType resultType, IdResult result, uint32_t graphConstantID)
      : op(Op::GraphConstantARM)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->graphConstantID = graphConstantID;
  }

  static constexpr Op OpCode = Op::GraphConstantARM;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  uint32_t graphConstantID;
};

struct OpGraphEntryPointARM
{
  OpGraphEntryPointARM(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->graph = Id::fromWord(it.word(1));
    word = 2;
    this->name = DecodeParam<rdcstr>(it, word);
    this->iface = MultiParam<Id>(it, word);
  }
  OpGraphEntryPointARM(Id graph, rdcstr name, const rdcarray<Id> &iface = {})
      : op(Op::GraphEntryPointARM)
      , wordCount(MinWordSize + ExtraWordCount(name) + MultiWordCount(iface))
  {
    this->graph = graph;
    this->name = name;
    this->iface = iface;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(graph.value());
    EncodeParam(words, name);
    for(size_t i=0; i < iface.size(); i++)
    {
      words.push_back(iface[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GraphEntryPointARM;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id graph;
  rdcstr name;
  rdcarray<Id> iface;
};

struct OpGraphARM
{
  OpGraphARM(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGraphARM(IdResultType resultType, IdResult result)
      : op(Op::GraphARM)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
  }

  static constexpr Op OpCode = Op::GraphARM;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
};

struct OpGraphInputARM
{
  OpGraphInputARM(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->inputIndex = Id::fromWord(it.word(3));
    word = 4;
    this->elementIndex = MultiParam<Id>(it, word);
  }
  OpGraphInputARM(IdResultType resultType, IdResult result, Id inputIndex, const rdcarray<Id> &elementIndex = {})
      : op(Op::GraphInputARM)
      , wordCount(MinWordSize + MultiWordCount(elementIndex))
  {
    this->resultType = resultType;
    this->result = result;
    this->inputIndex = inputIndex;
    this->elementIndex = elementIndex;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(inputIndex.value());
    for(size_t i=0; i < elementIndex.size(); i++)
    {
      words.push_back(elementIndex[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GraphInputARM;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id inputIndex;
  rdcarray<Id> elementIndex;
};

struct OpGraphSetOutputARM
{
  OpGraphSetOutputARM(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->value = Id::fromWord(it.word(1));
    this->outputIndex = Id::fromWord(it.word(2));
    word = 3;
    this->elementIndex = MultiParam<Id>(it, word);
  }
  OpGraphSetOutputARM(Id value, Id outputIndex, const rdcarray<Id> &elementIndex = {})
      : op(Op::GraphSetOutputARM)
      , wordCount(MinWordSize + MultiWordCount(elementIndex))
  {
    this->value = value;
    this->outputIndex = outputIndex;
    this->elementIndex = elementIndex;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(value.value());
    words.push_back(outputIndex.value());
    for(size_t i=0; i < elementIndex.size(); i++)
    {
      words.push_back(elementIndex[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GraphSetOutputARM;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id value;
  Id outputIndex;
  rdcarray<Id> elementIndex;
};

struct OpGraphEndARM
{
  OpGraphEndARM(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGraphEndARM()
      : op(Op::GraphEndARM)
      , wordCount(FixedWordSize)
  {
    // no operands
  }

  static constexpr Op OpCode = Op::GraphEndARM;
  static constexpr uint16_t FixedWordSize = 1U;
  Op op;
  uint16_t wordCount;
  // no operands
};

struct OpTypeGraphARM
{
  OpTypeGraphARM(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->result = Id::fromWord(it.word(1));
    this->numInputs = (uint32_t)it.word(2);
    word = 3;
    this->inOutTypes = MultiParam<Id>(it, word);
  }
  OpTypeGraphARM(IdResult result, uint32_t numInputs, const rdcarray<Id> &inOutTypes = {})
      : op(Op::TypeGraphARM)
      , wordCount(MinWordSize + MultiWordCount(inOutTypes))
  {
    this->result = result;
    this->numInputs = numInputs;
    this->inOutTypes = inOutTypes;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(result.value());
    words.push_back((uint32_t)numInputs);
    for(size_t i=0; i < inOutTypes.size(); i++)
    {
      words.push_back(inOutTypes[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::TypeGraphARM;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  uint32_t numInputs;
  rdcarray<Id> inOutTypes;
};

struct OpTerminateInvocation
{
  OpTerminateInvocation(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTerminateInvocation()
      : op(Op::TerminateInvocation)
      , wordCount(FixedWordSize)
  {
    // no operands
  }

  static constexpr Op OpCode = Op::TerminateInvocation;
  static constexpr uint16_t FixedWordSize = 1U;
  Op op;
  uint16_t wordCount;
  // no operands
};

struct OpTypeUntypedPointerKHR
{
  OpTypeUntypedPointerKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeUntypedPointerKHR(IdResult result, StorageClass storageClass)
      : op(Op::TypeUntypedPointerKHR)
      , wordCount(FixedWordSize)
  {
    this->result = result;
    this->storageClass = storageClass;
  }

  static constexpr Op OpCode = Op::TypeUntypedPointerKHR;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  StorageClass storageClass;
};

struct OpUntypedVariableKHR
{
  OpUntypedVariableKHR(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->storageClass = (StorageClass)it.word(3);
    this->dataType = (it.size() > 4) ? Id::fromWord(it.word(4)) : Id();
    this->initializer = (it.size() > 5) ? Id::fromWord(it.word(5)) : Id();
  }
  OpUntypedVariableKHR(IdResultType resultType, IdResult result, StorageClass storageClass, Id dataType = Id(), Id initializer = Id())
      : op(Op::UntypedVariableKHR)
      , wordCount(MinWordSize + OptionalWordCount(dataType) + OptionalWordCount(initializer))
  {
    this->resultType = resultType;
    this->result = result;
    this->storageClass = storageClass;
    this->dataType = dataType;
    this->initializer = initializer;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back((uint32_t)storageClass);
    if(dataType != Id()) words.push_back(dataType.value());
    if(initializer != Id()) words.push_back(initializer.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::UntypedVariableKHR;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  StorageClass storageClass;
  Id dataType;
  Id initializer;

  bool HasDataType() const { return wordCount > 4; }
  bool HasInitializer() const { return wordCount > 5; }
};

struct OpUntypedAccessChainKHR
{
  OpUntypedAccessChainKHR(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->baseType = Id::fromWord(it.word(3));
    this->base = Id::fromWord(it.word(4));
    word = 5;
    this->indexes = MultiParam<Id>(it, word);
  }
  OpUntypedAccessChainKHR(IdResultType resultType, IdResult result, Id baseType, Id base, const rdcarray<Id> &indexes = {})
      : op(Op::UntypedAccessChainKHR)
      , wordCount(MinWordSize + MultiWordCount(indexes))
  {
    this->resultType = resultType;
    this->result = result;
    this->baseType = baseType;
    this->base = base;
    this->indexes = indexes;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(baseType.value());
    words.push_back(base.value());
    for(size_t i=0; i < indexes.size(); i++)
    {
      words.push_back(indexes[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::UntypedAccessChainKHR;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id baseType;
  Id base;
  rdcarray<Id> indexes;
};

struct OpUntypedInBoundsAccessChainKHR
{
  OpUntypedInBoundsAccessChainKHR(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->baseType = Id::fromWord(it.word(3));
    this->base = Id::fromWord(it.word(4));
    word = 5;
    this->indexes = MultiParam<Id>(it, word);
  }
  OpUntypedInBoundsAccessChainKHR(IdResultType resultType, IdResult result, Id baseType, Id base, const rdcarray<Id> &indexes = {})
      : op(Op::UntypedInBoundsAccessChainKHR)
      , wordCount(MinWordSize + MultiWordCount(indexes))
  {
    this->resultType = resultType;
    this->result = result;
    this->baseType = baseType;
    this->base = base;
    this->indexes = indexes;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(baseType.value());
    words.push_back(base.value());
    for(size_t i=0; i < indexes.size(); i++)
    {
      words.push_back(indexes[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::UntypedInBoundsAccessChainKHR;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id baseType;
  Id base;
  rdcarray<Id> indexes;
};

struct OpSubgroupBallotKHR
{
  OpSubgroupBallotKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroupBallotKHR(IdResultType resultType, IdResult result, Id predicate)
      : op(Op::SubgroupBallotKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->predicate = predicate;
  }

  static constexpr Op OpCode = Op::SubgroupBallotKHR;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id predicate;
};

struct OpSubgroupFirstInvocationKHR
{
  OpSubgroupFirstInvocationKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroupFirstInvocationKHR(IdResultType resultType, IdResult result, Id value)
      : op(Op::SubgroupFirstInvocationKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->value = value;
  }

  static constexpr Op OpCode = Op::SubgroupFirstInvocationKHR;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id value;
};

struct OpUntypedPtrAccessChainKHR
{
  OpUntypedPtrAccessChainKHR(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->baseType = Id::fromWord(it.word(3));
    this->base = Id::fromWord(it.word(4));
    this->element = Id::fromWord(it.word(5));
    word = 6;
    this->indexes = MultiParam<Id>(it, word);
  }
  OpUntypedPtrAccessChainKHR(IdResultType resultType, IdResult result, Id baseType, Id base, Id element, const rdcarray<Id> &indexes = {})
      : op(Op::UntypedPtrAccessChainKHR)
      , wordCount(MinWordSize + MultiWordCount(indexes))
  {
    this->resultType = resultType;
    this->result = result;
    this->baseType = baseType;
    this->base = base;
    this->element = element;
    this->indexes = indexes;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(baseType.value());
    words.push_back(base.value());
    words.push_back(element.value());
    for(size_t i=0; i < indexes.size(); i++)
    {
      words.push_back(indexes[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::UntypedPtrAccessChainKHR;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id baseType;
  Id base;
  Id element;
  rdcarray<Id> indexes;
};

struct OpUntypedInBoundsPtrAccessChainKHR
{
  OpUntypedInBoundsPtrAccessChainKHR(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->baseType = Id::fromWord(it.word(3));
    this->base = Id::fromWord(it.word(4));
    this->element = Id::fromWord(it.word(5));
    word = 6;
    this->indexes = MultiParam<Id>(it, word);
  }
  OpUntypedInBoundsPtrAccessChainKHR(IdResultType resultType, IdResult result, Id baseType, Id base, Id element, const rdcarray<Id> &indexes = {})
      : op(Op::UntypedInBoundsPtrAccessChainKHR)
      , wordCount(MinWordSize + MultiWordCount(indexes))
  {
    this->resultType = resultType;
    this->result = result;
    this->baseType = baseType;
    this->base = base;
    this->element = element;
    this->indexes = indexes;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(baseType.value());
    words.push_back(base.value());
    words.push_back(element.value());
    for(size_t i=0; i < indexes.size(); i++)
    {
      words.push_back(indexes[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::UntypedInBoundsPtrAccessChainKHR;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id baseType;
  Id base;
  Id element;
  rdcarray<Id> indexes;
};

struct OpUntypedArrayLengthKHR
{
  OpUntypedArrayLengthKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpUntypedArrayLengthKHR(IdResultType resultType, IdResult result, Id structure, Id pointer, uint32_t arraymember)
      : op(Op::UntypedArrayLengthKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->structure = structure;
    this->pointer = pointer;
    this->arraymember = arraymember;
  }

  static constexpr Op OpCode = Op::UntypedArrayLengthKHR;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id structure;
  Id pointer;
  uint32_t arraymember;
};

struct OpUntypedPrefetchKHR
{
  OpUntypedPrefetchKHR(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->pointerType = Id::fromWord(it.word(1));
    this->numBytes = Id::fromWord(it.word(2));
    this->rW = (it.size() > 3) ? Id::fromWord(it.word(3)) : Id();
    this->locality = (it.size() > 4) ? Id::fromWord(it.word(4)) : Id();
    this->cacheType = (it.size() > 5) ? Id::fromWord(it.word(5)) : Id();
  }
  OpUntypedPrefetchKHR(Id pointerType, Id numBytes, Id rW = Id(), Id locality = Id(), Id cacheType = Id())
      : op(Op::UntypedPrefetchKHR)
      , wordCount(MinWordSize + OptionalWordCount(rW) + OptionalWordCount(locality) + OptionalWordCount(cacheType))
  {
    this->pointerType = pointerType;
    this->numBytes = numBytes;
    this->rW = rW;
    this->locality = locality;
    this->cacheType = cacheType;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(pointerType.value());
    words.push_back(numBytes.value());
    if(rW != Id()) words.push_back(rW.value());
    if(locality != Id()) words.push_back(locality.value());
    if(cacheType != Id()) words.push_back(cacheType.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::UntypedPrefetchKHR;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id pointerType;
  Id numBytes;
  Id rW;
  Id locality;
  Id cacheType;

  bool HasRW() const { return wordCount > 3; }
  bool HasLocality() const { return wordCount > 4; }
  bool HasCacheType() const { return wordCount > 5; }
};

struct OpFmaKHR
{
  OpFmaKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFmaKHR(IdResultType resultType, IdResult result, Id operand1, Id operand2, Id operand3)
      : op(Op::FmaKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
    this->operand3 = operand3;
  }

  static constexpr Op OpCode = Op::FmaKHR;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
  Id operand3;
};

struct OpSubgroupAllKHR
{
  OpSubgroupAllKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroupAllKHR(IdResultType resultType, IdResult result, Id predicate)
      : op(Op::SubgroupAllKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->predicate = predicate;
  }

  static constexpr Op OpCode = Op::SubgroupAllKHR;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id predicate;
};

struct OpSubgroupAnyKHR
{
  OpSubgroupAnyKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroupAnyKHR(IdResultType resultType, IdResult result, Id predicate)
      : op(Op::SubgroupAnyKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->predicate = predicate;
  }

  static constexpr Op OpCode = Op::SubgroupAnyKHR;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id predicate;
};

struct OpSubgroupAllEqualKHR
{
  OpSubgroupAllEqualKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroupAllEqualKHR(IdResultType resultType, IdResult result, Id predicate)
      : op(Op::SubgroupAllEqualKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->predicate = predicate;
  }

  static constexpr Op OpCode = Op::SubgroupAllEqualKHR;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id predicate;
};

struct OpGroupNonUniformRotateKHR
{
  OpGroupNonUniformRotateKHR(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->execution = Id::fromWord(it.word(3));
    this->value = Id::fromWord(it.word(4));
    this->delta = Id::fromWord(it.word(5));
    this->clusterSize = (it.size() > 6) ? Id::fromWord(it.word(6)) : Id();
  }
  OpGroupNonUniformRotateKHR(IdResultType resultType, IdResult result, IdScope execution, Id value, Id delta, Id clusterSize = Id())
      : op(Op::GroupNonUniformRotateKHR)
      , wordCount(MinWordSize + OptionalWordCount(clusterSize))
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->value = value;
    this->delta = delta;
    this->clusterSize = clusterSize;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(execution.value());
    words.push_back(value.value());
    words.push_back(delta.value());
    if(clusterSize != Id()) words.push_back(clusterSize.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::GroupNonUniformRotateKHR;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  Id value;
  Id delta;
  Id clusterSize;

  bool HasClusterSize() const { return wordCount > 6; }
};

struct OpSubgroupReadInvocationKHR
{
  OpSubgroupReadInvocationKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroupReadInvocationKHR(IdResultType resultType, IdResult result, Id value, Id index)
      : op(Op::SubgroupReadInvocationKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->value = value;
    this->index = index;
  }

  static constexpr Op OpCode = Op::SubgroupReadInvocationKHR;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id value;
  Id index;
};

struct OpExtInstWithForwardRefsKHR; // has operands with variable sizes

struct OpUntypedGroupAsyncCopyKHR
{
  OpUntypedGroupAsyncCopyKHR(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->execution = Id::fromWord(it.word(3));
    this->destination = Id::fromWord(it.word(4));
    this->source = Id::fromWord(it.word(5));
    this->elementNumBytes = Id::fromWord(it.word(6));
    this->numElements = Id::fromWord(it.word(7));
    this->stride = Id::fromWord(it.word(8));
    this->event = Id::fromWord(it.word(9));
    word = 10;
    this->destinationMemoryOperands = DecodeParam<MemoryAccessAndParamDatas>(it, word);
    this->sourceMemoryOperands = DecodeParam<MemoryAccessAndParamDatas>(it, word);
  }
  OpUntypedGroupAsyncCopyKHR(IdResultType resultType, IdResult result, Id execution, Id destination, Id source, Id elementNumBytes, Id numElements, Id stride, Id event, MemoryAccessAndParamDatas destinationMemoryOperands = MemoryAccess::None, MemoryAccessAndParamDatas sourceMemoryOperands = MemoryAccess::None)
      : op(Op::UntypedGroupAsyncCopyKHR)
      , wordCount(MinWordSize + ExtraWordCount(destinationMemoryOperands) + ExtraWordCount(sourceMemoryOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->destination = destination;
    this->source = source;
    this->elementNumBytes = elementNumBytes;
    this->numElements = numElements;
    this->stride = stride;
    this->event = event;
    this->destinationMemoryOperands = destinationMemoryOperands;
    this->sourceMemoryOperands = sourceMemoryOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(execution.value());
    words.push_back(destination.value());
    words.push_back(source.value());
    words.push_back(elementNumBytes.value());
    words.push_back(numElements.value());
    words.push_back(stride.value());
    words.push_back(event.value());
    EncodeParam(words, destinationMemoryOperands);
    EncodeParam(words, sourceMemoryOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::UntypedGroupAsyncCopyKHR;
  static constexpr uint16_t MinWordSize = 10U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id execution;
  Id destination;
  Id source;
  Id elementNumBytes;
  Id numElements;
  Id stride;
  Id event;
  MemoryAccessAndParamDatas destinationMemoryOperands;
  MemoryAccessAndParamDatas sourceMemoryOperands;
};

struct OpTraceRayKHR
{
  OpTraceRayKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTraceRayKHR(Id accel, Id rayFlags, Id cullMask, Id sBTOffset, Id sBTStride, Id missIndex, Id rayOrigin, Id rayTmin, Id rayDirection, Id rayTmax, Id payload)
      : op(Op::TraceRayKHR)
      , wordCount(FixedWordSize)
  {
    this->accel = accel;
    this->rayFlags = rayFlags;
    this->cullMask = cullMask;
    this->sBTOffset = sBTOffset;
    this->sBTStride = sBTStride;
    this->missIndex = missIndex;
    this->rayOrigin = rayOrigin;
    this->rayTmin = rayTmin;
    this->rayDirection = rayDirection;
    this->rayTmax = rayTmax;
    this->payload = payload;
  }

  static constexpr Op OpCode = Op::TraceRayKHR;
  static constexpr uint16_t FixedWordSize = 12U;
  Op op;
  uint16_t wordCount;
  Id accel;
  Id rayFlags;
  Id cullMask;
  Id sBTOffset;
  Id sBTStride;
  Id missIndex;
  Id rayOrigin;
  Id rayTmin;
  Id rayDirection;
  Id rayTmax;
  Id payload;
};

struct OpExecuteCallableKHR
{
  OpExecuteCallableKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpExecuteCallableKHR(Id sBTIndex, Id callableData)
      : op(Op::ExecuteCallableKHR)
      , wordCount(FixedWordSize)
  {
    this->sBTIndex = sBTIndex;
    this->callableData = callableData;
  }

  static constexpr Op OpCode = Op::ExecuteCallableKHR;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id sBTIndex;
  Id callableData;
};

struct OpConvertUToAccelerationStructureKHR
{
  OpConvertUToAccelerationStructureKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConvertUToAccelerationStructureKHR(IdResultType resultType, IdResult result, Id accel)
      : op(Op::ConvertUToAccelerationStructureKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->accel = accel;
  }

  static constexpr Op OpCode = Op::ConvertUToAccelerationStructureKHR;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id accel;
};

struct OpIgnoreIntersectionKHR
{
  OpIgnoreIntersectionKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpIgnoreIntersectionKHR()
      : op(Op::IgnoreIntersectionKHR)
      , wordCount(FixedWordSize)
  {
    // no operands
  }

  static constexpr Op OpCode = Op::IgnoreIntersectionKHR;
  static constexpr uint16_t FixedWordSize = 1U;
  Op op;
  uint16_t wordCount;
  // no operands
};

struct OpTerminateRayKHR
{
  OpTerminateRayKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTerminateRayKHR()
      : op(Op::TerminateRayKHR)
      , wordCount(FixedWordSize)
  {
    // no operands
  }

  static constexpr Op OpCode = Op::TerminateRayKHR;
  static constexpr uint16_t FixedWordSize = 1U;
  Op op;
  uint16_t wordCount;
  // no operands
};

struct OpSDot
{
  OpSDot(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->vector1 = Id::fromWord(it.word(3));
    this->vector2 = Id::fromWord(it.word(4));
    this->packedVectorFormat = (it.size() > 5) ? (PackedVectorFormat)it.word(5) : PackedVectorFormat::Invalid;
  }
  OpSDot(IdResultType resultType, IdResult result, Id vector1, Id vector2, PackedVectorFormat packedVectorFormat = PackedVectorFormat::Invalid)
      : op(Op::SDot)
      , wordCount(MinWordSize + OptionalWordCount(packedVectorFormat))
  {
    this->resultType = resultType;
    this->result = result;
    this->vector1 = vector1;
    this->vector2 = vector2;
    this->packedVectorFormat = packedVectorFormat;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(vector1.value());
    words.push_back(vector2.value());
    if(packedVectorFormat != PackedVectorFormat::Invalid) words.push_back((uint32_t)packedVectorFormat);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::SDot;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id vector1;
  Id vector2;
  PackedVectorFormat packedVectorFormat;

  bool HasPackedVectorFormat() const { return wordCount > 5; }
};

struct OpUDot
{
  OpUDot(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->vector1 = Id::fromWord(it.word(3));
    this->vector2 = Id::fromWord(it.word(4));
    this->packedVectorFormat = (it.size() > 5) ? (PackedVectorFormat)it.word(5) : PackedVectorFormat::Invalid;
  }
  OpUDot(IdResultType resultType, IdResult result, Id vector1, Id vector2, PackedVectorFormat packedVectorFormat = PackedVectorFormat::Invalid)
      : op(Op::UDot)
      , wordCount(MinWordSize + OptionalWordCount(packedVectorFormat))
  {
    this->resultType = resultType;
    this->result = result;
    this->vector1 = vector1;
    this->vector2 = vector2;
    this->packedVectorFormat = packedVectorFormat;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(vector1.value());
    words.push_back(vector2.value());
    if(packedVectorFormat != PackedVectorFormat::Invalid) words.push_back((uint32_t)packedVectorFormat);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::UDot;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id vector1;
  Id vector2;
  PackedVectorFormat packedVectorFormat;

  bool HasPackedVectorFormat() const { return wordCount > 5; }
};

struct OpSUDot
{
  OpSUDot(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->vector1 = Id::fromWord(it.word(3));
    this->vector2 = Id::fromWord(it.word(4));
    this->packedVectorFormat = (it.size() > 5) ? (PackedVectorFormat)it.word(5) : PackedVectorFormat::Invalid;
  }
  OpSUDot(IdResultType resultType, IdResult result, Id vector1, Id vector2, PackedVectorFormat packedVectorFormat = PackedVectorFormat::Invalid)
      : op(Op::SUDot)
      , wordCount(MinWordSize + OptionalWordCount(packedVectorFormat))
  {
    this->resultType = resultType;
    this->result = result;
    this->vector1 = vector1;
    this->vector2 = vector2;
    this->packedVectorFormat = packedVectorFormat;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(vector1.value());
    words.push_back(vector2.value());
    if(packedVectorFormat != PackedVectorFormat::Invalid) words.push_back((uint32_t)packedVectorFormat);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::SUDot;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id vector1;
  Id vector2;
  PackedVectorFormat packedVectorFormat;

  bool HasPackedVectorFormat() const { return wordCount > 5; }
};

struct OpSDotAccSat
{
  OpSDotAccSat(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->vector1 = Id::fromWord(it.word(3));
    this->vector2 = Id::fromWord(it.word(4));
    this->accumulator = Id::fromWord(it.word(5));
    this->packedVectorFormat = (it.size() > 6) ? (PackedVectorFormat)it.word(6) : PackedVectorFormat::Invalid;
  }
  OpSDotAccSat(IdResultType resultType, IdResult result, Id vector1, Id vector2, Id accumulator, PackedVectorFormat packedVectorFormat = PackedVectorFormat::Invalid)
      : op(Op::SDotAccSat)
      , wordCount(MinWordSize + OptionalWordCount(packedVectorFormat))
  {
    this->resultType = resultType;
    this->result = result;
    this->vector1 = vector1;
    this->vector2 = vector2;
    this->accumulator = accumulator;
    this->packedVectorFormat = packedVectorFormat;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(vector1.value());
    words.push_back(vector2.value());
    words.push_back(accumulator.value());
    if(packedVectorFormat != PackedVectorFormat::Invalid) words.push_back((uint32_t)packedVectorFormat);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::SDotAccSat;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id vector1;
  Id vector2;
  Id accumulator;
  PackedVectorFormat packedVectorFormat;

  bool HasPackedVectorFormat() const { return wordCount > 6; }
};

struct OpUDotAccSat
{
  OpUDotAccSat(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->vector1 = Id::fromWord(it.word(3));
    this->vector2 = Id::fromWord(it.word(4));
    this->accumulator = Id::fromWord(it.word(5));
    this->packedVectorFormat = (it.size() > 6) ? (PackedVectorFormat)it.word(6) : PackedVectorFormat::Invalid;
  }
  OpUDotAccSat(IdResultType resultType, IdResult result, Id vector1, Id vector2, Id accumulator, PackedVectorFormat packedVectorFormat = PackedVectorFormat::Invalid)
      : op(Op::UDotAccSat)
      , wordCount(MinWordSize + OptionalWordCount(packedVectorFormat))
  {
    this->resultType = resultType;
    this->result = result;
    this->vector1 = vector1;
    this->vector2 = vector2;
    this->accumulator = accumulator;
    this->packedVectorFormat = packedVectorFormat;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(vector1.value());
    words.push_back(vector2.value());
    words.push_back(accumulator.value());
    if(packedVectorFormat != PackedVectorFormat::Invalid) words.push_back((uint32_t)packedVectorFormat);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::UDotAccSat;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id vector1;
  Id vector2;
  Id accumulator;
  PackedVectorFormat packedVectorFormat;

  bool HasPackedVectorFormat() const { return wordCount > 6; }
};

struct OpSUDotAccSat
{
  OpSUDotAccSat(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->vector1 = Id::fromWord(it.word(3));
    this->vector2 = Id::fromWord(it.word(4));
    this->accumulator = Id::fromWord(it.word(5));
    this->packedVectorFormat = (it.size() > 6) ? (PackedVectorFormat)it.word(6) : PackedVectorFormat::Invalid;
  }
  OpSUDotAccSat(IdResultType resultType, IdResult result, Id vector1, Id vector2, Id accumulator, PackedVectorFormat packedVectorFormat = PackedVectorFormat::Invalid)
      : op(Op::SUDotAccSat)
      , wordCount(MinWordSize + OptionalWordCount(packedVectorFormat))
  {
    this->resultType = resultType;
    this->result = result;
    this->vector1 = vector1;
    this->vector2 = vector2;
    this->accumulator = accumulator;
    this->packedVectorFormat = packedVectorFormat;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(vector1.value());
    words.push_back(vector2.value());
    words.push_back(accumulator.value());
    if(packedVectorFormat != PackedVectorFormat::Invalid) words.push_back((uint32_t)packedVectorFormat);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::SUDotAccSat;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id vector1;
  Id vector2;
  Id accumulator;
  PackedVectorFormat packedVectorFormat;

  bool HasPackedVectorFormat() const { return wordCount > 6; }
};

struct OpTypeCooperativeMatrixKHR
{
  OpTypeCooperativeMatrixKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeCooperativeMatrixKHR(IdResult result, Id componentType, IdScope scope, Id rows, Id columns, Id use)
      : op(Op::TypeCooperativeMatrixKHR)
      , wordCount(FixedWordSize)
  {
    this->result = result;
    this->componentType = componentType;
    this->scope = scope;
    this->rows = rows;
    this->columns = columns;
    this->use = use;
  }

  static constexpr Op OpCode = Op::TypeCooperativeMatrixKHR;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  Id componentType;
  IdScope scope;
  Id rows;
  Id columns;
  Id use;
};

struct OpCooperativeMatrixLoadKHR
{
  OpCooperativeMatrixLoadKHR(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->pointer = Id::fromWord(it.word(3));
    this->memoryLayout = Id::fromWord(it.word(4));
    this->stride = (it.size() > 5) ? Id::fromWord(it.word(5)) : Id();
    this->memoryOperand = DecodeParam<MemoryAccessAndParamDatas>(it, word);
  }
  OpCooperativeMatrixLoadKHR(IdResultType resultType, IdResult result, Id pointer, Id memoryLayout, Id stride = Id(), MemoryAccessAndParamDatas memoryOperand = MemoryAccess::None)
      : op(Op::CooperativeMatrixLoadKHR)
      , wordCount(MinWordSize + OptionalWordCount(stride) + ExtraWordCount(memoryOperand))
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memoryLayout = memoryLayout;
    this->stride = stride;
    this->memoryOperand = memoryOperand;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(pointer.value());
    words.push_back(memoryLayout.value());
    if(stride != Id()) words.push_back(stride.value());
    EncodeParam(words, memoryOperand);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::CooperativeMatrixLoadKHR;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  Id memoryLayout;
  Id stride;
  MemoryAccessAndParamDatas memoryOperand;

  bool HasStride() const { return wordCount > 5; }
};

struct OpCooperativeMatrixStoreKHR
{
  OpCooperativeMatrixStoreKHR(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->pointer = Id::fromWord(it.word(1));
    this->object = Id::fromWord(it.word(2));
    this->memoryLayout = Id::fromWord(it.word(3));
    this->stride = (it.size() > 4) ? Id::fromWord(it.word(4)) : Id();
    this->memoryOperand = DecodeParam<MemoryAccessAndParamDatas>(it, word);
  }
  OpCooperativeMatrixStoreKHR(Id pointer, Id object, Id memoryLayout, Id stride = Id(), MemoryAccessAndParamDatas memoryOperand = MemoryAccess::None)
      : op(Op::CooperativeMatrixStoreKHR)
      , wordCount(MinWordSize + OptionalWordCount(stride) + ExtraWordCount(memoryOperand))
  {
    this->pointer = pointer;
    this->object = object;
    this->memoryLayout = memoryLayout;
    this->stride = stride;
    this->memoryOperand = memoryOperand;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(pointer.value());
    words.push_back(object.value());
    words.push_back(memoryLayout.value());
    if(stride != Id()) words.push_back(stride.value());
    EncodeParam(words, memoryOperand);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::CooperativeMatrixStoreKHR;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  Id pointer;
  Id object;
  Id memoryLayout;
  Id stride;
  MemoryAccessAndParamDatas memoryOperand;

  bool HasStride() const { return wordCount > 4; }
};

struct OpCooperativeMatrixMulAddKHR
{
  OpCooperativeMatrixMulAddKHR(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->a = Id::fromWord(it.word(3));
    this->b = Id::fromWord(it.word(4));
    this->c = Id::fromWord(it.word(5));
    this->cooperativeMatrixOperands = (it.size() > 6) ? (CooperativeMatrixOperands)it.word(6) : CooperativeMatrixOperands::NoneKHR;
  }
  OpCooperativeMatrixMulAddKHR(IdResultType resultType, IdResult result, Id a, Id b, Id c, CooperativeMatrixOperands cooperativeMatrixOperands = CooperativeMatrixOperands::NoneKHR)
      : op(Op::CooperativeMatrixMulAddKHR)
      , wordCount(MinWordSize + OptionalWordCount(cooperativeMatrixOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->a = a;
    this->b = b;
    this->c = c;
    this->cooperativeMatrixOperands = cooperativeMatrixOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(a.value());
    words.push_back(b.value());
    words.push_back(c.value());
    if(cooperativeMatrixOperands != CooperativeMatrixOperands::NoneKHR) words.push_back((uint32_t)cooperativeMatrixOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::CooperativeMatrixMulAddKHR;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id a;
  Id b;
  Id c;
  CooperativeMatrixOperands cooperativeMatrixOperands;

  bool HasCooperativeMatrixOperands() const { return wordCount > 6; }
};

struct OpCooperativeMatrixLengthKHR
{
  OpCooperativeMatrixLengthKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpCooperativeMatrixLengthKHR(IdResultType resultType, IdResult result, Id type)
      : op(Op::CooperativeMatrixLengthKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->type = type;
  }

  static constexpr Op OpCode = Op::CooperativeMatrixLengthKHR;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id type;
};

struct OpConstantCompositeReplicateEXT
{
  OpConstantCompositeReplicateEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConstantCompositeReplicateEXT(IdResultType resultType, IdResult result, Id value)
      : op(Op::ConstantCompositeReplicateEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->value = value;
  }

  static constexpr Op OpCode = Op::ConstantCompositeReplicateEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id value;
};

struct OpSpecConstantCompositeReplicateEXT
{
  OpSpecConstantCompositeReplicateEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSpecConstantCompositeReplicateEXT(IdResultType resultType, IdResult result, Id value)
      : op(Op::SpecConstantCompositeReplicateEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->value = value;
  }

  static constexpr Op OpCode = Op::SpecConstantCompositeReplicateEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id value;
};

struct OpCompositeConstructReplicateEXT
{
  OpCompositeConstructReplicateEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpCompositeConstructReplicateEXT(IdResultType resultType, IdResult result, Id value)
      : op(Op::CompositeConstructReplicateEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->value = value;
  }

  static constexpr Op OpCode = Op::CompositeConstructReplicateEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id value;
};

struct OpTypeRayQueryKHR
{
  OpTypeRayQueryKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeRayQueryKHR(IdResult result)
      : op(Op::TypeRayQueryKHR)
      , wordCount(FixedWordSize)
  {
    this->result = result;
  }

  static constexpr Op OpCode = Op::TypeRayQueryKHR;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  IdResult result;
};

struct OpRayQueryInitializeKHR
{
  OpRayQueryInitializeKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryInitializeKHR(Id rayQuery, Id accel, Id rayFlags, Id cullMask, Id rayOrigin, Id rayTMin, Id rayDirection, Id rayTMax)
      : op(Op::RayQueryInitializeKHR)
      , wordCount(FixedWordSize)
  {
    this->rayQuery = rayQuery;
    this->accel = accel;
    this->rayFlags = rayFlags;
    this->cullMask = cullMask;
    this->rayOrigin = rayOrigin;
    this->rayTMin = rayTMin;
    this->rayDirection = rayDirection;
    this->rayTMax = rayTMax;
  }

  static constexpr Op OpCode = Op::RayQueryInitializeKHR;
  static constexpr uint16_t FixedWordSize = 9U;
  Op op;
  uint16_t wordCount;
  Id rayQuery;
  Id accel;
  Id rayFlags;
  Id cullMask;
  Id rayOrigin;
  Id rayTMin;
  Id rayDirection;
  Id rayTMax;
};

struct OpRayQueryTerminateKHR
{
  OpRayQueryTerminateKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryTerminateKHR(Id rayQuery)
      : op(Op::RayQueryTerminateKHR)
      , wordCount(FixedWordSize)
  {
    this->rayQuery = rayQuery;
  }

  static constexpr Op OpCode = Op::RayQueryTerminateKHR;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  Id rayQuery;
};

struct OpRayQueryGenerateIntersectionKHR
{
  OpRayQueryGenerateIntersectionKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGenerateIntersectionKHR(Id rayQuery, Id hitT)
      : op(Op::RayQueryGenerateIntersectionKHR)
      , wordCount(FixedWordSize)
  {
    this->rayQuery = rayQuery;
    this->hitT = hitT;
  }

  static constexpr Op OpCode = Op::RayQueryGenerateIntersectionKHR;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id rayQuery;
  Id hitT;
};

struct OpRayQueryConfirmIntersectionKHR
{
  OpRayQueryConfirmIntersectionKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryConfirmIntersectionKHR(Id rayQuery)
      : op(Op::RayQueryConfirmIntersectionKHR)
      , wordCount(FixedWordSize)
  {
    this->rayQuery = rayQuery;
  }

  static constexpr Op OpCode = Op::RayQueryConfirmIntersectionKHR;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  Id rayQuery;
};

struct OpRayQueryProceedKHR
{
  OpRayQueryProceedKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryProceedKHR(IdResultType resultType, IdResult result, Id rayQuery)
      : op(Op::RayQueryProceedKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
  }

  static constexpr Op OpCode = Op::RayQueryProceedKHR;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
};

struct OpRayQueryGetIntersectionTypeKHR
{
  OpRayQueryGetIntersectionTypeKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionTypeKHR(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryGetIntersectionTypeKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionTypeKHR;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpImageSampleWeightedQCOM
{
  OpImageSampleWeightedQCOM(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpImageSampleWeightedQCOM(IdResultType resultType, IdResult result, Id texture, Id coordinates, Id weights)
      : op(Op::ImageSampleWeightedQCOM)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->texture = texture;
    this->coordinates = coordinates;
    this->weights = weights;
  }

  static constexpr Op OpCode = Op::ImageSampleWeightedQCOM;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id texture;
  Id coordinates;
  Id weights;
};

struct OpImageBoxFilterQCOM
{
  OpImageBoxFilterQCOM(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpImageBoxFilterQCOM(IdResultType resultType, IdResult result, Id texture, Id coordinates, Id boxSize)
      : op(Op::ImageBoxFilterQCOM)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->texture = texture;
    this->coordinates = coordinates;
    this->boxSize = boxSize;
  }

  static constexpr Op OpCode = Op::ImageBoxFilterQCOM;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id texture;
  Id coordinates;
  Id boxSize;
};

struct OpImageBlockMatchSSDQCOM
{
  OpImageBlockMatchSSDQCOM(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpImageBlockMatchSSDQCOM(IdResultType resultType, IdResult result, Id target, Id targetCoordinates, Id reference, Id referenceCoordinates, Id blockSize)
      : op(Op::ImageBlockMatchSSDQCOM)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->target = target;
    this->targetCoordinates = targetCoordinates;
    this->reference = reference;
    this->referenceCoordinates = referenceCoordinates;
    this->blockSize = blockSize;
  }

  static constexpr Op OpCode = Op::ImageBlockMatchSSDQCOM;
  static constexpr uint16_t FixedWordSize = 8U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id target;
  Id targetCoordinates;
  Id reference;
  Id referenceCoordinates;
  Id blockSize;
};

struct OpImageBlockMatchSADQCOM
{
  OpImageBlockMatchSADQCOM(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpImageBlockMatchSADQCOM(IdResultType resultType, IdResult result, Id target, Id targetCoordinates, Id reference, Id referenceCoordinates, Id blockSize)
      : op(Op::ImageBlockMatchSADQCOM)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->target = target;
    this->targetCoordinates = targetCoordinates;
    this->reference = reference;
    this->referenceCoordinates = referenceCoordinates;
    this->blockSize = blockSize;
  }

  static constexpr Op OpCode = Op::ImageBlockMatchSADQCOM;
  static constexpr uint16_t FixedWordSize = 8U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id target;
  Id targetCoordinates;
  Id reference;
  Id referenceCoordinates;
  Id blockSize;
};

struct OpBitCastArrayQCOM
{
  OpBitCastArrayQCOM(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpBitCastArrayQCOM(IdResultType resultType, IdResult result, Id sourceArray)
      : op(Op::BitCastArrayQCOM)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->sourceArray = sourceArray;
  }

  static constexpr Op OpCode = Op::BitCastArrayQCOM;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sourceArray;
};

struct OpImageBlockMatchWindowSSDQCOM
{
  OpImageBlockMatchWindowSSDQCOM(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpImageBlockMatchWindowSSDQCOM(IdResultType resultType, IdResult result, Id targetSampledImage, Id targetCoordinates, Id referenceSampledImage, Id referenceCoordinates, Id blockSize)
      : op(Op::ImageBlockMatchWindowSSDQCOM)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->targetSampledImage = targetSampledImage;
    this->targetCoordinates = targetCoordinates;
    this->referenceSampledImage = referenceSampledImage;
    this->referenceCoordinates = referenceCoordinates;
    this->blockSize = blockSize;
  }

  static constexpr Op OpCode = Op::ImageBlockMatchWindowSSDQCOM;
  static constexpr uint16_t FixedWordSize = 8U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id targetSampledImage;
  Id targetCoordinates;
  Id referenceSampledImage;
  Id referenceCoordinates;
  Id blockSize;
};

struct OpImageBlockMatchWindowSADQCOM
{
  OpImageBlockMatchWindowSADQCOM(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpImageBlockMatchWindowSADQCOM(IdResultType resultType, IdResult result, Id targetSampledImage, Id targetCoordinates, Id referenceSampledImage, Id referenceCoordinates, Id blockSize)
      : op(Op::ImageBlockMatchWindowSADQCOM)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->targetSampledImage = targetSampledImage;
    this->targetCoordinates = targetCoordinates;
    this->referenceSampledImage = referenceSampledImage;
    this->referenceCoordinates = referenceCoordinates;
    this->blockSize = blockSize;
  }

  static constexpr Op OpCode = Op::ImageBlockMatchWindowSADQCOM;
  static constexpr uint16_t FixedWordSize = 8U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id targetSampledImage;
  Id targetCoordinates;
  Id referenceSampledImage;
  Id referenceCoordinates;
  Id blockSize;
};

struct OpImageBlockMatchGatherSSDQCOM
{
  OpImageBlockMatchGatherSSDQCOM(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpImageBlockMatchGatherSSDQCOM(IdResultType resultType, IdResult result, Id targetSampledImage, Id targetCoordinates, Id referenceSampledImage, Id referenceCoordinates, Id blockSize)
      : op(Op::ImageBlockMatchGatherSSDQCOM)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->targetSampledImage = targetSampledImage;
    this->targetCoordinates = targetCoordinates;
    this->referenceSampledImage = referenceSampledImage;
    this->referenceCoordinates = referenceCoordinates;
    this->blockSize = blockSize;
  }

  static constexpr Op OpCode = Op::ImageBlockMatchGatherSSDQCOM;
  static constexpr uint16_t FixedWordSize = 8U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id targetSampledImage;
  Id targetCoordinates;
  Id referenceSampledImage;
  Id referenceCoordinates;
  Id blockSize;
};

struct OpImageBlockMatchGatherSADQCOM
{
  OpImageBlockMatchGatherSADQCOM(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpImageBlockMatchGatherSADQCOM(IdResultType resultType, IdResult result, Id targetSampledImage, Id targetCoordinates, Id referenceSampledImage, Id referenceCoordinates, Id blockSize)
      : op(Op::ImageBlockMatchGatherSADQCOM)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->targetSampledImage = targetSampledImage;
    this->targetCoordinates = targetCoordinates;
    this->referenceSampledImage = referenceSampledImage;
    this->referenceCoordinates = referenceCoordinates;
    this->blockSize = blockSize;
  }

  static constexpr Op OpCode = Op::ImageBlockMatchGatherSADQCOM;
  static constexpr uint16_t FixedWordSize = 8U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id targetSampledImage;
  Id targetCoordinates;
  Id referenceSampledImage;
  Id referenceCoordinates;
  Id blockSize;
};

struct OpCompositeConstructCoopMatQCOM
{
  OpCompositeConstructCoopMatQCOM(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpCompositeConstructCoopMatQCOM(IdResultType resultType, IdResult result, Id sourceArray)
      : op(Op::CompositeConstructCoopMatQCOM)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->sourceArray = sourceArray;
  }

  static constexpr Op OpCode = Op::CompositeConstructCoopMatQCOM;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sourceArray;
};

struct OpCompositeExtractCoopMatQCOM
{
  OpCompositeExtractCoopMatQCOM(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpCompositeExtractCoopMatQCOM(IdResultType resultType, IdResult result, Id sourceCooperativeMatrix)
      : op(Op::CompositeExtractCoopMatQCOM)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->sourceCooperativeMatrix = sourceCooperativeMatrix;
  }

  static constexpr Op OpCode = Op::CompositeExtractCoopMatQCOM;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sourceCooperativeMatrix;
};

struct OpExtractSubArrayQCOM
{
  OpExtractSubArrayQCOM(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpExtractSubArrayQCOM(IdResultType resultType, IdResult result, Id sourceArray, Id index)
      : op(Op::ExtractSubArrayQCOM)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->sourceArray = sourceArray;
    this->index = index;
  }

  static constexpr Op OpCode = Op::ExtractSubArrayQCOM;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sourceArray;
  Id index;
};

struct OpGroupIAddNonUniformAMD
{
  OpGroupIAddNonUniformAMD(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupIAddNonUniformAMD(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupIAddNonUniformAMD)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupIAddNonUniformAMD;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupFAddNonUniformAMD
{
  OpGroupFAddNonUniformAMD(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupFAddNonUniformAMD(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupFAddNonUniformAMD)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupFAddNonUniformAMD;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupFMinNonUniformAMD
{
  OpGroupFMinNonUniformAMD(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupFMinNonUniformAMD(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupFMinNonUniformAMD)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupFMinNonUniformAMD;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupUMinNonUniformAMD
{
  OpGroupUMinNonUniformAMD(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupUMinNonUniformAMD(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupUMinNonUniformAMD)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupUMinNonUniformAMD;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupSMinNonUniformAMD
{
  OpGroupSMinNonUniformAMD(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupSMinNonUniformAMD(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupSMinNonUniformAMD)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupSMinNonUniformAMD;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupFMaxNonUniformAMD
{
  OpGroupFMaxNonUniformAMD(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupFMaxNonUniformAMD(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupFMaxNonUniformAMD)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupFMaxNonUniformAMD;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupUMaxNonUniformAMD
{
  OpGroupUMaxNonUniformAMD(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupUMaxNonUniformAMD(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupUMaxNonUniformAMD)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupUMaxNonUniformAMD;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupSMaxNonUniformAMD
{
  OpGroupSMaxNonUniformAMD(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupSMaxNonUniformAMD(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupSMaxNonUniformAMD)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupSMaxNonUniformAMD;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpFragmentMaskFetchAMD
{
  OpFragmentMaskFetchAMD(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFragmentMaskFetchAMD(IdResultType resultType, IdResult result, Id image, Id coordinate)
      : op(Op::FragmentMaskFetchAMD)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->image = image;
    this->coordinate = coordinate;
  }

  static constexpr Op OpCode = Op::FragmentMaskFetchAMD;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id image;
  Id coordinate;
};

struct OpFragmentFetchAMD
{
  OpFragmentFetchAMD(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFragmentFetchAMD(IdResultType resultType, IdResult result, Id image, Id coordinate, Id fragmentIndex)
      : op(Op::FragmentFetchAMD)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->image = image;
    this->coordinate = coordinate;
    this->fragmentIndex = fragmentIndex;
  }

  static constexpr Op OpCode = Op::FragmentFetchAMD;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id image;
  Id coordinate;
  Id fragmentIndex;
};

struct OpReadClockKHR
{
  OpReadClockKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpReadClockKHR(IdResultType resultType, IdResult result, IdScope scope)
      : op(Op::ReadClockKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->scope = scope;
  }

  static constexpr Op OpCode = Op::ReadClockKHR;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope scope;
};

struct OpAllocateNodePayloadsAMDX
{
  OpAllocateNodePayloadsAMDX(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAllocateNodePayloadsAMDX(IdResultType resultType, IdResult result, IdScope visibility, Id payloadCount, Id nodeIndex)
      : op(Op::AllocateNodePayloadsAMDX)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->visibility = visibility;
    this->payloadCount = payloadCount;
    this->nodeIndex = nodeIndex;
  }

  static constexpr Op OpCode = Op::AllocateNodePayloadsAMDX;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope visibility;
  Id payloadCount;
  Id nodeIndex;
};

struct OpEnqueueNodePayloadsAMDX
{
  OpEnqueueNodePayloadsAMDX(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpEnqueueNodePayloadsAMDX(Id payloadArray)
      : op(Op::EnqueueNodePayloadsAMDX)
      , wordCount(FixedWordSize)
  {
    this->payloadArray = payloadArray;
  }

  static constexpr Op OpCode = Op::EnqueueNodePayloadsAMDX;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  Id payloadArray;
};

struct OpTypeNodePayloadArrayAMDX
{
  OpTypeNodePayloadArrayAMDX(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeNodePayloadArrayAMDX(IdResult result, Id payloadType)
      : op(Op::TypeNodePayloadArrayAMDX)
      , wordCount(FixedWordSize)
  {
    this->result = result;
    this->payloadType = payloadType;
  }

  static constexpr Op OpCode = Op::TypeNodePayloadArrayAMDX;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  Id payloadType;
};

struct OpFinishWritingNodePayloadAMDX
{
  OpFinishWritingNodePayloadAMDX(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFinishWritingNodePayloadAMDX(IdResultType resultType, IdResult result, Id payload)
      : op(Op::FinishWritingNodePayloadAMDX)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->payload = payload;
  }

  static constexpr Op OpCode = Op::FinishWritingNodePayloadAMDX;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id payload;
};

struct OpNodePayloadArrayLengthAMDX
{
  OpNodePayloadArrayLengthAMDX(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpNodePayloadArrayLengthAMDX(IdResultType resultType, IdResult result, Id payloadArray)
      : op(Op::NodePayloadArrayLengthAMDX)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->payloadArray = payloadArray;
  }

  static constexpr Op OpCode = Op::NodePayloadArrayLengthAMDX;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id payloadArray;
};

struct OpIsNodePayloadValidAMDX
{
  OpIsNodePayloadValidAMDX(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpIsNodePayloadValidAMDX(IdResultType resultType, IdResult result, Id payloadType, Id nodeIndex)
      : op(Op::IsNodePayloadValidAMDX)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->payloadType = payloadType;
    this->nodeIndex = nodeIndex;
  }

  static constexpr Op OpCode = Op::IsNodePayloadValidAMDX;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id payloadType;
  Id nodeIndex;
};

struct OpConstantStringAMDX
{
  OpConstantStringAMDX(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->result = Id::fromWord(it.word(1));
    word = 2;
    this->literalString = DecodeParam<rdcstr>(it, word);
  }
  OpConstantStringAMDX(IdResult result, rdcstr literalString)
      : op(Op::ConstantStringAMDX)
      , wordCount(MinWordSize + ExtraWordCount(literalString))
  {
    this->result = result;
    this->literalString = literalString;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(result.value());
    EncodeParam(words, literalString);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ConstantStringAMDX;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  rdcstr literalString;
};

struct OpSpecConstantStringAMDX
{
  OpSpecConstantStringAMDX(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->result = Id::fromWord(it.word(1));
    word = 2;
    this->literalString = DecodeParam<rdcstr>(it, word);
  }
  OpSpecConstantStringAMDX(IdResult result, rdcstr literalString)
      : op(Op::SpecConstantStringAMDX)
      , wordCount(MinWordSize + ExtraWordCount(literalString))
  {
    this->result = result;
    this->literalString = literalString;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(result.value());
    EncodeParam(words, literalString);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::SpecConstantStringAMDX;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  rdcstr literalString;
};

struct OpGroupNonUniformQuadAllKHR
{
  OpGroupNonUniformQuadAllKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformQuadAllKHR(IdResultType resultType, IdResult result, Id predicate)
      : op(Op::GroupNonUniformQuadAllKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->predicate = predicate;
  }

  static constexpr Op OpCode = Op::GroupNonUniformQuadAllKHR;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id predicate;
};

struct OpGroupNonUniformQuadAnyKHR
{
  OpGroupNonUniformQuadAnyKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformQuadAnyKHR(IdResultType resultType, IdResult result, Id predicate)
      : op(Op::GroupNonUniformQuadAnyKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->predicate = predicate;
  }

  static constexpr Op OpCode = Op::GroupNonUniformQuadAnyKHR;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id predicate;
};

struct OpTypeBufferEXT
{
  OpTypeBufferEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeBufferEXT(IdResult result, StorageClass storageClass)
      : op(Op::TypeBufferEXT)
      , wordCount(FixedWordSize)
  {
    this->result = result;
    this->storageClass = storageClass;
  }

  static constexpr Op OpCode = Op::TypeBufferEXT;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  StorageClass storageClass;
};

struct OpBufferPointerEXT
{
  OpBufferPointerEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpBufferPointerEXT(IdResultType resultType, IdResult result, Id buffer)
      : op(Op::BufferPointerEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->buffer = buffer;
  }

  static constexpr Op OpCode = Op::BufferPointerEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id buffer;
};

struct OpUntypedImageTexelPointerEXT
{
  OpUntypedImageTexelPointerEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpUntypedImageTexelPointerEXT(IdResultType resultType, IdResult result, Id imageType, Id image, Id coordinate, Id sample)
      : op(Op::UntypedImageTexelPointerEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->imageType = imageType;
    this->image = image;
    this->coordinate = coordinate;
    this->sample = sample;
  }

  static constexpr Op OpCode = Op::UntypedImageTexelPointerEXT;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id imageType;
  Id image;
  Id coordinate;
  Id sample;
};

struct OpMemberDecorateIdEXT
{
  OpMemberDecorateIdEXT(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->structureType = Id::fromWord(it.word(1));
    this->member = (uint32_t)it.word(2);
    word = 3;
    this->decoration = DecodeParam<DecorationAndParamData>(it, word);
  }
  OpMemberDecorateIdEXT(Id structureType, uint32_t member, DecorationAndParamData decoration)
      : op(Op::MemberDecorateIdEXT)
      , wordCount(MinWordSize + ExtraWordCount(decoration))
  {
    this->structureType = structureType;
    this->member = member;
    this->decoration = decoration;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(structureType.value());
    words.push_back((uint32_t)member);
    EncodeParam(words, decoration);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::MemberDecorateIdEXT;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  Id structureType;
  uint32_t member;
  DecorationAndParamData decoration;
};

struct OpConstantSizeOfEXT
{
  OpConstantSizeOfEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConstantSizeOfEXT(IdResultType resultType, IdResult result, Id type)
      : op(Op::ConstantSizeOfEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->type = type;
  }

  static constexpr Op OpCode = Op::ConstantSizeOfEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id type;
};

struct OpHitObjectRecordHitMotionNV
{
  OpHitObjectRecordHitMotionNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectRecordHitMotionNV(Id hitObject, Id accelerationStructure, Id instanceId, Id primitiveId, Id geometryIndex, Id hitKind, Id sBTRecordOffset, Id sBTRecordStride, Id origin, Id tMin, Id direction, Id tMax, Id currentTime, Id hitObjectAttributes)
      : op(Op::HitObjectRecordHitMotionNV)
      , wordCount(FixedWordSize)
  {
    this->hitObject = hitObject;
    this->accelerationStructure = accelerationStructure;
    this->instanceId = instanceId;
    this->primitiveId = primitiveId;
    this->geometryIndex = geometryIndex;
    this->hitKind = hitKind;
    this->sBTRecordOffset = sBTRecordOffset;
    this->sBTRecordStride = sBTRecordStride;
    this->origin = origin;
    this->tMin = tMin;
    this->direction = direction;
    this->tMax = tMax;
    this->currentTime = currentTime;
    this->hitObjectAttributes = hitObjectAttributes;
  }

  static constexpr Op OpCode = Op::HitObjectRecordHitMotionNV;
  static constexpr uint16_t FixedWordSize = 15U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id accelerationStructure;
  Id instanceId;
  Id primitiveId;
  Id geometryIndex;
  Id hitKind;
  Id sBTRecordOffset;
  Id sBTRecordStride;
  Id origin;
  Id tMin;
  Id direction;
  Id tMax;
  Id currentTime;
  Id hitObjectAttributes;
};

struct OpHitObjectRecordHitWithIndexMotionNV
{
  OpHitObjectRecordHitWithIndexMotionNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectRecordHitWithIndexMotionNV(Id hitObject, Id accelerationStructure, Id instanceId, Id primitiveId, Id geometryIndex, Id hitKind, Id sBTRecordIndex, Id origin, Id tMin, Id direction, Id tMax, Id currentTime, Id hitObjectAttributes)
      : op(Op::HitObjectRecordHitWithIndexMotionNV)
      , wordCount(FixedWordSize)
  {
    this->hitObject = hitObject;
    this->accelerationStructure = accelerationStructure;
    this->instanceId = instanceId;
    this->primitiveId = primitiveId;
    this->geometryIndex = geometryIndex;
    this->hitKind = hitKind;
    this->sBTRecordIndex = sBTRecordIndex;
    this->origin = origin;
    this->tMin = tMin;
    this->direction = direction;
    this->tMax = tMax;
    this->currentTime = currentTime;
    this->hitObjectAttributes = hitObjectAttributes;
  }

  static constexpr Op OpCode = Op::HitObjectRecordHitWithIndexMotionNV;
  static constexpr uint16_t FixedWordSize = 14U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id accelerationStructure;
  Id instanceId;
  Id primitiveId;
  Id geometryIndex;
  Id hitKind;
  Id sBTRecordIndex;
  Id origin;
  Id tMin;
  Id direction;
  Id tMax;
  Id currentTime;
  Id hitObjectAttributes;
};

struct OpHitObjectRecordMissMotionNV
{
  OpHitObjectRecordMissMotionNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectRecordMissMotionNV(Id hitObject, Id sBTIndex, Id origin, Id tMin, Id direction, Id tMax, Id currentTime)
      : op(Op::HitObjectRecordMissMotionNV)
      , wordCount(FixedWordSize)
  {
    this->hitObject = hitObject;
    this->sBTIndex = sBTIndex;
    this->origin = origin;
    this->tMin = tMin;
    this->direction = direction;
    this->tMax = tMax;
    this->currentTime = currentTime;
  }

  static constexpr Op OpCode = Op::HitObjectRecordMissMotionNV;
  static constexpr uint16_t FixedWordSize = 8U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id sBTIndex;
  Id origin;
  Id tMin;
  Id direction;
  Id tMax;
  Id currentTime;
};

struct OpHitObjectGetWorldToObjectNV
{
  OpHitObjectGetWorldToObjectNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetWorldToObjectNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetWorldToObjectNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetWorldToObjectNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetObjectToWorldNV
{
  OpHitObjectGetObjectToWorldNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetObjectToWorldNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetObjectToWorldNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetObjectToWorldNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetObjectRayDirectionNV
{
  OpHitObjectGetObjectRayDirectionNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetObjectRayDirectionNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetObjectRayDirectionNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetObjectRayDirectionNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetObjectRayOriginNV
{
  OpHitObjectGetObjectRayOriginNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetObjectRayOriginNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetObjectRayOriginNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetObjectRayOriginNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectTraceRayMotionNV
{
  OpHitObjectTraceRayMotionNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectTraceRayMotionNV(Id hitObject, Id accelerationStructure, Id rayFlags, Id cullmask, Id sBTRecordOffset, Id sBTRecordStride, Id missIndex, Id origin, Id tMin, Id direction, Id tMax, Id time, Id payload)
      : op(Op::HitObjectTraceRayMotionNV)
      , wordCount(FixedWordSize)
  {
    this->hitObject = hitObject;
    this->accelerationStructure = accelerationStructure;
    this->rayFlags = rayFlags;
    this->cullmask = cullmask;
    this->sBTRecordOffset = sBTRecordOffset;
    this->sBTRecordStride = sBTRecordStride;
    this->missIndex = missIndex;
    this->origin = origin;
    this->tMin = tMin;
    this->direction = direction;
    this->tMax = tMax;
    this->time = time;
    this->payload = payload;
  }

  static constexpr Op OpCode = Op::HitObjectTraceRayMotionNV;
  static constexpr uint16_t FixedWordSize = 14U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id accelerationStructure;
  Id rayFlags;
  Id cullmask;
  Id sBTRecordOffset;
  Id sBTRecordStride;
  Id missIndex;
  Id origin;
  Id tMin;
  Id direction;
  Id tMax;
  Id time;
  Id payload;
};

struct OpHitObjectGetShaderRecordBufferHandleNV
{
  OpHitObjectGetShaderRecordBufferHandleNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetShaderRecordBufferHandleNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetShaderRecordBufferHandleNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetShaderRecordBufferHandleNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetShaderBindingTableRecordIndexNV
{
  OpHitObjectGetShaderBindingTableRecordIndexNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetShaderBindingTableRecordIndexNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetShaderBindingTableRecordIndexNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetShaderBindingTableRecordIndexNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectRecordEmptyNV
{
  OpHitObjectRecordEmptyNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectRecordEmptyNV(Id hitObject)
      : op(Op::HitObjectRecordEmptyNV)
      , wordCount(FixedWordSize)
  {
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectRecordEmptyNV;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
};

struct OpHitObjectTraceRayNV
{
  OpHitObjectTraceRayNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectTraceRayNV(Id hitObject, Id accelerationStructure, Id rayFlags, Id cullmask, Id sBTRecordOffset, Id sBTRecordStride, Id missIndex, Id origin, Id tMin, Id direction, Id tMax, Id payload)
      : op(Op::HitObjectTraceRayNV)
      , wordCount(FixedWordSize)
  {
    this->hitObject = hitObject;
    this->accelerationStructure = accelerationStructure;
    this->rayFlags = rayFlags;
    this->cullmask = cullmask;
    this->sBTRecordOffset = sBTRecordOffset;
    this->sBTRecordStride = sBTRecordStride;
    this->missIndex = missIndex;
    this->origin = origin;
    this->tMin = tMin;
    this->direction = direction;
    this->tMax = tMax;
    this->payload = payload;
  }

  static constexpr Op OpCode = Op::HitObjectTraceRayNV;
  static constexpr uint16_t FixedWordSize = 13U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id accelerationStructure;
  Id rayFlags;
  Id cullmask;
  Id sBTRecordOffset;
  Id sBTRecordStride;
  Id missIndex;
  Id origin;
  Id tMin;
  Id direction;
  Id tMax;
  Id payload;
};

struct OpHitObjectRecordHitNV
{
  OpHitObjectRecordHitNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectRecordHitNV(Id hitObject, Id accelerationStructure, Id instanceId, Id primitiveId, Id geometryIndex, Id hitKind, Id sBTRecordOffset, Id sBTRecordStride, Id origin, Id tMin, Id direction, Id tMax, Id hitObjectAttributes)
      : op(Op::HitObjectRecordHitNV)
      , wordCount(FixedWordSize)
  {
    this->hitObject = hitObject;
    this->accelerationStructure = accelerationStructure;
    this->instanceId = instanceId;
    this->primitiveId = primitiveId;
    this->geometryIndex = geometryIndex;
    this->hitKind = hitKind;
    this->sBTRecordOffset = sBTRecordOffset;
    this->sBTRecordStride = sBTRecordStride;
    this->origin = origin;
    this->tMin = tMin;
    this->direction = direction;
    this->tMax = tMax;
    this->hitObjectAttributes = hitObjectAttributes;
  }

  static constexpr Op OpCode = Op::HitObjectRecordHitNV;
  static constexpr uint16_t FixedWordSize = 14U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id accelerationStructure;
  Id instanceId;
  Id primitiveId;
  Id geometryIndex;
  Id hitKind;
  Id sBTRecordOffset;
  Id sBTRecordStride;
  Id origin;
  Id tMin;
  Id direction;
  Id tMax;
  Id hitObjectAttributes;
};

struct OpHitObjectRecordHitWithIndexNV
{
  OpHitObjectRecordHitWithIndexNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectRecordHitWithIndexNV(Id hitObject, Id accelerationStructure, Id instanceId, Id primitiveId, Id geometryIndex, Id hitKind, Id sBTRecordIndex, Id origin, Id tMin, Id direction, Id tMax, Id hitObjectAttributes)
      : op(Op::HitObjectRecordHitWithIndexNV)
      , wordCount(FixedWordSize)
  {
    this->hitObject = hitObject;
    this->accelerationStructure = accelerationStructure;
    this->instanceId = instanceId;
    this->primitiveId = primitiveId;
    this->geometryIndex = geometryIndex;
    this->hitKind = hitKind;
    this->sBTRecordIndex = sBTRecordIndex;
    this->origin = origin;
    this->tMin = tMin;
    this->direction = direction;
    this->tMax = tMax;
    this->hitObjectAttributes = hitObjectAttributes;
  }

  static constexpr Op OpCode = Op::HitObjectRecordHitWithIndexNV;
  static constexpr uint16_t FixedWordSize = 13U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id accelerationStructure;
  Id instanceId;
  Id primitiveId;
  Id geometryIndex;
  Id hitKind;
  Id sBTRecordIndex;
  Id origin;
  Id tMin;
  Id direction;
  Id tMax;
  Id hitObjectAttributes;
};

struct OpHitObjectRecordMissNV
{
  OpHitObjectRecordMissNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectRecordMissNV(Id hitObject, Id sBTIndex, Id origin, Id tMin, Id direction, Id tMax)
      : op(Op::HitObjectRecordMissNV)
      , wordCount(FixedWordSize)
  {
    this->hitObject = hitObject;
    this->sBTIndex = sBTIndex;
    this->origin = origin;
    this->tMin = tMin;
    this->direction = direction;
    this->tMax = tMax;
  }

  static constexpr Op OpCode = Op::HitObjectRecordMissNV;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id sBTIndex;
  Id origin;
  Id tMin;
  Id direction;
  Id tMax;
};

struct OpHitObjectExecuteShaderNV
{
  OpHitObjectExecuteShaderNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectExecuteShaderNV(Id hitObject, Id payload)
      : op(Op::HitObjectExecuteShaderNV)
      , wordCount(FixedWordSize)
  {
    this->hitObject = hitObject;
    this->payload = payload;
  }

  static constexpr Op OpCode = Op::HitObjectExecuteShaderNV;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id payload;
};

struct OpHitObjectGetCurrentTimeNV
{
  OpHitObjectGetCurrentTimeNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetCurrentTimeNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetCurrentTimeNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetCurrentTimeNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetAttributesNV
{
  OpHitObjectGetAttributesNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetAttributesNV(Id hitObject, Id hitObjectAttribute)
      : op(Op::HitObjectGetAttributesNV)
      , wordCount(FixedWordSize)
  {
    this->hitObject = hitObject;
    this->hitObjectAttribute = hitObjectAttribute;
  }

  static constexpr Op OpCode = Op::HitObjectGetAttributesNV;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id hitObjectAttribute;
};

struct OpHitObjectGetHitKindNV
{
  OpHitObjectGetHitKindNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetHitKindNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetHitKindNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetHitKindNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetPrimitiveIndexNV
{
  OpHitObjectGetPrimitiveIndexNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetPrimitiveIndexNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetPrimitiveIndexNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetPrimitiveIndexNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetGeometryIndexNV
{
  OpHitObjectGetGeometryIndexNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetGeometryIndexNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetGeometryIndexNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetGeometryIndexNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetInstanceIdNV
{
  OpHitObjectGetInstanceIdNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetInstanceIdNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetInstanceIdNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetInstanceIdNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetInstanceCustomIndexNV
{
  OpHitObjectGetInstanceCustomIndexNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetInstanceCustomIndexNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetInstanceCustomIndexNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetInstanceCustomIndexNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetWorldRayDirectionNV
{
  OpHitObjectGetWorldRayDirectionNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetWorldRayDirectionNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetWorldRayDirectionNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetWorldRayDirectionNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetWorldRayOriginNV
{
  OpHitObjectGetWorldRayOriginNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetWorldRayOriginNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetWorldRayOriginNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetWorldRayOriginNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetRayTMaxNV
{
  OpHitObjectGetRayTMaxNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetRayTMaxNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetRayTMaxNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetRayTMaxNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetRayTMinNV
{
  OpHitObjectGetRayTMinNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetRayTMinNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetRayTMinNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetRayTMinNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectIsEmptyNV
{
  OpHitObjectIsEmptyNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectIsEmptyNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectIsEmptyNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectIsEmptyNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectIsHitNV
{
  OpHitObjectIsHitNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectIsHitNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectIsHitNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectIsHitNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectIsMissNV
{
  OpHitObjectIsMissNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectIsMissNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectIsMissNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectIsMissNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpReorderThreadWithHitObjectNV
{
  OpReorderThreadWithHitObjectNV(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->hitObject = Id::fromWord(it.word(1));
    this->hint = (it.size() > 2) ? Id::fromWord(it.word(2)) : Id();
    this->bits = (it.size() > 3) ? Id::fromWord(it.word(3)) : Id();
  }
  OpReorderThreadWithHitObjectNV(Id hitObject, Id hint = Id(), Id bits = Id())
      : op(Op::ReorderThreadWithHitObjectNV)
      , wordCount(MinWordSize + OptionalWordCount(hint) + OptionalWordCount(bits))
  {
    this->hitObject = hitObject;
    this->hint = hint;
    this->bits = bits;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(hitObject.value());
    if(hint != Id()) words.push_back(hint.value());
    if(bits != Id()) words.push_back(bits.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ReorderThreadWithHitObjectNV;
  static constexpr uint16_t MinWordSize = 2U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id hint;
  Id bits;

  bool HasHint() const { return wordCount > 2; }
  bool HasBits() const { return wordCount > 3; }
};

struct OpReorderThreadWithHintNV
{
  OpReorderThreadWithHintNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpReorderThreadWithHintNV(Id hint, Id bits)
      : op(Op::ReorderThreadWithHintNV)
      , wordCount(FixedWordSize)
  {
    this->hint = hint;
    this->bits = bits;
  }

  static constexpr Op OpCode = Op::ReorderThreadWithHintNV;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id hint;
  Id bits;
};

struct OpTypeHitObjectNV
{
  OpTypeHitObjectNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeHitObjectNV(IdResult result)
      : op(Op::TypeHitObjectNV)
      , wordCount(FixedWordSize)
  {
    this->result = result;
  }

  static constexpr Op OpCode = Op::TypeHitObjectNV;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  IdResult result;
};

struct OpImageSampleFootprintNV
{
  OpImageSampleFootprintNV(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->sampledImage = Id::fromWord(it.word(3));
    this->coordinate = Id::fromWord(it.word(4));
    this->granularity = Id::fromWord(it.word(5));
    this->coarse = Id::fromWord(it.word(6));
    word = 7;
    this->imageOperands = DecodeParam<ImageOperandsAndParamDatas>(it, word);
  }
  OpImageSampleFootprintNV(IdResultType resultType, IdResult result, Id sampledImage, Id coordinate, Id granularity, Id coarse, ImageOperandsAndParamDatas imageOperands = ImageOperands::None)
      : op(Op::ImageSampleFootprintNV)
      , wordCount(MinWordSize + ExtraWordCount(imageOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->sampledImage = sampledImage;
    this->coordinate = coordinate;
    this->granularity = granularity;
    this->coarse = coarse;
    this->imageOperands = imageOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(sampledImage.value());
    words.push_back(coordinate.value());
    words.push_back(granularity.value());
    words.push_back(coarse.value());
    EncodeParam(words, imageOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ImageSampleFootprintNV;
  static constexpr uint16_t MinWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id sampledImage;
  Id coordinate;
  Id granularity;
  Id coarse;
  ImageOperandsAndParamDatas imageOperands;
};

struct OpTypeVectorIdEXT
{
  OpTypeVectorIdEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeVectorIdEXT(IdResult result, Id componentType, Id componentCount)
      : op(Op::TypeVectorIdEXT)
      , wordCount(FixedWordSize)
  {
    this->result = result;
    this->componentType = componentType;
    this->componentCount = componentCount;
  }

  static constexpr Op OpCode = Op::TypeVectorIdEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  Id componentType;
  Id componentCount;
};

struct OpCooperativeVectorMatrixMulNV
{
  OpCooperativeVectorMatrixMulNV(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->input = Id::fromWord(it.word(3));
    this->inputInterpretation = Id::fromWord(it.word(4));
    this->matrix = Id::fromWord(it.word(5));
    this->matrixOffset = Id::fromWord(it.word(6));
    this->matrixInterpretation = Id::fromWord(it.word(7));
    this->m = Id::fromWord(it.word(8));
    this->k = Id::fromWord(it.word(9));
    this->memoryLayout = Id::fromWord(it.word(10));
    this->transpose = Id::fromWord(it.word(11));
    this->matrixStride = (it.size() > 12) ? Id::fromWord(it.word(12)) : Id();
    this->cooperativeMatrixOperands = (it.size() > 13) ? (CooperativeMatrixOperands)it.word(13) : CooperativeMatrixOperands::NoneKHR;
  }
  OpCooperativeVectorMatrixMulNV(IdResultType resultType, IdResult result, Id input, Id inputInterpretation, Id matrix, Id matrixOffset, Id matrixInterpretation, Id m, Id k, Id memoryLayout, Id transpose, Id matrixStride = Id(), CooperativeMatrixOperands cooperativeMatrixOperands = CooperativeMatrixOperands::NoneKHR)
      : op(Op::CooperativeVectorMatrixMulNV)
      , wordCount(MinWordSize + OptionalWordCount(matrixStride) + OptionalWordCount(cooperativeMatrixOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->input = input;
    this->inputInterpretation = inputInterpretation;
    this->matrix = matrix;
    this->matrixOffset = matrixOffset;
    this->matrixInterpretation = matrixInterpretation;
    this->m = m;
    this->k = k;
    this->memoryLayout = memoryLayout;
    this->transpose = transpose;
    this->matrixStride = matrixStride;
    this->cooperativeMatrixOperands = cooperativeMatrixOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(input.value());
    words.push_back(inputInterpretation.value());
    words.push_back(matrix.value());
    words.push_back(matrixOffset.value());
    words.push_back(matrixInterpretation.value());
    words.push_back(m.value());
    words.push_back(k.value());
    words.push_back(memoryLayout.value());
    words.push_back(transpose.value());
    if(matrixStride != Id()) words.push_back(matrixStride.value());
    if(cooperativeMatrixOperands != CooperativeMatrixOperands::NoneKHR) words.push_back((uint32_t)cooperativeMatrixOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::CooperativeVectorMatrixMulNV;
  static constexpr uint16_t MinWordSize = 12U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id input;
  Id inputInterpretation;
  Id matrix;
  Id matrixOffset;
  Id matrixInterpretation;
  Id m;
  Id k;
  Id memoryLayout;
  Id transpose;
  Id matrixStride;
  CooperativeMatrixOperands cooperativeMatrixOperands;

  bool HasMatrixStride() const { return wordCount > 12; }
  bool HasCooperativeMatrixOperands() const { return wordCount > 13; }
};

struct OpCooperativeVectorOuterProductAccumulateNV
{
  OpCooperativeVectorOuterProductAccumulateNV(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->pointer = Id::fromWord(it.word(1));
    this->offset = Id::fromWord(it.word(2));
    this->a = Id::fromWord(it.word(3));
    this->b = Id::fromWord(it.word(4));
    this->memoryLayout = Id::fromWord(it.word(5));
    this->matrixInterpretation = Id::fromWord(it.word(6));
    this->matrixStride = (it.size() > 7) ? Id::fromWord(it.word(7)) : Id();
  }
  OpCooperativeVectorOuterProductAccumulateNV(Id pointer, Id offset, Id a, Id b, Id memoryLayout, Id matrixInterpretation, Id matrixStride = Id())
      : op(Op::CooperativeVectorOuterProductAccumulateNV)
      , wordCount(MinWordSize + OptionalWordCount(matrixStride))
  {
    this->pointer = pointer;
    this->offset = offset;
    this->a = a;
    this->b = b;
    this->memoryLayout = memoryLayout;
    this->matrixInterpretation = matrixInterpretation;
    this->matrixStride = matrixStride;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(pointer.value());
    words.push_back(offset.value());
    words.push_back(a.value());
    words.push_back(b.value());
    words.push_back(memoryLayout.value());
    words.push_back(matrixInterpretation.value());
    if(matrixStride != Id()) words.push_back(matrixStride.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::CooperativeVectorOuterProductAccumulateNV;
  static constexpr uint16_t MinWordSize = 7U;
  Op op;
  uint16_t wordCount;
  Id pointer;
  Id offset;
  Id a;
  Id b;
  Id memoryLayout;
  Id matrixInterpretation;
  Id matrixStride;

  bool HasMatrixStride() const { return wordCount > 7; }
};

struct OpCooperativeVectorReduceSumAccumulateNV
{
  OpCooperativeVectorReduceSumAccumulateNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpCooperativeVectorReduceSumAccumulateNV(Id pointer, Id offset, Id v)
      : op(Op::CooperativeVectorReduceSumAccumulateNV)
      , wordCount(FixedWordSize)
  {
    this->pointer = pointer;
    this->offset = offset;
    this->v = v;
  }

  static constexpr Op OpCode = Op::CooperativeVectorReduceSumAccumulateNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  Id pointer;
  Id offset;
  Id v;
};

struct OpCooperativeVectorMatrixMulAddNV
{
  OpCooperativeVectorMatrixMulAddNV(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->input = Id::fromWord(it.word(3));
    this->inputInterpretation = Id::fromWord(it.word(4));
    this->matrix = Id::fromWord(it.word(5));
    this->matrixOffset = Id::fromWord(it.word(6));
    this->matrixInterpretation = Id::fromWord(it.word(7));
    this->bias = Id::fromWord(it.word(8));
    this->biasOffset = Id::fromWord(it.word(9));
    this->biasInterpretation = Id::fromWord(it.word(10));
    this->m = Id::fromWord(it.word(11));
    this->k = Id::fromWord(it.word(12));
    this->memoryLayout = Id::fromWord(it.word(13));
    this->transpose = Id::fromWord(it.word(14));
    this->matrixStride = (it.size() > 15) ? Id::fromWord(it.word(15)) : Id();
    this->cooperativeMatrixOperands = (it.size() > 16) ? (CooperativeMatrixOperands)it.word(16) : CooperativeMatrixOperands::NoneKHR;
  }
  OpCooperativeVectorMatrixMulAddNV(IdResultType resultType, IdResult result, Id input, Id inputInterpretation, Id matrix, Id matrixOffset, Id matrixInterpretation, Id bias, Id biasOffset, Id biasInterpretation, Id m, Id k, Id memoryLayout, Id transpose, Id matrixStride = Id(), CooperativeMatrixOperands cooperativeMatrixOperands = CooperativeMatrixOperands::NoneKHR)
      : op(Op::CooperativeVectorMatrixMulAddNV)
      , wordCount(MinWordSize + OptionalWordCount(matrixStride) + OptionalWordCount(cooperativeMatrixOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->input = input;
    this->inputInterpretation = inputInterpretation;
    this->matrix = matrix;
    this->matrixOffset = matrixOffset;
    this->matrixInterpretation = matrixInterpretation;
    this->bias = bias;
    this->biasOffset = biasOffset;
    this->biasInterpretation = biasInterpretation;
    this->m = m;
    this->k = k;
    this->memoryLayout = memoryLayout;
    this->transpose = transpose;
    this->matrixStride = matrixStride;
    this->cooperativeMatrixOperands = cooperativeMatrixOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(input.value());
    words.push_back(inputInterpretation.value());
    words.push_back(matrix.value());
    words.push_back(matrixOffset.value());
    words.push_back(matrixInterpretation.value());
    words.push_back(bias.value());
    words.push_back(biasOffset.value());
    words.push_back(biasInterpretation.value());
    words.push_back(m.value());
    words.push_back(k.value());
    words.push_back(memoryLayout.value());
    words.push_back(transpose.value());
    if(matrixStride != Id()) words.push_back(matrixStride.value());
    if(cooperativeMatrixOperands != CooperativeMatrixOperands::NoneKHR) words.push_back((uint32_t)cooperativeMatrixOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::CooperativeVectorMatrixMulAddNV;
  static constexpr uint16_t MinWordSize = 15U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id input;
  Id inputInterpretation;
  Id matrix;
  Id matrixOffset;
  Id matrixInterpretation;
  Id bias;
  Id biasOffset;
  Id biasInterpretation;
  Id m;
  Id k;
  Id memoryLayout;
  Id transpose;
  Id matrixStride;
  CooperativeMatrixOperands cooperativeMatrixOperands;

  bool HasMatrixStride() const { return wordCount > 15; }
  bool HasCooperativeMatrixOperands() const { return wordCount > 16; }
};

struct OpCooperativeMatrixConvertNV
{
  OpCooperativeMatrixConvertNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpCooperativeMatrixConvertNV(IdResultType resultType, IdResult result, Id matrix)
      : op(Op::CooperativeMatrixConvertNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->matrix = matrix;
  }

  static constexpr Op OpCode = Op::CooperativeMatrixConvertNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id matrix;
};

struct OpEmitMeshTasksEXT
{
  OpEmitMeshTasksEXT(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->groupCountX = Id::fromWord(it.word(1));
    this->groupCountY = Id::fromWord(it.word(2));
    this->groupCountZ = Id::fromWord(it.word(3));
    this->payload = (it.size() > 4) ? Id::fromWord(it.word(4)) : Id();
  }
  OpEmitMeshTasksEXT(Id groupCountX, Id groupCountY, Id groupCountZ, Id payload = Id())
      : op(Op::EmitMeshTasksEXT)
      , wordCount(MinWordSize + OptionalWordCount(payload))
  {
    this->groupCountX = groupCountX;
    this->groupCountY = groupCountY;
    this->groupCountZ = groupCountZ;
    this->payload = payload;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(groupCountX.value());
    words.push_back(groupCountY.value());
    words.push_back(groupCountZ.value());
    if(payload != Id()) words.push_back(payload.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::EmitMeshTasksEXT;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  Id groupCountX;
  Id groupCountY;
  Id groupCountZ;
  Id payload;

  bool HasPayload() const { return wordCount > 4; }
};

struct OpSetMeshOutputsEXT
{
  OpSetMeshOutputsEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSetMeshOutputsEXT(Id vertexCount, Id primitiveCount)
      : op(Op::SetMeshOutputsEXT)
      , wordCount(FixedWordSize)
  {
    this->vertexCount = vertexCount;
    this->primitiveCount = primitiveCount;
  }

  static constexpr Op OpCode = Op::SetMeshOutputsEXT;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id vertexCount;
  Id primitiveCount;
};

struct OpGroupNonUniformPartitionEXT
{
  OpGroupNonUniformPartitionEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformPartitionEXT(IdResultType resultType, IdResult result, Id value)
      : op(Op::GroupNonUniformPartitionEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->value = value;
  }

  static constexpr Op OpCode = Op::GroupNonUniformPartitionEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id value;
};

struct OpWritePackedPrimitiveIndices4x8NV
{
  OpWritePackedPrimitiveIndices4x8NV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpWritePackedPrimitiveIndices4x8NV(Id indexOffset, Id packedIndices)
      : op(Op::WritePackedPrimitiveIndices4x8NV)
      , wordCount(FixedWordSize)
  {
    this->indexOffset = indexOffset;
    this->packedIndices = packedIndices;
  }

  static constexpr Op OpCode = Op::WritePackedPrimitiveIndices4x8NV;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id indexOffset;
  Id packedIndices;
};

struct OpFetchMicroTriangleVertexPositionNV
{
  OpFetchMicroTriangleVertexPositionNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFetchMicroTriangleVertexPositionNV(IdResultType resultType, IdResult result, Id accel, Id instanceId, Id geometryIndex, Id primitiveIndex, Id barycentric)
      : op(Op::FetchMicroTriangleVertexPositionNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->accel = accel;
    this->instanceId = instanceId;
    this->geometryIndex = geometryIndex;
    this->primitiveIndex = primitiveIndex;
    this->barycentric = barycentric;
  }

  static constexpr Op OpCode = Op::FetchMicroTriangleVertexPositionNV;
  static constexpr uint16_t FixedWordSize = 8U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id accel;
  Id instanceId;
  Id geometryIndex;
  Id primitiveIndex;
  Id barycentric;
};

struct OpFetchMicroTriangleVertexBarycentricNV
{
  OpFetchMicroTriangleVertexBarycentricNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFetchMicroTriangleVertexBarycentricNV(IdResultType resultType, IdResult result, Id accel, Id instanceId, Id geometryIndex, Id primitiveIndex, Id barycentric)
      : op(Op::FetchMicroTriangleVertexBarycentricNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->accel = accel;
    this->instanceId = instanceId;
    this->geometryIndex = geometryIndex;
    this->primitiveIndex = primitiveIndex;
    this->barycentric = barycentric;
  }

  static constexpr Op OpCode = Op::FetchMicroTriangleVertexBarycentricNV;
  static constexpr uint16_t FixedWordSize = 8U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id accel;
  Id instanceId;
  Id geometryIndex;
  Id primitiveIndex;
  Id barycentric;
};

struct OpCooperativeVectorLoadNV
{
  OpCooperativeVectorLoadNV(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->pointer = Id::fromWord(it.word(3));
    this->offset = Id::fromWord(it.word(4));
    word = 5;
    this->memoryAccess = DecodeParam<MemoryAccessAndParamDatas>(it, word);
  }
  OpCooperativeVectorLoadNV(IdResultType resultType, IdResult result, Id pointer, Id offset, MemoryAccessAndParamDatas memoryAccess = MemoryAccess::None)
      : op(Op::CooperativeVectorLoadNV)
      , wordCount(MinWordSize + ExtraWordCount(memoryAccess))
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->offset = offset;
    this->memoryAccess = memoryAccess;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(pointer.value());
    words.push_back(offset.value());
    EncodeParam(words, memoryAccess);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::CooperativeVectorLoadNV;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  Id offset;
  MemoryAccessAndParamDatas memoryAccess;
};

struct OpCooperativeVectorStoreNV
{
  OpCooperativeVectorStoreNV(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->pointer = Id::fromWord(it.word(1));
    this->offset = Id::fromWord(it.word(2));
    this->object = Id::fromWord(it.word(3));
    word = 4;
    this->memoryAccess = DecodeParam<MemoryAccessAndParamDatas>(it, word);
  }
  OpCooperativeVectorStoreNV(Id pointer, Id offset, Id object, MemoryAccessAndParamDatas memoryAccess = MemoryAccess::None)
      : op(Op::CooperativeVectorStoreNV)
      , wordCount(MinWordSize + ExtraWordCount(memoryAccess))
  {
    this->pointer = pointer;
    this->offset = offset;
    this->object = object;
    this->memoryAccess = memoryAccess;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(pointer.value());
    words.push_back(offset.value());
    words.push_back(object.value());
    EncodeParam(words, memoryAccess);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::CooperativeVectorStoreNV;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  Id pointer;
  Id offset;
  Id object;
  MemoryAccessAndParamDatas memoryAccess;
};

struct OpHitObjectRecordFromQueryEXT
{
  OpHitObjectRecordFromQueryEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectRecordFromQueryEXT(Id hitObject, Id rayQuery, Id sBTRecordIndex, Id hitObjectAttributes)
      : op(Op::HitObjectRecordFromQueryEXT)
      , wordCount(FixedWordSize)
  {
    this->hitObject = hitObject;
    this->rayQuery = rayQuery;
    this->sBTRecordIndex = sBTRecordIndex;
    this->hitObjectAttributes = hitObjectAttributes;
  }

  static constexpr Op OpCode = Op::HitObjectRecordFromQueryEXT;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id rayQuery;
  Id sBTRecordIndex;
  Id hitObjectAttributes;
};

struct OpHitObjectRecordMissEXT
{
  OpHitObjectRecordMissEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectRecordMissEXT(Id hitObject, Id rayFlags, Id missIndex, Id rayOrigin, Id rayTmin, Id rayDirection, Id rayTmax)
      : op(Op::HitObjectRecordMissEXT)
      , wordCount(FixedWordSize)
  {
    this->hitObject = hitObject;
    this->rayFlags = rayFlags;
    this->missIndex = missIndex;
    this->rayOrigin = rayOrigin;
    this->rayTmin = rayTmin;
    this->rayDirection = rayDirection;
    this->rayTmax = rayTmax;
  }

  static constexpr Op OpCode = Op::HitObjectRecordMissEXT;
  static constexpr uint16_t FixedWordSize = 8U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id rayFlags;
  Id missIndex;
  Id rayOrigin;
  Id rayTmin;
  Id rayDirection;
  Id rayTmax;
};

struct OpHitObjectRecordMissMotionEXT
{
  OpHitObjectRecordMissMotionEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectRecordMissMotionEXT(Id hitObject, Id rayFlags, Id missIndex, Id rayOrigin, Id rayTmin, Id rayDirection, Id rayTmax, Id currentTime)
      : op(Op::HitObjectRecordMissMotionEXT)
      , wordCount(FixedWordSize)
  {
    this->hitObject = hitObject;
    this->rayFlags = rayFlags;
    this->missIndex = missIndex;
    this->rayOrigin = rayOrigin;
    this->rayTmin = rayTmin;
    this->rayDirection = rayDirection;
    this->rayTmax = rayTmax;
    this->currentTime = currentTime;
  }

  static constexpr Op OpCode = Op::HitObjectRecordMissMotionEXT;
  static constexpr uint16_t FixedWordSize = 9U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id rayFlags;
  Id missIndex;
  Id rayOrigin;
  Id rayTmin;
  Id rayDirection;
  Id rayTmax;
  Id currentTime;
};

struct OpHitObjectGetIntersectionTriangleVertexPositionsEXT
{
  OpHitObjectGetIntersectionTriangleVertexPositionsEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetIntersectionTriangleVertexPositionsEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetIntersectionTriangleVertexPositionsEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetIntersectionTriangleVertexPositionsEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetRayFlagsEXT
{
  OpHitObjectGetRayFlagsEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetRayFlagsEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetRayFlagsEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetRayFlagsEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectSetShaderBindingTableRecordIndexEXT
{
  OpHitObjectSetShaderBindingTableRecordIndexEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectSetShaderBindingTableRecordIndexEXT(Id hitObject, Id sBTRecordIndex)
      : op(Op::HitObjectSetShaderBindingTableRecordIndexEXT)
      , wordCount(FixedWordSize)
  {
    this->hitObject = hitObject;
    this->sBTRecordIndex = sBTRecordIndex;
  }

  static constexpr Op OpCode = Op::HitObjectSetShaderBindingTableRecordIndexEXT;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id sBTRecordIndex;
};

struct OpHitObjectReorderExecuteShaderEXT
{
  OpHitObjectReorderExecuteShaderEXT(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->hitObject = Id::fromWord(it.word(1));
    this->payload = Id::fromWord(it.word(2));
    this->hint = (it.size() > 3) ? Id::fromWord(it.word(3)) : Id();
    this->bits = (it.size() > 4) ? Id::fromWord(it.word(4)) : Id();
  }
  OpHitObjectReorderExecuteShaderEXT(Id hitObject, Id payload, Id hint = Id(), Id bits = Id())
      : op(Op::HitObjectReorderExecuteShaderEXT)
      , wordCount(MinWordSize + OptionalWordCount(hint) + OptionalWordCount(bits))
  {
    this->hitObject = hitObject;
    this->payload = payload;
    this->hint = hint;
    this->bits = bits;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(hitObject.value());
    words.push_back(payload.value());
    if(hint != Id()) words.push_back(hint.value());
    if(bits != Id()) words.push_back(bits.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::HitObjectReorderExecuteShaderEXT;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id payload;
  Id hint;
  Id bits;

  bool HasHint() const { return wordCount > 3; }
  bool HasBits() const { return wordCount > 4; }
};

struct OpHitObjectTraceReorderExecuteEXT
{
  OpHitObjectTraceReorderExecuteEXT(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->hitObject = Id::fromWord(it.word(1));
    this->accelerationStructure = Id::fromWord(it.word(2));
    this->rayFlags = Id::fromWord(it.word(3));
    this->cullMask = Id::fromWord(it.word(4));
    this->sBTOffset = Id::fromWord(it.word(5));
    this->sBTStride = Id::fromWord(it.word(6));
    this->missIndex = Id::fromWord(it.word(7));
    this->rayOrigin = Id::fromWord(it.word(8));
    this->rayTmin = Id::fromWord(it.word(9));
    this->rayDirection = Id::fromWord(it.word(10));
    this->rayTmax = Id::fromWord(it.word(11));
    this->payload = Id::fromWord(it.word(12));
    this->hint = (it.size() > 13) ? Id::fromWord(it.word(13)) : Id();
    this->bits = (it.size() > 14) ? Id::fromWord(it.word(14)) : Id();
  }
  OpHitObjectTraceReorderExecuteEXT(Id hitObject, Id accelerationStructure, Id rayFlags, Id cullMask, Id sBTOffset, Id sBTStride, Id missIndex, Id rayOrigin, Id rayTmin, Id rayDirection, Id rayTmax, Id payload, Id hint = Id(), Id bits = Id())
      : op(Op::HitObjectTraceReorderExecuteEXT)
      , wordCount(MinWordSize + OptionalWordCount(hint) + OptionalWordCount(bits))
  {
    this->hitObject = hitObject;
    this->accelerationStructure = accelerationStructure;
    this->rayFlags = rayFlags;
    this->cullMask = cullMask;
    this->sBTOffset = sBTOffset;
    this->sBTStride = sBTStride;
    this->missIndex = missIndex;
    this->rayOrigin = rayOrigin;
    this->rayTmin = rayTmin;
    this->rayDirection = rayDirection;
    this->rayTmax = rayTmax;
    this->payload = payload;
    this->hint = hint;
    this->bits = bits;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(hitObject.value());
    words.push_back(accelerationStructure.value());
    words.push_back(rayFlags.value());
    words.push_back(cullMask.value());
    words.push_back(sBTOffset.value());
    words.push_back(sBTStride.value());
    words.push_back(missIndex.value());
    words.push_back(rayOrigin.value());
    words.push_back(rayTmin.value());
    words.push_back(rayDirection.value());
    words.push_back(rayTmax.value());
    words.push_back(payload.value());
    if(hint != Id()) words.push_back(hint.value());
    if(bits != Id()) words.push_back(bits.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::HitObjectTraceReorderExecuteEXT;
  static constexpr uint16_t MinWordSize = 13U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id accelerationStructure;
  Id rayFlags;
  Id cullMask;
  Id sBTOffset;
  Id sBTStride;
  Id missIndex;
  Id rayOrigin;
  Id rayTmin;
  Id rayDirection;
  Id rayTmax;
  Id payload;
  Id hint;
  Id bits;

  bool HasHint() const { return wordCount > 13; }
  bool HasBits() const { return wordCount > 14; }
};

struct OpHitObjectTraceMotionReorderExecuteEXT
{
  OpHitObjectTraceMotionReorderExecuteEXT(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->hitObject = Id::fromWord(it.word(1));
    this->accelerationStructure = Id::fromWord(it.word(2));
    this->rayFlags = Id::fromWord(it.word(3));
    this->cullMask = Id::fromWord(it.word(4));
    this->sBTOffset = Id::fromWord(it.word(5));
    this->sBTStride = Id::fromWord(it.word(6));
    this->missIndex = Id::fromWord(it.word(7));
    this->rayOrigin = Id::fromWord(it.word(8));
    this->rayTmin = Id::fromWord(it.word(9));
    this->rayDirection = Id::fromWord(it.word(10));
    this->rayTmax = Id::fromWord(it.word(11));
    this->currentTime = Id::fromWord(it.word(12));
    this->payload = Id::fromWord(it.word(13));
    this->hint = (it.size() > 14) ? Id::fromWord(it.word(14)) : Id();
    this->bits = (it.size() > 15) ? Id::fromWord(it.word(15)) : Id();
  }
  OpHitObjectTraceMotionReorderExecuteEXT(Id hitObject, Id accelerationStructure, Id rayFlags, Id cullMask, Id sBTOffset, Id sBTStride, Id missIndex, Id rayOrigin, Id rayTmin, Id rayDirection, Id rayTmax, Id currentTime, Id payload, Id hint = Id(), Id bits = Id())
      : op(Op::HitObjectTraceMotionReorderExecuteEXT)
      , wordCount(MinWordSize + OptionalWordCount(hint) + OptionalWordCount(bits))
  {
    this->hitObject = hitObject;
    this->accelerationStructure = accelerationStructure;
    this->rayFlags = rayFlags;
    this->cullMask = cullMask;
    this->sBTOffset = sBTOffset;
    this->sBTStride = sBTStride;
    this->missIndex = missIndex;
    this->rayOrigin = rayOrigin;
    this->rayTmin = rayTmin;
    this->rayDirection = rayDirection;
    this->rayTmax = rayTmax;
    this->currentTime = currentTime;
    this->payload = payload;
    this->hint = hint;
    this->bits = bits;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(hitObject.value());
    words.push_back(accelerationStructure.value());
    words.push_back(rayFlags.value());
    words.push_back(cullMask.value());
    words.push_back(sBTOffset.value());
    words.push_back(sBTStride.value());
    words.push_back(missIndex.value());
    words.push_back(rayOrigin.value());
    words.push_back(rayTmin.value());
    words.push_back(rayDirection.value());
    words.push_back(rayTmax.value());
    words.push_back(currentTime.value());
    words.push_back(payload.value());
    if(hint != Id()) words.push_back(hint.value());
    if(bits != Id()) words.push_back(bits.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::HitObjectTraceMotionReorderExecuteEXT;
  static constexpr uint16_t MinWordSize = 14U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id accelerationStructure;
  Id rayFlags;
  Id cullMask;
  Id sBTOffset;
  Id sBTStride;
  Id missIndex;
  Id rayOrigin;
  Id rayTmin;
  Id rayDirection;
  Id rayTmax;
  Id currentTime;
  Id payload;
  Id hint;
  Id bits;

  bool HasHint() const { return wordCount > 14; }
  bool HasBits() const { return wordCount > 15; }
};

struct OpTypeHitObjectEXT
{
  OpTypeHitObjectEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeHitObjectEXT(IdResult result)
      : op(Op::TypeHitObjectEXT)
      , wordCount(FixedWordSize)
  {
    this->result = result;
  }

  static constexpr Op OpCode = Op::TypeHitObjectEXT;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  IdResult result;
};

struct OpReorderThreadWithHintEXT
{
  OpReorderThreadWithHintEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpReorderThreadWithHintEXT(Id hint, Id bits)
      : op(Op::ReorderThreadWithHintEXT)
      , wordCount(FixedWordSize)
  {
    this->hint = hint;
    this->bits = bits;
  }

  static constexpr Op OpCode = Op::ReorderThreadWithHintEXT;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id hint;
  Id bits;
};

struct OpReorderThreadWithHitObjectEXT
{
  OpReorderThreadWithHitObjectEXT(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->hitObject = Id::fromWord(it.word(1));
    this->hint = (it.size() > 2) ? Id::fromWord(it.word(2)) : Id();
    this->bits = (it.size() > 3) ? Id::fromWord(it.word(3)) : Id();
  }
  OpReorderThreadWithHitObjectEXT(Id hitObject, Id hint = Id(), Id bits = Id())
      : op(Op::ReorderThreadWithHitObjectEXT)
      , wordCount(MinWordSize + OptionalWordCount(hint) + OptionalWordCount(bits))
  {
    this->hitObject = hitObject;
    this->hint = hint;
    this->bits = bits;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(hitObject.value());
    if(hint != Id()) words.push_back(hint.value());
    if(bits != Id()) words.push_back(bits.value());
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ReorderThreadWithHitObjectEXT;
  static constexpr uint16_t MinWordSize = 2U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id hint;
  Id bits;

  bool HasHint() const { return wordCount > 2; }
  bool HasBits() const { return wordCount > 3; }
};

struct OpHitObjectTraceRayEXT
{
  OpHitObjectTraceRayEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectTraceRayEXT(Id hitObject, Id accelerationStructure, Id rayFlags, Id cullMask, Id sBTOffset, Id sBTStride, Id missIndex, Id rayOrigin, Id rayTmin, Id rayDirection, Id rayTmax, Id payload)
      : op(Op::HitObjectTraceRayEXT)
      , wordCount(FixedWordSize)
  {
    this->hitObject = hitObject;
    this->accelerationStructure = accelerationStructure;
    this->rayFlags = rayFlags;
    this->cullMask = cullMask;
    this->sBTOffset = sBTOffset;
    this->sBTStride = sBTStride;
    this->missIndex = missIndex;
    this->rayOrigin = rayOrigin;
    this->rayTmin = rayTmin;
    this->rayDirection = rayDirection;
    this->rayTmax = rayTmax;
    this->payload = payload;
  }

  static constexpr Op OpCode = Op::HitObjectTraceRayEXT;
  static constexpr uint16_t FixedWordSize = 13U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id accelerationStructure;
  Id rayFlags;
  Id cullMask;
  Id sBTOffset;
  Id sBTStride;
  Id missIndex;
  Id rayOrigin;
  Id rayTmin;
  Id rayDirection;
  Id rayTmax;
  Id payload;
};

struct OpHitObjectTraceRayMotionEXT
{
  OpHitObjectTraceRayMotionEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectTraceRayMotionEXT(Id hitObject, Id accelerationStructure, Id rayFlags, Id cullMask, Id sBTOffset, Id sBTStride, Id missIndex, Id rayOrigin, Id rayTmin, Id rayDirection, Id rayTmax, Id currentTime, Id payload)
      : op(Op::HitObjectTraceRayMotionEXT)
      , wordCount(FixedWordSize)
  {
    this->hitObject = hitObject;
    this->accelerationStructure = accelerationStructure;
    this->rayFlags = rayFlags;
    this->cullMask = cullMask;
    this->sBTOffset = sBTOffset;
    this->sBTStride = sBTStride;
    this->missIndex = missIndex;
    this->rayOrigin = rayOrigin;
    this->rayTmin = rayTmin;
    this->rayDirection = rayDirection;
    this->rayTmax = rayTmax;
    this->currentTime = currentTime;
    this->payload = payload;
  }

  static constexpr Op OpCode = Op::HitObjectTraceRayMotionEXT;
  static constexpr uint16_t FixedWordSize = 14U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id accelerationStructure;
  Id rayFlags;
  Id cullMask;
  Id sBTOffset;
  Id sBTStride;
  Id missIndex;
  Id rayOrigin;
  Id rayTmin;
  Id rayDirection;
  Id rayTmax;
  Id currentTime;
  Id payload;
};

struct OpHitObjectRecordEmptyEXT
{
  OpHitObjectRecordEmptyEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectRecordEmptyEXT(Id hitObject)
      : op(Op::HitObjectRecordEmptyEXT)
      , wordCount(FixedWordSize)
  {
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectRecordEmptyEXT;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
};

struct OpHitObjectExecuteShaderEXT
{
  OpHitObjectExecuteShaderEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectExecuteShaderEXT(Id hitObject, Id payload)
      : op(Op::HitObjectExecuteShaderEXT)
      , wordCount(FixedWordSize)
  {
    this->hitObject = hitObject;
    this->payload = payload;
  }

  static constexpr Op OpCode = Op::HitObjectExecuteShaderEXT;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id payload;
};

struct OpHitObjectGetCurrentTimeEXT
{
  OpHitObjectGetCurrentTimeEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetCurrentTimeEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetCurrentTimeEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetCurrentTimeEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetAttributesEXT
{
  OpHitObjectGetAttributesEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetAttributesEXT(Id hitObject, Id hitObjectAttribute)
      : op(Op::HitObjectGetAttributesEXT)
      , wordCount(FixedWordSize)
  {
    this->hitObject = hitObject;
    this->hitObjectAttribute = hitObjectAttribute;
  }

  static constexpr Op OpCode = Op::HitObjectGetAttributesEXT;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id hitObject;
  Id hitObjectAttribute;
};

struct OpHitObjectGetHitKindEXT
{
  OpHitObjectGetHitKindEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetHitKindEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetHitKindEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetHitKindEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetPrimitiveIndexEXT
{
  OpHitObjectGetPrimitiveIndexEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetPrimitiveIndexEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetPrimitiveIndexEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetPrimitiveIndexEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetGeometryIndexEXT
{
  OpHitObjectGetGeometryIndexEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetGeometryIndexEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetGeometryIndexEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetGeometryIndexEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetInstanceIdEXT
{
  OpHitObjectGetInstanceIdEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetInstanceIdEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetInstanceIdEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetInstanceIdEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetInstanceCustomIndexEXT
{
  OpHitObjectGetInstanceCustomIndexEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetInstanceCustomIndexEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetInstanceCustomIndexEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetInstanceCustomIndexEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetObjectRayOriginEXT
{
  OpHitObjectGetObjectRayOriginEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetObjectRayOriginEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetObjectRayOriginEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetObjectRayOriginEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetObjectRayDirectionEXT
{
  OpHitObjectGetObjectRayDirectionEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetObjectRayDirectionEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetObjectRayDirectionEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetObjectRayDirectionEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetWorldRayDirectionEXT
{
  OpHitObjectGetWorldRayDirectionEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetWorldRayDirectionEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetWorldRayDirectionEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetWorldRayDirectionEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetWorldRayOriginEXT
{
  OpHitObjectGetWorldRayOriginEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetWorldRayOriginEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetWorldRayOriginEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetWorldRayOriginEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetObjectToWorldEXT
{
  OpHitObjectGetObjectToWorldEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetObjectToWorldEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetObjectToWorldEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetObjectToWorldEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetWorldToObjectEXT
{
  OpHitObjectGetWorldToObjectEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetWorldToObjectEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetWorldToObjectEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetWorldToObjectEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetRayTMaxEXT
{
  OpHitObjectGetRayTMaxEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetRayTMaxEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetRayTMaxEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetRayTMaxEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpReportIntersectionKHR
{
  OpReportIntersectionKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpReportIntersectionKHR(IdResultType resultType, IdResult result, Id hit, Id hitKind)
      : op(Op::ReportIntersectionKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hit = hit;
    this->hitKind = hitKind;
  }

  static constexpr Op OpCode = Op::ReportIntersectionKHR;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hit;
  Id hitKind;
};

struct OpIgnoreIntersectionNV
{
  OpIgnoreIntersectionNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpIgnoreIntersectionNV()
      : op(Op::IgnoreIntersectionNV)
      , wordCount(FixedWordSize)
  {
    // no operands
  }

  static constexpr Op OpCode = Op::IgnoreIntersectionNV;
  static constexpr uint16_t FixedWordSize = 1U;
  Op op;
  uint16_t wordCount;
  // no operands
};

struct OpTerminateRayNV
{
  OpTerminateRayNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTerminateRayNV()
      : op(Op::TerminateRayNV)
      , wordCount(FixedWordSize)
  {
    // no operands
  }

  static constexpr Op OpCode = Op::TerminateRayNV;
  static constexpr uint16_t FixedWordSize = 1U;
  Op op;
  uint16_t wordCount;
  // no operands
};

struct OpTraceNV
{
  OpTraceNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTraceNV(Id accel, Id rayFlags, Id cullMask, Id sBTOffset, Id sBTStride, Id missIndex, Id rayOrigin, Id rayTmin, Id rayDirection, Id rayTmax, Id payloadId)
      : op(Op::TraceNV)
      , wordCount(FixedWordSize)
  {
    this->accel = accel;
    this->rayFlags = rayFlags;
    this->cullMask = cullMask;
    this->sBTOffset = sBTOffset;
    this->sBTStride = sBTStride;
    this->missIndex = missIndex;
    this->rayOrigin = rayOrigin;
    this->rayTmin = rayTmin;
    this->rayDirection = rayDirection;
    this->rayTmax = rayTmax;
    this->payloadId = payloadId;
  }

  static constexpr Op OpCode = Op::TraceNV;
  static constexpr uint16_t FixedWordSize = 12U;
  Op op;
  uint16_t wordCount;
  Id accel;
  Id rayFlags;
  Id cullMask;
  Id sBTOffset;
  Id sBTStride;
  Id missIndex;
  Id rayOrigin;
  Id rayTmin;
  Id rayDirection;
  Id rayTmax;
  Id payloadId;
};

struct OpTraceMotionNV
{
  OpTraceMotionNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTraceMotionNV(Id accel, Id rayFlags, Id cullMask, Id sBTOffset, Id sBTStride, Id missIndex, Id rayOrigin, Id rayTmin, Id rayDirection, Id rayTmax, Id time, Id payloadId)
      : op(Op::TraceMotionNV)
      , wordCount(FixedWordSize)
  {
    this->accel = accel;
    this->rayFlags = rayFlags;
    this->cullMask = cullMask;
    this->sBTOffset = sBTOffset;
    this->sBTStride = sBTStride;
    this->missIndex = missIndex;
    this->rayOrigin = rayOrigin;
    this->rayTmin = rayTmin;
    this->rayDirection = rayDirection;
    this->rayTmax = rayTmax;
    this->time = time;
    this->payloadId = payloadId;
  }

  static constexpr Op OpCode = Op::TraceMotionNV;
  static constexpr uint16_t FixedWordSize = 13U;
  Op op;
  uint16_t wordCount;
  Id accel;
  Id rayFlags;
  Id cullMask;
  Id sBTOffset;
  Id sBTStride;
  Id missIndex;
  Id rayOrigin;
  Id rayTmin;
  Id rayDirection;
  Id rayTmax;
  Id time;
  Id payloadId;
};

struct OpTraceRayMotionNV
{
  OpTraceRayMotionNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTraceRayMotionNV(Id accel, Id rayFlags, Id cullMask, Id sBTOffset, Id sBTStride, Id missIndex, Id rayOrigin, Id rayTmin, Id rayDirection, Id rayTmax, Id time, Id payload)
      : op(Op::TraceRayMotionNV)
      , wordCount(FixedWordSize)
  {
    this->accel = accel;
    this->rayFlags = rayFlags;
    this->cullMask = cullMask;
    this->sBTOffset = sBTOffset;
    this->sBTStride = sBTStride;
    this->missIndex = missIndex;
    this->rayOrigin = rayOrigin;
    this->rayTmin = rayTmin;
    this->rayDirection = rayDirection;
    this->rayTmax = rayTmax;
    this->time = time;
    this->payload = payload;
  }

  static constexpr Op OpCode = Op::TraceRayMotionNV;
  static constexpr uint16_t FixedWordSize = 13U;
  Op op;
  uint16_t wordCount;
  Id accel;
  Id rayFlags;
  Id cullMask;
  Id sBTOffset;
  Id sBTStride;
  Id missIndex;
  Id rayOrigin;
  Id rayTmin;
  Id rayDirection;
  Id rayTmax;
  Id time;
  Id payload;
};

struct OpRayQueryGetIntersectionTriangleVertexPositionsKHR
{
  OpRayQueryGetIntersectionTriangleVertexPositionsKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionTriangleVertexPositionsKHR(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryGetIntersectionTriangleVertexPositionsKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionTriangleVertexPositionsKHR;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpTypeAccelerationStructureKHR
{
  OpTypeAccelerationStructureKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeAccelerationStructureKHR(IdResult result)
      : op(Op::TypeAccelerationStructureKHR)
      , wordCount(FixedWordSize)
  {
    this->result = result;
  }

  static constexpr Op OpCode = Op::TypeAccelerationStructureKHR;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  IdResult result;
};

struct OpExecuteCallableNV
{
  OpExecuteCallableNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpExecuteCallableNV(Id sBTIndex, Id callableDataId)
      : op(Op::ExecuteCallableNV)
      , wordCount(FixedWordSize)
  {
    this->sBTIndex = sBTIndex;
    this->callableDataId = callableDataId;
  }

  static constexpr Op OpCode = Op::ExecuteCallableNV;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id sBTIndex;
  Id callableDataId;
};

struct OpRayQueryGetIntersectionClusterIdNV
{
  OpRayQueryGetIntersectionClusterIdNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionClusterIdNV(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryGetIntersectionClusterIdNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionClusterIdNV;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpHitObjectGetClusterIdNV
{
  OpHitObjectGetClusterIdNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetClusterIdNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetClusterIdNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetClusterIdNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetRayTMinEXT
{
  OpHitObjectGetRayTMinEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetRayTMinEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetRayTMinEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetRayTMinEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetShaderBindingTableRecordIndexEXT
{
  OpHitObjectGetShaderBindingTableRecordIndexEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetShaderBindingTableRecordIndexEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetShaderBindingTableRecordIndexEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetShaderBindingTableRecordIndexEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetShaderRecordBufferHandleEXT
{
  OpHitObjectGetShaderRecordBufferHandleEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetShaderRecordBufferHandleEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetShaderRecordBufferHandleEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetShaderRecordBufferHandleEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectIsEmptyEXT
{
  OpHitObjectIsEmptyEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectIsEmptyEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectIsEmptyEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectIsEmptyEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectIsHitEXT
{
  OpHitObjectIsHitEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectIsHitEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectIsHitEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectIsHitEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectIsMissEXT
{
  OpHitObjectIsMissEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectIsMissEXT(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectIsMissEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectIsMissEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpTypeCooperativeMatrixNV
{
  OpTypeCooperativeMatrixNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeCooperativeMatrixNV(IdResult result, Id componentType, IdScope execution, Id rows, Id columns)
      : op(Op::TypeCooperativeMatrixNV)
      , wordCount(FixedWordSize)
  {
    this->result = result;
    this->componentType = componentType;
    this->execution = execution;
    this->rows = rows;
    this->columns = columns;
  }

  static constexpr Op OpCode = Op::TypeCooperativeMatrixNV;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  Id componentType;
  IdScope execution;
  Id rows;
  Id columns;
};

struct OpCooperativeMatrixLoadNV
{
  OpCooperativeMatrixLoadNV(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->pointer = Id::fromWord(it.word(3));
    this->stride = Id::fromWord(it.word(4));
    this->columnMajor = Id::fromWord(it.word(5));
    word = 6;
    this->memoryAccess = DecodeParam<MemoryAccessAndParamDatas>(it, word);
  }
  OpCooperativeMatrixLoadNV(IdResultType resultType, IdResult result, Id pointer, Id stride, Id columnMajor, MemoryAccessAndParamDatas memoryAccess = MemoryAccess::None)
      : op(Op::CooperativeMatrixLoadNV)
      , wordCount(MinWordSize + ExtraWordCount(memoryAccess))
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->stride = stride;
    this->columnMajor = columnMajor;
    this->memoryAccess = memoryAccess;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(pointer.value());
    words.push_back(stride.value());
    words.push_back(columnMajor.value());
    EncodeParam(words, memoryAccess);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::CooperativeMatrixLoadNV;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  Id stride;
  Id columnMajor;
  MemoryAccessAndParamDatas memoryAccess;
};

struct OpCooperativeMatrixStoreNV
{
  OpCooperativeMatrixStoreNV(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->pointer = Id::fromWord(it.word(1));
    this->object = Id::fromWord(it.word(2));
    this->stride = Id::fromWord(it.word(3));
    this->columnMajor = Id::fromWord(it.word(4));
    word = 5;
    this->memoryAccess = DecodeParam<MemoryAccessAndParamDatas>(it, word);
  }
  OpCooperativeMatrixStoreNV(Id pointer, Id object, Id stride, Id columnMajor, MemoryAccessAndParamDatas memoryAccess = MemoryAccess::None)
      : op(Op::CooperativeMatrixStoreNV)
      , wordCount(MinWordSize + ExtraWordCount(memoryAccess))
  {
    this->pointer = pointer;
    this->object = object;
    this->stride = stride;
    this->columnMajor = columnMajor;
    this->memoryAccess = memoryAccess;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(pointer.value());
    words.push_back(object.value());
    words.push_back(stride.value());
    words.push_back(columnMajor.value());
    EncodeParam(words, memoryAccess);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::CooperativeMatrixStoreNV;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  Id pointer;
  Id object;
  Id stride;
  Id columnMajor;
  MemoryAccessAndParamDatas memoryAccess;
};

struct OpCooperativeMatrixMulAddNV
{
  OpCooperativeMatrixMulAddNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpCooperativeMatrixMulAddNV(IdResultType resultType, IdResult result, Id a, Id b, Id c)
      : op(Op::CooperativeMatrixMulAddNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->a = a;
    this->b = b;
    this->c = c;
  }

  static constexpr Op OpCode = Op::CooperativeMatrixMulAddNV;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id a;
  Id b;
  Id c;
};

struct OpCooperativeMatrixLengthNV
{
  OpCooperativeMatrixLengthNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpCooperativeMatrixLengthNV(IdResultType resultType, IdResult result, Id type)
      : op(Op::CooperativeMatrixLengthNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->type = type;
  }

  static constexpr Op OpCode = Op::CooperativeMatrixLengthNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id type;
};

struct OpBeginInvocationInterlockEXT
{
  OpBeginInvocationInterlockEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpBeginInvocationInterlockEXT()
      : op(Op::BeginInvocationInterlockEXT)
      , wordCount(FixedWordSize)
  {
    // no operands
  }

  static constexpr Op OpCode = Op::BeginInvocationInterlockEXT;
  static constexpr uint16_t FixedWordSize = 1U;
  Op op;
  uint16_t wordCount;
  // no operands
};

struct OpEndInvocationInterlockEXT
{
  OpEndInvocationInterlockEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpEndInvocationInterlockEXT()
      : op(Op::EndInvocationInterlockEXT)
      , wordCount(FixedWordSize)
  {
    // no operands
  }

  static constexpr Op OpCode = Op::EndInvocationInterlockEXT;
  static constexpr uint16_t FixedWordSize = 1U;
  Op op;
  uint16_t wordCount;
  // no operands
};

struct OpCooperativeMatrixReduceNV
{
  OpCooperativeMatrixReduceNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpCooperativeMatrixReduceNV(IdResultType resultType, IdResult result, Id matrix, CooperativeMatrixReduce reduce, Id combineFunc)
      : op(Op::CooperativeMatrixReduceNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->matrix = matrix;
    this->reduce = reduce;
    this->combineFunc = combineFunc;
  }

  static constexpr Op OpCode = Op::CooperativeMatrixReduceNV;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id matrix;
  CooperativeMatrixReduce reduce;
  Id combineFunc;
};

struct OpCooperativeMatrixLoadTensorNV
{
  OpCooperativeMatrixLoadTensorNV(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->pointer = Id::fromWord(it.word(3));
    this->object = Id::fromWord(it.word(4));
    this->tensorLayout = Id::fromWord(it.word(5));
    word = 6;
    this->memoryOperand = DecodeParam<MemoryAccessAndParamDatas>(it, word);
    this->tensorAddressingOperands = DecodeParam<TensorAddressingOperandsAndParamDatas>(it, word);
  }
  OpCooperativeMatrixLoadTensorNV(IdResultType resultType, IdResult result, Id pointer, Id object, Id tensorLayout, MemoryAccessAndParamDatas memoryOperand, TensorAddressingOperandsAndParamDatas tensorAddressingOperands)
      : op(Op::CooperativeMatrixLoadTensorNV)
      , wordCount(MinWordSize + ExtraWordCount(memoryOperand) + ExtraWordCount(tensorAddressingOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->object = object;
    this->tensorLayout = tensorLayout;
    this->memoryOperand = memoryOperand;
    this->tensorAddressingOperands = tensorAddressingOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(pointer.value());
    words.push_back(object.value());
    words.push_back(tensorLayout.value());
    EncodeParam(words, memoryOperand);
    EncodeParam(words, tensorAddressingOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::CooperativeMatrixLoadTensorNV;
  static constexpr uint16_t MinWordSize = 8U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  Id object;
  Id tensorLayout;
  MemoryAccessAndParamDatas memoryOperand;
  TensorAddressingOperandsAndParamDatas tensorAddressingOperands;
};

struct OpCooperativeMatrixStoreTensorNV
{
  OpCooperativeMatrixStoreTensorNV(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->pointer = Id::fromWord(it.word(1));
    this->object = Id::fromWord(it.word(2));
    this->tensorLayout = Id::fromWord(it.word(3));
    word = 4;
    this->memoryOperand = DecodeParam<MemoryAccessAndParamDatas>(it, word);
    this->tensorAddressingOperands = DecodeParam<TensorAddressingOperandsAndParamDatas>(it, word);
  }
  OpCooperativeMatrixStoreTensorNV(Id pointer, Id object, Id tensorLayout, MemoryAccessAndParamDatas memoryOperand, TensorAddressingOperandsAndParamDatas tensorAddressingOperands)
      : op(Op::CooperativeMatrixStoreTensorNV)
      , wordCount(MinWordSize + ExtraWordCount(memoryOperand) + ExtraWordCount(tensorAddressingOperands))
  {
    this->pointer = pointer;
    this->object = object;
    this->tensorLayout = tensorLayout;
    this->memoryOperand = memoryOperand;
    this->tensorAddressingOperands = tensorAddressingOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(pointer.value());
    words.push_back(object.value());
    words.push_back(tensorLayout.value());
    EncodeParam(words, memoryOperand);
    EncodeParam(words, tensorAddressingOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::CooperativeMatrixStoreTensorNV;
  static constexpr uint16_t MinWordSize = 6U;
  Op op;
  uint16_t wordCount;
  Id pointer;
  Id object;
  Id tensorLayout;
  MemoryAccessAndParamDatas memoryOperand;
  TensorAddressingOperandsAndParamDatas tensorAddressingOperands;
};

struct OpCooperativeMatrixPerElementOpNV
{
  OpCooperativeMatrixPerElementOpNV(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->matrix = Id::fromWord(it.word(3));
    this->func = Id::fromWord(it.word(4));
    word = 5;
    this->operands = MultiParam<Id>(it, word);
  }
  OpCooperativeMatrixPerElementOpNV(IdResultType resultType, IdResult result, Id matrix, Id func, const rdcarray<Id> &operands = {})
      : op(Op::CooperativeMatrixPerElementOpNV)
      , wordCount(MinWordSize + MultiWordCount(operands))
  {
    this->resultType = resultType;
    this->result = result;
    this->matrix = matrix;
    this->func = func;
    this->operands = operands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(matrix.value());
    words.push_back(func.value());
    for(size_t i=0; i < operands.size(); i++)
    {
      words.push_back(operands[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::CooperativeMatrixPerElementOpNV;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id matrix;
  Id func;
  rdcarray<Id> operands;
};

struct OpTypeTensorLayoutNV
{
  OpTypeTensorLayoutNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeTensorLayoutNV(IdResult result, Id dim, Id clampMode)
      : op(Op::TypeTensorLayoutNV)
      , wordCount(FixedWordSize)
  {
    this->result = result;
    this->dim = dim;
    this->clampMode = clampMode;
  }

  static constexpr Op OpCode = Op::TypeTensorLayoutNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  Id dim;
  Id clampMode;
};

struct OpTypeTensorViewNV
{
  OpTypeTensorViewNV(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->result = Id::fromWord(it.word(1));
    this->dim = Id::fromWord(it.word(2));
    this->hasDimensions = Id::fromWord(it.word(3));
    word = 4;
    this->p = MultiParam<Id>(it, word);
  }
  OpTypeTensorViewNV(IdResult result, Id dim, Id hasDimensions, const rdcarray<Id> &p = {})
      : op(Op::TypeTensorViewNV)
      , wordCount(MinWordSize + MultiWordCount(p))
  {
    this->result = result;
    this->dim = dim;
    this->hasDimensions = hasDimensions;
    this->p = p;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(result.value());
    words.push_back(dim.value());
    words.push_back(hasDimensions.value());
    for(size_t i=0; i < p.size(); i++)
    {
      words.push_back(p[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::TypeTensorViewNV;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  Id dim;
  Id hasDimensions;
  rdcarray<Id> p;
};

struct OpCreateTensorLayoutNV
{
  OpCreateTensorLayoutNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpCreateTensorLayoutNV(IdResultType resultType, IdResult result)
      : op(Op::CreateTensorLayoutNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
  }

  static constexpr Op OpCode = Op::CreateTensorLayoutNV;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
};

struct OpTensorLayoutSetDimensionNV
{
  OpTensorLayoutSetDimensionNV(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->tensorLayout = Id::fromWord(it.word(3));
    word = 4;
    this->dim = MultiParam<Id>(it, word);
  }
  OpTensorLayoutSetDimensionNV(IdResultType resultType, IdResult result, Id tensorLayout, const rdcarray<Id> &dim = {})
      : op(Op::TensorLayoutSetDimensionNV)
      , wordCount(MinWordSize + MultiWordCount(dim))
  {
    this->resultType = resultType;
    this->result = result;
    this->tensorLayout = tensorLayout;
    this->dim = dim;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(tensorLayout.value());
    for(size_t i=0; i < dim.size(); i++)
    {
      words.push_back(dim[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::TensorLayoutSetDimensionNV;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id tensorLayout;
  rdcarray<Id> dim;
};

struct OpTensorLayoutSetStrideNV
{
  OpTensorLayoutSetStrideNV(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->tensorLayout = Id::fromWord(it.word(3));
    word = 4;
    this->stride = MultiParam<Id>(it, word);
  }
  OpTensorLayoutSetStrideNV(IdResultType resultType, IdResult result, Id tensorLayout, const rdcarray<Id> &stride = {})
      : op(Op::TensorLayoutSetStrideNV)
      , wordCount(MinWordSize + MultiWordCount(stride))
  {
    this->resultType = resultType;
    this->result = result;
    this->tensorLayout = tensorLayout;
    this->stride = stride;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(tensorLayout.value());
    for(size_t i=0; i < stride.size(); i++)
    {
      words.push_back(stride[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::TensorLayoutSetStrideNV;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id tensorLayout;
  rdcarray<Id> stride;
};

struct OpTensorLayoutSliceNV
{
  OpTensorLayoutSliceNV(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->tensorLayout = Id::fromWord(it.word(3));
    word = 4;
    this->operands = MultiParam<Id>(it, word);
  }
  OpTensorLayoutSliceNV(IdResultType resultType, IdResult result, Id tensorLayout, const rdcarray<Id> &operands = {})
      : op(Op::TensorLayoutSliceNV)
      , wordCount(MinWordSize + MultiWordCount(operands))
  {
    this->resultType = resultType;
    this->result = result;
    this->tensorLayout = tensorLayout;
    this->operands = operands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(tensorLayout.value());
    for(size_t i=0; i < operands.size(); i++)
    {
      words.push_back(operands[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::TensorLayoutSliceNV;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id tensorLayout;
  rdcarray<Id> operands;
};

struct OpTensorLayoutSetClampValueNV
{
  OpTensorLayoutSetClampValueNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTensorLayoutSetClampValueNV(IdResultType resultType, IdResult result, Id tensorLayout, Id value)
      : op(Op::TensorLayoutSetClampValueNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->tensorLayout = tensorLayout;
    this->value = value;
  }

  static constexpr Op OpCode = Op::TensorLayoutSetClampValueNV;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id tensorLayout;
  Id value;
};

struct OpCreateTensorViewNV
{
  OpCreateTensorViewNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpCreateTensorViewNV(IdResultType resultType, IdResult result)
      : op(Op::CreateTensorViewNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
  }

  static constexpr Op OpCode = Op::CreateTensorViewNV;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
};

struct OpTensorViewSetDimensionNV
{
  OpTensorViewSetDimensionNV(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->tensorView = Id::fromWord(it.word(3));
    word = 4;
    this->dim = MultiParam<Id>(it, word);
  }
  OpTensorViewSetDimensionNV(IdResultType resultType, IdResult result, Id tensorView, const rdcarray<Id> &dim = {})
      : op(Op::TensorViewSetDimensionNV)
      , wordCount(MinWordSize + MultiWordCount(dim))
  {
    this->resultType = resultType;
    this->result = result;
    this->tensorView = tensorView;
    this->dim = dim;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(tensorView.value());
    for(size_t i=0; i < dim.size(); i++)
    {
      words.push_back(dim[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::TensorViewSetDimensionNV;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id tensorView;
  rdcarray<Id> dim;
};

struct OpTensorViewSetStrideNV
{
  OpTensorViewSetStrideNV(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->tensorView = Id::fromWord(it.word(3));
    word = 4;
    this->stride = MultiParam<Id>(it, word);
  }
  OpTensorViewSetStrideNV(IdResultType resultType, IdResult result, Id tensorView, const rdcarray<Id> &stride = {})
      : op(Op::TensorViewSetStrideNV)
      , wordCount(MinWordSize + MultiWordCount(stride))
  {
    this->resultType = resultType;
    this->result = result;
    this->tensorView = tensorView;
    this->stride = stride;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(tensorView.value());
    for(size_t i=0; i < stride.size(); i++)
    {
      words.push_back(stride[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::TensorViewSetStrideNV;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id tensorView;
  rdcarray<Id> stride;
};

struct OpDemoteToHelperInvocation
{
  OpDemoteToHelperInvocation(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpDemoteToHelperInvocation()
      : op(Op::DemoteToHelperInvocation)
      , wordCount(FixedWordSize)
  {
    // no operands
  }

  static constexpr Op OpCode = Op::DemoteToHelperInvocation;
  static constexpr uint16_t FixedWordSize = 1U;
  Op op;
  uint16_t wordCount;
  // no operands
};

struct OpIsHelperInvocationEXT
{
  OpIsHelperInvocationEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpIsHelperInvocationEXT(IdResultType resultType, IdResult result)
      : op(Op::IsHelperInvocationEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
  }

  static constexpr Op OpCode = Op::IsHelperInvocationEXT;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
};

struct OpTensorViewSetClipNV
{
  OpTensorViewSetClipNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTensorViewSetClipNV(IdResultType resultType, IdResult result, Id tensorView, Id clipRowOffset, Id clipRowSpan, Id clipColOffset, Id clipColSpan)
      : op(Op::TensorViewSetClipNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->tensorView = tensorView;
    this->clipRowOffset = clipRowOffset;
    this->clipRowSpan = clipRowSpan;
    this->clipColOffset = clipColOffset;
    this->clipColSpan = clipColSpan;
  }

  static constexpr Op OpCode = Op::TensorViewSetClipNV;
  static constexpr uint16_t FixedWordSize = 8U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id tensorView;
  Id clipRowOffset;
  Id clipRowSpan;
  Id clipColOffset;
  Id clipColSpan;
};

struct OpTensorLayoutSetBlockSizeNV
{
  OpTensorLayoutSetBlockSizeNV(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->tensorLayout = Id::fromWord(it.word(3));
    word = 4;
    this->blockSize = MultiParam<Id>(it, word);
  }
  OpTensorLayoutSetBlockSizeNV(IdResultType resultType, IdResult result, Id tensorLayout, const rdcarray<Id> &blockSize = {})
      : op(Op::TensorLayoutSetBlockSizeNV)
      , wordCount(MinWordSize + MultiWordCount(blockSize))
  {
    this->resultType = resultType;
    this->result = result;
    this->tensorLayout = tensorLayout;
    this->blockSize = blockSize;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(tensorLayout.value());
    for(size_t i=0; i < blockSize.size(); i++)
    {
      words.push_back(blockSize[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::TensorLayoutSetBlockSizeNV;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id tensorLayout;
  rdcarray<Id> blockSize;
};

struct OpCooperativeMatrixTransposeNV
{
  OpCooperativeMatrixTransposeNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpCooperativeMatrixTransposeNV(IdResultType resultType, IdResult result, Id matrix)
      : op(Op::CooperativeMatrixTransposeNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->matrix = matrix;
  }

  static constexpr Op OpCode = Op::CooperativeMatrixTransposeNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id matrix;
};

struct OpConvertUToImageNV
{
  OpConvertUToImageNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConvertUToImageNV(IdResultType resultType, IdResult result, Id operand)
      : op(Op::ConvertUToImageNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand = operand;
  }

  static constexpr Op OpCode = Op::ConvertUToImageNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand;
};

struct OpConvertUToSamplerNV
{
  OpConvertUToSamplerNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConvertUToSamplerNV(IdResultType resultType, IdResult result, Id operand)
      : op(Op::ConvertUToSamplerNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand = operand;
  }

  static constexpr Op OpCode = Op::ConvertUToSamplerNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand;
};

struct OpConvertImageToUNV
{
  OpConvertImageToUNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConvertImageToUNV(IdResultType resultType, IdResult result, Id operand)
      : op(Op::ConvertImageToUNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand = operand;
  }

  static constexpr Op OpCode = Op::ConvertImageToUNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand;
};

struct OpConvertSamplerToUNV
{
  OpConvertSamplerToUNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConvertSamplerToUNV(IdResultType resultType, IdResult result, Id operand)
      : op(Op::ConvertSamplerToUNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand = operand;
  }

  static constexpr Op OpCode = Op::ConvertSamplerToUNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand;
};

struct OpConvertUToSampledImageNV
{
  OpConvertUToSampledImageNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConvertUToSampledImageNV(IdResultType resultType, IdResult result, Id operand)
      : op(Op::ConvertUToSampledImageNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand = operand;
  }

  static constexpr Op OpCode = Op::ConvertUToSampledImageNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand;
};

struct OpConvertSampledImageToUNV
{
  OpConvertSampledImageToUNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConvertSampledImageToUNV(IdResultType resultType, IdResult result, Id operand)
      : op(Op::ConvertSampledImageToUNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand = operand;
  }

  static constexpr Op OpCode = Op::ConvertSampledImageToUNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand;
};

struct OpSamplerImageAddressingModeNV
{
  OpSamplerImageAddressingModeNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSamplerImageAddressingModeNV(uint32_t bitWidth)
      : op(Op::SamplerImageAddressingModeNV)
      , wordCount(FixedWordSize)
  {
    this->bitWidth = bitWidth;
  }

  static constexpr Op OpCode = Op::SamplerImageAddressingModeNV;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  uint32_t bitWidth;
};

struct OpRawAccessChainNV
{
  OpRawAccessChainNV(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->base = Id::fromWord(it.word(3));
    this->bytestride = Id::fromWord(it.word(4));
    this->elementindex = Id::fromWord(it.word(5));
    this->byteoffset = Id::fromWord(it.word(6));
    this->rawAccessChainOperands = (it.size() > 7) ? (RawAccessChainOperands)it.word(7) : RawAccessChainOperands::None;
  }
  OpRawAccessChainNV(IdResultType resultType, IdResult result, Id base, Id bytestride, Id elementindex, Id byteoffset, RawAccessChainOperands rawAccessChainOperands = RawAccessChainOperands::None)
      : op(Op::RawAccessChainNV)
      , wordCount(MinWordSize + OptionalWordCount(rawAccessChainOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->base = base;
    this->bytestride = bytestride;
    this->elementindex = elementindex;
    this->byteoffset = byteoffset;
    this->rawAccessChainOperands = rawAccessChainOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(base.value());
    words.push_back(bytestride.value());
    words.push_back(elementindex.value());
    words.push_back(byteoffset.value());
    if(rawAccessChainOperands != RawAccessChainOperands::None) words.push_back((uint32_t)rawAccessChainOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::RawAccessChainNV;
  static constexpr uint16_t MinWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id base;
  Id bytestride;
  Id elementindex;
  Id byteoffset;
  RawAccessChainOperands rawAccessChainOperands;

  bool HasRawAccessChainOperands() const { return wordCount > 7; }
};

struct OpRayQueryGetIntersectionSpherePositionNV
{
  OpRayQueryGetIntersectionSpherePositionNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionSpherePositionNV(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryGetIntersectionSpherePositionNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionSpherePositionNV;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpRayQueryGetIntersectionSphereRadiusNV
{
  OpRayQueryGetIntersectionSphereRadiusNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionSphereRadiusNV(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryGetIntersectionSphereRadiusNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionSphereRadiusNV;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpRayQueryGetIntersectionLSSPositionsNV
{
  OpRayQueryGetIntersectionLSSPositionsNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionLSSPositionsNV(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryGetIntersectionLSSPositionsNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionLSSPositionsNV;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpRayQueryGetIntersectionLSSRadiiNV
{
  OpRayQueryGetIntersectionLSSRadiiNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionLSSRadiiNV(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryGetIntersectionLSSRadiiNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionLSSRadiiNV;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpRayQueryGetIntersectionLSSHitValueNV
{
  OpRayQueryGetIntersectionLSSHitValueNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionLSSHitValueNV(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryGetIntersectionLSSHitValueNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionLSSHitValueNV;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpHitObjectGetSpherePositionNV
{
  OpHitObjectGetSpherePositionNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetSpherePositionNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetSpherePositionNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetSpherePositionNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetSphereRadiusNV
{
  OpHitObjectGetSphereRadiusNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetSphereRadiusNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetSphereRadiusNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetSphereRadiusNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetLSSPositionsNV
{
  OpHitObjectGetLSSPositionsNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetLSSPositionsNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetLSSPositionsNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetLSSPositionsNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectGetLSSRadiiNV
{
  OpHitObjectGetLSSRadiiNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectGetLSSRadiiNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectGetLSSRadiiNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectGetLSSRadiiNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectIsSphereHitNV
{
  OpHitObjectIsSphereHitNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectIsSphereHitNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectIsSphereHitNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectIsSphereHitNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpHitObjectIsLSSHitNV
{
  OpHitObjectIsLSSHitNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpHitObjectIsLSSHitNV(IdResultType resultType, IdResult result, Id hitObject)
      : op(Op::HitObjectIsLSSHitNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hitObject = hitObject;
  }

  static constexpr Op OpCode = Op::HitObjectIsLSSHitNV;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id hitObject;
};

struct OpRayQueryIsSphereHitNV
{
  OpRayQueryIsSphereHitNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryIsSphereHitNV(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryIsSphereHitNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryIsSphereHitNV;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpRayQueryIsLSSHitNV
{
  OpRayQueryIsLSSHitNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryIsLSSHitNV(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryIsLSSHitNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryIsLSSHitNV;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpSubgroupShuffleINTEL
{
  OpSubgroupShuffleINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroupShuffleINTEL(IdResultType resultType, IdResult result, Id data, Id invocationId)
      : op(Op::SubgroupShuffleINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->data = data;
    this->invocationId = invocationId;
  }

  static constexpr Op OpCode = Op::SubgroupShuffleINTEL;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id data;
  Id invocationId;
};

struct OpSubgroupShuffleDownINTEL
{
  OpSubgroupShuffleDownINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroupShuffleDownINTEL(IdResultType resultType, IdResult result, Id current, Id next, Id delta)
      : op(Op::SubgroupShuffleDownINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->current = current;
    this->next = next;
    this->delta = delta;
  }

  static constexpr Op OpCode = Op::SubgroupShuffleDownINTEL;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id current;
  Id next;
  Id delta;
};

struct OpSubgroupShuffleUpINTEL
{
  OpSubgroupShuffleUpINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroupShuffleUpINTEL(IdResultType resultType, IdResult result, Id previous, Id current, Id delta)
      : op(Op::SubgroupShuffleUpINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->previous = previous;
    this->current = current;
    this->delta = delta;
  }

  static constexpr Op OpCode = Op::SubgroupShuffleUpINTEL;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id previous;
  Id current;
  Id delta;
};

struct OpSubgroupShuffleXorINTEL
{
  OpSubgroupShuffleXorINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroupShuffleXorINTEL(IdResultType resultType, IdResult result, Id data, Id value)
      : op(Op::SubgroupShuffleXorINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->data = data;
    this->value = value;
  }

  static constexpr Op OpCode = Op::SubgroupShuffleXorINTEL;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id data;
  Id value;
};

struct OpSubgroupBlockReadINTEL
{
  OpSubgroupBlockReadINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroupBlockReadINTEL(IdResultType resultType, IdResult result, Id ptr)
      : op(Op::SubgroupBlockReadINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->ptr = ptr;
  }

  static constexpr Op OpCode = Op::SubgroupBlockReadINTEL;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id ptr;
};

struct OpSubgroupBlockWriteINTEL
{
  OpSubgroupBlockWriteINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroupBlockWriteINTEL(Id ptr, Id data)
      : op(Op::SubgroupBlockWriteINTEL)
      , wordCount(FixedWordSize)
  {
    this->ptr = ptr;
    this->data = data;
  }

  static constexpr Op OpCode = Op::SubgroupBlockWriteINTEL;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id ptr;
  Id data;
};

struct OpSubgroupImageBlockReadINTEL
{
  OpSubgroupImageBlockReadINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroupImageBlockReadINTEL(IdResultType resultType, IdResult result, Id image, Id coordinate)
      : op(Op::SubgroupImageBlockReadINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->image = image;
    this->coordinate = coordinate;
  }

  static constexpr Op OpCode = Op::SubgroupImageBlockReadINTEL;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id image;
  Id coordinate;
};

struct OpSubgroupImageBlockWriteINTEL
{
  OpSubgroupImageBlockWriteINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroupImageBlockWriteINTEL(Id image, Id coordinate, Id data)
      : op(Op::SubgroupImageBlockWriteINTEL)
      , wordCount(FixedWordSize)
  {
    this->image = image;
    this->coordinate = coordinate;
    this->data = data;
  }

  static constexpr Op OpCode = Op::SubgroupImageBlockWriteINTEL;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  Id image;
  Id coordinate;
  Id data;
};

struct OpSubgroupImageMediaBlockReadINTEL
{
  OpSubgroupImageMediaBlockReadINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroupImageMediaBlockReadINTEL(IdResultType resultType, IdResult result, Id image, Id coordinate, Id width, Id height)
      : op(Op::SubgroupImageMediaBlockReadINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->image = image;
    this->coordinate = coordinate;
    this->width = width;
    this->height = height;
  }

  static constexpr Op OpCode = Op::SubgroupImageMediaBlockReadINTEL;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id image;
  Id coordinate;
  Id width;
  Id height;
};

struct OpSubgroupImageMediaBlockWriteINTEL
{
  OpSubgroupImageMediaBlockWriteINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroupImageMediaBlockWriteINTEL(Id image, Id coordinate, Id width, Id height, Id data)
      : op(Op::SubgroupImageMediaBlockWriteINTEL)
      , wordCount(FixedWordSize)
  {
    this->image = image;
    this->coordinate = coordinate;
    this->width = width;
    this->height = height;
    this->data = data;
  }

  static constexpr Op OpCode = Op::SubgroupImageMediaBlockWriteINTEL;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  Id image;
  Id coordinate;
  Id width;
  Id height;
  Id data;
};

struct OpUCountLeadingZerosINTEL
{
  OpUCountLeadingZerosINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpUCountLeadingZerosINTEL(IdResultType resultType, IdResult result, Id operand)
      : op(Op::UCountLeadingZerosINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand = operand;
  }

  static constexpr Op OpCode = Op::UCountLeadingZerosINTEL;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand;
};

struct OpUCountTrailingZerosINTEL
{
  OpUCountTrailingZerosINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpUCountTrailingZerosINTEL(IdResultType resultType, IdResult result, Id operand)
      : op(Op::UCountTrailingZerosINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand = operand;
  }

  static constexpr Op OpCode = Op::UCountTrailingZerosINTEL;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand;
};

struct OpAbsISubINTEL
{
  OpAbsISubINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAbsISubINTEL(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::AbsISubINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::AbsISubINTEL;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpAbsUSubINTEL
{
  OpAbsUSubINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAbsUSubINTEL(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::AbsUSubINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::AbsUSubINTEL;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpIAddSatINTEL
{
  OpIAddSatINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpIAddSatINTEL(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::IAddSatINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::IAddSatINTEL;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpUAddSatINTEL
{
  OpUAddSatINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpUAddSatINTEL(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::UAddSatINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::UAddSatINTEL;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpIAverageINTEL
{
  OpIAverageINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpIAverageINTEL(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::IAverageINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::IAverageINTEL;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpUAverageINTEL
{
  OpUAverageINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpUAverageINTEL(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::UAverageINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::UAverageINTEL;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpIAverageRoundedINTEL
{
  OpIAverageRoundedINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpIAverageRoundedINTEL(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::IAverageRoundedINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::IAverageRoundedINTEL;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpUAverageRoundedINTEL
{
  OpUAverageRoundedINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpUAverageRoundedINTEL(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::UAverageRoundedINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::UAverageRoundedINTEL;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpISubSatINTEL
{
  OpISubSatINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpISubSatINTEL(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::ISubSatINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::ISubSatINTEL;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpUSubSatINTEL
{
  OpUSubSatINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpUSubSatINTEL(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::USubSatINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::USubSatINTEL;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpIMul32x16INTEL
{
  OpIMul32x16INTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpIMul32x16INTEL(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::IMul32x16INTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::IMul32x16INTEL;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpUMul32x16INTEL
{
  OpUMul32x16INTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpUMul32x16INTEL(IdResultType resultType, IdResult result, Id operand1, Id operand2)
      : op(Op::UMul32x16INTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand1 = operand1;
    this->operand2 = operand2;
  }

  static constexpr Op OpCode = Op::UMul32x16INTEL;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand1;
  Id operand2;
};

struct OpAtomicFMinEXT
{
  OpAtomicFMinEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicFMinEXT(IdResultType resultType, IdResult result, Id pointer, IdScope memory, IdMemorySemantics semantics, Id value)
      : op(Op::AtomicFMinEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memory = memory;
    this->semantics = semantics;
    this->value = value;
  }

  static constexpr Op OpCode = Op::AtomicFMinEXT;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  IdScope memory;
  IdMemorySemantics semantics;
  Id value;
};

struct OpAtomicFMaxEXT
{
  OpAtomicFMaxEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicFMaxEXT(IdResultType resultType, IdResult result, Id pointer, IdScope memory, IdMemorySemantics semantics, Id value)
      : op(Op::AtomicFMaxEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memory = memory;
    this->semantics = semantics;
    this->value = value;
  }

  static constexpr Op OpCode = Op::AtomicFMaxEXT;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  IdScope memory;
  IdMemorySemantics semantics;
  Id value;
};

struct OpAssumeTrueKHR
{
  OpAssumeTrueKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAssumeTrueKHR(Id condition)
      : op(Op::AssumeTrueKHR)
      , wordCount(FixedWordSize)
  {
    this->condition = condition;
  }

  static constexpr Op OpCode = Op::AssumeTrueKHR;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  Id condition;
};

struct OpExpectKHR
{
  OpExpectKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpExpectKHR(IdResultType resultType, IdResult result, Id value, Id expectedValue)
      : op(Op::ExpectKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->value = value;
    this->expectedValue = expectedValue;
  }

  static constexpr Op OpCode = Op::ExpectKHR;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id value;
  Id expectedValue;
};

struct OpDecorateString
{
  OpDecorateString(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->target = Id::fromWord(it.word(1));
    word = 2;
    this->decoration = DecodeParam<DecorationAndParamData>(it, word);
  }
  OpDecorateString(Id target, DecorationAndParamData decoration)
      : op(Op::DecorateString)
      , wordCount(MinWordSize + ExtraWordCount(decoration))
  {
    this->target = target;
    this->decoration = decoration;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(target.value());
    EncodeParam(words, decoration);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::DecorateString;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id target;
  DecorationAndParamData decoration;
};

struct OpMemberDecorateString
{
  OpMemberDecorateString(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->structType = Id::fromWord(it.word(1));
    this->member = (uint32_t)it.word(2);
    word = 3;
    this->decoration = DecodeParam<DecorationAndParamData>(it, word);
  }
  OpMemberDecorateString(Id structType, uint32_t member, DecorationAndParamData decoration)
      : op(Op::MemberDecorateString)
      , wordCount(MinWordSize + ExtraWordCount(decoration))
  {
    this->structType = structType;
    this->member = member;
    this->decoration = decoration;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(structType.value());
    words.push_back((uint32_t)member);
    EncodeParam(words, decoration);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::MemberDecorateString;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  Id structType;
  uint32_t member;
  DecorationAndParamData decoration;
};

struct OpVariableLengthArrayINTEL
{
  OpVariableLengthArrayINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpVariableLengthArrayINTEL(IdResultType resultType, IdResult result, Id length)
      : op(Op::VariableLengthArrayINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->length = length;
  }

  static constexpr Op OpCode = Op::VariableLengthArrayINTEL;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id length;
};

struct OpSaveMemoryINTEL
{
  OpSaveMemoryINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSaveMemoryINTEL(IdResultType resultType, IdResult result)
      : op(Op::SaveMemoryINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
  }

  static constexpr Op OpCode = Op::SaveMemoryINTEL;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
};

struct OpRestoreMemoryINTEL
{
  OpRestoreMemoryINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRestoreMemoryINTEL(Id ptr)
      : op(Op::RestoreMemoryINTEL)
      , wordCount(FixedWordSize)
  {
    this->ptr = ptr;
  }

  static constexpr Op OpCode = Op::RestoreMemoryINTEL;
  static constexpr uint16_t FixedWordSize = 2U;
  Op op;
  uint16_t wordCount;
  Id ptr;
};

struct OpLoopControlINTEL
{
  OpLoopControlINTEL(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    word = 1;
    this->loopControlParameters = MultiParam<uint32_t>(it, word);
  }
  OpLoopControlINTEL(const rdcarray<uint32_t> &loopControlParameters = {})
      : op(Op::LoopControlINTEL)
      , wordCount(MinWordSize + MultiWordCount(loopControlParameters))
  {
    this->loopControlParameters = loopControlParameters;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    for(size_t i=0; i < loopControlParameters.size(); i++)
    {
      words.push_back((uint32_t)loopControlParameters[i]);
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::LoopControlINTEL;
  static constexpr uint16_t MinWordSize = 1U;
  Op op;
  uint16_t wordCount;
  rdcarray<uint32_t> loopControlParameters;
};

struct OpRayQueryGetRayTMinKHR
{
  OpRayQueryGetRayTMinKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetRayTMinKHR(IdResultType resultType, IdResult result, Id rayQuery)
      : op(Op::RayQueryGetRayTMinKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
  }

  static constexpr Op OpCode = Op::RayQueryGetRayTMinKHR;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
};

struct OpRayQueryGetRayFlagsKHR
{
  OpRayQueryGetRayFlagsKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetRayFlagsKHR(IdResultType resultType, IdResult result, Id rayQuery)
      : op(Op::RayQueryGetRayFlagsKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
  }

  static constexpr Op OpCode = Op::RayQueryGetRayFlagsKHR;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
};

struct OpRayQueryGetIntersectionTKHR
{
  OpRayQueryGetIntersectionTKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionTKHR(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryGetIntersectionTKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionTKHR;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpRayQueryGetIntersectionInstanceCustomIndexKHR
{
  OpRayQueryGetIntersectionInstanceCustomIndexKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionInstanceCustomIndexKHR(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryGetIntersectionInstanceCustomIndexKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionInstanceCustomIndexKHR;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpRayQueryGetIntersectionInstanceIdKHR
{
  OpRayQueryGetIntersectionInstanceIdKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionInstanceIdKHR(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryGetIntersectionInstanceIdKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionInstanceIdKHR;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR
{
  OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpRayQueryGetIntersectionGeometryIndexKHR
{
  OpRayQueryGetIntersectionGeometryIndexKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionGeometryIndexKHR(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryGetIntersectionGeometryIndexKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionGeometryIndexKHR;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpRayQueryGetIntersectionPrimitiveIndexKHR
{
  OpRayQueryGetIntersectionPrimitiveIndexKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionPrimitiveIndexKHR(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryGetIntersectionPrimitiveIndexKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionPrimitiveIndexKHR;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpRayQueryGetIntersectionBarycentricsKHR
{
  OpRayQueryGetIntersectionBarycentricsKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionBarycentricsKHR(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryGetIntersectionBarycentricsKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionBarycentricsKHR;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpRayQueryGetIntersectionFrontFaceKHR
{
  OpRayQueryGetIntersectionFrontFaceKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionFrontFaceKHR(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryGetIntersectionFrontFaceKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionFrontFaceKHR;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpRayQueryGetIntersectionCandidateAABBOpaqueKHR
{
  OpRayQueryGetIntersectionCandidateAABBOpaqueKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionCandidateAABBOpaqueKHR(IdResultType resultType, IdResult result, Id rayQuery)
      : op(Op::RayQueryGetIntersectionCandidateAABBOpaqueKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionCandidateAABBOpaqueKHR;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
};

struct OpRayQueryGetIntersectionObjectRayDirectionKHR
{
  OpRayQueryGetIntersectionObjectRayDirectionKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionObjectRayDirectionKHR(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryGetIntersectionObjectRayDirectionKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionObjectRayDirectionKHR;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpRayQueryGetIntersectionObjectRayOriginKHR
{
  OpRayQueryGetIntersectionObjectRayOriginKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionObjectRayOriginKHR(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryGetIntersectionObjectRayOriginKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionObjectRayOriginKHR;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpRayQueryGetWorldRayDirectionKHR
{
  OpRayQueryGetWorldRayDirectionKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetWorldRayDirectionKHR(IdResultType resultType, IdResult result, Id rayQuery)
      : op(Op::RayQueryGetWorldRayDirectionKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
  }

  static constexpr Op OpCode = Op::RayQueryGetWorldRayDirectionKHR;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
};

struct OpRayQueryGetWorldRayOriginKHR
{
  OpRayQueryGetWorldRayOriginKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetWorldRayOriginKHR(IdResultType resultType, IdResult result, Id rayQuery)
      : op(Op::RayQueryGetWorldRayOriginKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
  }

  static constexpr Op OpCode = Op::RayQueryGetWorldRayOriginKHR;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
};

struct OpRayQueryGetIntersectionObjectToWorldKHR
{
  OpRayQueryGetIntersectionObjectToWorldKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionObjectToWorldKHR(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryGetIntersectionObjectToWorldKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionObjectToWorldKHR;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpRayQueryGetIntersectionWorldToObjectKHR
{
  OpRayQueryGetIntersectionWorldToObjectKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRayQueryGetIntersectionWorldToObjectKHR(IdResultType resultType, IdResult result, Id rayQuery, Id intersection)
      : op(Op::RayQueryGetIntersectionWorldToObjectKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->rayQuery = rayQuery;
    this->intersection = intersection;
  }

  static constexpr Op OpCode = Op::RayQueryGetIntersectionWorldToObjectKHR;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id rayQuery;
  Id intersection;
};

struct OpAtomicFAddEXT
{
  OpAtomicFAddEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpAtomicFAddEXT(IdResultType resultType, IdResult result, Id pointer, IdScope memory, IdMemorySemantics semantics, Id value)
      : op(Op::AtomicFAddEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->pointer = pointer;
    this->memory = memory;
    this->semantics = semantics;
    this->value = value;
  }

  static constexpr Op OpCode = Op::AtomicFAddEXT;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id pointer;
  IdScope memory;
  IdMemorySemantics semantics;
  Id value;
};

struct OpTypeBufferSurfaceINTEL
{
  OpTypeBufferSurfaceINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeBufferSurfaceINTEL(IdResult result, AccessQualifier accessQualifier)
      : op(Op::TypeBufferSurfaceINTEL)
      , wordCount(FixedWordSize)
  {
    this->result = result;
    this->accessQualifier = accessQualifier;
  }

  static constexpr Op OpCode = Op::TypeBufferSurfaceINTEL;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  AccessQualifier accessQualifier;
};

struct OpTypeStructContinuedINTEL
{
  OpTypeStructContinuedINTEL(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    word = 1;
    this->members = MultiParam<Id>(it, word);
  }
  OpTypeStructContinuedINTEL(const rdcarray<Id> &members = {})
      : op(Op::TypeStructContinuedINTEL)
      , wordCount(MinWordSize + MultiWordCount(members))
  {
    this->members = members;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    for(size_t i=0; i < members.size(); i++)
    {
      words.push_back(members[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::TypeStructContinuedINTEL;
  static constexpr uint16_t MinWordSize = 1U;
  Op op;
  uint16_t wordCount;
  rdcarray<Id> members;
};

struct OpConstantCompositeContinuedINTEL
{
  OpConstantCompositeContinuedINTEL(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    word = 1;
    this->constituents = MultiParam<Id>(it, word);
  }
  OpConstantCompositeContinuedINTEL(const rdcarray<Id> &constituents = {})
      : op(Op::ConstantCompositeContinuedINTEL)
      , wordCount(MinWordSize + MultiWordCount(constituents))
  {
    this->constituents = constituents;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    for(size_t i=0; i < constituents.size(); i++)
    {
      words.push_back(constituents[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ConstantCompositeContinuedINTEL;
  static constexpr uint16_t MinWordSize = 1U;
  Op op;
  uint16_t wordCount;
  rdcarray<Id> constituents;
};

struct OpSpecConstantCompositeContinuedINTEL
{
  OpSpecConstantCompositeContinuedINTEL(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    word = 1;
    this->constituents = MultiParam<Id>(it, word);
  }
  OpSpecConstantCompositeContinuedINTEL(const rdcarray<Id> &constituents = {})
      : op(Op::SpecConstantCompositeContinuedINTEL)
      , wordCount(MinWordSize + MultiWordCount(constituents))
  {
    this->constituents = constituents;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    for(size_t i=0; i < constituents.size(); i++)
    {
      words.push_back(constituents[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::SpecConstantCompositeContinuedINTEL;
  static constexpr uint16_t MinWordSize = 1U;
  Op op;
  uint16_t wordCount;
  rdcarray<Id> constituents;
};

struct OpCompositeConstructContinuedINTEL
{
  OpCompositeConstructContinuedINTEL(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    word = 3;
    this->constituents = MultiParam<Id>(it, word);
  }
  OpCompositeConstructContinuedINTEL(IdResultType resultType, IdResult result, const rdcarray<Id> &constituents = {})
      : op(Op::CompositeConstructContinuedINTEL)
      , wordCount(MinWordSize + MultiWordCount(constituents))
  {
    this->resultType = resultType;
    this->result = result;
    this->constituents = constituents;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    for(size_t i=0; i < constituents.size(); i++)
    {
      words.push_back(constituents[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::CompositeConstructContinuedINTEL;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  rdcarray<Id> constituents;
};

struct OpConvertFToBF16INTEL
{
  OpConvertFToBF16INTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConvertFToBF16INTEL(IdResultType resultType, IdResult result, Id floatValue)
      : op(Op::ConvertFToBF16INTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->floatValue = floatValue;
  }

  static constexpr Op OpCode = Op::ConvertFToBF16INTEL;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id floatValue;
};

struct OpConvertBF16ToFINTEL
{
  OpConvertBF16ToFINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConvertBF16ToFINTEL(IdResultType resultType, IdResult result, Id bFloat16Value)
      : op(Op::ConvertBF16ToFINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->bFloat16Value = bFloat16Value;
  }

  static constexpr Op OpCode = Op::ConvertBF16ToFINTEL;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id bFloat16Value;
};

struct OpControlBarrierArriveINTEL
{
  OpControlBarrierArriveINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpControlBarrierArriveINTEL(IdScope execution, IdScope memory, IdMemorySemantics semantics)
      : op(Op::ControlBarrierArriveINTEL)
      , wordCount(FixedWordSize)
  {
    this->execution = execution;
    this->memory = memory;
    this->semantics = semantics;
  }

  static constexpr Op OpCode = Op::ControlBarrierArriveINTEL;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdScope execution;
  IdScope memory;
  IdMemorySemantics semantics;
};

struct OpControlBarrierWaitINTEL
{
  OpControlBarrierWaitINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpControlBarrierWaitINTEL(IdScope execution, IdScope memory, IdMemorySemantics semantics)
      : op(Op::ControlBarrierWaitINTEL)
      , wordCount(FixedWordSize)
  {
    this->execution = execution;
    this->memory = memory;
    this->semantics = semantics;
  }

  static constexpr Op OpCode = Op::ControlBarrierWaitINTEL;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdScope execution;
  IdScope memory;
  IdMemorySemantics semantics;
};

struct OpArithmeticFenceEXT
{
  OpArithmeticFenceEXT(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpArithmeticFenceEXT(IdResultType resultType, IdResult result, Id target)
      : op(Op::ArithmeticFenceEXT)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->target = target;
  }

  static constexpr Op OpCode = Op::ArithmeticFenceEXT;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id target;
};

struct OpSubgroupBlockPrefetchINTEL
{
  OpSubgroupBlockPrefetchINTEL(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->ptr = Id::fromWord(it.word(1));
    this->numBytes = Id::fromWord(it.word(2));
    word = 3;
    this->memoryAccess = DecodeParam<MemoryAccessAndParamDatas>(it, word);
  }
  OpSubgroupBlockPrefetchINTEL(Id ptr, Id numBytes, MemoryAccessAndParamDatas memoryAccess = MemoryAccess::None)
      : op(Op::SubgroupBlockPrefetchINTEL)
      , wordCount(MinWordSize + ExtraWordCount(memoryAccess))
  {
    this->ptr = ptr;
    this->numBytes = numBytes;
    this->memoryAccess = memoryAccess;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(ptr.value());
    words.push_back(numBytes.value());
    EncodeParam(words, memoryAccess);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::SubgroupBlockPrefetchINTEL;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id ptr;
  Id numBytes;
  MemoryAccessAndParamDatas memoryAccess;
};

struct OpSubgroup2DBlockLoadINTEL
{
  OpSubgroup2DBlockLoadINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroup2DBlockLoadINTEL(Id elementSize, Id blockWidth, Id blockHeight, Id blockCount, Id srcBasePointer, Id memoryWidth, Id memoryHeight, Id memoryPitch, Id coordinate, Id dstPointer)
      : op(Op::Subgroup2DBlockLoadINTEL)
      , wordCount(FixedWordSize)
  {
    this->elementSize = elementSize;
    this->blockWidth = blockWidth;
    this->blockHeight = blockHeight;
    this->blockCount = blockCount;
    this->srcBasePointer = srcBasePointer;
    this->memoryWidth = memoryWidth;
    this->memoryHeight = memoryHeight;
    this->memoryPitch = memoryPitch;
    this->coordinate = coordinate;
    this->dstPointer = dstPointer;
  }

  static constexpr Op OpCode = Op::Subgroup2DBlockLoadINTEL;
  static constexpr uint16_t FixedWordSize = 11U;
  Op op;
  uint16_t wordCount;
  Id elementSize;
  Id blockWidth;
  Id blockHeight;
  Id blockCount;
  Id srcBasePointer;
  Id memoryWidth;
  Id memoryHeight;
  Id memoryPitch;
  Id coordinate;
  Id dstPointer;
};

struct OpSubgroup2DBlockLoadTransformINTEL
{
  OpSubgroup2DBlockLoadTransformINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroup2DBlockLoadTransformINTEL(Id elementSize, Id blockWidth, Id blockHeight, Id blockCount, Id srcBasePointer, Id memoryWidth, Id memoryHeight, Id memoryPitch, Id coordinate, Id dstPointer)
      : op(Op::Subgroup2DBlockLoadTransformINTEL)
      , wordCount(FixedWordSize)
  {
    this->elementSize = elementSize;
    this->blockWidth = blockWidth;
    this->blockHeight = blockHeight;
    this->blockCount = blockCount;
    this->srcBasePointer = srcBasePointer;
    this->memoryWidth = memoryWidth;
    this->memoryHeight = memoryHeight;
    this->memoryPitch = memoryPitch;
    this->coordinate = coordinate;
    this->dstPointer = dstPointer;
  }

  static constexpr Op OpCode = Op::Subgroup2DBlockLoadTransformINTEL;
  static constexpr uint16_t FixedWordSize = 11U;
  Op op;
  uint16_t wordCount;
  Id elementSize;
  Id blockWidth;
  Id blockHeight;
  Id blockCount;
  Id srcBasePointer;
  Id memoryWidth;
  Id memoryHeight;
  Id memoryPitch;
  Id coordinate;
  Id dstPointer;
};

struct OpSubgroup2DBlockLoadTransposeINTEL
{
  OpSubgroup2DBlockLoadTransposeINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroup2DBlockLoadTransposeINTEL(Id elementSize, Id blockWidth, Id blockHeight, Id blockCount, Id srcBasePointer, Id memoryWidth, Id memoryHeight, Id memoryPitch, Id coordinate, Id dstPointer)
      : op(Op::Subgroup2DBlockLoadTransposeINTEL)
      , wordCount(FixedWordSize)
  {
    this->elementSize = elementSize;
    this->blockWidth = blockWidth;
    this->blockHeight = blockHeight;
    this->blockCount = blockCount;
    this->srcBasePointer = srcBasePointer;
    this->memoryWidth = memoryWidth;
    this->memoryHeight = memoryHeight;
    this->memoryPitch = memoryPitch;
    this->coordinate = coordinate;
    this->dstPointer = dstPointer;
  }

  static constexpr Op OpCode = Op::Subgroup2DBlockLoadTransposeINTEL;
  static constexpr uint16_t FixedWordSize = 11U;
  Op op;
  uint16_t wordCount;
  Id elementSize;
  Id blockWidth;
  Id blockHeight;
  Id blockCount;
  Id srcBasePointer;
  Id memoryWidth;
  Id memoryHeight;
  Id memoryPitch;
  Id coordinate;
  Id dstPointer;
};

struct OpSubgroup2DBlockPrefetchINTEL
{
  OpSubgroup2DBlockPrefetchINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroup2DBlockPrefetchINTEL(Id elementSize, Id blockWidth, Id blockHeight, Id blockCount, Id srcBasePointer, Id memoryWidth, Id memoryHeight, Id memoryPitch, Id coordinate)
      : op(Op::Subgroup2DBlockPrefetchINTEL)
      , wordCount(FixedWordSize)
  {
    this->elementSize = elementSize;
    this->blockWidth = blockWidth;
    this->blockHeight = blockHeight;
    this->blockCount = blockCount;
    this->srcBasePointer = srcBasePointer;
    this->memoryWidth = memoryWidth;
    this->memoryHeight = memoryHeight;
    this->memoryPitch = memoryPitch;
    this->coordinate = coordinate;
  }

  static constexpr Op OpCode = Op::Subgroup2DBlockPrefetchINTEL;
  static constexpr uint16_t FixedWordSize = 10U;
  Op op;
  uint16_t wordCount;
  Id elementSize;
  Id blockWidth;
  Id blockHeight;
  Id blockCount;
  Id srcBasePointer;
  Id memoryWidth;
  Id memoryHeight;
  Id memoryPitch;
  Id coordinate;
};

struct OpSubgroup2DBlockStoreINTEL
{
  OpSubgroup2DBlockStoreINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSubgroup2DBlockStoreINTEL(Id elementSize, Id blockWidth, Id blockHeight, Id blockCount, Id srcPointer, Id dstBasePointer, Id memoryWidth, Id memoryHeight, Id memoryPitch, Id coordinate)
      : op(Op::Subgroup2DBlockStoreINTEL)
      , wordCount(FixedWordSize)
  {
    this->elementSize = elementSize;
    this->blockWidth = blockWidth;
    this->blockHeight = blockHeight;
    this->blockCount = blockCount;
    this->srcPointer = srcPointer;
    this->dstBasePointer = dstBasePointer;
    this->memoryWidth = memoryWidth;
    this->memoryHeight = memoryHeight;
    this->memoryPitch = memoryPitch;
    this->coordinate = coordinate;
  }

  static constexpr Op OpCode = Op::Subgroup2DBlockStoreINTEL;
  static constexpr uint16_t FixedWordSize = 11U;
  Op op;
  uint16_t wordCount;
  Id elementSize;
  Id blockWidth;
  Id blockHeight;
  Id blockCount;
  Id srcPointer;
  Id dstBasePointer;
  Id memoryWidth;
  Id memoryHeight;
  Id memoryPitch;
  Id coordinate;
};

struct OpSubgroupMatrixMultiplyAccumulateINTEL
{
  OpSubgroupMatrixMultiplyAccumulateINTEL(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->kDim = Id::fromWord(it.word(3));
    this->matrixA = Id::fromWord(it.word(4));
    this->matrixB = Id::fromWord(it.word(5));
    this->matrixC = Id::fromWord(it.word(6));
    this->matrixMultiplyAccumulateOperands = (it.size() > 7) ? (MatrixMultiplyAccumulateOperands)it.word(7) : MatrixMultiplyAccumulateOperands::None;
  }
  OpSubgroupMatrixMultiplyAccumulateINTEL(IdResultType resultType, IdResult result, Id kDim, Id matrixA, Id matrixB, Id matrixC, MatrixMultiplyAccumulateOperands matrixMultiplyAccumulateOperands = MatrixMultiplyAccumulateOperands::None)
      : op(Op::SubgroupMatrixMultiplyAccumulateINTEL)
      , wordCount(MinWordSize + OptionalWordCount(matrixMultiplyAccumulateOperands))
  {
    this->resultType = resultType;
    this->result = result;
    this->kDim = kDim;
    this->matrixA = matrixA;
    this->matrixB = matrixB;
    this->matrixC = matrixC;
    this->matrixMultiplyAccumulateOperands = matrixMultiplyAccumulateOperands;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back(kDim.value());
    words.push_back(matrixA.value());
    words.push_back(matrixB.value());
    words.push_back(matrixC.value());
    if(matrixMultiplyAccumulateOperands != MatrixMultiplyAccumulateOperands::None) words.push_back((uint32_t)matrixMultiplyAccumulateOperands);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::SubgroupMatrixMultiplyAccumulateINTEL;
  static constexpr uint16_t MinWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id kDim;
  Id matrixA;
  Id matrixB;
  Id matrixC;
  MatrixMultiplyAccumulateOperands matrixMultiplyAccumulateOperands;

  bool HasMatrixMultiplyAccumulateOperands() const { return wordCount > 7; }
};

struct OpBitwiseFunctionINTEL
{
  OpBitwiseFunctionINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpBitwiseFunctionINTEL(IdResultType resultType, IdResult result, Id a, Id b, Id c, Id lUTIndex)
      : op(Op::BitwiseFunctionINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->a = a;
    this->b = b;
    this->c = c;
    this->lUTIndex = lUTIndex;
  }

  static constexpr Op OpCode = Op::BitwiseFunctionINTEL;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id a;
  Id b;
  Id c;
  Id lUTIndex;
};

struct OpUntypedVariableLengthArrayINTEL
{
  OpUntypedVariableLengthArrayINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpUntypedVariableLengthArrayINTEL(IdResultType resultType, IdResult result, Id elementType, Id length)
      : op(Op::UntypedVariableLengthArrayINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->elementType = elementType;
    this->length = length;
  }

  static constexpr Op OpCode = Op::UntypedVariableLengthArrayINTEL;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id elementType;
  Id length;
};

struct OpConditionalExtensionINTEL
{
  OpConditionalExtensionINTEL(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->condition = Id::fromWord(it.word(1));
    word = 2;
    this->name = DecodeParam<rdcstr>(it, word);
  }
  OpConditionalExtensionINTEL(Id condition, rdcstr name)
      : op(Op::ConditionalExtensionINTEL)
      , wordCount(MinWordSize + ExtraWordCount(name))
  {
    this->condition = condition;
    this->name = name;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(condition.value());
    EncodeParam(words, name);
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ConditionalExtensionINTEL;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id condition;
  rdcstr name;
};

struct OpConditionalEntryPointINTEL
{
  OpConditionalEntryPointINTEL(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->condition = Id::fromWord(it.word(1));
    this->executionModel = (ExecutionModel)it.word(2);
    this->entryPoint = Id::fromWord(it.word(3));
    word = 4;
    this->name = DecodeParam<rdcstr>(it, word);
    this->iface = MultiParam<Id>(it, word);
  }
  OpConditionalEntryPointINTEL(Id condition, ExecutionModel executionModel, Id entryPoint, rdcstr name, const rdcarray<Id> &iface = {})
      : op(Op::ConditionalEntryPointINTEL)
      , wordCount(MinWordSize + ExtraWordCount(name) + MultiWordCount(iface))
  {
    this->condition = condition;
    this->executionModel = executionModel;
    this->entryPoint = entryPoint;
    this->name = name;
    this->iface = iface;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(condition.value());
    words.push_back((uint32_t)executionModel);
    words.push_back(entryPoint.value());
    EncodeParam(words, name);
    for(size_t i=0; i < iface.size(); i++)
    {
      words.push_back(iface[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ConditionalEntryPointINTEL;
  static constexpr uint16_t MinWordSize = 5U;
  Op op;
  uint16_t wordCount;
  Id condition;
  ExecutionModel executionModel;
  Id entryPoint;
  rdcstr name;
  rdcarray<Id> iface;
};

struct OpConditionalCapabilityINTEL
{
  OpConditionalCapabilityINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConditionalCapabilityINTEL(Id condition, Capability capability)
      : op(Op::ConditionalCapabilityINTEL)
      , wordCount(FixedWordSize)
  {
    this->condition = condition;
    this->capability = capability;
  }

  static constexpr Op OpCode = Op::ConditionalCapabilityINTEL;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id condition;
  Capability capability;
};

struct OpSpecConstantTargetINTEL
{
  OpSpecConstantTargetINTEL(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    this->target = (uint32_t)it.word(3);
    word = 4;
    this->features = MultiParam<uint32_t>(it, word);
  }
  OpSpecConstantTargetINTEL(IdResultType resultType, IdResult result, uint32_t target, const rdcarray<uint32_t> &features = {})
      : op(Op::SpecConstantTargetINTEL)
      , wordCount(MinWordSize + MultiWordCount(features))
  {
    this->resultType = resultType;
    this->result = result;
    this->target = target;
    this->features = features;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    words.push_back((uint32_t)target);
    for(size_t i=0; i < features.size(); i++)
    {
      words.push_back((uint32_t)features[i]);
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::SpecConstantTargetINTEL;
  static constexpr uint16_t MinWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  uint32_t target;
  rdcarray<uint32_t> features;
};

struct OpSpecConstantArchitectureINTEL
{
  OpSpecConstantArchitectureINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpSpecConstantArchitectureINTEL(IdResultType resultType, IdResult result, uint32_t category, uint32_t family, uint32_t opcode, uint32_t architecture)
      : op(Op::SpecConstantArchitectureINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->category = category;
    this->family = family;
    this->opcode = opcode;
    this->architecture = architecture;
  }

  static constexpr Op OpCode = Op::SpecConstantArchitectureINTEL;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  uint32_t category;
  uint32_t family;
  uint32_t opcode;
  uint32_t architecture;
};

struct OpSpecConstantCapabilitiesINTEL
{
  OpSpecConstantCapabilitiesINTEL(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    word = 3;
    this->capabilities = MultiParam<Capability>(it, word);
  }
  OpSpecConstantCapabilitiesINTEL(IdResultType resultType, IdResult result, const rdcarray<Capability> &capabilities = {})
      : op(Op::SpecConstantCapabilitiesINTEL)
      , wordCount(MinWordSize + MultiWordCount(capabilities))
  {
    this->resultType = resultType;
    this->result = result;
    this->capabilities = capabilities;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    for(size_t i=0; i < capabilities.size(); i++)
    {
      words.push_back((uint32_t)capabilities[i]);
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::SpecConstantCapabilitiesINTEL;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  rdcarray<Capability> capabilities;
};

struct OpConditionalCopyObjectINTEL
{
  OpConditionalCopyObjectINTEL(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->resultType = Id::fromWord(it.word(1));
    this->result = Id::fromWord(it.word(2));
    word = 3;
    this->conditional_arguments = MultiParam<Id>(it, word);
  }
  OpConditionalCopyObjectINTEL(IdResultType resultType, IdResult result, const rdcarray<Id> &conditional_arguments = {})
      : op(Op::ConditionalCopyObjectINTEL)
      , wordCount(MinWordSize + MultiWordCount(conditional_arguments))
  {
    this->resultType = resultType;
    this->result = result;
    this->conditional_arguments = conditional_arguments;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(resultType.value());
    words.push_back(result.value());
    for(size_t i=0; i < conditional_arguments.size(); i++)
    {
      words.push_back(conditional_arguments[i].value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::ConditionalCopyObjectINTEL;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  rdcarray<Id> conditional_arguments;
};

struct OpGroupIMulKHR
{
  OpGroupIMulKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupIMulKHR(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupIMulKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupIMulKHR;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupFMulKHR
{
  OpGroupFMulKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupFMulKHR(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupFMulKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupFMulKHR;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupBitwiseAndKHR
{
  OpGroupBitwiseAndKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupBitwiseAndKHR(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupBitwiseAndKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupBitwiseAndKHR;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupBitwiseOrKHR
{
  OpGroupBitwiseOrKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupBitwiseOrKHR(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupBitwiseOrKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupBitwiseOrKHR;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupBitwiseXorKHR
{
  OpGroupBitwiseXorKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupBitwiseXorKHR(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupBitwiseXorKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupBitwiseXorKHR;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupLogicalAndKHR
{
  OpGroupLogicalAndKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupLogicalAndKHR(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupLogicalAndKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupLogicalAndKHR;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupLogicalOrKHR
{
  OpGroupLogicalOrKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupLogicalOrKHR(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupLogicalOrKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupLogicalOrKHR;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpGroupLogicalXorKHR
{
  OpGroupLogicalXorKHR(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupLogicalXorKHR(IdResultType resultType, IdResult result, IdScope execution, GroupOperation operation, Id x)
      : op(Op::GroupLogicalXorKHR)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->operation = operation;
    this->x = x;
  }

  static constexpr Op OpCode = Op::GroupLogicalXorKHR;
  static constexpr uint16_t FixedWordSize = 6U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  IdScope execution;
  GroupOperation operation;
  Id x;
};

struct OpRoundFToTF32INTEL
{
  OpRoundFToTF32INTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpRoundFToTF32INTEL(IdResultType resultType, IdResult result, Id floatValue)
      : op(Op::RoundFToTF32INTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->floatValue = floatValue;
  }

  static constexpr Op OpCode = Op::RoundFToTF32INTEL;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id floatValue;
};

struct OpMaskedGatherINTEL
{
  OpMaskedGatherINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpMaskedGatherINTEL(IdResultType resultType, IdResult result, Id ptrVector, uint32_t alignment, Id mask, Id fillEmpty)
      : op(Op::MaskedGatherINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->ptrVector = ptrVector;
    this->alignment = alignment;
    this->mask = mask;
    this->fillEmpty = fillEmpty;
  }

  static constexpr Op OpCode = Op::MaskedGatherINTEL;
  static constexpr uint16_t FixedWordSize = 7U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id ptrVector;
  uint32_t alignment;
  Id mask;
  Id fillEmpty;
};

struct OpMaskedScatterINTEL
{
  OpMaskedScatterINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpMaskedScatterINTEL(Id inputVector, Id ptrVector, uint32_t alignment, Id mask)
      : op(Op::MaskedScatterINTEL)
      , wordCount(FixedWordSize)
  {
    this->inputVector = inputVector;
    this->ptrVector = ptrVector;
    this->alignment = alignment;
    this->mask = mask;
  }

  static constexpr Op OpCode = Op::MaskedScatterINTEL;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  Id inputVector;
  Id ptrVector;
  uint32_t alignment;
  Id mask;
};

struct OpConvertHandleToImageINTEL
{
  OpConvertHandleToImageINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConvertHandleToImageINTEL(IdResultType resultType, IdResult result, Id operand)
      : op(Op::ConvertHandleToImageINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand = operand;
  }

  static constexpr Op OpCode = Op::ConvertHandleToImageINTEL;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand;
};

struct OpConvertHandleToSamplerINTEL
{
  OpConvertHandleToSamplerINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConvertHandleToSamplerINTEL(IdResultType resultType, IdResult result, Id operand)
      : op(Op::ConvertHandleToSamplerINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand = operand;
  }

  static constexpr Op OpCode = Op::ConvertHandleToSamplerINTEL;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand;
};

struct OpConvertHandleToSampledImageINTEL
{
  OpConvertHandleToSampledImageINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpConvertHandleToSampledImageINTEL(IdResultType resultType, IdResult result, Id operand)
      : op(Op::ConvertHandleToSampledImageINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->operand = operand;
  }

  static constexpr Op OpCode = Op::ConvertHandleToSampledImageINTEL;
  static constexpr uint16_t FixedWordSize = 4U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result;
  Id operand;
};

template<typename T>
inline rdcstr ParamToStr(const std::function<rdcstr(rdcspv::Id)> &idName, const T &el)
{
  return ToStr(el);
}

template<>
rdcstr ParamToStr(const std::function<rdcstr(rdcspv::Id)> &idName, const Id &el);
template<>
rdcstr ParamToStr(const std::function<rdcstr(rdcspv::Id)> &idName, const rdcstr &el);
template<>
rdcstr ParamToStr(const std::function<rdcstr(rdcspv::Id)> &idName, const PairIdRefLiteralInteger &el);
template<>
rdcstr ParamToStr(const std::function<rdcstr(rdcspv::Id)> &idName, const PairIdRefIdRef &el);

template<>
rdcstr ParamToStr(const std::function<rdcstr(rdcspv::Id)> &idName, const rdcspv::ImageOperandsAndParamDatas &el);
template<>
rdcstr ParamToStr(const std::function<rdcstr(rdcspv::Id)> &idName, const rdcspv::LoopControlAndParamDatas &el);
template<>
rdcstr ParamToStr(const std::function<rdcstr(rdcspv::Id)> &idName, const rdcspv::MemoryAccessAndParamDatas &el);
template<>
rdcstr ParamToStr(const std::function<rdcstr(rdcspv::Id)> &idName, const rdcspv::ExecutionModeAndParamData &el);
template<>
rdcstr ParamToStr(const std::function<rdcstr(rdcspv::Id)> &idName, const rdcspv::DecorationAndParamData &el);
template<>
rdcstr ParamToStr(const std::function<rdcstr(rdcspv::Id)> &idName, const rdcspv::TensorAddressingOperandsAndParamDatas &el);
template<>
rdcstr ParamToStr(const std::function<rdcstr(rdcspv::Id)> &idName, const rdcspv::TensorOperandsAndParamDatas &el);


template<typename U>
inline rdcstr ParamsToStr(const std::function<rdcstr(rdcspv::Id)> &idName, const rdcarray<U> &ids)
{
  rdcstr ret = "{";
  for(size_t i=0; i < ids.size(); i++)
  {
    ret += ParamToStr(idName, ids[i]);
    if(i + 1 < ids.size())
      ret += ", ";
  }
  ret += "}";
  return ret;
}

extern bool ManualForEachID(const ConstIter &it, const std::function<void(Id,bool)> &callback);

struct OpDecoder
{
  OpDecoder(const ConstIter &it);

  static void ForEachID(const ConstIter &it, const std::function<void(Id,bool)> &callback);
  static rdcstr Disassemble(const ConstIter &it, const std::function<rdcstr(Id,Id)> &declName, const std::function<rdcstr(rdcspv::Id)> &idName, const std::function<uint32_t(Id)> &constIntVal);
  
  Op op;
  uint16_t wordCount;
  Id result;
  Id resultType;
};

}; // namespace rdcspv
