Edit

kc3-lang/angle/src/common/spirv/spirv_instruction_builder_autogen.cpp

Branch :

  • Show log

    Commit

  • Author : Shahbaz Youssefi
    Date : 2021-06-23 23:20:33
    Hash : 0461d8d4
    Message : Vulkan: SPIR-V Gen: texture and image built-ins GLSL contains a large number of built-in texture* and image* functions, but these map to only a handful of SPIR-V instructions. The bulk of the work to map these is to extract the arguments from the built-ins based on their ordinal position. Bug: angleproject:4889 Change-Id: I760d986bd9171ddde35f9f046c549ca53252df17 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2992980 Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>

  • src/common/spirv/spirv_instruction_builder_autogen.cpp
  • // GENERATED FILE - DO NOT EDIT.
    // Generated by gen_spirv_builder_and_parser.py using data from spirv.core.grammar.json.
    //
    // Copyright 2021 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    // spirv_instruction_builder_autogen.cpp:
    //   Functions to generate SPIR-V binary for each instruction.
    
    #include "spirv_instruction_builder_autogen.h"
    
    #include <string.h>
    
    #include "common/debug.h"
    
    namespace angle
    {
    namespace spirv
    {
    namespace
    {
    uint32_t MakeLengthOp(size_t length, spv::Op op)
    {
        ASSERT(length <= 0xFFFFu);
        ASSERT(op <= 0xFFFFu);
    
        return static_cast<uint32_t>(length) << 16 | op;
    }
    }  // anonymous namespace
    
    void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t idCount)
    {
        // Header:
        //
        //  - Magic number
        //  - Version (1.0)
        //  - ANGLE's Generator number:
        //     * 24 for tool id (higher 16 bits)
        //     * 0 for tool version (lower 16 bits))
        //  - Bound (idCount)
        //  - 0 (reserved)
        constexpr uint32_t kANGLEGeneratorId = 24;
    
        ASSERT(blob->empty());
    
        blob->push_back(spv::MagicNumber);
        blob->push_back(0x00010000);
        blob->push_back(kANGLEGeneratorId << 16 | 0);
        blob->push_back(idCount);
        blob->push_back(0x00000000);
    }
    
    void WriteNop(Blob *blob)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
    
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpNop);
    }
    void WriteUndef(Blob *blob, IdResultType idResultType, IdResult idResult)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpUndef);
    }
    void WriteSourceContinued(Blob *blob, LiteralString continuedSource)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        {
            size_t d = blob->size();
            blob->resize(d + strlen(continuedSource) / 4 + 1, 0);
            ASSERT(IsLittleEndian());
            strcpy(reinterpret_cast<char *>(blob->data() + d), continuedSource);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSourceContinued);
    }
    void WriteSource(Blob *blob,
                     spv::SourceLanguage sourceLanguage,
                     LiteralInteger version,
                     const IdRef *file,
                     const LiteralString *source)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(sourceLanguage);
        blob->push_back(version);
        if (file)
        {
            blob->push_back(*file);
        }
        if (source)
        {
            {
                size_t d = blob->size();
                blob->resize(d + strlen(*source) / 4 + 1, 0);
                ASSERT(IsLittleEndian());
                strcpy(reinterpret_cast<char *>(blob->data() + d), *source);
            }
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSource);
    }
    void WriteSourceExtension(Blob *blob, LiteralString extension)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        {
            size_t d = blob->size();
            blob->resize(d + strlen(extension) / 4 + 1, 0);
            ASSERT(IsLittleEndian());
            strcpy(reinterpret_cast<char *>(blob->data() + d), extension);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSourceExtension);
    }
    void WriteName(Blob *blob, IdRef target, LiteralString name)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(target);
        {
            size_t d = blob->size();
            blob->resize(d + strlen(name) / 4 + 1, 0);
            ASSERT(IsLittleEndian());
            strcpy(reinterpret_cast<char *>(blob->data() + d), name);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpName);
    }
    void WriteMemberName(Blob *blob, IdRef type, LiteralInteger member, LiteralString name)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(type);
        blob->push_back(member);
        {
            size_t d = blob->size();
            blob->resize(d + strlen(name) / 4 + 1, 0);
            ASSERT(IsLittleEndian());
            strcpy(reinterpret_cast<char *>(blob->data() + d), name);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpMemberName);
    }
    void WriteString(Blob *blob, IdResult idResult, LiteralString string)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResult);
        {
            size_t d = blob->size();
            blob->resize(d + strlen(string) / 4 + 1, 0);
            ASSERT(IsLittleEndian());
            strcpy(reinterpret_cast<char *>(blob->data() + d), string);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpString);
    }
    void WriteLine(Blob *blob, IdRef file, LiteralInteger line, LiteralInteger column)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(file);
        blob->push_back(line);
        blob->push_back(column);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpLine);
    }
    void WriteExtension(Blob *blob, LiteralString name)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        {
            size_t d = blob->size();
            blob->resize(d + strlen(name) / 4 + 1, 0);
            ASSERT(IsLittleEndian());
            strcpy(reinterpret_cast<char *>(blob->data() + d), name);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpExtension);
    }
    void WriteExtInstImport(Blob *blob, IdResult idResult, LiteralString name)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResult);
        {
            size_t d = blob->size();
            blob->resize(d + strlen(name) / 4 + 1, 0);
            ASSERT(IsLittleEndian());
            strcpy(reinterpret_cast<char *>(blob->data() + d), name);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpExtInstImport);
    }
    void WriteExtInst(Blob *blob,
                      IdResultType idResultType,
                      IdResult idResult,
                      IdRef set,
                      LiteralExtInstInteger instruction,
                      const IdRefList &operandList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(set);
        blob->push_back(instruction);
        for (const auto &operand : operandList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpExtInst);
    }
    void WriteMemoryModel(Blob *blob,
                          spv::AddressingModel addressingModel,
                          spv::MemoryModel memoryModel)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(addressingModel);
        blob->push_back(memoryModel);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpMemoryModel);
    }
    void WriteEntryPoint(Blob *blob,
                         spv::ExecutionModel executionModel,
                         IdRef entryPoint,
                         LiteralString name,
                         const IdRefList &interfaceList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(executionModel);
        blob->push_back(entryPoint);
        {
            size_t d = blob->size();
            blob->resize(d + strlen(name) / 4 + 1, 0);
            ASSERT(IsLittleEndian());
            strcpy(reinterpret_cast<char *>(blob->data() + d), name);
        }
        for (const auto &operand : interfaceList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpEntryPoint);
    }
    void WriteExecutionMode(Blob *blob,
                            IdRef entryPoint,
                            spv::ExecutionMode mode,
                            const LiteralIntegerList &operandsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(entryPoint);
        blob->push_back(mode);
        for (const auto &operand : operandsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpExecutionMode);
    }
    void WriteCapability(Blob *blob, spv::Capability capability)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(capability);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpCapability);
    }
    void WriteTypeVoid(Blob *blob, IdResult idResult)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResult);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpTypeVoid);
    }
    void WriteTypeBool(Blob *blob, IdResult idResult)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResult);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpTypeBool);
    }
    void WriteTypeInt(Blob *blob, IdResult idResult, LiteralInteger width, LiteralInteger signedness)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResult);
        blob->push_back(width);
        blob->push_back(signedness);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpTypeInt);
    }
    void WriteTypeFloat(Blob *blob, IdResult idResult, LiteralInteger width)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResult);
        blob->push_back(width);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpTypeFloat);
    }
    void WriteTypeVector(Blob *blob,
                         IdResult idResult,
                         IdRef componentType,
                         LiteralInteger componentCount)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResult);
        blob->push_back(componentType);
        blob->push_back(componentCount);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpTypeVector);
    }
    void WriteTypeMatrix(Blob *blob, IdResult idResult, IdRef columnType, LiteralInteger columnCount)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResult);
        blob->push_back(columnType);
        blob->push_back(columnCount);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpTypeMatrix);
    }
    void WriteTypeImage(Blob *blob,
                        IdResult idResult,
                        IdRef sampledType,
                        spv::Dim dim,
                        LiteralInteger depth,
                        LiteralInteger arrayed,
                        LiteralInteger mS,
                        LiteralInteger sampled,
                        spv::ImageFormat imageFormat,
                        const spv::AccessQualifier *accessQualifier)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResult);
        blob->push_back(sampledType);
        blob->push_back(dim);
        blob->push_back(depth);
        blob->push_back(arrayed);
        blob->push_back(mS);
        blob->push_back(sampled);
        blob->push_back(imageFormat);
        if (accessQualifier)
        {
            blob->push_back(*accessQualifier);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpTypeImage);
    }
    void WriteTypeSampler(Blob *blob, IdResult idResult)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResult);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpTypeSampler);
    }
    void WriteTypeSampledImage(Blob *blob, IdResult idResult, IdRef imageType)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResult);
        blob->push_back(imageType);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpTypeSampledImage);
    }
    void WriteTypeArray(Blob *blob, IdResult idResult, IdRef elementType, IdRef length)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResult);
        blob->push_back(elementType);
        blob->push_back(length);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpTypeArray);
    }
    void WriteTypeRuntimeArray(Blob *blob, IdResult idResult, IdRef elementType)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResult);
        blob->push_back(elementType);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpTypeRuntimeArray);
    }
    void WriteTypeStruct(Blob *blob, IdResult idResult, const IdRefList &memberList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResult);
        for (const auto &operand : memberList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpTypeStruct);
    }
    void WriteTypePointer(Blob *blob, IdResult idResult, spv::StorageClass storageClass, IdRef type)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResult);
        blob->push_back(storageClass);
        blob->push_back(type);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpTypePointer);
    }
    void WriteTypeFunction(Blob *blob,
                           IdResult idResult,
                           IdRef returnType,
                           const IdRefList &parameterList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResult);
        blob->push_back(returnType);
        for (const auto &operand : parameterList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpTypeFunction);
    }
    void WriteConstantTrue(Blob *blob, IdResultType idResultType, IdResult idResult)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpConstantTrue);
    }
    void WriteConstantFalse(Blob *blob, IdResultType idResultType, IdResult idResult)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpConstantFalse);
    }
    void WriteConstant(Blob *blob,
                       IdResultType idResultType,
                       IdResult idResult,
                       LiteralContextDependentNumber value)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(value);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpConstant);
    }
    void WriteConstantComposite(Blob *blob,
                                IdResultType idResultType,
                                IdResult idResult,
                                const IdRefList &constituentsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        for (const auto &operand : constituentsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpConstantComposite);
    }
    void WriteConstantNull(Blob *blob, IdResultType idResultType, IdResult idResult)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpConstantNull);
    }
    void WriteSpecConstantTrue(Blob *blob, IdResultType idResultType, IdResult idResult)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSpecConstantTrue);
    }
    void WriteSpecConstantFalse(Blob *blob, IdResultType idResultType, IdResult idResult)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSpecConstantFalse);
    }
    void WriteSpecConstant(Blob *blob,
                           IdResultType idResultType,
                           IdResult idResult,
                           LiteralContextDependentNumber value)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(value);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSpecConstant);
    }
    void WriteSpecConstantComposite(Blob *blob,
                                    IdResultType idResultType,
                                    IdResult idResult,
                                    const IdRefList &constituentsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        for (const auto &operand : constituentsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSpecConstantComposite);
    }
    void WriteFunction(Blob *blob,
                       IdResultType idResultType,
                       IdResult idResult,
                       spv::FunctionControlMask functionControl,
                       IdRef functionType)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(functionControl);
        blob->push_back(functionType);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFunction);
    }
    void WriteFunctionParameter(Blob *blob, IdResultType idResultType, IdResult idResult)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFunctionParameter);
    }
    void WriteFunctionEnd(Blob *blob)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
    
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFunctionEnd);
    }
    void WriteFunctionCall(Blob *blob,
                           IdResultType idResultType,
                           IdResult idResult,
                           IdRef function,
                           const IdRefList &argumentList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(function);
        for (const auto &operand : argumentList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFunctionCall);
    }
    void WriteVariable(Blob *blob,
                       IdResultType idResultType,
                       IdResult idResult,
                       spv::StorageClass storageClass,
                       const IdRef *initializer)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(storageClass);
        if (initializer)
        {
            blob->push_back(*initializer);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpVariable);
    }
    void WriteImageTexelPointer(Blob *blob,
                                IdResultType idResultType,
                                IdResult idResult,
                                IdRef image,
                                IdRef coordinate,
                                IdRef sample)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(image);
        blob->push_back(coordinate);
        blob->push_back(sample);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageTexelPointer);
    }
    void WriteLoad(Blob *blob,
                   IdResultType idResultType,
                   IdResult idResult,
                   IdRef pointer,
                   const spv::MemoryAccessMask *memoryAccess)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(pointer);
        if (memoryAccess)
        {
            blob->push_back(*memoryAccess);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpLoad);
    }
    void WriteStore(Blob *blob, IdRef pointer, IdRef object, const spv::MemoryAccessMask *memoryAccess)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(pointer);
        blob->push_back(object);
        if (memoryAccess)
        {
            blob->push_back(*memoryAccess);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpStore);
    }
    void WriteCopyMemory(Blob *blob,
                         IdRef target,
                         IdRef source,
                         const spv::MemoryAccessMask *memoryAccess)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(target);
        blob->push_back(source);
        if (memoryAccess)
        {
            blob->push_back(*memoryAccess);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpCopyMemory);
    }
    void WriteAccessChain(Blob *blob,
                          IdResultType idResultType,
                          IdResult idResult,
                          IdRef base,
                          const IdRefList &indexesList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(base);
        for (const auto &operand : indexesList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpAccessChain);
    }
    void WriteInBoundsAccessChain(Blob *blob,
                                  IdResultType idResultType,
                                  IdResult idResult,
                                  IdRef base,
                                  const IdRefList &indexesList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(base);
        for (const auto &operand : indexesList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpInBoundsAccessChain);
    }
    void WriteArrayLength(Blob *blob,
                          IdResultType idResultType,
                          IdResult idResult,
                          IdRef structure,
                          LiteralInteger arraymember)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(structure);
        blob->push_back(arraymember);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpArrayLength);
    }
    void WriteDecorate(Blob *blob,
                       IdRef target,
                       spv::Decoration decoration,
                       const LiteralIntegerList &valuesList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(target);
        blob->push_back(decoration);
        for (const auto &operand : valuesList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpDecorate);
    }
    void WriteMemberDecorate(Blob *blob,
                             IdRef structureType,
                             LiteralInteger member,
                             spv::Decoration decoration,
                             const LiteralIntegerList &valuesList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(structureType);
        blob->push_back(member);
        blob->push_back(decoration);
        for (const auto &operand : valuesList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpMemberDecorate);
    }
    void WriteDecorationGroup(Blob *blob, IdResult idResult)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResult);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpDecorationGroup);
    }
    void WriteGroupDecorate(Blob *blob, IdRef decorationGroup, const IdRefList &targetsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(decorationGroup);
        for (const auto &operand : targetsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupDecorate);
    }
    void WriteGroupMemberDecorate(Blob *blob,
                                  IdRef decorationGroup,
                                  const PairIdRefLiteralIntegerList &targetsPairList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(decorationGroup);
        for (const auto &operand : targetsPairList)
        {
            blob->push_back(operand.id);
            blob->push_back(operand.literal);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupMemberDecorate);
    }
    void WriteVectorExtractDynamic(Blob *blob,
                                   IdResultType idResultType,
                                   IdResult idResult,
                                   IdRef vector,
                                   IdRef index)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(vector);
        blob->push_back(index);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpVectorExtractDynamic);
    }
    void WriteVectorInsertDynamic(Blob *blob,
                                  IdResultType idResultType,
                                  IdResult idResult,
                                  IdRef vector,
                                  IdRef component,
                                  IdRef index)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(vector);
        blob->push_back(component);
        blob->push_back(index);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpVectorInsertDynamic);
    }
    void WriteVectorShuffle(Blob *blob,
                            IdResultType idResultType,
                            IdResult idResult,
                            IdRef vector1,
                            IdRef vector2,
                            const LiteralIntegerList &componentsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(vector1);
        blob->push_back(vector2);
        for (const auto &operand : componentsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpVectorShuffle);
    }
    void WriteCompositeConstruct(Blob *blob,
                                 IdResultType idResultType,
                                 IdResult idResult,
                                 const IdRefList &constituentsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        for (const auto &operand : constituentsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpCompositeConstruct);
    }
    void WriteCompositeExtract(Blob *blob,
                               IdResultType idResultType,
                               IdResult idResult,
                               IdRef composite,
                               const LiteralIntegerList &indexesList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(composite);
        for (const auto &operand : indexesList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpCompositeExtract);
    }
    void WriteCompositeInsert(Blob *blob,
                              IdResultType idResultType,
                              IdResult idResult,
                              IdRef object,
                              IdRef composite,
                              const LiteralIntegerList &indexesList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(object);
        blob->push_back(composite);
        for (const auto &operand : indexesList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpCompositeInsert);
    }
    void WriteCopyObject(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef operand)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpCopyObject);
    }
    void WriteTranspose(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef matrix)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(matrix);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpTranspose);
    }
    void WriteSampledImage(Blob *blob,
                           IdResultType idResultType,
                           IdResult idResult,
                           IdRef image,
                           IdRef sampler)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(image);
        blob->push_back(sampler);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSampledImage);
    }
    void WriteImageSampleImplicitLod(Blob *blob,
                                     IdResultType idResultType,
                                     IdResult idResult,
                                     IdRef sampledImage,
                                     IdRef coordinate,
                                     const spv::ImageOperandsMask *imageOperands,
                                     const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        if (imageOperands)
        {
            blob->push_back(*imageOperands);
        }
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageSampleImplicitLod);
    }
    void WriteImageSampleExplicitLod(Blob *blob,
                                     IdResultType idResultType,
                                     IdResult idResult,
                                     IdRef sampledImage,
                                     IdRef coordinate,
                                     spv::ImageOperandsMask imageOperands,
                                     const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        blob->push_back(imageOperands);
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageSampleExplicitLod);
    }
    void WriteImageSampleDrefImplicitLod(Blob *blob,
                                         IdResultType idResultType,
                                         IdResult idResult,
                                         IdRef sampledImage,
                                         IdRef coordinate,
                                         IdRef dref,
                                         const spv::ImageOperandsMask *imageOperands,
                                         const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        blob->push_back(dref);
        if (imageOperands)
        {
            blob->push_back(*imageOperands);
        }
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageSampleDrefImplicitLod);
    }
    void WriteImageSampleDrefExplicitLod(Blob *blob,
                                         IdResultType idResultType,
                                         IdResult idResult,
                                         IdRef sampledImage,
                                         IdRef coordinate,
                                         IdRef dref,
                                         spv::ImageOperandsMask imageOperands,
                                         const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        blob->push_back(dref);
        blob->push_back(imageOperands);
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageSampleDrefExplicitLod);
    }
    void WriteImageSampleProjImplicitLod(Blob *blob,
                                         IdResultType idResultType,
                                         IdResult idResult,
                                         IdRef sampledImage,
                                         IdRef coordinate,
                                         const spv::ImageOperandsMask *imageOperands,
                                         const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        if (imageOperands)
        {
            blob->push_back(*imageOperands);
        }
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageSampleProjImplicitLod);
    }
    void WriteImageSampleProjExplicitLod(Blob *blob,
                                         IdResultType idResultType,
                                         IdResult idResult,
                                         IdRef sampledImage,
                                         IdRef coordinate,
                                         spv::ImageOperandsMask imageOperands,
                                         const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        blob->push_back(imageOperands);
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageSampleProjExplicitLod);
    }
    void WriteImageSampleProjDrefImplicitLod(Blob *blob,
                                             IdResultType idResultType,
                                             IdResult idResult,
                                             IdRef sampledImage,
                                             IdRef coordinate,
                                             IdRef dref,
                                             const spv::ImageOperandsMask *imageOperands,
                                             const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        blob->push_back(dref);
        if (imageOperands)
        {
            blob->push_back(*imageOperands);
        }
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] =
            MakeLengthOp(blob->size() - startSize, spv::OpImageSampleProjDrefImplicitLod);
    }
    void WriteImageSampleProjDrefExplicitLod(Blob *blob,
                                             IdResultType idResultType,
                                             IdResult idResult,
                                             IdRef sampledImage,
                                             IdRef coordinate,
                                             IdRef dref,
                                             spv::ImageOperandsMask imageOperands,
                                             const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        blob->push_back(dref);
        blob->push_back(imageOperands);
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] =
            MakeLengthOp(blob->size() - startSize, spv::OpImageSampleProjDrefExplicitLod);
    }
    void WriteImageFetch(Blob *blob,
                         IdResultType idResultType,
                         IdResult idResult,
                         IdRef image,
                         IdRef coordinate,
                         const spv::ImageOperandsMask *imageOperands,
                         const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(image);
        blob->push_back(coordinate);
        if (imageOperands)
        {
            blob->push_back(*imageOperands);
        }
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageFetch);
    }
    void WriteImageGather(Blob *blob,
                          IdResultType idResultType,
                          IdResult idResult,
                          IdRef sampledImage,
                          IdRef coordinate,
                          IdRef component,
                          const spv::ImageOperandsMask *imageOperands,
                          const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        blob->push_back(component);
        if (imageOperands)
        {
            blob->push_back(*imageOperands);
        }
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageGather);
    }
    void WriteImageDrefGather(Blob *blob,
                              IdResultType idResultType,
                              IdResult idResult,
                              IdRef sampledImage,
                              IdRef coordinate,
                              IdRef dref,
                              const spv::ImageOperandsMask *imageOperands,
                              const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        blob->push_back(dref);
        if (imageOperands)
        {
            blob->push_back(*imageOperands);
        }
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageDrefGather);
    }
    void WriteImageRead(Blob *blob,
                        IdResultType idResultType,
                        IdResult idResult,
                        IdRef image,
                        IdRef coordinate,
                        const spv::ImageOperandsMask *imageOperands,
                        const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(image);
        blob->push_back(coordinate);
        if (imageOperands)
        {
            blob->push_back(*imageOperands);
        }
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageRead);
    }
    void WriteImageWrite(Blob *blob,
                         IdRef image,
                         IdRef coordinate,
                         IdRef texel,
                         const spv::ImageOperandsMask *imageOperands,
                         const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(image);
        blob->push_back(coordinate);
        blob->push_back(texel);
        if (imageOperands)
        {
            blob->push_back(*imageOperands);
        }
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageWrite);
    }
    void WriteImage(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef sampledImage)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImage);
    }
    void WriteImageQuerySizeLod(Blob *blob,
                                IdResultType idResultType,
                                IdResult idResult,
                                IdRef image,
                                IdRef levelofDetail)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(image);
        blob->push_back(levelofDetail);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageQuerySizeLod);
    }
    void WriteImageQuerySize(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef image)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(image);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageQuerySize);
    }
    void WriteImageQueryLod(Blob *blob,
                            IdResultType idResultType,
                            IdResult idResult,
                            IdRef sampledImage,
                            IdRef coordinate)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageQueryLod);
    }
    void WriteImageQueryLevels(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef image)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(image);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageQueryLevels);
    }
    void WriteImageQuerySamples(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef image)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(image);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageQuerySamples);
    }
    void WriteConvertFToU(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef floatValue)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(floatValue);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpConvertFToU);
    }
    void WriteConvertFToS(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef floatValue)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(floatValue);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpConvertFToS);
    }
    void WriteConvertSToF(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef signedValue)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(signedValue);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpConvertSToF);
    }
    void WriteConvertUToF(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef unsignedValue)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(unsignedValue);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpConvertUToF);
    }
    void WriteUConvert(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef unsignedValue)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(unsignedValue);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpUConvert);
    }
    void WriteSConvert(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef signedValue)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(signedValue);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSConvert);
    }
    void WriteFConvert(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef floatValue)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(floatValue);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFConvert);
    }
    void WriteQuantizeToF16(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef value)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(value);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpQuantizeToF16);
    }
    void WriteBitcast(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef operand)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpBitcast);
    }
    void WriteSNegate(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef operand)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSNegate);
    }
    void WriteFNegate(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef operand)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFNegate);
    }
    void WriteIAdd(Blob *blob,
                   IdResultType idResultType,
                   IdResult idResult,
                   IdRef operand1,
                   IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpIAdd);
    }
    void WriteFAdd(Blob *blob,
                   IdResultType idResultType,
                   IdResult idResult,
                   IdRef operand1,
                   IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFAdd);
    }
    void WriteISub(Blob *blob,
                   IdResultType idResultType,
                   IdResult idResult,
                   IdRef operand1,
                   IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpISub);
    }
    void WriteFSub(Blob *blob,
                   IdResultType idResultType,
                   IdResult idResult,
                   IdRef operand1,
                   IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFSub);
    }
    void WriteIMul(Blob *blob,
                   IdResultType idResultType,
                   IdResult idResult,
                   IdRef operand1,
                   IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpIMul);
    }
    void WriteFMul(Blob *blob,
                   IdResultType idResultType,
                   IdResult idResult,
                   IdRef operand1,
                   IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFMul);
    }
    void WriteUDiv(Blob *blob,
                   IdResultType idResultType,
                   IdResult idResult,
                   IdRef operand1,
                   IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpUDiv);
    }
    void WriteSDiv(Blob *blob,
                   IdResultType idResultType,
                   IdResult idResult,
                   IdRef operand1,
                   IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSDiv);
    }
    void WriteFDiv(Blob *blob,
                   IdResultType idResultType,
                   IdResult idResult,
                   IdRef operand1,
                   IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFDiv);
    }
    void WriteUMod(Blob *blob,
                   IdResultType idResultType,
                   IdResult idResult,
                   IdRef operand1,
                   IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpUMod);
    }
    void WriteSRem(Blob *blob,
                   IdResultType idResultType,
                   IdResult idResult,
                   IdRef operand1,
                   IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSRem);
    }
    void WriteSMod(Blob *blob,
                   IdResultType idResultType,
                   IdResult idResult,
                   IdRef operand1,
                   IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSMod);
    }
    void WriteFRem(Blob *blob,
                   IdResultType idResultType,
                   IdResult idResult,
                   IdRef operand1,
                   IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFRem);
    }
    void WriteFMod(Blob *blob,
                   IdResultType idResultType,
                   IdResult idResult,
                   IdRef operand1,
                   IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFMod);
    }
    void WriteVectorTimesScalar(Blob *blob,
                                IdResultType idResultType,
                                IdResult idResult,
                                IdRef vector,
                                IdRef scalar)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(vector);
        blob->push_back(scalar);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpVectorTimesScalar);
    }
    void WriteMatrixTimesScalar(Blob *blob,
                                IdResultType idResultType,
                                IdResult idResult,
                                IdRef matrix,
                                IdRef scalar)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(matrix);
        blob->push_back(scalar);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpMatrixTimesScalar);
    }
    void WriteVectorTimesMatrix(Blob *blob,
                                IdResultType idResultType,
                                IdResult idResult,
                                IdRef vector,
                                IdRef matrix)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(vector);
        blob->push_back(matrix);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpVectorTimesMatrix);
    }
    void WriteMatrixTimesVector(Blob *blob,
                                IdResultType idResultType,
                                IdResult idResult,
                                IdRef matrix,
                                IdRef vector)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(matrix);
        blob->push_back(vector);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpMatrixTimesVector);
    }
    void WriteMatrixTimesMatrix(Blob *blob,
                                IdResultType idResultType,
                                IdResult idResult,
                                IdRef leftMatrix,
                                IdRef rightMatrix)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(leftMatrix);
        blob->push_back(rightMatrix);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpMatrixTimesMatrix);
    }
    void WriteOuterProduct(Blob *blob,
                           IdResultType idResultType,
                           IdResult idResult,
                           IdRef vector1,
                           IdRef vector2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(vector1);
        blob->push_back(vector2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpOuterProduct);
    }
    void WriteDot(Blob *blob,
                  IdResultType idResultType,
                  IdResult idResult,
                  IdRef vector1,
                  IdRef vector2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(vector1);
        blob->push_back(vector2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpDot);
    }
    void WriteIAddCarry(Blob *blob,
                        IdResultType idResultType,
                        IdResult idResult,
                        IdRef operand1,
                        IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpIAddCarry);
    }
    void WriteISubBorrow(Blob *blob,
                         IdResultType idResultType,
                         IdResult idResult,
                         IdRef operand1,
                         IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpISubBorrow);
    }
    void WriteUMulExtended(Blob *blob,
                           IdResultType idResultType,
                           IdResult idResult,
                           IdRef operand1,
                           IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpUMulExtended);
    }
    void WriteSMulExtended(Blob *blob,
                           IdResultType idResultType,
                           IdResult idResult,
                           IdRef operand1,
                           IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSMulExtended);
    }
    void WriteAny(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef vector)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(vector);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpAny);
    }
    void WriteAll(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef vector)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(vector);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpAll);
    }
    void WriteIsNan(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef x)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(x);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpIsNan);
    }
    void WriteIsInf(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef x)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(x);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpIsInf);
    }
    void WriteLogicalEqual(Blob *blob,
                           IdResultType idResultType,
                           IdResult idResult,
                           IdRef operand1,
                           IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpLogicalEqual);
    }
    void WriteLogicalNotEqual(Blob *blob,
                              IdResultType idResultType,
                              IdResult idResult,
                              IdRef operand1,
                              IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpLogicalNotEqual);
    }
    void WriteLogicalOr(Blob *blob,
                        IdResultType idResultType,
                        IdResult idResult,
                        IdRef operand1,
                        IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpLogicalOr);
    }
    void WriteLogicalAnd(Blob *blob,
                         IdResultType idResultType,
                         IdResult idResult,
                         IdRef operand1,
                         IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpLogicalAnd);
    }
    void WriteLogicalNot(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef operand)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpLogicalNot);
    }
    void WriteSelect(Blob *blob,
                     IdResultType idResultType,
                     IdResult idResult,
                     IdRef condition,
                     IdRef object1,
                     IdRef object2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(condition);
        blob->push_back(object1);
        blob->push_back(object2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSelect);
    }
    void WriteIEqual(Blob *blob,
                     IdResultType idResultType,
                     IdResult idResult,
                     IdRef operand1,
                     IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpIEqual);
    }
    void WriteINotEqual(Blob *blob,
                        IdResultType idResultType,
                        IdResult idResult,
                        IdRef operand1,
                        IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpINotEqual);
    }
    void WriteUGreaterThan(Blob *blob,
                           IdResultType idResultType,
                           IdResult idResult,
                           IdRef operand1,
                           IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpUGreaterThan);
    }
    void WriteSGreaterThan(Blob *blob,
                           IdResultType idResultType,
                           IdResult idResult,
                           IdRef operand1,
                           IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSGreaterThan);
    }
    void WriteUGreaterThanEqual(Blob *blob,
                                IdResultType idResultType,
                                IdResult idResult,
                                IdRef operand1,
                                IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpUGreaterThanEqual);
    }
    void WriteSGreaterThanEqual(Blob *blob,
                                IdResultType idResultType,
                                IdResult idResult,
                                IdRef operand1,
                                IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSGreaterThanEqual);
    }
    void WriteULessThan(Blob *blob,
                        IdResultType idResultType,
                        IdResult idResult,
                        IdRef operand1,
                        IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpULessThan);
    }
    void WriteSLessThan(Blob *blob,
                        IdResultType idResultType,
                        IdResult idResult,
                        IdRef operand1,
                        IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSLessThan);
    }
    void WriteULessThanEqual(Blob *blob,
                             IdResultType idResultType,
                             IdResult idResult,
                             IdRef operand1,
                             IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpULessThanEqual);
    }
    void WriteSLessThanEqual(Blob *blob,
                             IdResultType idResultType,
                             IdResult idResult,
                             IdRef operand1,
                             IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSLessThanEqual);
    }
    void WriteFOrdEqual(Blob *blob,
                        IdResultType idResultType,
                        IdResult idResult,
                        IdRef operand1,
                        IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFOrdEqual);
    }
    void WriteFUnordEqual(Blob *blob,
                          IdResultType idResultType,
                          IdResult idResult,
                          IdRef operand1,
                          IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFUnordEqual);
    }
    void WriteFOrdNotEqual(Blob *blob,
                           IdResultType idResultType,
                           IdResult idResult,
                           IdRef operand1,
                           IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFOrdNotEqual);
    }
    void WriteFUnordNotEqual(Blob *blob,
                             IdResultType idResultType,
                             IdResult idResult,
                             IdRef operand1,
                             IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFUnordNotEqual);
    }
    void WriteFOrdLessThan(Blob *blob,
                           IdResultType idResultType,
                           IdResult idResult,
                           IdRef operand1,
                           IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFOrdLessThan);
    }
    void WriteFUnordLessThan(Blob *blob,
                             IdResultType idResultType,
                             IdResult idResult,
                             IdRef operand1,
                             IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFUnordLessThan);
    }
    void WriteFOrdGreaterThan(Blob *blob,
                              IdResultType idResultType,
                              IdResult idResult,
                              IdRef operand1,
                              IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFOrdGreaterThan);
    }
    void WriteFUnordGreaterThan(Blob *blob,
                                IdResultType idResultType,
                                IdResult idResult,
                                IdRef operand1,
                                IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFUnordGreaterThan);
    }
    void WriteFOrdLessThanEqual(Blob *blob,
                                IdResultType idResultType,
                                IdResult idResult,
                                IdRef operand1,
                                IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFOrdLessThanEqual);
    }
    void WriteFUnordLessThanEqual(Blob *blob,
                                  IdResultType idResultType,
                                  IdResult idResult,
                                  IdRef operand1,
                                  IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFUnordLessThanEqual);
    }
    void WriteFOrdGreaterThanEqual(Blob *blob,
                                   IdResultType idResultType,
                                   IdResult idResult,
                                   IdRef operand1,
                                   IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFOrdGreaterThanEqual);
    }
    void WriteFUnordGreaterThanEqual(Blob *blob,
                                     IdResultType idResultType,
                                     IdResult idResult,
                                     IdRef operand1,
                                     IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFUnordGreaterThanEqual);
    }
    void WriteShiftRightLogical(Blob *blob,
                                IdResultType idResultType,
                                IdResult idResult,
                                IdRef base,
                                IdRef shift)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(base);
        blob->push_back(shift);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpShiftRightLogical);
    }
    void WriteShiftRightArithmetic(Blob *blob,
                                   IdResultType idResultType,
                                   IdResult idResult,
                                   IdRef base,
                                   IdRef shift)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(base);
        blob->push_back(shift);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpShiftRightArithmetic);
    }
    void WriteShiftLeftLogical(Blob *blob,
                               IdResultType idResultType,
                               IdResult idResult,
                               IdRef base,
                               IdRef shift)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(base);
        blob->push_back(shift);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpShiftLeftLogical);
    }
    void WriteBitwiseOr(Blob *blob,
                        IdResultType idResultType,
                        IdResult idResult,
                        IdRef operand1,
                        IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpBitwiseOr);
    }
    void WriteBitwiseXor(Blob *blob,
                         IdResultType idResultType,
                         IdResult idResult,
                         IdRef operand1,
                         IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpBitwiseXor);
    }
    void WriteBitwiseAnd(Blob *blob,
                         IdResultType idResultType,
                         IdResult idResult,
                         IdRef operand1,
                         IdRef operand2)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand1);
        blob->push_back(operand2);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpBitwiseAnd);
    }
    void WriteNot(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef operand)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(operand);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpNot);
    }
    void WriteBitFieldInsert(Blob *blob,
                             IdResultType idResultType,
                             IdResult idResult,
                             IdRef base,
                             IdRef insert,
                             IdRef offset,
                             IdRef count)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(base);
        blob->push_back(insert);
        blob->push_back(offset);
        blob->push_back(count);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpBitFieldInsert);
    }
    void WriteBitFieldSExtract(Blob *blob,
                               IdResultType idResultType,
                               IdResult idResult,
                               IdRef base,
                               IdRef offset,
                               IdRef count)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(base);
        blob->push_back(offset);
        blob->push_back(count);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpBitFieldSExtract);
    }
    void WriteBitFieldUExtract(Blob *blob,
                               IdResultType idResultType,
                               IdResult idResult,
                               IdRef base,
                               IdRef offset,
                               IdRef count)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(base);
        blob->push_back(offset);
        blob->push_back(count);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpBitFieldUExtract);
    }
    void WriteBitReverse(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef base)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(base);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpBitReverse);
    }
    void WriteBitCount(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef base)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(base);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpBitCount);
    }
    void WriteDPdx(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef p)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(p);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpDPdx);
    }
    void WriteDPdy(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef p)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(p);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpDPdy);
    }
    void WriteFwidth(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef p)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(p);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFwidth);
    }
    void WriteDPdxFine(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef p)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(p);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpDPdxFine);
    }
    void WriteDPdyFine(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef p)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(p);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpDPdyFine);
    }
    void WriteFwidthFine(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef p)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(p);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFwidthFine);
    }
    void WriteDPdxCoarse(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef p)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(p);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpDPdxCoarse);
    }
    void WriteDPdyCoarse(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef p)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(p);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpDPdyCoarse);
    }
    void WriteFwidthCoarse(Blob *blob, IdResultType idResultType, IdResult idResult, IdRef p)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(p);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpFwidthCoarse);
    }
    void WriteEmitVertex(Blob *blob)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
    
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpEmitVertex);
    }
    void WriteEndPrimitive(Blob *blob)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
    
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpEndPrimitive);
    }
    void WriteEmitStreamVertex(Blob *blob, IdRef stream)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(stream);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpEmitStreamVertex);
    }
    void WriteEndStreamPrimitive(Blob *blob, IdRef stream)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(stream);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpEndStreamPrimitive);
    }
    void WriteControlBarrier(Blob *blob, IdScope execution, IdScope memory, IdMemorySemantics semantics)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(execution);
        blob->push_back(memory);
        blob->push_back(semantics);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpControlBarrier);
    }
    void WriteMemoryBarrier(Blob *blob, IdScope memory, IdMemorySemantics semantics)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(memory);
        blob->push_back(semantics);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpMemoryBarrier);
    }
    void WriteAtomicLoad(Blob *blob,
                         IdResultType idResultType,
                         IdResult idResult,
                         IdRef pointer,
                         IdScope scope,
                         IdMemorySemantics semantics)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(pointer);
        blob->push_back(scope);
        blob->push_back(semantics);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpAtomicLoad);
    }
    void WriteAtomicStore(Blob *blob,
                          IdRef pointer,
                          IdScope scope,
                          IdMemorySemantics semantics,
                          IdRef value)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(pointer);
        blob->push_back(scope);
        blob->push_back(semantics);
        blob->push_back(value);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpAtomicStore);
    }
    void WriteAtomicExchange(Blob *blob,
                             IdResultType idResultType,
                             IdResult idResult,
                             IdRef pointer,
                             IdScope scope,
                             IdMemorySemantics semantics,
                             IdRef value)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(pointer);
        blob->push_back(scope);
        blob->push_back(semantics);
        blob->push_back(value);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpAtomicExchange);
    }
    void WriteAtomicCompareExchange(Blob *blob,
                                    IdResultType idResultType,
                                    IdResult idResult,
                                    IdRef pointer,
                                    IdScope scope,
                                    IdMemorySemantics equal,
                                    IdMemorySemantics unequal,
                                    IdRef value,
                                    IdRef comparator)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(pointer);
        blob->push_back(scope);
        blob->push_back(equal);
        blob->push_back(unequal);
        blob->push_back(value);
        blob->push_back(comparator);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpAtomicCompareExchange);
    }
    void WriteAtomicIIncrement(Blob *blob,
                               IdResultType idResultType,
                               IdResult idResult,
                               IdRef pointer,
                               IdScope scope,
                               IdMemorySemantics semantics)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(pointer);
        blob->push_back(scope);
        blob->push_back(semantics);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpAtomicIIncrement);
    }
    void WriteAtomicIDecrement(Blob *blob,
                               IdResultType idResultType,
                               IdResult idResult,
                               IdRef pointer,
                               IdScope scope,
                               IdMemorySemantics semantics)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(pointer);
        blob->push_back(scope);
        blob->push_back(semantics);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpAtomicIDecrement);
    }
    void WriteAtomicIAdd(Blob *blob,
                         IdResultType idResultType,
                         IdResult idResult,
                         IdRef pointer,
                         IdScope scope,
                         IdMemorySemantics semantics,
                         IdRef value)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(pointer);
        blob->push_back(scope);
        blob->push_back(semantics);
        blob->push_back(value);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpAtomicIAdd);
    }
    void WriteAtomicISub(Blob *blob,
                         IdResultType idResultType,
                         IdResult idResult,
                         IdRef pointer,
                         IdScope scope,
                         IdMemorySemantics semantics,
                         IdRef value)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(pointer);
        blob->push_back(scope);
        blob->push_back(semantics);
        blob->push_back(value);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpAtomicISub);
    }
    void WriteAtomicSMin(Blob *blob,
                         IdResultType idResultType,
                         IdResult idResult,
                         IdRef pointer,
                         IdScope scope,
                         IdMemorySemantics semantics,
                         IdRef value)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(pointer);
        blob->push_back(scope);
        blob->push_back(semantics);
        blob->push_back(value);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpAtomicSMin);
    }
    void WriteAtomicUMin(Blob *blob,
                         IdResultType idResultType,
                         IdResult idResult,
                         IdRef pointer,
                         IdScope scope,
                         IdMemorySemantics semantics,
                         IdRef value)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(pointer);
        blob->push_back(scope);
        blob->push_back(semantics);
        blob->push_back(value);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpAtomicUMin);
    }
    void WriteAtomicSMax(Blob *blob,
                         IdResultType idResultType,
                         IdResult idResult,
                         IdRef pointer,
                         IdScope scope,
                         IdMemorySemantics semantics,
                         IdRef value)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(pointer);
        blob->push_back(scope);
        blob->push_back(semantics);
        blob->push_back(value);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpAtomicSMax);
    }
    void WriteAtomicUMax(Blob *blob,
                         IdResultType idResultType,
                         IdResult idResult,
                         IdRef pointer,
                         IdScope scope,
                         IdMemorySemantics semantics,
                         IdRef value)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(pointer);
        blob->push_back(scope);
        blob->push_back(semantics);
        blob->push_back(value);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpAtomicUMax);
    }
    void WriteAtomicAnd(Blob *blob,
                        IdResultType idResultType,
                        IdResult idResult,
                        IdRef pointer,
                        IdScope scope,
                        IdMemorySemantics semantics,
                        IdRef value)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(pointer);
        blob->push_back(scope);
        blob->push_back(semantics);
        blob->push_back(value);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpAtomicAnd);
    }
    void WriteAtomicOr(Blob *blob,
                       IdResultType idResultType,
                       IdResult idResult,
                       IdRef pointer,
                       IdScope scope,
                       IdMemorySemantics semantics,
                       IdRef value)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(pointer);
        blob->push_back(scope);
        blob->push_back(semantics);
        blob->push_back(value);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpAtomicOr);
    }
    void WriteAtomicXor(Blob *blob,
                        IdResultType idResultType,
                        IdResult idResult,
                        IdRef pointer,
                        IdScope scope,
                        IdMemorySemantics semantics,
                        IdRef value)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(pointer);
        blob->push_back(scope);
        blob->push_back(semantics);
        blob->push_back(value);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpAtomicXor);
    }
    void WritePhi(Blob *blob,
                  IdResultType idResultType,
                  IdResult idResult,
                  const PairIdRefIdRefList &variableParentPairList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        for (const auto &operand : variableParentPairList)
        {
            blob->push_back(operand.id1);
            blob->push_back(operand.id2);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpPhi);
    }
    void WriteLoopMerge(Blob *blob,
                        IdRef mergeBlock,
                        IdRef continueTarget,
                        spv::LoopControlMask loopControl)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(mergeBlock);
        blob->push_back(continueTarget);
        blob->push_back(loopControl);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpLoopMerge);
    }
    void WriteSelectionMerge(Blob *blob, IdRef mergeBlock, spv::SelectionControlMask selectionControl)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(mergeBlock);
        blob->push_back(selectionControl);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSelectionMerge);
    }
    void WriteLabel(Blob *blob, IdResult idResult)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResult);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpLabel);
    }
    void WriteBranch(Blob *blob, IdRef targetLabel)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(targetLabel);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpBranch);
    }
    void WriteBranchConditional(Blob *blob,
                                IdRef condition,
                                IdRef trueLabel,
                                IdRef falseLabel,
                                const LiteralIntegerList &branchweightsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(condition);
        blob->push_back(trueLabel);
        blob->push_back(falseLabel);
        for (const auto &operand : branchweightsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpBranchConditional);
    }
    void WriteSwitch(Blob *blob,
                     IdRef selector,
                     IdRef default_,
                     const PairLiteralIntegerIdRefList &targetPairList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(selector);
        blob->push_back(default_);
        for (const auto &operand : targetPairList)
        {
            blob->push_back(operand.literal);
            blob->push_back(operand.id);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpSwitch);
    }
    void WriteKill(Blob *blob)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
    
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpKill);
    }
    void WriteReturn(Blob *blob)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
    
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpReturn);
    }
    void WriteReturnValue(Blob *blob, IdRef value)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(value);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpReturnValue);
    }
    void WriteUnreachable(Blob *blob)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
    
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpUnreachable);
    }
    void WriteGroupAll(Blob *blob,
                       IdResultType idResultType,
                       IdResult idResult,
                       IdScope execution,
                       IdRef predicate)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(execution);
        blob->push_back(predicate);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupAll);
    }
    void WriteGroupAny(Blob *blob,
                       IdResultType idResultType,
                       IdResult idResult,
                       IdScope execution,
                       IdRef predicate)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(execution);
        blob->push_back(predicate);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupAny);
    }
    void WriteGroupBroadcast(Blob *blob,
                             IdResultType idResultType,
                             IdResult idResult,
                             IdScope execution,
                             IdRef value,
                             IdRef localId)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(execution);
        blob->push_back(value);
        blob->push_back(localId);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupBroadcast);
    }
    void WriteGroupIAdd(Blob *blob,
                        IdResultType idResultType,
                        IdResult idResult,
                        IdScope execution,
                        spv::GroupOperation operation,
                        IdRef x)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(execution);
        blob->push_back(operation);
        blob->push_back(x);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupIAdd);
    }
    void WriteGroupFAdd(Blob *blob,
                        IdResultType idResultType,
                        IdResult idResult,
                        IdScope execution,
                        spv::GroupOperation operation,
                        IdRef x)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(execution);
        blob->push_back(operation);
        blob->push_back(x);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupFAdd);
    }
    void WriteGroupFMin(Blob *blob,
                        IdResultType idResultType,
                        IdResult idResult,
                        IdScope execution,
                        spv::GroupOperation operation,
                        IdRef x)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(execution);
        blob->push_back(operation);
        blob->push_back(x);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupFMin);
    }
    void WriteGroupUMin(Blob *blob,
                        IdResultType idResultType,
                        IdResult idResult,
                        IdScope execution,
                        spv::GroupOperation operation,
                        IdRef x)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(execution);
        blob->push_back(operation);
        blob->push_back(x);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupUMin);
    }
    void WriteGroupSMin(Blob *blob,
                        IdResultType idResultType,
                        IdResult idResult,
                        IdScope execution,
                        spv::GroupOperation operation,
                        IdRef x)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(execution);
        blob->push_back(operation);
        blob->push_back(x);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupSMin);
    }
    void WriteGroupFMax(Blob *blob,
                        IdResultType idResultType,
                        IdResult idResult,
                        IdScope execution,
                        spv::GroupOperation operation,
                        IdRef x)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(execution);
        blob->push_back(operation);
        blob->push_back(x);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupFMax);
    }
    void WriteGroupUMax(Blob *blob,
                        IdResultType idResultType,
                        IdResult idResult,
                        IdScope execution,
                        spv::GroupOperation operation,
                        IdRef x)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(execution);
        blob->push_back(operation);
        blob->push_back(x);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupUMax);
    }
    void WriteGroupSMax(Blob *blob,
                        IdResultType idResultType,
                        IdResult idResult,
                        IdScope execution,
                        spv::GroupOperation operation,
                        IdRef x)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(execution);
        blob->push_back(operation);
        blob->push_back(x);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupSMax);
    }
    void WriteImageSparseSampleImplicitLod(Blob *blob,
                                           IdResultType idResultType,
                                           IdResult idResult,
                                           IdRef sampledImage,
                                           IdRef coordinate,
                                           const spv::ImageOperandsMask *imageOperands,
                                           const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        if (imageOperands)
        {
            blob->push_back(*imageOperands);
        }
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] =
            MakeLengthOp(blob->size() - startSize, spv::OpImageSparseSampleImplicitLod);
    }
    void WriteImageSparseSampleExplicitLod(Blob *blob,
                                           IdResultType idResultType,
                                           IdResult idResult,
                                           IdRef sampledImage,
                                           IdRef coordinate,
                                           spv::ImageOperandsMask imageOperands,
                                           const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        blob->push_back(imageOperands);
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] =
            MakeLengthOp(blob->size() - startSize, spv::OpImageSparseSampleExplicitLod);
    }
    void WriteImageSparseSampleDrefImplicitLod(Blob *blob,
                                               IdResultType idResultType,
                                               IdResult idResult,
                                               IdRef sampledImage,
                                               IdRef coordinate,
                                               IdRef dref,
                                               const spv::ImageOperandsMask *imageOperands,
                                               const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        blob->push_back(dref);
        if (imageOperands)
        {
            blob->push_back(*imageOperands);
        }
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] =
            MakeLengthOp(blob->size() - startSize, spv::OpImageSparseSampleDrefImplicitLod);
    }
    void WriteImageSparseSampleDrefExplicitLod(Blob *blob,
                                               IdResultType idResultType,
                                               IdResult idResult,
                                               IdRef sampledImage,
                                               IdRef coordinate,
                                               IdRef dref,
                                               spv::ImageOperandsMask imageOperands,
                                               const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        blob->push_back(dref);
        blob->push_back(imageOperands);
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] =
            MakeLengthOp(blob->size() - startSize, spv::OpImageSparseSampleDrefExplicitLod);
    }
    void WriteImageSparseSampleProjImplicitLod(Blob *blob,
                                               IdResultType idResultType,
                                               IdResult idResult,
                                               IdRef sampledImage,
                                               IdRef coordinate,
                                               const spv::ImageOperandsMask *imageOperands,
                                               const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        if (imageOperands)
        {
            blob->push_back(*imageOperands);
        }
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] =
            MakeLengthOp(blob->size() - startSize, spv::OpImageSparseSampleProjImplicitLod);
    }
    void WriteImageSparseSampleProjExplicitLod(Blob *blob,
                                               IdResultType idResultType,
                                               IdResult idResult,
                                               IdRef sampledImage,
                                               IdRef coordinate,
                                               spv::ImageOperandsMask imageOperands,
                                               const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        blob->push_back(imageOperands);
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] =
            MakeLengthOp(blob->size() - startSize, spv::OpImageSparseSampleProjExplicitLod);
    }
    void WriteImageSparseSampleProjDrefImplicitLod(Blob *blob,
                                                   IdResultType idResultType,
                                                   IdResult idResult,
                                                   IdRef sampledImage,
                                                   IdRef coordinate,
                                                   IdRef dref,
                                                   const spv::ImageOperandsMask *imageOperands,
                                                   const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        blob->push_back(dref);
        if (imageOperands)
        {
            blob->push_back(*imageOperands);
        }
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] =
            MakeLengthOp(blob->size() - startSize, spv::OpImageSparseSampleProjDrefImplicitLod);
    }
    void WriteImageSparseSampleProjDrefExplicitLod(Blob *blob,
                                                   IdResultType idResultType,
                                                   IdResult idResult,
                                                   IdRef sampledImage,
                                                   IdRef coordinate,
                                                   IdRef dref,
                                                   spv::ImageOperandsMask imageOperands,
                                                   const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        blob->push_back(dref);
        blob->push_back(imageOperands);
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] =
            MakeLengthOp(blob->size() - startSize, spv::OpImageSparseSampleProjDrefExplicitLod);
    }
    void WriteImageSparseFetch(Blob *blob,
                               IdResultType idResultType,
                               IdResult idResult,
                               IdRef image,
                               IdRef coordinate,
                               const spv::ImageOperandsMask *imageOperands,
                               const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(image);
        blob->push_back(coordinate);
        if (imageOperands)
        {
            blob->push_back(*imageOperands);
        }
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageSparseFetch);
    }
    void WriteImageSparseGather(Blob *blob,
                                IdResultType idResultType,
                                IdResult idResult,
                                IdRef sampledImage,
                                IdRef coordinate,
                                IdRef component,
                                const spv::ImageOperandsMask *imageOperands,
                                const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        blob->push_back(component);
        if (imageOperands)
        {
            blob->push_back(*imageOperands);
        }
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageSparseGather);
    }
    void WriteImageSparseDrefGather(Blob *blob,
                                    IdResultType idResultType,
                                    IdResult idResult,
                                    IdRef sampledImage,
                                    IdRef coordinate,
                                    IdRef dref,
                                    const spv::ImageOperandsMask *imageOperands,
                                    const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(sampledImage);
        blob->push_back(coordinate);
        blob->push_back(dref);
        if (imageOperands)
        {
            blob->push_back(*imageOperands);
        }
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageSparseDrefGather);
    }
    void WriteImageSparseTexelsResident(Blob *blob,
                                        IdResultType idResultType,
                                        IdResult idResult,
                                        IdRef residentCode)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(residentCode);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageSparseTexelsResident);
    }
    void WriteNoLine(Blob *blob)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
    
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpNoLine);
    }
    void WriteImageSparseRead(Blob *blob,
                              IdResultType idResultType,
                              IdResult idResult,
                              IdRef image,
                              IdRef coordinate,
                              const spv::ImageOperandsMask *imageOperands,
                              const IdRefList &imageOperandIdsList)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(image);
        blob->push_back(coordinate);
        if (imageOperands)
        {
            blob->push_back(*imageOperands);
        }
        for (const auto &operand : imageOperandIdsList)
        {
            blob->push_back(operand);
        }
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpImageSparseRead);
    }
    void WriteGroupIAddNonUniformAMD(Blob *blob,
                                     IdResultType idResultType,
                                     IdResult idResult,
                                     IdScope execution,
                                     spv::GroupOperation operation,
                                     IdRef x)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(execution);
        blob->push_back(operation);
        blob->push_back(x);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupIAddNonUniformAMD);
    }
    void WriteGroupFAddNonUniformAMD(Blob *blob,
                                     IdResultType idResultType,
                                     IdResult idResult,
                                     IdScope execution,
                                     spv::GroupOperation operation,
                                     IdRef x)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(execution);
        blob->push_back(operation);
        blob->push_back(x);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupFAddNonUniformAMD);
    }
    void WriteGroupFMinNonUniformAMD(Blob *blob,
                                     IdResultType idResultType,
                                     IdResult idResult,
                                     IdScope execution,
                                     spv::GroupOperation operation,
                                     IdRef x)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(execution);
        blob->push_back(operation);
        blob->push_back(x);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupFMinNonUniformAMD);
    }
    void WriteGroupUMinNonUniformAMD(Blob *blob,
                                     IdResultType idResultType,
                                     IdResult idResult,
                                     IdScope execution,
                                     spv::GroupOperation operation,
                                     IdRef x)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(execution);
        blob->push_back(operation);
        blob->push_back(x);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupUMinNonUniformAMD);
    }
    void WriteGroupSMinNonUniformAMD(Blob *blob,
                                     IdResultType idResultType,
                                     IdResult idResult,
                                     IdScope execution,
                                     spv::GroupOperation operation,
                                     IdRef x)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(execution);
        blob->push_back(operation);
        blob->push_back(x);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupSMinNonUniformAMD);
    }
    void WriteGroupFMaxNonUniformAMD(Blob *blob,
                                     IdResultType idResultType,
                                     IdResult idResult,
                                     IdScope execution,
                                     spv::GroupOperation operation,
                                     IdRef x)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(execution);
        blob->push_back(operation);
        blob->push_back(x);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupFMaxNonUniformAMD);
    }
    void WriteGroupUMaxNonUniformAMD(Blob *blob,
                                     IdResultType idResultType,
                                     IdResult idResult,
                                     IdScope execution,
                                     spv::GroupOperation operation,
                                     IdRef x)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(execution);
        blob->push_back(operation);
        blob->push_back(x);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupUMaxNonUniformAMD);
    }
    void WriteGroupSMaxNonUniformAMD(Blob *blob,
                                     IdResultType idResultType,
                                     IdResult idResult,
                                     IdScope execution,
                                     spv::GroupOperation operation,
                                     IdRef x)
    {
        const size_t startSize = blob->size();
        blob->push_back(0);
        blob->push_back(idResultType);
        blob->push_back(idResult);
        blob->push_back(execution);
        blob->push_back(operation);
        blob->push_back(x);
        (*blob)[startSize] = MakeLengthOp(blob->size() - startSize, spv::OpGroupSMaxNonUniformAMD);
    }
    
    }  // namespace spirv
    }  // namespace angle