// Copyright 2023 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "src/tint/lang/spirv/writer/printer/printer.h"

#include <utility>

#include "spirv/unified1/GLSL.std.450.h"
#include "spirv/unified1/spirv.h"
#include "src/tint/lang/core/constant/scalar.h"
#include "src/tint/lang/core/constant/splat.h"
#include "src/tint/lang/core/fluent_types.h"
#include "src/tint/lang/core/ir/access.h"
#include "src/tint/lang/core/ir/binary.h"
#include "src/tint/lang/core/ir/bitcast.h"
#include "src/tint/lang/core/ir/block.h"
#include "src/tint/lang/core/ir/block_param.h"
#include "src/tint/lang/core/ir/break_if.h"
#include "src/tint/lang/core/ir/construct.h"
#include "src/tint/lang/core/ir/continue.h"
#include "src/tint/lang/core/ir/convert.h"
#include "src/tint/lang/core/ir/core_builtin_call.h"
#include "src/tint/lang/core/ir/exit_if.h"
#include "src/tint/lang/core/ir/exit_loop.h"
#include "src/tint/lang/core/ir/exit_switch.h"
#include "src/tint/lang/core/ir/if.h"
#include "src/tint/lang/core/ir/intrinsic_call.h"
#include "src/tint/lang/core/ir/let.h"
#include "src/tint/lang/core/ir/load.h"
#include "src/tint/lang/core/ir/load_vector_element.h"
#include "src/tint/lang/core/ir/loop.h"
#include "src/tint/lang/core/ir/module.h"
#include "src/tint/lang/core/ir/multi_in_block.h"
#include "src/tint/lang/core/ir/next_iteration.h"
#include "src/tint/lang/core/ir/return.h"
#include "src/tint/lang/core/ir/store.h"
#include "src/tint/lang/core/ir/store_vector_element.h"
#include "src/tint/lang/core/ir/switch.h"
#include "src/tint/lang/core/ir/swizzle.h"
#include "src/tint/lang/core/ir/terminate_invocation.h"
#include "src/tint/lang/core/ir/terminator.h"
#include "src/tint/lang/core/ir/unreachable.h"
#include "src/tint/lang/core/ir/user_call.h"
#include "src/tint/lang/core/ir/validator.h"
#include "src/tint/lang/core/ir/var.h"
#include "src/tint/lang/core/type/array.h"
#include "src/tint/lang/core/type/atomic.h"
#include "src/tint/lang/core/type/bool.h"
#include "src/tint/lang/core/type/depth_multisampled_texture.h"
#include "src/tint/lang/core/type/depth_texture.h"
#include "src/tint/lang/core/type/f16.h"
#include "src/tint/lang/core/type/f32.h"
#include "src/tint/lang/core/type/i32.h"
#include "src/tint/lang/core/type/matrix.h"
#include "src/tint/lang/core/type/multisampled_texture.h"
#include "src/tint/lang/core/type/pointer.h"
#include "src/tint/lang/core/type/sampled_texture.h"
#include "src/tint/lang/core/type/sampler.h"
#include "src/tint/lang/core/type/storage_texture.h"
#include "src/tint/lang/core/type/struct.h"
#include "src/tint/lang/core/type/texture.h"
#include "src/tint/lang/core/type/type.h"
#include "src/tint/lang/core/type/u32.h"
#include "src/tint/lang/core/type/vector.h"
#include "src/tint/lang/core/type/void.h"
#include "src/tint/lang/spirv/ir/intrinsic_call.h"
#include "src/tint/lang/spirv/type/sampled_image.h"
#include "src/tint/lang/spirv/writer/ast_printer/ast_printer.h"
#include "src/tint/lang/spirv/writer/common/module.h"
#include "src/tint/lang/spirv/writer/raise/builtin_polyfill.h"
#include "src/tint/utils/macros/scoped_assignment.h"
#include "src/tint/utils/rtti/switch.h"

using namespace tint::core::fluent_types;     // NOLINT
using namespace tint::core::number_suffixes;  // NOLINT

