/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2019-2022 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 (c) 2014-2020 The Khronos Group Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and/or associated documentation files (the "Materials"),
 * to deal in the Materials without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Materials, and to permit persons to whom the
 * Materials are furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Materials.
 *
 * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
 * STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
 * HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
 *
 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
 * IN THE MATERIALS.
 ******************************************************************************/

#pragma once

// 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 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 PairLiteralIntegerIdRef { uint32_t first; Id second; };

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 PairLiteralIntegerIdRef DecodeParam(const ConstIter &it, uint32_t &word)
{
  if(word >= it.size()) return {};
  
  PairLiteralIntegerIdRef ret = { 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;
}

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::InitiationIntervalINTEL)
  {
    ret.initiationIntervalINTEL = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::MaxConcurrencyINTEL)
  {
    ret.maxConcurrencyINTEL = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::DependencyArrayINTEL)
  {
    ret.dependencyArrayINTEL = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::PipelineEnableINTEL)
  {
    ret.pipelineEnableINTEL = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::LoopCoalesceINTEL)
  {
    ret.loopCoalesceINTEL = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::MaxInterleavingINTEL)
  {
    ret.maxInterleavingINTEL = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::SpeculatedIterationsINTEL)
  {
    ret.speculatedIterationsINTEL = (uint32_t)it.word(word);
    word += 1;
  }
  if(ret.flags & LoopControl::NoFusionINTEL)
  {
    ret.noFusionINTEL = (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::InitiationIntervalINTEL)
  {
    words.push_back((uint32_t)param.initiationIntervalINTEL);
  }
  if(param.flags & LoopControl::MaxConcurrencyINTEL)
  {
    words.push_back((uint32_t)param.maxConcurrencyINTEL);
  }
  if(param.flags & LoopControl::DependencyArrayINTEL)
  {
    words.push_back((uint32_t)param.dependencyArrayINTEL);
  }
  if(param.flags & LoopControl::PipelineEnableINTEL)
  {
    words.push_back((uint32_t)param.pipelineEnableINTEL);
  }
  if(param.flags & LoopControl::LoopCoalesceINTEL)
  {
    words.push_back((uint32_t)param.loopCoalesceINTEL);
  }
  if(param.flags & LoopControl::MaxInterleavingINTEL)
  {
    words.push_back((uint32_t)param.maxInterleavingINTEL);
  }
  if(param.flags & LoopControl::SpeculatedIterationsINTEL)
  {
    words.push_back((uint32_t)param.speculatedIterationsINTEL);
  }
  if(param.flags & LoopControl::NoFusionINTEL)
  {
    words.push_back((uint32_t)param.noFusionINTEL);
  }
}

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::InitiationIntervalINTEL: return 1;
    case LoopControl::MaxConcurrencyINTEL: return 1;
    case LoopControl::DependencyArrayINTEL: return 1;
    case LoopControl::PipelineEnableINTEL: return 1;
    case LoopControl::LoopCoalesceINTEL: return 1;
    case LoopControl::MaxInterleavingINTEL: return 1;
    case LoopControl::SpeculatedIterationsINTEL: return 1;
    case LoopControl::NoFusionINTEL: return 1;
    default: break;
  }
  return 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 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::OutputPrimitivesNV>
{
  uint32_t outputPrimitivesNV;
  ExecutionModeParam(uint32_t outputPrimitivesNVParam) {  outputPrimitivesNV = outputPrimitivesNVParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::OutputPrimitivesNV);
    ret.outputPrimitivesNV = outputPrimitivesNV;
    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::NamedBarrierCountINTEL>
{
  uint32_t namedBarrierCountINTEL;
  ExecutionModeParam(uint32_t namedBarrierCountINTELParam) {  namedBarrierCountINTEL = namedBarrierCountINTELParam; }
  operator ExecutionModeAndParamData()
  {
    ExecutionModeAndParamData ret(ExecutionMode::NamedBarrierCountINTEL);
    ret.namedBarrierCountINTEL = namedBarrierCountINTEL;
    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::OutputPrimitivesNV:
      ret.outputPrimitivesNV = (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::NamedBarrierCountINTEL:
      ret.namedBarrierCountINTEL = (uint32_t)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::OutputPrimitivesNV:
      words.push_back((uint32_t)param.outputPrimitivesNV);
      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::NamedBarrierCountINTEL:
      words.push_back((uint32_t)param.namedBarrierCountINTEL);
      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::OutputPrimitivesNV: 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::NamedBarrierCountINTEL: 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 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::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::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::NumbanksINTEL>
{
  uint32_t numbanksINTEL;
  DecorationParam(uint32_t numbanksINTELParam) {  numbanksINTEL = numbanksINTELParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::NumbanksINTEL);
    ret.numbanksINTEL = numbanksINTEL;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::BankwidthINTEL>
{
  uint32_t bankwidthINTEL;
  DecorationParam(uint32_t bankwidthINTELParam) {  bankwidthINTEL = bankwidthINTELParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::BankwidthINTEL);
    ret.bankwidthINTEL = bankwidthINTEL;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::MaxPrivateCopiesINTEL>
{
  uint32_t maxPrivateCopiesINTEL;
  DecorationParam(uint32_t maxPrivateCopiesINTELParam) {  maxPrivateCopiesINTEL = maxPrivateCopiesINTELParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::MaxPrivateCopiesINTEL);
    ret.maxPrivateCopiesINTEL = maxPrivateCopiesINTEL;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::MaxReplicatesINTEL>
{
  uint32_t maxReplicatesINTEL;
  DecorationParam(uint32_t maxReplicatesINTELParam) {  maxReplicatesINTEL = maxReplicatesINTELParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::MaxReplicatesINTEL);
    ret.maxReplicatesINTEL = maxReplicatesINTEL;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::BankBitsINTEL>
{
  uint32_t bankBitsINTEL;
  DecorationParam(uint32_t bankBitsINTELParam) {  bankBitsINTEL = bankBitsINTELParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::BankBitsINTEL);
    ret.bankBitsINTEL = bankBitsINTEL;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::ForcePow2DepthINTEL>
{
  uint32_t forcePow2DepthINTEL;
  DecorationParam(uint32_t forcePow2DepthINTELParam) {  forcePow2DepthINTEL = forcePow2DepthINTELParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::ForcePow2DepthINTEL);
    ret.forcePow2DepthINTEL = forcePow2DepthINTEL;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::CacheSizeINTEL>
{
  uint32_t cacheSizeINTEL;
  DecorationParam(uint32_t cacheSizeINTELParam) {  cacheSizeINTEL = cacheSizeINTELParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::CacheSizeINTEL);
    ret.cacheSizeINTEL = cacheSizeINTEL;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::PrefetchINTEL>
{
  uint32_t prefetchINTEL;
  DecorationParam(uint32_t prefetchINTELParam) {  prefetchINTEL = prefetchINTELParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::PrefetchINTEL);
    ret.prefetchINTEL = prefetchINTEL;
    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::BufferLocationINTEL>
{
  uint32_t bufferLocationINTEL;
  DecorationParam(uint32_t bufferLocationINTELParam) {  bufferLocationINTEL = bufferLocationINTELParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::BufferLocationINTEL);
    ret.bufferLocationINTEL = bufferLocationINTEL;
    return ret;
  }
};

template<>
struct DecorationParam<Decoration::IOPipeStorageINTEL>
{
  uint32_t iOPipeStorageINTEL;
  DecorationParam(uint32_t iOPipeStorageINTELParam) {  iOPipeStorageINTEL = iOPipeStorageINTELParam; }
  operator DecorationAndParamData()
  {
    DecorationAndParamData ret(Decoration::IOPipeStorageINTEL);
    ret.iOPipeStorageINTEL = iOPipeStorageINTEL;
    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<>
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::SecondaryViewportRelativeNV:
      ret.secondaryViewportRelativeNV = (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::NumbanksINTEL:
      ret.numbanksINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::BankwidthINTEL:
      ret.bankwidthINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::MaxPrivateCopiesINTEL:
      ret.maxPrivateCopiesINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::MaxReplicatesINTEL:
      ret.maxReplicatesINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::BankBitsINTEL:
      ret.bankBitsINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::ForcePow2DepthINTEL:
      ret.forcePow2DepthINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::CacheSizeINTEL:
      ret.cacheSizeINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::PrefetchINTEL:
      ret.prefetchINTEL = (uint32_t)it.word(word);
      word += 1;
      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::BufferLocationINTEL:
      ret.bufferLocationINTEL = (uint32_t)it.word(word);
      word += 1;
      break;
    case Decoration::IOPipeStorageINTEL:
      ret.iOPipeStorageINTEL = (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;
    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::SecondaryViewportRelativeNV:
      words.push_back((uint32_t)param.secondaryViewportRelativeNV);
      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::NumbanksINTEL:
      words.push_back((uint32_t)param.numbanksINTEL);
      break;
    case Decoration::BankwidthINTEL:
      words.push_back((uint32_t)param.bankwidthINTEL);
      break;
    case Decoration::MaxPrivateCopiesINTEL:
      words.push_back((uint32_t)param.maxPrivateCopiesINTEL);
      break;
    case Decoration::MaxReplicatesINTEL:
      words.push_back((uint32_t)param.maxReplicatesINTEL);
      break;
    case Decoration::BankBitsINTEL:
      words.push_back((uint32_t)param.bankBitsINTEL);
      break;
    case Decoration::ForcePow2DepthINTEL:
      words.push_back((uint32_t)param.forcePow2DepthINTEL);
      break;
    case Decoration::CacheSizeINTEL:
      words.push_back((uint32_t)param.cacheSizeINTEL);
      break;
    case Decoration::PrefetchINTEL:
      words.push_back((uint32_t)param.prefetchINTEL);
      break;
    case Decoration::AliasScopeINTEL:
      words.push_back(param.aliasScopeINTEL.value());
      break;
    case Decoration::NoAliasINTEL:
      words.push_back(param.noAliasINTEL.value());
      break;
    case Decoration::BufferLocationINTEL:
      words.push_back((uint32_t)param.bufferLocationINTEL);
      break;
    case Decoration::IOPipeStorageINTEL:
      words.push_back((uint32_t)param.iOPipeStorageINTEL);
      break;
    case Decoration::FunctionFloatingPointModeINTEL:
      words.push_back((uint32_t)param.functionFloatingPointModeINTEL.targetWidth);
      words.push_back((uint32_t)param.functionFloatingPointModeINTEL.fPOperationMode);
      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::SecondaryViewportRelativeNV: 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::NumbanksINTEL: return 1;
    case Decoration::BankwidthINTEL: return 1;
    case Decoration::MaxPrivateCopiesINTEL: return 1;
    case Decoration::MaxReplicatesINTEL: return 1;
    case Decoration::BankBitsINTEL: return 1;
    case Decoration::ForcePow2DepthINTEL: return 1;
    case Decoration::CacheSizeINTEL: return 1;
    case Decoration::PrefetchINTEL: return 1;
    case Decoration::AliasScopeINTEL: return 1;
    case Decoration::NoAliasINTEL: return 1;
    case Decoration::BufferLocationINTEL: return 1;
    case Decoration::IOPipeStorageINTEL: return 1;
    case Decoration::FunctionFloatingPointModeINTEL: 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 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 PairLiteralIntegerIdRef &val)
{
  return val.second != 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)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeFloat(IdResult result, uint32_t width)
      : op(Op::TypeFloat)
      , wordCount(FixedWordSize)
  {
    this->result = result;
    this->width = width;
  }

  static constexpr Op OpCode = Op::TypeFloat;
  static constexpr uint16_t FixedWordSize = 3U;
  Op op;
  uint16_t wordCount;
  IdResult result;
  uint32_t width;
};

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
{
  OpSwitch(const ConstIter &it)
  {
    uint32_t word = 0;(void)word;
    this->op = OpCode;
    this->wordCount = (uint16_t)it.size();
    this->selector = Id::fromWord(it.word(1));
    this->def = Id::fromWord(it.word(2));
    word = 3;
    this->target = MultiParam<PairLiteralIntegerIdRef>(it, word);
  }
  OpSwitch(Id selector, Id def, const rdcarray<PairLiteralIntegerIdRef> &target = {})
      : op(Op::Switch)
      , wordCount(MinWordSize + MultiWordCount(target))
  {
    this->selector = selector;
    this->def = def;
    this->target = target;
  }
  operator Operation() const
  {
    rdcarray<uint32_t> words;
    words.push_back(selector.value());
    words.push_back(def.value());
    for(size_t i=0; i < target.size(); i++)
    {
      words.push_back((uint32_t)target[i].first); words.push_back(target[i].second.value());
    }
    return Operation(OpCode, words);
  }

  static constexpr Op OpCode = Op::Switch;
  static constexpr uint16_t MinWordSize = 3U;
  Op op;
  uint16_t wordCount;
  Id selector;
  Id def;
  rdcarray<PairLiteralIntegerIdRef> target;
};

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 id)
      : op(Op::GroupNonUniformBroadcast)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->value = value;
    this->id = id;
  }

  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 id;
};

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 id)
      : op(Op::GroupNonUniformShuffle)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->execution = execution;
    this->value = value;
    this->id = id;
  }

  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 id;
};

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 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 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 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 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 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 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 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 OpGroupNonUniformPartitionNV
{
  OpGroupNonUniformPartitionNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpGroupNonUniformPartitionNV(IdResultType resultType, IdResult result, Id value)
      : op(Op::GroupNonUniformPartitionNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->value = value;
  }

  static constexpr Op OpCode = Op::GroupNonUniformPartitionNV;
  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 OpReportIntersectionNV
{
  OpReportIntersectionNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpReportIntersectionNV(IdResultType resultType, IdResult result, Id hit, Id hitKind)
      : op(Op::ReportIntersectionNV)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->hit = hit;
    this->hitKind = hitKind;
  }

  static constexpr Op OpCode = Op::ReportIntersectionNV;
  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 OpTypeAccelerationStructureNV
{
  OpTypeAccelerationStructureNV(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpTypeAccelerationStructureNV(IdResult result)
      : op(Op::TypeAccelerationStructureNV)
      , wordCount(FixedWordSize)
  {
    this->result = result;
  }

  static constexpr Op OpCode = Op::TypeAccelerationStructureNV;
  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 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 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 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 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 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 OpReadPipeBlockingINTEL
{
  OpReadPipeBlockingINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpReadPipeBlockingINTEL(IdResultType resultType, IdResult result, Id packetSize, Id packetAlignment)
      : op(Op::ReadPipeBlockingINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result = result;
    this->packetSize = packetSize;
    this->packetAlignment = packetAlignment;
  }

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

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

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

struct OpFPGARegINTEL
{
  OpFPGARegINTEL(const ConstIter &it)
  {
    memcpy(this, it.words(), sizeof(*this));
  }
  OpFPGARegINTEL(IdResultType resultType, IdResult result0, Id result1, Id input)
      : op(Op::FPGARegINTEL)
      , wordCount(FixedWordSize)
  {
    this->resultType = resultType;
    this->result0 = result0;
    this->result1 = result1;
    this->input = input;
  }

  static constexpr Op OpCode = Op::FPGARegINTEL;
  static constexpr uint16_t FixedWordSize = 5U;
  Op op;
  uint16_t wordCount;
  IdResultType resultType;
  IdResult result0;
  Id result1;
  Id input;
};

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 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 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;
};

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 PairLiteralIntegerIdRef &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<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;
}

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
