// 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/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 raise::SampledImage* si) -> const core::type::Type* {
            auto* img = DedupType(si->Image(), types);
            if (img != si->Image()) {
                return types.Get<raise::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 raise::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::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::kSampledImage:
            op = spv::Op::OpSampledImage;
            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