namespace tint::spirv::writer {
namespace {

constexpr uint32_t kWriterVersion = 1;

SpvStorageClass StorageClass(core::AddressSpace addrspace) {
    switch (addrspace) {
        case core::AddressSpace::kHandle:
            return SpvStorageClassUniformConstant;
        case core::AddressSpace::kFunction:
            return SpvStorageClassFunction;
        case core::AddressSpace::kIn:
            return SpvStorageClassInput;
        case core::AddressSpace::kPrivate:
            return SpvStorageClassPrivate;
        case core::AddressSpace::kPushConstant:
            return SpvStorageClassPushConstant;
        case core::AddressSpace::kOut:
            return SpvStorageClassOutput;
        case core::AddressSpace::kStorage:
            return SpvStorageClassStorageBuffer;
        case core::AddressSpace::kUniform:
            return SpvStorageClassUniform;
        case core::AddressSpace::kWorkgroup:
            return SpvStorageClassWorkgroup;
        default:
            return SpvStorageClassMax;
    }
}

const core::type::Type* DedupType(const core::type::Type* ty, core::type::Manager& types) {
    return Switch(
        ty,

        // Atomics are not a distinct type in SPIR-V.
        [&](const core::type::Atomic* atomic) { return atomic->Type(); },

        // Depth textures are always declared as sampled textures.
        [&](const core::type::DepthTexture* depth) {
            return types.Get<core::type::SampledTexture>(depth->dim(), types.f32());
        },
        [&](const core::type::DepthMultisampledTexture* depth) {
            return types.Get<core::type::MultisampledTexture>(depth->dim(), types.f32());
        },

        // Both sampler types are the same in SPIR-V.
        [&](const core::type::Sampler* s) -> const core::type::Type* {
            if (s->IsComparison()) {
                return types.Get<core::type::Sampler>(core::type::SamplerKind::kSampler);
            }
            return s;
        },

        // Dedup a SampledImage if its underlying image will be deduped.
        [&](const type::SampledImage* si) -> const core::type::Type* {
            auto* img = DedupType(si->Image(), types);
            if (img != si->Image()) {
                return types.Get<type::SampledImage>(img);
            }
            return si;
        },

        [&](Default) { return ty; });
}

}  // namespace

Printer::Printer(core::ir::Module* module, bool zero_init_workgroup_mem)
    : ir_(module), b_(*module), zero_init_workgroup_memory_(zero_init_workgroup_mem) {}

Result<std::vector<uint32_t>, std::string> Printer::Generate() {
    auto valid = core::ir::ValidateAndDumpIfNeeded(*ir_, "SPIR-V writer");
    if (!valid) {
        return std::move(valid.Failure());
    }

    // TODO(crbug.com/tint/1906): Check supported extensions.

    module_.PushCapability(SpvCapabilityShader);
    module_.PushMemoryModel(spv::Op::OpMemoryModel, {U32Operand(SpvAddressingModelLogical),
                                                     U32Operand(SpvMemoryModelGLSL450)});

    // TODO(crbug.com/tint/1906): Emit extensions.

    // Emit module-scope declarations.
    if (ir_->root_block) {
        EmitRootBlock(ir_->root_block);
    }

    // Emit functions.
    for (auto* func : ir_->functions) {
        EmitFunction(func);
    }

    // Serialize the module into binary SPIR-V.
    BinaryWriter writer;
    writer.WriteHeader(module_.IdBound(), kWriterVersion);
    writer.WriteModule(&module_);
    return std::move(writer.Result());
}

uint32_t Printer::Builtin(core::BuiltinValue builtin, core::AddressSpace addrspace) {
    switch (builtin) {
        case core::BuiltinValue::kPointSize:
            return SpvBuiltInPointSize;
        case core::BuiltinValue::kFragDepth:
            return SpvBuiltInFragDepth;
        case core::BuiltinValue::kFrontFacing:
            return SpvBuiltInFrontFacing;
        case core::BuiltinValue::kGlobalInvocationId:
            return SpvBuiltInGlobalInvocationId;
        case core::BuiltinValue::kInstanceIndex:
            return SpvBuiltInInstanceIndex;
        case core::BuiltinValue::kLocalInvocationId:
            return SpvBuiltInLocalInvocationId;
        case core::BuiltinValue::kLocalInvocationIndex:
            return SpvBuiltInLocalInvocationIndex;
        case core::BuiltinValue::kNumWorkgroups:
            return SpvBuiltInNumWorkgroups;
        case core::BuiltinValue::kPosition:
            if (addrspace == core::AddressSpace::kOut) {
                // Vertex output.
                return SpvBuiltInPosition;
            } else {
                // Fragment input.
                return SpvBuiltInFragCoord;
            }
        case core::BuiltinValue::kSampleIndex:
            module_.PushCapability(SpvCapabilitySampleRateShading);
            return SpvBuiltInSampleId;
        case core::BuiltinValue::kSampleMask:
            return SpvBuiltInSampleMask;
        case core::BuiltinValue::kSubgroupInvocationId:
            module_.PushCapability(SpvCapabilityGroupNonUniform);
            return SpvBuiltInSubgroupLocalInvocationId;
        case core::BuiltinValue::kSubgroupSize:
            module_.PushCapability(SpvCapabilityGroupNonUniform);
            return SpvBuiltInSubgroupSize;
        case core::BuiltinValue::kVertexIndex:
            return SpvBuiltInVertexIndex;
        case core::BuiltinValue::kWorkgroupId:
            return SpvBuiltInWorkgroupId;
        case core::BuiltinValue::kUndefined:
            return SpvBuiltInMax;
    }
    return SpvBuiltInMax;
}

uint32_t Printer::Constant(core::ir::Constant* constant) {
    // If it is a literal operand, just return the value.
    if (auto* literal = constant->As<raise::LiteralOperand>()) {
        return literal->Value()->ValueAs<uint32_t>();
    }

    auto id = Constant(constant->Value());

    // Set the name for the SPIR-V result ID if provided in the module.
    if (auto name = ir_->NameOf(constant)) {
        module_.PushDebug(spv::Op::OpName, {id, Operand(name.Name())});
    }

    return id;
}

uint32_t Printer::Constant(const core::constant::Value* constant) {
    return constants_.GetOrCreate(constant, [&] {
        auto id = module_.NextId();
        auto* ty = constant->Type();
        Switch(
            ty,  //
            [&](const core::type::Bool*) {
                module_.PushType(
                    constant->ValueAs<bool>() ? spv::Op::OpConstantTrue : spv::Op::OpConstantFalse,
                    {Type(ty), id});
            },
            [&](const core::type::I32*) {
                module_.PushType(spv::Op::OpConstant, {Type(ty), id, constant->ValueAs<u32>()});
            },
            [&](const core::type::U32*) {
                module_.PushType(spv::Op::OpConstant,
                                 {Type(ty), id, U32Operand(constant->ValueAs<i32>())});
            },
            [&](const core::type::F32*) {
                module_.PushType(spv::Op::OpConstant, {Type(ty), id, constant->ValueAs<f32>()});
            },
            [&](const core::type::F16*) {
                module_.PushType(
                    spv::Op::OpConstant,
                    {Type(ty), id, U32Operand(constant->ValueAs<f16>().BitsRepresentation())});
            },
            [&](const core::type::Vector* vec) {
                OperandList operands = {Type(ty), id};
                for (uint32_t i = 0; i < vec->Width(); i++) {
                    operands.push_back(Constant(constant->Index(i)));
                }
                module_.PushType(spv::Op::OpConstantComposite, operands);
            },
            [&](const core::type::Matrix* mat) {
                OperandList operands = {Type(ty), id};
                for (uint32_t i = 0; i < mat->columns(); i++) {
                    operands.push_back(Constant(constant->Index(i)));
                }
                module_.PushType(spv::Op::OpConstantComposite, operands);
            },
            [&](const core::type::Array* arr) {
                TINT_ASSERT(arr->ConstantCount());
                OperandList operands = {Type(ty), id};
                for (uint32_t i = 0; i < arr->ConstantCount(); i++) {
                    operands.push_back(Constant(constant->Index(i)));
                }
                module_.PushType(spv::Op::OpConstantComposite, operands);
            },
            [&](const core::type::Struct* str) {
                OperandList operands = {Type(ty), id};
                for (uint32_t i = 0; i < str->Members().Length(); i++) {
                    operands.push_back(Constant(constant->Index(i)));
                }
                module_.PushType(spv::Op::OpConstantComposite, operands);
            },
            [&](Default) { TINT_ICE() << "unhandled constant type: " << ty->FriendlyName(); });
        return id;
    });
}

uint32_t Printer::ConstantNull(const core::type::Type* type) {
    return constant_nulls_.GetOrCreate(type, [&] {
        auto id = module_.NextId();
        module_.PushType(spv::Op::OpConstantNull, {Type(type), id});
        return id;
    });
}

uint32_t Printer::Undef(const core::type::Type* type) {
    return undef_values_.GetOrCreate(type, [&] {
        auto id = module_.NextId();
        module_.PushType(spv::Op::OpUndef, {Type(type), id});
        return id;
    });
}

uint32_t Printer::Type(const core::type::Type* ty) {
    ty = DedupType(ty, ir_->Types());
    return types_.GetOrCreate(ty, [&] {
        auto id = module_.NextId();
        Switch(
            ty,  //
            [&](const core::type::Void*) { module_.PushType(spv::Op::OpTypeVoid, {id}); },
            [&](const core::type::Bool*) { module_.PushType(spv::Op::OpTypeBool, {id}); },
            [&](const core::type::I32*) {
                module_.PushType(spv::Op::OpTypeInt, {id, 32u, 1u});
            },
            [&](const core::type::U32*) {
                module_.PushType(spv::Op::OpTypeInt, {id, 32u, 0u});
            },
            [&](const core::type::F32*) {
                module_.PushType(spv::Op::OpTypeFloat, {id, 32u});
            },
            [&](const core::type::F16*) {
                module_.PushCapability(SpvCapabilityFloat16);
                module_.PushCapability(SpvCapabilityUniformAndStorageBuffer16BitAccess);
                module_.PushCapability(SpvCapabilityStorageBuffer16BitAccess);
                module_.PushCapability(SpvCapabilityStorageInputOutput16);
                module_.PushType(spv::Op::OpTypeFloat, {id, 16u});
            },
            [&](const core::type::Vector* vec) {
                module_.PushType(spv::Op::OpTypeVector, {id, Type(vec->type()), vec->Width()});
            },
            [&](const core::type::Matrix* mat) {
                module_.PushType(spv::Op::OpTypeMatrix,
                                 {id, Type(mat->ColumnType()), mat->columns()});
            },
            [&](const core::type::Array* arr) {
                if (arr->ConstantCount()) {
                    auto* count = b_.ConstantValue(u32(arr->ConstantCount().value()));
                    module_.PushType(spv::Op::OpTypeArray,
                                     {id, Type(arr->ElemType()), Constant(count)});
                } else {
                    TINT_ASSERT(arr->Count()->Is<core::type::RuntimeArrayCount>());
                    module_.PushType(spv::Op::OpTypeRuntimeArray, {id, Type(arr->ElemType())});
                }
                module_.PushAnnot(spv::Op::OpDecorate,
                                  {id, U32Operand(SpvDecorationArrayStride), arr->Stride()});
            },
            [&](const core::type::Pointer* ptr) {
                module_.PushType(
                    spv::Op::OpTypePointer,
                    {id, U32Operand(StorageClass(ptr->AddressSpace())), Type(ptr->StoreType())});
            },
            [&](const core::type::Struct* str) { EmitStructType(id, str); },
            [&](const core::type::Texture* tex) { EmitTextureType(id, tex); },
            [&](const core::type::Sampler*) { module_.PushType(spv::Op::OpTypeSampler, {id}); },
            [&](const type::SampledImage* s) {
                module_.PushType(spv::Op::OpTypeSampledImage, {id, Type(s->Image())});
            },
            [&](Default) { TINT_ICE() << "unhandled type: " << ty->FriendlyName(); });
        return id;
    });
}

uint32_t Printer::Value(core::ir::Instruction* inst) {
    return Value(inst->Result());
}

uint32_t Printer::Value(core::ir::Value* value) {
    return Switch(
        value,  //
        [&](core::ir::Constant* constant) { return Constant(constant); },
        [&](core::ir::Value*) {
            return values_.GetOrCreate(value, [&] { return module_.NextId(); });
        });
}

uint32_t Printer::Label(core::ir::Block* block) {
    return block_labels_.GetOrCreate(block, [&] { return module_.NextId(); });
}

void Printer::EmitStructType(uint32_t id, const core::type::Struct* str) {
    // Helper to return `type` or a potentially nested array element type within `type` as a matrix
    // type, or nullptr if no such matrix type is present.
    auto get_nested_matrix_type = [&](const core::type::Type* type) {
        while (auto* arr = type->As<core::type::Array>()) {
            type = arr->ElemType();
        }
        return type->As<core::type::Matrix>();
    };

    OperandList operands = {id};
    for (auto* member : str->Members()) {
        operands.push_back(Type(member->Type()));

        // Generate struct member offset decoration.
        module_.PushAnnot(
            spv::Op::OpMemberDecorate,
            {operands[0], member->Index(), U32Operand(SpvDecorationOffset), member->Offset()});

        // Emit matrix layout decorations if necessary.
        if (auto* matrix_type = get_nested_matrix_type(member->Type())) {
            const uint32_t effective_row_count = (matrix_type->rows() == 2) ? 2 : 4;
            module_.PushAnnot(spv::Op::OpMemberDecorate,
                              {id, member->Index(), U32Operand(SpvDecorationColMajor)});
            module_.PushAnnot(spv::Op::OpMemberDecorate,
                              {id, member->Index(), U32Operand(SpvDecorationMatrixStride),
                               Operand(effective_row_count * matrix_type->type()->Size())});
        }

        if (member->Name().IsValid()) {
            module_.PushDebug(spv::Op::OpMemberName,
                              {operands[0], member->Index(), Operand(member->Name().Name())});
        }
    }
    module_.PushType(spv::Op::OpTypeStruct, std::move(operands));

    // Add a Block decoration if necessary.
    if (str->StructFlags().Contains(core::type::StructFlag::kBlock)) {
        module_.PushAnnot(spv::Op::OpDecorate, {id, U32Operand(SpvDecorationBlock)});
    }

    if (str->Name().IsValid()) {
        module_.PushDebug(spv::Op::OpName, {operands[0], Operand(str->Name().Name())});
    }
}

void Printer::EmitTextureType(uint32_t id, const core::type::Texture* texture) {
    uint32_t sampled_type = Switch(
        texture,  //
        [&](const core::type::SampledTexture* t) { return Type(t->type()); },
        [&](const core::type::MultisampledTexture* t) { return Type(t->type()); },
        [&](const core::type::StorageTexture* t) { return Type(t->type()); },
        [&](Default) {
            TINT_ICE() << "unhandled texture type: " << texture->TypeInfo().name;
            return 0u;
        });

    uint32_t dim = SpvDimMax;
    uint32_t array = 0u;
    switch (texture->dim()) {
        case core::type::TextureDimension::kNone: {
            break;
        }
        case core::type::TextureDimension::k1d: {
            dim = SpvDim1D;
            if (texture->Is<core::type::SampledTexture>()) {
                module_.PushCapability(SpvCapabilitySampled1D);
            } else if (texture->Is<core::type::StorageTexture>()) {
                module_.PushCapability(SpvCapabilityImage1D);
            }
            break;
        }
        case core::type::TextureDimension::k2d: {
            dim = SpvDim2D;
            break;
        }
        case core::type::TextureDimension::k2dArray: {
            dim = SpvDim2D;
            array = 1u;
            break;
        }
        case core::type::TextureDimension::k3d: {
            dim = SpvDim3D;
            break;
        }
        case core::type::TextureDimension::kCube: {
            dim = SpvDimCube;
            break;
        }
        case core::type::TextureDimension::kCubeArray: {
            dim = SpvDimCube;
            array = 1u;
            if (texture->Is<core::type::SampledTexture>()) {
                module_.PushCapability(SpvCapabilitySampledCubeArray);
            }
            break;
        }
    }

    // The Vulkan spec says: The "Depth" operand of OpTypeImage is ignored.
    // In SPIRV, 0 means not depth, 1 means depth, and 2 means unknown.
    // Using anything other than 0 is problematic on various Vulkan drivers.
    uint32_t depth = 0u;

    uint32_t ms = 0u;
    if (texture->Is<core::type::MultisampledTexture>()) {
        ms = 1u;
    }

    uint32_t sampled = 2u;
    if (texture->IsAnyOf<core::type::MultisampledTexture, core::type::SampledTexture>()) {
        sampled = 1u;
    }

    uint32_t format = SpvImageFormat_::SpvImageFormatUnknown;
    if (auto* st = texture->As<core::type::StorageTexture>()) {
        format = TexelFormat(st->texel_format());
    }

    module_.PushType(spv::Op::OpTypeImage,
                     {id, sampled_type, dim, depth, array, ms, sampled, format});
}

void Printer::EmitFunction(core::ir::Function* func) {
    auto id = Value(func);

    // Emit the function name.
    module_.PushDebug(spv::Op::OpName, {id, Operand(ir_->NameOf(func).Name())});

    // Emit OpEntryPoint and OpExecutionMode declarations if needed.
    if (func->Stage() != core::ir::Function::PipelineStage::kUndefined) {
        EmitEntryPoint(func, id);
    }

    // Get the ID for the return type.
    auto return_type_id = Type(func->ReturnType());

    FunctionType function_type{return_type_id, {}};
    InstructionList params;

    // Generate function parameter declarations and add their type IDs to the function signature.
    for (auto* param : func->Params()) {
        auto param_type_id = Type(param->Type());
        auto param_id = Value(param);
        params.push_back(Instruction(spv::Op::OpFunctionParameter, {param_type_id, param_id}));
        function_type.param_type_ids.Push(param_type_id);
        if (auto name = ir_->NameOf(param)) {
            module_.PushDebug(spv::Op::OpName, {param_id, Operand(name.Name())});
        }
    }

    // Get the ID for the function type (creating it if needed).
    auto function_type_id = function_types_.GetOrCreate(function_type, [&] {
        auto func_ty_id = module_.NextId();
        OperandList operands = {func_ty_id, return_type_id};
        operands.insert(operands.end(), function_type.param_type_ids.begin(),
                        function_type.param_type_ids.end());
        module_.PushType(spv::Op::OpTypeFunction, operands);
        return func_ty_id;
    });

    // Declare the function.
    auto decl =
        Instruction{spv::Op::OpFunction,
                    {return_type_id, id, U32Operand(SpvFunctionControlMaskNone), function_type_id}};

    // Create a function that we will add instructions to.
    auto entry_block = module_.NextId();
    current_function_ = Function(decl, entry_block, std::move(params));
    TINT_DEFER(current_function_ = Function());

    // Emit the body of the function.
    EmitBlock(func->Block());

    // Add the function to the module.
    module_.PushFunction(current_function_);
}

void Printer::EmitEntryPoint(core::ir::Function* func, uint32_t id) {
    SpvExecutionModel stage = SpvExecutionModelMax;
    switch (func->Stage()) {
        case core::ir::Function::PipelineStage::kCompute: {
            stage = SpvExecutionModelGLCompute;
            module_.PushExecutionMode(
                spv::Op::OpExecutionMode,
                {id, U32Operand(SpvExecutionModeLocalSize), func->WorkgroupSize()->at(0),
                 func->WorkgroupSize()->at(1), func->WorkgroupSize()->at(2)});
            break;
        }
        case core::ir::Function::PipelineStage::kFragment: {
            stage = SpvExecutionModelFragment;
            module_.PushExecutionMode(spv::Op::OpExecutionMode,
                                      {id, U32Operand(SpvExecutionModeOriginUpperLeft)});
            break;
        }
        case core::ir::Function::PipelineStage::kVertex: {
            stage = SpvExecutionModelVertex;
            break;
        }
        case core::ir::Function::PipelineStage::kUndefined:
            TINT_ICE() << "undefined pipeline stage for entry point";
            return;
    }

    OperandList operands = {U32Operand(stage), id, ir_->NameOf(func).Name()};

    // Add the list of all referenced shader IO variables.
    if (ir_->root_block) {
        for (auto* global : *ir_->root_block) {
            auto* var = global->As<core::ir::Var>();
            if (!var) {
                continue;
            }

            auto* ptr = var->Result()->Type()->As<core::type::Pointer>();
            if (!(ptr->AddressSpace() == core::AddressSpace::kIn ||
                  ptr->AddressSpace() == core::AddressSpace::kOut)) {
                continue;
            }

            // Determine if this IO variable is used by the entry point.
            bool used = false;
            for (const auto& use : var->Result()->Usages()) {
                auto* block = use.instruction->Block();
                while (block->Parent()) {
                    block = block->Parent()->Block();
                }
                if (block == func->Block()) {
                    used = true;
                    break;
                }
            }
            if (!used) {
                continue;
            }
            operands.push_back(Value(var));

            // Add the `DepthReplacing` execution mode if `frag_depth` is used.
            if (var->Attributes().builtin == core::BuiltinValue::kFragDepth) {
                module_.PushExecutionMode(spv::Op::OpExecutionMode,
                                          {id, U32Operand(SpvExecutionModeDepthReplacing)});
            }
        }
    }

    module_.PushEntryPoint(spv::Op::OpEntryPoint, operands);
}

void Printer::EmitRootBlock(core::ir::Block* root_block) {
    for (auto* inst : *root_block) {
        Switch(
            inst,  //
            [&](core::ir::Var* v) { return EmitVar(v); },
            [&](Default) {
                TINT_ICE() << "unimplemented root block instruction: " << inst->TypeInfo().name;
            });
    }
}

void Printer::EmitBlock(core::ir::Block* block) {
    // Emit the label.
    // Skip if this is the function's entry block, as it will be emitted by the function object.
    if (!current_function_.instructions().empty()) {
        current_function_.push_inst(spv::Op::OpLabel, {Label(block)});
    }

    // If there are no instructions in the block, it's a dead end, so we shouldn't be able to get
    // here to begin with.
    if (block->IsEmpty()) {
        current_function_.push_inst(spv::Op::OpUnreachable, {});
        return;
    }

    if (auto* mib = block->As<core::ir::MultiInBlock>()) {
        // Emit all OpPhi nodes for incoming branches to block.
        EmitIncomingPhis(mib);
    }

    // Emit the block's statements.
    EmitBlockInstructions(block);
}

void Printer::EmitIncomingPhis(core::ir::MultiInBlock* block) {
    // Emit Phi nodes for all the incoming block parameters
    for (size_t param_idx = 0; param_idx < block->Params().Length(); param_idx++) {
        auto* param = block->Params()[param_idx];
        OperandList ops{Type(param->Type()), Value(param)};

        for (auto* incoming : block->InboundSiblingBranches()) {
            auto* arg = incoming->Args()[param_idx];
            ops.push_back(Value(arg));
            ops.push_back(GetTerminatorBlockLabel(incoming));
        }

        current_function_.push_inst(spv::Op::OpPhi, std::move(ops));
    }
}

void Printer::EmitBlockInstructions(core::ir::Block* block) {
    for (auto* inst : *block) {
        Switch(
            inst,                                                                 //
            [&](core::ir::Access* a) { EmitAccess(a); },                          //
            [&](core::ir::Binary* b) { EmitBinary(b); },                          //
            [&](core::ir::Bitcast* b) { EmitBitcast(b); },                        //
            [&](core::ir::CoreBuiltinCall* b) { EmitCoreBuiltinCall(b); },        //
            [&](spirv::ir::BuiltinCall* b) { EmitSpirvBuiltinCall(b); },          //
            [&](core::ir::Construct* c) { EmitConstruct(c); },                    //
            [&](core::ir::Convert* c) { EmitConvert(c); },                        //
            [&](spirv::ir::IntrinsicCall* i) { EmitIntrinsicCall(i); },           //
            [&](core::ir::Load* l) { EmitLoad(l); },                              //
            [&](core::ir::LoadVectorElement* l) { EmitLoadVectorElement(l); },    //
            [&](core::ir::Loop* l) { EmitLoop(l); },                              //
            [&](core::ir::Switch* sw) { EmitSwitch(sw); },                        //
            [&](core::ir::Swizzle* s) { EmitSwizzle(s); },                        //
            [&](core::ir::Store* s) { EmitStore(s); },                            //
            [&](core::ir::StoreVectorElement* s) { EmitStoreVectorElement(s); },  //
            [&](core::ir::UserCall* c) { EmitUserCall(c); },                      //
            [&](core::ir::Unary* u) { EmitUnary(u); },                            //
            [&](core::ir::Var* v) { EmitVar(v); },                                //
            [&](core::ir::Let* l) { EmitLet(l); },                                //
            [&](core::ir::If* i) { EmitIf(i); },                                  //
            [&](core::ir::Terminator* t) { EmitTerminator(t); },                  //
            [&](Default) { TINT_ICE() << "unimplemented instruction: " << inst->TypeInfo().name; });

        // Set the name for the SPIR-V result ID if provided in the module.
        if (inst->Result() && !inst->Is<core::ir::Var>()) {
            if (auto name = ir_->NameOf(inst)) {
                module_.PushDebug(spv::Op::OpName, {Value(inst), Operand(name.Name())});
            }
        }
    }

    if (block->IsEmpty()) {
        // If the last emitted instruction is not a branch, then this should be unreachable.
        current_function_.push_inst(spv::Op::OpUnreachable, {});
    }
}

void Printer::EmitTerminator(core::ir::Terminator* t) {
    tint::Switch(  //
        t,         //
        [&](core::ir::Return*) {
            if (!t->Args().IsEmpty()) {
                TINT_ASSERT(t->Args().Length() == 1u);
                OperandList operands;
                operands.push_back(Value(t->Args()[0]));
                current_function_.push_inst(spv::Op::OpReturnValue, operands);
            } else {
                current_function_.push_inst(spv::Op::OpReturn, {});
            }
            return;
        },
        [&](core::ir::BreakIf* breakif) {
            current_function_.push_inst(spv::Op::OpBranchConditional,
                                        {
                                            Value(breakif->Condition()),
                                            loop_merge_label_,
                                            loop_header_label_,
                                        });
        },
        [&](core::ir::Continue* cont) {
            current_function_.push_inst(spv::Op::OpBranch, {Label(cont->Loop()->Continuing())});
        },
        [&](core::ir::ExitIf*) {
            current_function_.push_inst(spv::Op::OpBranch, {if_merge_label_});
        },
        [&](core::ir::ExitLoop*) {
            current_function_.push_inst(spv::Op::OpBranch, {loop_merge_label_});
        },
        [&](core::ir::ExitSwitch*) {
            current_function_.push_inst(spv::Op::OpBranch, {switch_merge_label_});
        },
        [&](core::ir::NextIteration*) {
            current_function_.push_inst(spv::Op::OpBranch, {loop_header_label_});
        },
        [&](core::ir::TerminateInvocation*) { current_function_.push_inst(spv::Op::OpKill, {}); },
        [&](core::ir::Unreachable*) { current_function_.push_inst(spv::Op::OpUnreachable, {}); },

        [&](Default) { TINT_ICE() << "unimplemented branch: " << t->TypeInfo().name; });
}

void Printer::EmitIf(core::ir::If* i) {
    auto* true_block = i->True();
    auto* false_block = i->False();

    // Generate labels for the blocks. We emit the true or false block if it:
    // 1. contains instructions other then the branch, or
    // 2. branches somewhere instead of exiting the loop (e.g. return or break), or
    // 3. the if returns a value
    // Otherwise we skip them and branch straight to the merge block.
    uint32_t merge_label = GetMergeLabel(i);
    TINT_SCOPED_ASSIGNMENT(if_merge_label_, merge_label);

    uint32_t true_label = merge_label;
    uint32_t false_label = merge_label;
    if (true_block->Length() > 1 || i->HasResults() ||
        (true_block->HasTerminator() && !true_block->Terminator()->Is<core::ir::ExitIf>())) {
        true_label = Label(true_block);
    }
    if (false_block->Length() > 1 || i->HasResults() ||
        (false_block->HasTerminator() && !false_block->Terminator()->Is<core::ir::ExitIf>())) {
        false_label = Label(false_block);
    }

    // Emit the OpSelectionMerge and OpBranchConditional instructions.
    current_function_.push_inst(spv::Op::OpSelectionMerge,
                                {merge_label, U32Operand(SpvSelectionControlMaskNone)});
    current_function_.push_inst(spv::Op::OpBranchConditional,
                                {Value(i->Condition()), true_label, false_label});

    // Emit the `true` and `false` blocks, if they're not being skipped.
    if (true_label != merge_label) {
        EmitBlock(true_block);
    }
    if (false_label != merge_label) {
        EmitBlock(false_block);
    }

    current_function_.push_inst(spv::Op::OpLabel, {merge_label});

    // Emit the OpPhis for the ExitIfs
    EmitExitPhis(i);
}

void Printer::EmitAccess(core::ir::Access* access) {
    auto* ty = access->Result()->Type();

    auto id = Value(access);
    OperandList operands = {Type(ty), id, Value(access->Object())};

    if (ty->Is<core::type::Pointer>()) {
        // Use OpAccessChain for accesses into pointer types.
        for (auto* idx : access->Indices()) {
            operands.push_back(Value(idx));
        }
        current_function_.push_inst(spv::Op::OpAccessChain, std::move(operands));
        return;
    }

    // For non-pointer types, we assume that the indices are constants and use OpCompositeExtract.
    // If we hit a non-constant index into a vector type, use OpVectorExtractDynamic for it.
    auto* source_ty = access->Object()->Type();
    for (auto* idx : access->Indices()) {
        if (auto* constant = idx->As<core::ir::Constant>()) {
            // Push the index to the chain and update the current type.
            auto i = constant->Value()->ValueAs<u32>();
            operands.push_back(i);
            source_ty = source_ty->Element(i);
        } else {
            // The VarForDynamicIndex transform ensures that only value types that are vectors
            // will be dynamically indexed, as we can use OpVectorExtractDynamic for this case.
            TINT_ASSERT(source_ty->Is<core::type::Vector>());

            // If this wasn't the first access in the chain then emit the chain so far as an
            // OpCompositeExtract, creating a new result ID for the resulting vector.
            auto vec_id = Value(access->Object());
            if (operands.size() > 3) {
                vec_id = module_.NextId();
                operands[0] = Type(source_ty);
                operands[1] = vec_id;
                current_function_.push_inst(spv::Op::OpCompositeExtract, std::move(operands));
            }

            // Now emit the OpVectorExtractDynamic instruction.
            operands = {Type(ty), id, vec_id, Value(idx)};
            current_function_.push_inst(spv::Op::OpVectorExtractDynamic, std::move(operands));
            return;
        }
    }
    current_function_.push_inst(spv::Op::OpCompositeExtract, std::move(operands));
}

void Printer::EmitBinary(core::ir::Binary* binary) {
    auto id = Value(binary);
    auto lhs = Value(binary->LHS());
    auto rhs = Value(binary->RHS());
    auto* ty = binary->Result()->Type();
    auto* lhs_ty = binary->LHS()->Type();

    // Determine the opcode.
    spv::Op op = spv::Op::Max;
    switch (binary->Kind()) {
        case core::ir::Binary::Kind::kAdd: {
            op = ty->is_integer_scalar_or_vector() ? spv::Op::OpIAdd : spv::Op::OpFAdd;
            break;
        }
        case core::ir::Binary::Kind::kDivide: {
            if (ty->is_signed_integer_scalar_or_vector()) {
                op = spv::Op::OpSDiv;
            } else if (ty->is_unsigned_integer_scalar_or_vector()) {
                op = spv::Op::OpUDiv;
            } else if (ty->is_float_scalar_or_vector()) {
                op = spv::Op::OpFDiv;
            }
            break;
        }
        case core::ir::Binary::Kind::kMultiply: {
            if (ty->is_integer_scalar_or_vector()) {
                op = spv::Op::OpIMul;
            } else if (ty->is_float_scalar_or_vector()) {
                op = spv::Op::OpFMul;
            }
            break;
        }
        case core::ir::Binary::Kind::kSubtract: {
            op = ty->is_integer_scalar_or_vector() ? spv::Op::OpISub : spv::Op::OpFSub;
            break;
        }
        case core::ir::Binary::Kind::kModulo: {
            if (ty->is_signed_integer_scalar_or_vector()) {
                op = spv::Op::OpSRem;
            } else if (ty->is_unsigned_integer_scalar_or_vector()) {
                op = spv::Op::OpUMod;
            } else if (ty->is_float_scalar_or_vector()) {
                op = spv::Op::OpFRem;
            }
            break;
        }

        case core::ir::Binary::Kind::kAnd: {
            if (ty->is_integer_scalar_or_vector()) {
                op = spv::Op::OpBitwiseAnd;
            } else if (ty->is_bool_scalar_or_vector()) {
                op = spv::Op::OpLogicalAnd;
            }
            break;
        }
        case core::ir::Binary::Kind::kOr: {
            if (ty->is_integer_scalar_or_vector()) {
                op = spv::Op::OpBitwiseOr;
            } else if (ty->is_bool_scalar_or_vector()) {
                op = spv::Op::OpLogicalOr;
            }
            break;
        }
        case core::ir::Binary::Kind::kXor: {
            op = spv::Op::OpBitwiseXor;
            break;
        }

        case core::ir::Binary::Kind::kShiftLeft: {
            op = spv::Op::OpShiftLeftLogical;
            break;
        }
        case core::ir::Binary::Kind::kShiftRight: {
            if (ty->is_signed_integer_scalar_or_vector()) {
                op = spv::Op::OpShiftRightArithmetic;
            } else if (ty->is_unsigned_integer_scalar_or_vector()) {
                op = spv::Op::OpShiftRightLogical;
            }
            break;
        }

        case core::ir::Binary::Kind::kEqual: {
            if (lhs_ty->is_bool_scalar_or_vector()) {
                op = spv::Op::OpLogicalEqual;
            } else if (lhs_ty->is_float_scalar_or_vector()) {
                op = spv::Op::OpFOrdEqual;
            } else if (lhs_ty->is_integer_scalar_or_vector()) {
                op = spv::Op::OpIEqual;
            }
            break;
        }
        case core::ir::Binary::Kind::kNotEqual: {
            if (lhs_ty->is_bool_scalar_or_vector()) {
                op = spv::Op::OpLogicalNotEqual;
            } else if (lhs_ty->is_float_scalar_or_vector()) {
                op = spv::Op::OpFOrdNotEqual;
            } else if (lhs_ty->is_integer_scalar_or_vector()) {
                op = spv::Op::OpINotEqual;
            }
            break;
        }
        case core::ir::Binary::Kind::kGreaterThan: {
            if (lhs_ty->is_float_scalar_or_vector()) {
                op = spv::Op::OpFOrdGreaterThan;
            } else if (lhs_ty->is_signed_integer_scalar_or_vector()) {
                op = spv::Op::OpSGreaterThan;
            } else if (lhs_ty->is_unsigned_integer_scalar_or_vector()) {
                op = spv::Op::OpUGreaterThan;
            }
            break;
        }
        case core::ir::Binary::Kind::kGreaterThanEqual: {
            if (lhs_ty->is_float_scalar_or_vector()) {
                op = spv::Op::OpFOrdGreaterThanEqual;
            } else if (lhs_ty->is_signed_integer_scalar_or_vector()) {
                op = spv::Op::OpSGreaterThanEqual;
            } else if (lhs_ty->is_unsigned_integer_scalar_or_vector()) {
                op = spv::Op::OpUGreaterThanEqual;
            }
            break;
        }
        case core::ir::Binary::Kind::kLessThan: {
            if (lhs_ty->is_float_scalar_or_vector()) {
                op = spv::Op::OpFOrdLessThan;
            } else if (lhs_ty->is_signed_integer_scalar_or_vector()) {
                op = spv::Op::OpSLessThan;
            } else if (lhs_ty->is_unsigned_integer_scalar_or_vector()) {
                op = spv::Op::OpULessThan;
            }
            break;
        }
        case core::ir::Binary::Kind::kLessThanEqual: {
            if (lhs_ty->is_float_scalar_or_vector()) {
                op = spv::Op::OpFOrdLessThanEqual;
            } else if (lhs_ty->is_signed_integer_scalar_or_vector()) {
                op = spv::Op::OpSLessThanEqual;
            } else if (lhs_ty->is_unsigned_integer_scalar_or_vector()) {
                op = spv::Op::OpULessThanEqual;
            }
            break;
        }
    }

    // Emit the instruction.
    current_function_.push_inst(op, {Type(ty), id, lhs, rhs});
}

void Printer::EmitBitcast(core::ir::Bitcast* bitcast) {
    auto* ty = bitcast->Result()->Type();
    if (ty == bitcast->Val()->Type()) {
        values_.Add(bitcast->Result(), Value(bitcast->Val()));
        return;
    }
    current_function_.push_inst(spv::Op::OpBitcast,
                                {Type(ty), Value(bitcast), Value(bitcast->Val())});
}

void Printer::EmitSpirvBuiltinCall(spirv::ir::BuiltinCall* builtin) {
    auto id = Value(builtin);

    spv::Op op = spv::Op::Max;
    switch (builtin->Func()) {
        case spirv::ir::Function::kArrayLength:
            op = spv::Op::OpArrayLength;
            break;
        case spirv::ir::Function::kAtomicIadd:
            op = spv::Op::OpAtomicIAdd;
            break;
        case spirv::ir::Function::kAtomicIsub:
            op = spv::Op::OpAtomicISub;
            break;
        case spirv::ir::Function::kAtomicAnd:
            op = spv::Op::OpAtomicAnd;
            break;
        case spirv::ir::Function::kAtomicCompareExchange:
            op = spv::Op::OpAtomicCompareExchange;
            break;
        case spirv::ir::Function::kAtomicExchange:
            op = spv::Op::OpAtomicExchange;
            break;
        case spirv::ir::Function::kAtomicLoad:
            op = spv::Op::OpAtomicLoad;
            break;
        case spirv::ir::Function::kAtomicOr:
            op = spv::Op::OpAtomicOr;
            break;
        case spirv::ir::Function::kAtomicSmax:
            op = spv::Op::OpAtomicSMax;
            break;
        case spirv::ir::Function::kAtomicSmin:
            op = spv::Op::OpAtomicSMin;
            break;
        case spirv::ir::Function::kAtomicStore:
            op = spv::Op::OpAtomicStore;
            break;
        case spirv::ir::Function::kAtomicUmax:
            op = spv::Op::OpAtomicUMax;
            break;
        case spirv::ir::Function::kAtomicUmin:
            op = spv::Op::OpAtomicUMin;
            break;
        case spirv::ir::Function::kAtomicXor:
            op = spv::Op::OpAtomicXor;
            break;
        case spirv::ir::Function::kDot:
            op = spv::Op::OpDot;
            break;
        case spirv::ir::Function::kMatrixTimesMatrix:
            op = spv::Op::OpMatrixTimesMatrix;
            break;
        case spirv::ir::Function::kMatrixTimesScalar:
            op = spv::Op::OpMatrixTimesScalar;
            break;
        case spirv::ir::Function::kMatrixTimesVector:
            op = spv::Op::OpMatrixTimesVector;
            break;
        case spirv::ir::Function::kSampledImage:
            op = spv::Op::OpSampledImage;
            break;
        case spirv::ir::Function::kSelect:
            op = spv::Op::OpSelect;
            break;
        case spirv::ir::Function::kVectorTimesMatrix:
            op = spv::Op::OpVectorTimesMatrix;
            break;
        case spirv::ir::Function::kVectorTimesScalar:
            op = spv::Op::OpVectorTimesScalar;
            break;
        case spirv::ir::Function::kNone:
            TINT_ICE() << "undefined spirv ir function";
            return;
    }

    OperandList operands;
    if (!builtin->Result()->Type()->Is<core::type::Void>()) {
        operands = {Type(builtin->Result()->Type()), id};
    }
    for (auto* arg : builtin->Args()) {
        operands.push_back(Value(arg));
    }
    current_function_.push_inst(op, operands);
}

void Printer::EmitCoreBuiltinCall(core::ir::CoreBuiltinCall* builtin) {
    auto* result_ty = builtin->Result()->Type();

    if (builtin->Func() == core::Function::kAbs &&
        result_ty->is_unsigned_integer_scalar_or_vector()) {
        // abs() is a no-op for unsigned integers.
        values_.Add(builtin->Result(), Value(builtin->Args()[0]));
        return;
    }
    if ((builtin->Func() == core::Function::kAll || builtin->Func() == core::Function::kAny) &&
        builtin->Args()[0]->Type()->Is<core::type::Bool>()) {
        // all() and any() are passthroughs for scalar arguments.
        values_.Add(builtin->Result(), Value(builtin->Args()[0]));
        return;
    }

    auto id = Value(builtin);

    spv::Op op = spv::Op::Max;
    OperandList operands = {Type(result_ty), id};

    // Helper to set up the opcode and operand list for a GLSL extended instruction.
    auto glsl_ext_inst = [&](enum GLSLstd450 inst) {
        constexpr const char* kGLSLstd450 = "GLSL.std.450";
        op = spv::Op::OpExtInst;
        operands.push_back(imports_.GetOrCreate(kGLSLstd450, [&] {
            // Import the instruction set the first time it is requested.
            auto import = module_.NextId();
            module_.PushExtImport(spv::Op::OpExtInstImport, {import, Operand(kGLSLstd450)});
            return import;
        }));
        operands.push_back(U32Operand(inst));
    };

    // Determine the opcode.
    switch (builtin->Func()) {
        case core::Function::kAbs:
            if (result_ty->is_float_scalar_or_vector()) {
                glsl_ext_inst(GLSLstd450FAbs);
            } else if (result_ty->is_signed_integer_scalar_or_vector()) {
                glsl_ext_inst(GLSLstd450SAbs);
            }
            break;
        case core::Function::kAll:
            op = spv::Op::OpAll;
            break;
        case core::Function::kAny:
            op = spv::Op::OpAny;
            break;
        case core::Function::kAcos:
            glsl_ext_inst(GLSLstd450Acos);
            break;
        case core::Function::kAcosh:
            glsl_ext_inst(GLSLstd450Acosh);
            break;
        case core::Function::kAsin:
            glsl_ext_inst(GLSLstd450Asin);
            break;
        case core::Function::kAsinh:
            glsl_ext_inst(GLSLstd450Asinh);
            break;
        case core::Function::kAtan:
            glsl_ext_inst(GLSLstd450Atan);
            break;
        case core::Function::kAtan2:
            glsl_ext_inst(GLSLstd450Atan2);
            break;
        case core::Function::kAtanh:
            glsl_ext_inst(GLSLstd450Atanh);
            break;
        case core::Function::kClamp:
            if (result_ty->is_float_scalar_or_vector()) {
                glsl_ext_inst(GLSLstd450NClamp);
            } else if (result_ty->is_unsigned_integer_scalar_or_vector()) {
                glsl_ext_inst(GLSLstd450UClamp);
            } else if (result_ty->is_signed_integer_scalar_or_vector()) {
                glsl_ext_inst(GLSLstd450SClamp);
            }
            break;
        case core::Function::kCeil:
            glsl_ext_inst(GLSLstd450Ceil);
            break;
        case core::Function::kCos:
            glsl_ext_inst(GLSLstd450Cos);
            break;
        case core::Function::kCosh:
            glsl_ext_inst(GLSLstd450Cosh);
            break;
        case core::Function::kCountOneBits:
            op = spv::Op::OpBitCount;
            break;
        case core::Function::kCross:
            glsl_ext_inst(GLSLstd450Cross);
            break;
        case core::Function::kDegrees:
            glsl_ext_inst(GLSLstd450Degrees);
            break;
        case core::Function::kDeterminant:
            glsl_ext_inst(GLSLstd450Determinant);
            break;
        case core::Function::kDistance:
            glsl_ext_inst(GLSLstd450Distance);
            break;
        case core::Function::kDpdx:
            op = spv::Op::OpDPdx;
            break;
        case core::Function::kDpdxCoarse:
            module_.PushCapability(SpvCapabilityDerivativeControl);
            op = spv::Op::OpDPdxCoarse;
            break;
        case core::Function::kDpdxFine:
            module_.PushCapability(SpvCapabilityDerivativeControl);
            op = spv::Op::OpDPdxFine;
            break;
        case core::Function::kDpdy:
            op = spv::Op::OpDPdy;
            break;
        case core::Function::kDpdyCoarse:
            module_.PushCapability(SpvCapabilityDerivativeControl);
            op = spv::Op::OpDPdyCoarse;
            break;
        case core::Function::kDpdyFine:
            module_.PushCapability(SpvCapabilityDerivativeControl);
            op = spv::Op::OpDPdyFine;
            break;
        case core::Function::kExp:
            glsl_ext_inst(GLSLstd450Exp);
            break;
        case core::Function::kExp2:
            glsl_ext_inst(GLSLstd450Exp2);
            break;
        case core::Function::kExtractBits:
            op = result_ty->is_signed_integer_scalar_or_vector() ? spv::Op::OpBitFieldSExtract
                                                                 : spv::Op::OpBitFieldUExtract;
            break;
        case core::Function::kFaceForward:
            glsl_ext_inst(GLSLstd450FaceForward);
            break;
        case core::Function::kFloor:
            glsl_ext_inst(GLSLstd450Floor);
            break;
        case core::Function::kFma:
            glsl_ext_inst(GLSLstd450Fma);
            break;
        case core::Function::kFract:
            glsl_ext_inst(GLSLstd450Fract);
            break;
        case core::Function::kFrexp:
            glsl_ext_inst(GLSLstd450FrexpStruct);
            break;
        case core::Function::kFwidth:
            op = spv::Op::OpFwidth;
            break;
        case core::Function::kFwidthCoarse:
            module_.PushCapability(SpvCapabilityDerivativeControl);
            op = spv::Op::OpFwidthCoarse;
            break;
        case core::Function::kFwidthFine:
            module_.PushCapability(SpvCapabilityDerivativeControl);
            op = spv::Op::OpFwidthFine;
            break;
        case core::Function::kInsertBits:
            op = spv::Op::OpBitFieldInsert;
            break;
        case core::Function::kInverseSqrt:
            glsl_ext_inst(GLSLstd450InverseSqrt);
            break;
        case core::Function::kLdexp:
            glsl_ext_inst(GLSLstd450Ldexp);
            break;
        case core::Function::kLength:
            glsl_ext_inst(GLSLstd450Length);
            break;
        case core::Function::kLog:
            glsl_ext_inst(GLSLstd450Log);
            break;
        case core::Function::kLog2:
            glsl_ext_inst(GLSLstd450Log2);
            break;
        case core::Function::kMax:
            if (result_ty->is_float_scalar_or_vector()) {
                glsl_ext_inst(GLSLstd450FMax);
            } else if (result_ty->is_signed_integer_scalar_or_vector()) {
                glsl_ext_inst(GLSLstd450SMax);
            } else if (result_ty->is_unsigned_integer_scalar_or_vector()) {
                glsl_ext_inst(GLSLstd450UMax);
            }
            break;
        case core::Function::kMin:
            if (result_ty->is_float_scalar_or_vector()) {
                glsl_ext_inst(GLSLstd450FMin);
            } else if (result_ty->is_signed_integer_scalar_or_vector()) {
                glsl_ext_inst(GLSLstd450SMin);
            } else if (result_ty->is_unsigned_integer_scalar_or_vector()) {
                glsl_ext_inst(GLSLstd450UMin);
            }
            break;
        case core::Function::kMix:
            glsl_ext_inst(GLSLstd450FMix);
            break;
        case core::Function::kModf:
            glsl_ext_inst(GLSLstd450ModfStruct);
            break;
        case core::Function::kNormalize:
            glsl_ext_inst(GLSLstd450Normalize);
            break;
        case core::Function::kPack2X16Float:
            glsl_ext_inst(GLSLstd450PackHalf2x16);
            break;
        case core::Function::kPack2X16Snorm:
            glsl_ext_inst(GLSLstd450PackSnorm2x16);
            break;
        case core::Function::kPack2X16Unorm:
            glsl_ext_inst(GLSLstd450PackUnorm2x16);
            break;
        case core::Function::kPack4X8Snorm:
            glsl_ext_inst(GLSLstd450PackSnorm4x8);
            break;
        case core::Function::kPack4X8Unorm:
            glsl_ext_inst(GLSLstd450PackUnorm4x8);
            break;
        case core::Function::kPow:
            glsl_ext_inst(GLSLstd450Pow);
            break;
        case core::Function::kQuantizeToF16:
            op = spv::Op::OpQuantizeToF16;
            break;
        case core::Function::kRadians:
            glsl_ext_inst(GLSLstd450Radians);
            break;
        case core::Function::kReflect:
            glsl_ext_inst(GLSLstd450Reflect);
            break;
        case core::Function::kRefract:
            glsl_ext_inst(GLSLstd450Refract);
            break;
        case core::Function::kReverseBits:
            op = spv::Op::OpBitReverse;
            break;
        case core::Function::kRound:
            glsl_ext_inst(GLSLstd450RoundEven);
            break;
        case core::Function::kSign:
            if (result_ty->is_float_scalar_or_vector()) {
                glsl_ext_inst(GLSLstd450FSign);
            } else if (result_ty->is_signed_integer_scalar_or_vector()) {
                glsl_ext_inst(GLSLstd450SSign);
            }
            break;
        case core::Function::kSin:
            glsl_ext_inst(GLSLstd450Sin);
            break;
        case core::Function::kSinh:
            glsl_ext_inst(GLSLstd450Sinh);
            break;
        case core::Function::kSmoothstep:
            glsl_ext_inst(GLSLstd450SmoothStep);
            break;
        case core::Function::kSqrt:
            glsl_ext_inst(GLSLstd450Sqrt);
            break;
        case core::Function::kStep:
            glsl_ext_inst(GLSLstd450Step);
            break;
        case core::Function::kStorageBarrier:
            op = spv::Op::OpControlBarrier;
            operands.clear();
            operands.push_back(Constant(b_.ConstantValue(u32(spv::Scope::Workgroup))));
            operands.push_back(Constant(b_.ConstantValue(u32(spv::Scope::Workgroup))));
            operands.push_back(
                Constant(b_.ConstantValue(u32(spv::MemorySemanticsMask::UniformMemory |
                                              spv::MemorySemanticsMask::AcquireRelease))));
            break;
        case core::Function::kSubgroupBallot:
            module_.PushCapability(SpvCapabilityGroupNonUniformBallot);
            op = spv::Op::OpGroupNonUniformBallot;
            operands.push_back(Constant(ir_->constant_values.Get(u32(spv::Scope::Subgroup))));
            operands.push_back(Constant(ir_->constant_values.Get(true)));
            break;
        case core::Function::kTan:
            glsl_ext_inst(GLSLstd450Tan);
            break;
        case core::Function::kTanh:
            glsl_ext_inst(GLSLstd450Tanh);
            break;
        case core::Function::kTextureBarrier:
            op = spv::Op::OpControlBarrier;
            operands.clear();
            operands.push_back(Constant(b_.ConstantValue(u32(spv::Scope::Workgroup))));
            operands.push_back(Constant(b_.ConstantValue(u32(spv::Scope::Workgroup))));
            operands.push_back(
                Constant(b_.ConstantValue(u32(spv::MemorySemanticsMask::ImageMemory |
                                              spv::MemorySemanticsMask::AcquireRelease))));
            break;
        case core::Function::kTextureNumLevels:
            module_.PushCapability(SpvCapabilityImageQuery);
            op = spv::Op::OpImageQueryLevels;
            break;
        case core::Function::kTextureNumSamples:
            module_.PushCapability(SpvCapabilityImageQuery);
            op = spv::Op::OpImageQuerySamples;
            break;
        case core::Function::kTranspose:
            op = spv::Op::OpTranspose;
            break;
        case core::Function::kTrunc:
            glsl_ext_inst(GLSLstd450Trunc);
            break;
        case core::Function::kUnpack2X16Float:
            glsl_ext_inst(GLSLstd450UnpackHalf2x16);
            break;
        case core::Function::kUnpack2X16Snorm:
            glsl_ext_inst(GLSLstd450UnpackSnorm2x16);
            break;
        case core::Function::kUnpack2X16Unorm:
            glsl_ext_inst(GLSLstd450UnpackUnorm2x16);
            break;
        case core::Function::kUnpack4X8Snorm:
            glsl_ext_inst(GLSLstd450UnpackSnorm4x8);
            break;
        case core::Function::kUnpack4X8Unorm:
            glsl_ext_inst(GLSLstd450UnpackUnorm4x8);
            break;
        case core::Function::kWorkgroupBarrier:
            op = spv::Op::OpControlBarrier;
            operands.clear();
            operands.push_back(Constant(b_.ConstantValue(u32(spv::Scope::Workgroup))));
            operands.push_back(Constant(b_.ConstantValue(u32(spv::Scope::Workgroup))));
            operands.push_back(
                Constant(b_.ConstantValue(u32(spv::MemorySemanticsMask::WorkgroupMemory |
                                              spv::MemorySemanticsMask::AcquireRelease))));
            break;
        default:
            TINT_ICE() << "unimplemented builtin function: " << builtin->Func();
    }
    TINT_ASSERT(op != spv::Op::Max);

    // Add the arguments to the builtin call.
    for (auto* arg : builtin->Args()) {
        operands.push_back(Value(arg));
    }

    // Emit the instruction.
    current_function_.push_inst(op, operands);
}

void Printer::EmitConstruct(core::ir::Construct* construct) {
    // If there is just a single argument with the same type as the result, this is an identity
    // constructor and we can just pass through the ID of the argument.
    if (construct->Args().Length() == 1 &&
        construct->Result()->Type() == construct->Args()[0]->Type()) {
        values_.Add(construct->Result(), Value(construct->Args()[0]));
        return;
    }

    OperandList operands = {Type(construct->Result()->Type()), Value(construct)};
    for (auto* arg : construct->Args()) {
        operands.push_back(Value(arg));
    }
    current_function_.push_inst(spv::Op::OpCompositeConstruct, std::move(operands));
}

void Printer::EmitConvert(core::ir::Convert* convert) {
    auto* res_ty = convert->Result()->Type();
    auto* arg_ty = convert->Args()[0]->Type();

    OperandList operands = {Type(convert->Result()->Type()), Value(convert)};
    for (auto* arg : convert->Args()) {
        operands.push_back(Value(arg));
    }

    spv::Op op = spv::Op::Max;
    if (res_ty->is_signed_integer_scalar_or_vector() && arg_ty->is_float_scalar_or_vector()) {
        // float to signed int.
        op = spv::Op::OpConvertFToS;
    } else if (res_ty->is_unsigned_integer_scalar_or_vector() &&
               arg_ty->is_float_scalar_or_vector()) {
        // float to unsigned int.
        op = spv::Op::OpConvertFToU;
    } else if (res_ty->is_float_scalar_or_vector() &&
               arg_ty->is_signed_integer_scalar_or_vector()) {
        // signed int to float.
        op = spv::Op::OpConvertSToF;
    } else if (res_ty->is_float_scalar_or_vector() &&
               arg_ty->is_unsigned_integer_scalar_or_vector()) {
        // unsigned int to float.
        op = spv::Op::OpConvertUToF;
    } else if (res_ty->is_float_scalar_or_vector() && arg_ty->is_float_scalar_or_vector() &&
               res_ty->Size() != arg_ty->Size()) {
        // float to float (different bitwidth).
        op = spv::Op::OpFConvert;
    } else if (res_ty->is_integer_scalar_or_vector() && arg_ty->is_integer_scalar_or_vector() &&
               res_ty->Size() == arg_ty->Size()) {
        // int to int (same bitwidth, different signedness).
        op = spv::Op::OpBitcast;
    } else if (res_ty->is_bool_scalar_or_vector()) {
        if (arg_ty->is_integer_scalar_or_vector()) {
            // int to bool.
            op = spv::Op::OpINotEqual;
        } else {
            // float to bool.
            op = spv::Op::OpFUnordNotEqual;
        }
        operands.push_back(ConstantNull(arg_ty));
    } else if (arg_ty->is_bool_scalar_or_vector()) {
        // Select between constant one and zero, splatting them to vectors if necessary.
        core::ir::Constant* one = nullptr;
        core::ir::Constant* zero = nullptr;
        Switch(
            res_ty->DeepestElement(),  //
            [&](const core::type::F32*) {
                one = b_.Constant(1_f);
                zero = b_.Constant(0_f);
            },
            [&](const core::type::F16*) {
                one = b_.Constant(1_h);
                zero = b_.Constant(0_h);
            },
            [&](const core::type::I32*) {
                one = b_.Constant(1_i);
                zero = b_.Constant(0_i);
            },
            [&](const core::type::U32*) {
                one = b_.Constant(1_u);
                zero = b_.Constant(0_u);
            });
        TINT_ASSERT_OR_RETURN(one && zero);

        if (auto* vec = res_ty->As<core::type::Vector>()) {
            // Splat the scalars into vectors.
            one = b_.Splat(vec, one, vec->Width());
            zero = b_.Splat(vec, zero, vec->Width());
        }

        op = spv::Op::OpSelect;
        operands.push_back(Constant(b_.ConstantValue(one)));
        operands.push_back(Constant(b_.ConstantValue(zero)));
    } else {
        TINT_ICE() << "unhandled convert instruction";
    }

    current_function_.push_inst(op, std::move(operands));
}

void Printer::EmitIntrinsicCall(spirv::ir::IntrinsicCall* call) {
    auto id = Value(call);

    spv::Op op = spv::Op::Max;
    switch (call->Kind()) {
        case spirv::ir::Intrinsic::kImageFetch:
            op = spv::Op::OpImageFetch;
            break;
        case spirv::ir::Intrinsic::kImageGather:
            op = spv::Op::OpImageGather;
            break;
        case spirv::ir::Intrinsic::kImageDrefGather:
            op = spv::Op::OpImageDrefGather;
            break;
        case spirv::ir::Intrinsic::kImageQuerySize:
            module_.PushCapability(SpvCapabilityImageQuery);
            op = spv::Op::OpImageQuerySize;
            break;
        case spirv::ir::Intrinsic::kImageQuerySizeLod:
            module_.PushCapability(SpvCapabilityImageQuery);
            op = spv::Op::OpImageQuerySizeLod;
            break;
        case spirv::ir::Intrinsic::kImageRead:
            op = spv::Op::OpImageRead;
            break;
        case spirv::ir::Intrinsic::kImageSampleImplicitLod:
            op = spv::Op::OpImageSampleImplicitLod;
            break;
        case spirv::ir::Intrinsic::kImageSampleExplicitLod:
            op = spv::Op::OpImageSampleExplicitLod;
            break;
        case spirv::ir::Intrinsic::kImageSampleDrefImplicitLod:
            op = spv::Op::OpImageSampleDrefImplicitLod;
            break;
        case spirv::ir::Intrinsic::kImageSampleDrefExplicitLod:
            op = spv::Op::OpImageSampleDrefExplicitLod;
            break;
        case spirv::ir::Intrinsic::kImageWrite:
            op = spv::Op::OpImageWrite;
            break;
        case spirv::ir::Intrinsic::kUndefined:
            TINT_ICE() << "undefined spirv intrinsic";
            return;
    }

    OperandList operands;
    if (!call->Result()->Type()->Is<core::type::Void>()) {
        operands = {Type(call->Result()->Type()), id};
    }
    for (auto* arg : call->Args()) {
        operands.push_back(Value(arg));
    }
    current_function_.push_inst(op, operands);
}

void Printer::EmitLoad(core::ir::Load* load) {
    current_function_.push_inst(spv::Op::OpLoad,
                                {Type(load->Result()->Type()), Value(load), Value(load->From())});
}

void Printer::EmitLoadVectorElement(core::ir::LoadVectorElement* load) {
    auto* vec_ptr_ty = load->From()->Type()->As<core::type::Pointer>();
    auto* el_ty = load->Result()->Type();
    auto* el_ptr_ty = ir_->Types().ptr(vec_ptr_ty->AddressSpace(), el_ty, vec_ptr_ty->Access());
    auto el_ptr_id = module_.NextId();
    current_function_.push_inst(
        spv::Op::OpAccessChain,
        {Type(el_ptr_ty), el_ptr_id, Value(load->From()), Value(load->Index())});
    current_function_.push_inst(spv::Op::OpLoad,
                                {Type(load->Result()->Type()), Value(load), el_ptr_id});
}

void Printer::EmitLoop(core::ir::Loop* loop) {
    auto init_label = loop->HasInitializer() ? Label(loop->Initializer()) : 0;
    auto body_label = Label(loop->Body());
    auto continuing_label = Label(loop->Continuing());

    auto header_label = module_.NextId();
    TINT_SCOPED_ASSIGNMENT(loop_header_label_, header_label);

    auto merge_label = GetMergeLabel(loop);
    TINT_SCOPED_ASSIGNMENT(loop_merge_label_, merge_label);

    if (init_label != 0) {
        // Emit the loop initializer.
        current_function_.push_inst(spv::Op::OpBranch, {init_label});
        EmitBlock(loop->Initializer());
    } else {
        // No initializer. Branch to body.
        current_function_.push_inst(spv::Op::OpBranch, {header_label});
    }

    // Emit the loop body header, which contains the OpLoopMerge and OpPhis.
    // This then unconditionally branches to body_label
    current_function_.push_inst(spv::Op::OpLabel, {header_label});
    EmitIncomingPhis(loop->Body());
    current_function_.push_inst(
        spv::Op::OpLoopMerge, {merge_label, continuing_label, U32Operand(SpvLoopControlMaskNone)});
    current_function_.push_inst(spv::Op::OpBranch, {body_label});

    // Emit the loop body
    current_function_.push_inst(spv::Op::OpLabel, {body_label});
    EmitBlockInstructions(loop->Body());

    // Emit the loop continuing block.
    if (loop->Continuing()->HasTerminator()) {
        EmitBlock(loop->Continuing());
    } else {
        // We still need to emit a continuing block with a back-edge, even if it is unreachable.
        current_function_.push_inst(spv::Op::OpLabel, {continuing_label});
        current_function_.push_inst(spv::Op::OpBranch, {header_label});
    }

    // Emit the loop merge block.
    current_function_.push_inst(spv::Op::OpLabel, {merge_label});

    // Emit the OpPhis for the ExitLoops
    EmitExitPhis(loop);
}

void Printer::EmitSwitch(core::ir::Switch* swtch) {
    // Find the default selector. There must be exactly one.
    uint32_t default_label = 0u;
    for (auto& c : swtch->Cases()) {
        for (auto& sel : c.selectors) {
            if (sel.IsDefault()) {
                default_label = Label(c.Block());
            }
        }
    }
    TINT_ASSERT(default_label != 0u);

    // Build the operands to the OpSwitch instruction.
    OperandList switch_operands = {Value(swtch->Condition()), default_label};
    for (auto& c : swtch->Cases()) {
        auto label = Label(c.Block());
        for (auto& sel : c.selectors) {
            if (sel.IsDefault()) {
                continue;
            }
            switch_operands.push_back(sel.val->Value()->ValueAs<uint32_t>());
            switch_operands.push_back(label);
        }
    }

    uint32_t merge_label = GetMergeLabel(swtch);
    TINT_SCOPED_ASSIGNMENT(switch_merge_label_, merge_label);

    // Emit the OpSelectionMerge and OpSwitch instructions.
    current_function_.push_inst(spv::Op::OpSelectionMerge,
                                {merge_label, U32Operand(SpvSelectionControlMaskNone)});
    current_function_.push_inst(spv::Op::OpSwitch, switch_operands);

    // Emit the cases.
    for (auto& c : swtch->Cases()) {
        EmitBlock(c.Block());
    }

    // Emit the switch merge block.
    current_function_.push_inst(spv::Op::OpLabel, {merge_label});

    // Emit the OpPhis for the ExitSwitches
    EmitExitPhis(swtch);
}

void Printer::EmitSwizzle(core::ir::Swizzle* swizzle) {
    auto id = Value(swizzle);
    auto obj = Value(swizzle->Object());
    OperandList operands = {Type(swizzle->Result()->Type()), id, obj, obj};
    for (auto idx : swizzle->Indices()) {
        operands.push_back(idx);
    }
    current_function_.push_inst(spv::Op::OpVectorShuffle, operands);
}

void Printer::EmitStore(core::ir::Store* store) {
    current_function_.push_inst(spv::Op::OpStore, {Value(store->To()), Value(store->From())});
}

void Printer::EmitStoreVectorElement(core::ir::StoreVectorElement* store) {
    auto* vec_ptr_ty = store->To()->Type()->As<core::type::Pointer>();
    auto* el_ty = store->Value()->Type();
    auto* el_ptr_ty = ir_->Types().ptr(vec_ptr_ty->AddressSpace(), el_ty, vec_ptr_ty->Access());
    auto el_ptr_id = module_.NextId();
    current_function_.push_inst(
        spv::Op::OpAccessChain,
        {Type(el_ptr_ty), el_ptr_id, Value(store->To()), Value(store->Index())});
    current_function_.push_inst(spv::Op::OpStore, {el_ptr_id, Value(store->Value())});
}

void Printer::EmitUnary(core::ir::Unary* unary) {
    auto id = Value(unary);
    auto* ty = unary->Result()->Type();
    spv::Op op = spv::Op::Max;
    switch (unary->Kind()) {
        case core::ir::Unary::Kind::kComplement:
            op = spv::Op::OpNot;
            break;
        case core::ir::Unary::Kind::kNegation:
            if (ty->is_float_scalar_or_vector()) {
                op = spv::Op::OpFNegate;
            } else if (ty->is_signed_integer_scalar_or_vector()) {
                op = spv::Op::OpSNegate;
            }
            break;
    }
    current_function_.push_inst(op, {Type(ty), id, Value(unary->Val())});
}

void Printer::EmitUserCall(core::ir::UserCall* call) {
    auto id = Value(call);
    OperandList operands = {Type(call->Result()->Type()), id, Value(call->Func())};
    for (auto* arg : call->Args()) {
        operands.push_back(Value(arg));
    }
    current_function_.push_inst(spv::Op::OpFunctionCall, operands);
}

void Printer::EmitIOAttributes(uint32_t id,
                               const core::ir::IOAttributes& attrs,
                               core::AddressSpace addrspace) {
    if (attrs.location) {
        module_.PushAnnot(spv::Op::OpDecorate,
                          {id, U32Operand(SpvDecorationLocation), *attrs.location});
    }
    if (attrs.index) {
        module_.PushAnnot(spv::Op::OpDecorate, {id, U32Operand(SpvDecorationIndex), *attrs.index});
    }
    if (attrs.interpolation) {
        switch (attrs.interpolation->type) {
            case core::InterpolationType::kLinear:
                module_.PushAnnot(spv::Op::OpDecorate,
                                  {id, U32Operand(SpvDecorationNoPerspective)});
                break;
            case core::InterpolationType::kFlat:
                module_.PushAnnot(spv::Op::OpDecorate, {id, U32Operand(SpvDecorationFlat)});
                break;
            case core::InterpolationType::kPerspective:
            case core::InterpolationType::kUndefined:
                break;
        }
        switch (attrs.interpolation->sampling) {
            case core::InterpolationSampling::kCentroid:
                module_.PushAnnot(spv::Op::OpDecorate, {id, U32Operand(SpvDecorationCentroid)});
                break;
            case core::InterpolationSampling::kSample:
                module_.PushCapability(SpvCapabilitySampleRateShading);
                module_.PushAnnot(spv::Op::OpDecorate, {id, U32Operand(SpvDecorationSample)});
                break;
            case core::InterpolationSampling::kCenter:
            case core::InterpolationSampling::kUndefined:
                break;
        }
    }
    if (attrs.builtin) {
        module_.PushAnnot(spv::Op::OpDecorate, {id, U32Operand(SpvDecorationBuiltIn),
                                                Builtin(*attrs.builtin, addrspace)});
    }
    if (attrs.invariant) {
        module_.PushAnnot(spv::Op::OpDecorate, {id, U32Operand(SpvDecorationInvariant)});
    }
}

void Printer::EmitVar(core::ir::Var* var) {
    auto id = Value(var);
    auto* ptr = var->Result()->Type()->As<core::type::Pointer>();
    auto* store_ty = ptr->StoreType();
    auto ty = Type(ptr);

    switch (ptr->AddressSpace()) {
        case core::AddressSpace::kFunction: {
            TINT_ASSERT(current_function_);
            if (var->Initializer()) {
                current_function_.push_var({ty, id, U32Operand(SpvStorageClassFunction)});
                current_function_.push_inst(spv::Op::OpStore, {id, Value(var->Initializer())});
            } else {
                current_function_.push_var(
                    {ty, id, U32Operand(SpvStorageClassFunction), ConstantNull(store_ty)});
            }
            break;
        }
        case core::AddressSpace::kIn: {
            TINT_ASSERT(!current_function_);
            module_.PushType(spv::Op::OpVariable, {ty, id, U32Operand(SpvStorageClassInput)});
            EmitIOAttributes(id, var->Attributes(), core::AddressSpace::kIn);
            break;
        }
        case core::AddressSpace::kPrivate: {
            TINT_ASSERT(!current_function_);
            OperandList operands = {ty, id, U32Operand(SpvStorageClassPrivate)};
            if (var->Initializer()) {
                TINT_ASSERT(var->Initializer()->Is<core::ir::Constant>());
                operands.push_back(Value(var->Initializer()));
            } else {
                operands.push_back(ConstantNull(store_ty));
            }
            module_.PushType(spv::Op::OpVariable, operands);
            break;
        }
        case core::AddressSpace::kPushConstant: {
            TINT_ASSERT(!current_function_);
            module_.PushType(spv::Op::OpVariable,
                             {ty, id, U32Operand(SpvStorageClassPushConstant)});
            break;
        }
        case core::AddressSpace::kOut: {
            TINT_ASSERT(!current_function_);
            module_.PushType(spv::Op::OpVariable, {ty, id, U32Operand(SpvStorageClassOutput)});
            EmitIOAttributes(id, var->Attributes(), core::AddressSpace::kOut);
            break;
        }
        case core::AddressSpace::kHandle:
        case core::AddressSpace::kStorage:
        case core::AddressSpace::kUniform: {
            TINT_ASSERT(!current_function_);
            module_.PushType(spv::Op::OpVariable,
                             {ty, id, U32Operand(StorageClass(ptr->AddressSpace()))});
            auto bp = var->BindingPoint().value();
            module_.PushAnnot(spv::Op::OpDecorate,
                              {id, U32Operand(SpvDecorationDescriptorSet), bp.group});
            module_.PushAnnot(spv::Op::OpDecorate,
                              {id, U32Operand(SpvDecorationBinding), bp.binding});

            // Add NonReadable and NonWritable decorations to storage textures and buffers.
            auto* st = store_ty->As<core::type::StorageTexture>();
            if (st || store_ty->Is<core::type::Struct>()) {
                auto access = st ? st->access() : ptr->Access();
                if (access == core::Access::kRead) {
                    module_.PushAnnot(spv::Op::OpDecorate,
                                      {id, U32Operand(SpvDecorationNonWritable)});
                } else if (access == core::Access::kWrite) {
                    module_.PushAnnot(spv::Op::OpDecorate,
                                      {id, U32Operand(SpvDecorationNonReadable)});
                }
            }
            break;
        }
        case core::AddressSpace::kWorkgroup: {
            TINT_ASSERT(!current_function_);
            OperandList operands = {ty, id, U32Operand(SpvStorageClassWorkgroup)};
            if (zero_init_workgroup_memory_) {
                // If requested, use the VK_KHR_zero_initialize_workgroup_memory to zero-initialize
                // the workgroup variable using an null constant initializer.
                operands.push_back(ConstantNull(store_ty));
            }
            module_.PushType(spv::Op::OpVariable, operands);
            break;
        }
        default: {
            TINT_ICE() << "unimplemented variable address space " << ptr->AddressSpace();
        }
    }

    // Set the name if present.
    if (auto name = ir_->NameOf(var)) {
        module_.PushDebug(spv::Op::OpName, {id, Operand(name.Name())});
    }
}

void Printer::EmitLet(core::ir::Let* let) {
    auto id = Value(let->Value());
    values_.Add(let->Result(), id);
}

void Printer::EmitExitPhis(core::ir::ControlInstruction* inst) {
    struct Branch {
        uint32_t label = 0;
        core::ir::Value* value = nullptr;
        bool operator<(const Branch& other) const { return label < other.label; }
    };

    auto results = inst->Results();
    for (size_t index = 0; index < results.Length(); index++) {
        auto* result = results[index];
        auto* ty = result->Type();

        Vector<Branch, 8> branches;
        branches.Reserve(inst->Exits().Count());
        for (auto& exit : inst->Exits()) {
            branches.Push(Branch{GetTerminatorBlockLabel(exit), exit->Args()[index]});
        }
        branches.Sort();  // Sort the branches by label to ensure deterministic output

        OperandList ops{Type(ty), Value(result)};
        for (auto& branch : branches) {
            if (branch.value == nullptr) {
                ops.push_back(Undef(ty));
            } else {
                ops.push_back(Value(branch.value));
            }
            ops.push_back(branch.label);
        }
        current_function_.push_inst(spv::Op::OpPhi, std::move(ops));
    }
}

uint32_t Printer::GetMergeLabel(core::ir::ControlInstruction* ci) {
    return merge_block_labels_.GetOrCreate(ci, [&] { return module_.NextId(); });
}

uint32_t Printer::GetTerminatorBlockLabel(core::ir::Terminator* t) {
    // Walk backwards from `t` until we find a control instruction.
    auto* inst = t->prev;
    while (inst) {
        auto* prev = inst->prev;
        if (auto* ci = inst->As<core::ir::ControlInstruction>()) {
            // This is the last control instruction before `t`, so use its merge block label.
            return GetMergeLabel(ci);
        }
        inst = prev;
    }

    // There were no control instructions before `t`, so use the label of the parent block.
    return Label(t->Block());
}

uint32_t Printer::TexelFormat(const core::TexelFormat format) {
    switch (format) {
        case core::TexelFormat::kBgra8Unorm:
            TINT_ICE() << "bgra8unorm should have been polyfilled to rgba8unorm";
            return SpvImageFormatUnknown;
        case core::TexelFormat::kR32Uint:
            return SpvImageFormatR32ui;
        case core::TexelFormat::kR32Sint:
            return SpvImageFormatR32i;
        case core::TexelFormat::kR32Float:
            return SpvImageFormatR32f;
        case core::TexelFormat::kRgba8Unorm:
            return SpvImageFormatRgba8;
        case core::TexelFormat::kRgba8Snorm:
            return SpvImageFormatRgba8Snorm;
        case core::TexelFormat::kRgba8Uint:
            return SpvImageFormatRgba8ui;
        case core::TexelFormat::kRgba8Sint:
            return SpvImageFormatRgba8i;
        case core::TexelFormat::kRg32Uint:
            module_.PushCapability(SpvCapabilityStorageImageExtendedFormats);
            return SpvImageFormatRg32ui;
        case core::TexelFormat::kRg32Sint:
            module_.PushCapability(SpvCapabilityStorageImageExtendedFormats);
            return SpvImageFormatRg32i;
        case core::TexelFormat::kRg32Float:
            module_.PushCapability(SpvCapabilityStorageImageExtendedFormats);
            return SpvImageFormatRg32f;
        case core::TexelFormat::kRgba16Uint:
            return SpvImageFormatRgba16ui;
        case core::TexelFormat::kRgba16Sint:
            return SpvImageFormatRgba16i;
        case core::TexelFormat::kRgba16Float:
            return SpvImageFormatRgba16f;
        case core::TexelFormat::kRgba32Uint:
            return SpvImageFormatRgba32ui;
        case core::TexelFormat::kRgba32Sint:
            return SpvImageFormatRgba32i;
        case core::TexelFormat::kRgba32Float:
            return SpvImageFormatRgba32f;
        case core::TexelFormat::kUndefined:
            return SpvImageFormatUnknown;
    }
    return SpvImageFormatUnknown;
}

}  // namespace tint::spirv::writer
