// Copyright 2023 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "src/tint/lang/spirv/reader/parser/parser.h"

#include <algorithm>
#include <list>
#include <memory>
#include <optional>
#include <span>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#include "src/tint/utils/ice/ice.h"
#include "src/utils/numeric.h"

#define SPV_ENABLE_UTILITY_CODE
#include "spirv/unified1/spirv.hpp11"

// This header is in an external dependency, so warnings cannot be fixed without upstream changes.
TINT_BEGIN_DISABLE_WARNING(NEWLINE_EOF);
TINT_BEGIN_DISABLE_WARNING(OLD_STYLE_CAST);
TINT_BEGIN_DISABLE_WARNING(SIGN_CONVERSION);
TINT_BEGIN_DISABLE_WARNING(WEAK_VTABLES);
TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
TINT_BEGIN_DISABLE_WARNING(LIFETIME_SAFETY_INVALIDATION);
#include "source/opt/build_module.h"
#include "source/opt/resolve_binding_conflicts_pass.h"
#include "source/opt/split_combined_image_sampler_pass.h"
TINT_END_DISABLE_WARNING(LIFETIME_SAFETY_INVALIDATION);
TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
TINT_END_DISABLE_WARNING(WEAK_VTABLES);
TINT_END_DISABLE_WARNING(SIGN_CONVERSION);
TINT_END_DISABLE_WARNING(OLD_STYLE_CAST);
TINT_END_DISABLE_WARNING(NEWLINE_EOF);

#include "src/tint/lang/core/ir/builder.h"
#include "src/tint/lang/core/ir/module.h"
#include "src/tint/lang/core/ir/referenced_module_vars.h"
#include "src/tint/lang/core/type/builtin_structs.h"
#include "src/tint/lang/spirv/builtin_fn.h"
#include "src/tint/lang/spirv/ir/builtin_call.h"
#include "src/tint/lang/spirv/type/explicit_layout_array.h"
#include "src/tint/lang/spirv/type/image.h"
#include "src/tint/lang/spirv/type/literal.h"
#include "src/tint/lang/spirv/type/sampled_image.h"
#include "src/tint/lang/spirv/validate/validate.h"

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

namespace tint::spirv::reader {

namespace {

// Stores information for operands which need to be calculated after a block is complete. Because
// a phi can store values which come after it, we can't calculate the value when the `OpPhi` is
// seen.
struct ReplacementValue {
    // The terminator instruction the operand belongs to
    core::ir::Terminator* terminator;
    // The operand index in `terminator` to replace
    uint32_t idx;
    // The SPIR-V value id to create the value from
    uint32_t value_id;
};

/// The SPIR-V environment that we validate against.
constexpr auto kTargetEnv = SPV_ENV_VULKAN_1_1;

/// PIMPL class for SPIR-V parser.
/// Validates the SPIR-V module and then parses it to produce a Tint IR module.
class Parser {
  public:
    explicit Parser(const Options& options) : options_(options) {}
    ~Parser() = default;

    /// @param spirv the SPIR-V binary data
    /// @returns the generated SPIR-V IR module on success, or failure
    Result<core::ir::Module> Run(std::span<const uint32_t> spirv) {
        // Validate the incoming SPIR-V binary.
        validate::Options options{
            .target_env = kTargetEnv,
            .uniform_buffer_standard_layout = true,
        };
        TINT_CHECK_RESULT(validate::Validate(spirv, options));

        // Build the SPIR-V tools internal representation of the SPIR-V module.
        spvtools::Context context(kTargetEnv);
        spirv_context_ = spvtools::BuildModule(kTargetEnv, context.CContext()->consumer,
                                               spirv.data(), spirv.size());
        if (!spirv_context_) {
            return Failure("failed to build the internal representation of the module");
        }

        // Run SPIR-V opt transforms to make the input friendlier for the SPIR-V frontend.
        {
            spvtools::opt::SplitCombinedImageSamplerPass pass;
            auto status = pass.Run(spirv_context_.get());
            if (status == spvtools::opt::Pass::Status::Failure) {
                return Failure("failed to run SplitCombinedImageSamplerPass in SPIR-V opt");
            }
        }
        if (options_.sampler_mappings.empty()) {
            spvtools::opt::ResolveBindingConflictsPass pass;
            auto status = pass.Run(spirv_context_.get());
            if (status == spvtools::opt::Pass::Status::Failure) {
                return Failure("failed to run ResolveBindingConflictsPass in SPIR-V opt");
            }
        }

        // Check for unsupported extensions.
        for (const auto& ext : spirv_context_->extensions()) {
            auto name = ext.GetOperand(0).AsString();
            if (name != "SPV_KHR_storage_buffer_storage_class" &&
                name != "SPV_KHR_non_semantic_info" &&     //
                name != "SPV_KHR_16bit_storage" &&         //
                name != "SPV_KHR_terminate_invocation" &&  //
                // TODO(423644565): We assume the barriers are correct. We should check for any
                // operation that makes barrier assumptions that aren't consistent with WGSL and
                // generate the needed barriers.
                name != "SPV_KHR_vulkan_memory_model") {
                return Failure("SPIR-V extension '" + name + "' is not supported");
            }
        }

        // Check for unsupported capabilities.
        for (auto it = spirv_context_->capability_begin(); it != spirv_context_->capability_end();
             ++it) {
            auto capability = static_cast<spv::Capability>(it->GetSingleWordInOperand(0));
            switch (capability) {
                case spv::Capability::ClipDistance:
                case spv::Capability::DerivativeControl:
                case spv::Capability::Float16:
                case spv::Capability::Geometry:
                case spv::Capability::GroupNonUniform:
                case spv::Capability::GroupNonUniformArithmetic:
                case spv::Capability::GroupNonUniformBallot:
                case spv::Capability::GroupNonUniformQuad:
                case spv::Capability::GroupNonUniformShuffle:
                case spv::Capability::GroupNonUniformShuffleRelative:
                case spv::Capability::GroupNonUniformVote:
                case spv::Capability::Image1D:
                case spv::Capability::ImageQuery:
                case spv::Capability::InputAttachment:
                case spv::Capability::Matrix:
                case spv::Capability::Sampled1D:
                case spv::Capability::SampledCubeArray:
                case spv::Capability::SampleRateShading:
                case spv::Capability::Shader:
                case spv::Capability::StorageBuffer16BitAccess:
                case spv::Capability::StorageImageExtendedFormats:
                case spv::Capability::StorageInputOutput16:
                case spv::Capability::StoragePushConstant16:
                case spv::Capability::UniformAndStorageBuffer16BitAccess:
                case spv::Capability::VulkanMemoryModel:
                case spv::Capability::VulkanMemoryModelDeviceScope:
                    // Supported
                    break;
                default:
                    return Failure("SPIR-V capability '" +
                                   std::string(spv::CapabilityToString(capability)) +
                                   "' is not supported");
            }
        }

        // Check for unsupported types.
        for (const auto& type : *spirv_context_->get_type_mgr()) {
            switch (type.second->kind()) {
                case spvtools::opt::analysis::Type::kArray: {
                    auto kind = type.second->AsArray()->element_type()->kind();
                    if (kind == spvtools::opt::analysis::Type::kImage ||
                        kind == spvtools::opt::analysis::Type::kSampler) {
                        return Failure("arrays of handle types are not supported");
                    }
                    break;
                }
                case spvtools::opt::analysis::Type::kImage: {
                    auto* img = type.second->AsImage();
                    if (img->is_arrayed() && img->is_multisampled()) {
                        return Failure("arrayed multisampled images are not supported");
                    }
                    break;
                }
                default:
                    break;
            }
        }

        // Register imported instruction sets
        for (const auto& import : spirv_context_->ext_inst_imports()) {
            auto name = import.GetInOperand(0).AsString();

            if (name == "GLSL.std.450") {
                glsl_std_450_imports_.insert(import.result_id());
            } else if (name.find("NonSemantic.") == 0) {
                ignored_imports_.insert(import.result_id());
            } else {
                return Failure("Unrecognized extended instruction set: " + name);
            }
        }

        // Set properties that are supported by the SPIR-V parser.
        ir_.properties.Add(core::ir::Property::kAllowLocationForNumericComposites);
        ir_.properties.Add(core::ir::Property::kAllowMultipleEntryPoints);
        ir_.properties.Add(core::ir::Property::kAllowNonCoreTypes);
        ir_.properties.Add(core::ir::Property::kAllowOverrides);
        ir_.properties.Add(core::ir::Property::kAllowPhonyInstructions);
        ir_.properties.Add(core::ir::Property::kAllowPointSizeBuiltin);
        ir_.properties.Add(core::ir::Property::kAllowPointerToHandle);
        ir_.properties.Add(core::ir::Property::kAllowStructMatrixDecorations);
        ir_.properties.Add(core::ir::Property::kAllowUnannotatedModuleIOVariables);
        ir_.properties.Add(core::ir::Property::kAllowVectorElementPointer);
        ir_.properties.Add(core::ir::Property::kAllowBackendSpecificShaderIO);
        ir_.properties.Add(core::ir::Property::kAllow16BitFloats);

        RegisterNames();

        id_stack_.emplace_back();
        {
            TINT_SCOPED_ASSIGNMENT(current_block_, ir_.root_block);
            EmitSpecConstants();
            TINT_CHECK_RESULT(EmitModuleScopeVariables());
        }

        TINT_CHECK_RESULT(EmitFunctions());
        TINT_CHECK_RESULT(EmitEntryPointAttributes());

        RemapSamplers();
        RemapBufferBlockAddressSpace();
        AddRefToOutputsIfNeeded();

        return std::move(ir_);
    }

    // If the spir-v struct was marked as `BufferBlock` then we always treat this as a storage
    // address space. We do this as a post-pass because we have to propagate the change through all
    // the types that derive from the buffer block, e.g. any access needs to change from `Uniform`
    // to `Storage` address space.
    void RemapBufferBlockAddressSpace() {
        for (auto* inst : *ir_.root_block) {
            auto* var = inst->As<core::ir::Var>();
            if (!var) {
                continue;
            }

            auto* ptr = var->Result()->Type()->As<core::type::Pointer>();
            TINT_ASSERT(ptr);

            auto* str = ptr->UnwrapPtr()->As<core::type::Struct>();
            if (!str) {
                continue;
            }
            if (!storage_buffer_types_.contains(str)) {
                continue;
            }
            auto iter = var_to_original_access_mode_.find(var);
            TINT_ASSERT(iter != var_to_original_access_mode_.end());
            auto access_mode = iter->second;

            // Handle the case of the struct members all being marked as `NonWritable`
            if (consider_non_writable_.contains(str)) {
                access_mode = core::Access::kRead;
            }

            // Storage buffer can not be `write` only
            if (access_mode == core::Access::kWrite) {
                access_mode = core::Access::kReadWrite;
            }

            var->Result()->SetType(ty_.ptr(core::AddressSpace::kStorage, str, access_mode));
            UpdateUsagesToStorageAddressSpace(var->Result(), access_mode);
        }
    }

    void UpdateUsagesToStorageAddressSpace(core::ir::Value* val, core::Access access_mode) {
        for (auto& usage : val->UsagesUnsorted()) {
            if (usage->instruction->Results().IsEmpty()) {
                continue;
            }

            auto* res = usage->instruction->Result();
            auto* ptr = res->Type()->As<core::type::Pointer>();
            if (!ptr) {
                continue;
            }
            TINT_ASSERT(ptr->AddressSpace() == core::AddressSpace::kUniform);

            res->SetType(ty_.ptr(core::AddressSpace::kStorage, ptr->StoreType(), access_mode));
            UpdateUsagesToStorageAddressSpace(res, access_mode);
        }
    }

    void AddRefToOutputsIfNeeded() {
        for (auto& entry_point : spirv_context_->module()->entry_points()) {
            uint32_t spv_id = entry_point.GetSingleWordInOperand(1);
            TINT_ASSERT(functions_.Contains(spv_id));

            auto* func = *(functions_.Get(spv_id));
            for (uint32_t i = 3; i < entry_point.NumInOperands(); ++i) {
                auto* val = Value(entry_point.GetSingleWordInOperand(i));
                b_.Phony(val)->InsertBefore(func->Block()->Front());
            }
        }
    }

    void RemapSamplers() {
        for (auto* inst : *ir_.root_block) {
            auto* var = inst->As<core::ir::Var>();
            if (!var) {
                continue;
            }
            auto* ptr = var->Result()->Type()->As<core::type::Pointer>();
            TINT_ASSERT(ptr);

            if (!ptr->StoreType()->As<core::type::Sampler>()) {
                continue;
            }

            TINT_ASSERT(var->BindingPoint().has_value());

            auto bp = var->BindingPoint().value();
            auto used = used_bindings.GetOrAddZero(bp);

            // Only one use is the sampler itself.
            if (used == 1) {
                continue;
            }

            auto& binding = max_binding.GetOrAddZero(bp.group);
            binding += 1;

            var->SetBindingPoint(bp.group, binding);
        }
    }

    std::optional<uint16_t> GetSpecId(const spvtools::opt::Instruction& inst) {
        auto decos =
            spirv_context_->get_decoration_mgr()->GetDecorationsFor(inst.result_id(), true);
        for (const auto* deco_inst : decos) {
            TINT_ASSERT(deco_inst->opcode() == spv::Op::OpDecorate);

            if (deco_inst->GetSingleWordInOperand(1) ==
                static_cast<uint32_t>(spv::Decoration::SpecId)) {
                return {static_cast<uint16_t>(deco_inst->GetSingleWordInOperand(2))};
            }
        }
        return std::nullopt;
    }

    void CreateOverride(const spvtools::opt::Instruction& inst,
                        core::ir::Value* value,
                        std::optional<uint16_t> spec_id) {
        auto* override_ = b_.Override(Type(inst.type_id()));
        override_->SetInitializer(value);

        if (spec_id.has_value()) {
            override_->SetOverrideId(OverrideId{spec_id.value()});
        }

        Emit(override_, inst.result_id());

        Symbol name = GetSymbolFor(inst.result_id());
        if (name.IsValid()) {
            ir_.SetName(override_, name);
        }
    }

    // Generate a module-scope const declaration for each instruction
    // that is OpSpecConstantTrue, OpSpecConstantFalse, or OpSpecConstant.
    void EmitSpecConstants() {
        for (auto& inst : spirv_context_->types_values()) {
            switch (inst.opcode()) {
                case spv::Op::OpSpecConstantTrue:
                case spv::Op::OpSpecConstantFalse: {
                    auto* value = b_.Value(inst.opcode() == spv::Op::OpSpecConstantTrue);
                    auto spec_id = GetSpecId(inst);

                    if (spec_id.has_value()) {
                        CreateOverride(inst, value, spec_id);
                    } else {
                        // No spec_id means treat this as a constant.
                        AddValue(inst.result_id(), value);
                    }
                    break;
                }
                case spv::Op::OpSpecConstant: {
                    auto literal = inst.GetSingleWordInOperand(0);
                    auto* ty = spirv_context_->get_type_mgr()->GetType(inst.type_id());

                    auto* constant =
                        spirv_context_->get_constant_mgr()->GetConstant(ty, std::vector{literal});

                    core::ir::Value* value = tint::Switch(
                        Type(spirv_context_->get_type_mgr()->GetId(ty)),  //
                        [&](const core::type::I32*) {
                            return b_.Constant(i32(constant->GetS32()));
                        },
                        [&](const core::type::U32*) {
                            return b_.Constant(u32(constant->GetU32()));
                        },
                        [&](const core::type::F32*) {
                            return b_.Constant(f32(constant->GetFloat()));
                        },
                        [&](const core::type::F16*) {
                            auto bits = constant->AsScalarConstant()->GetU32BitValue();
                            return b_.Constant(f16::FromBits(static_cast<uint16_t>(bits)));
                        },
                        TINT_ICE_ON_NO_MATCH);

                    auto spec_id = GetSpecId(inst);
                    CreateOverride(inst, value, spec_id);
                    break;
                }
                case spv::Op::OpSpecConstantOp: {
                    auto op = inst.GetSingleWordInOperand(0);

                    // Store the name away and remove it from the name list.
                    // This keeps any `Emit*` call in the switch below for
                    // gaining the name we want associated to the override.
                    std::string name;
                    auto iter = id_to_name_.find(inst.result_id());
                    if (iter != id_to_name_.end()) {
                        name = iter->second;
                        id_to_name_.erase(inst.result_id());
                    }

                    switch (static_cast<spv::Op>(op)) {
                        case spv::Op::OpBitwiseAnd:
                            EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kBitwiseAnd, 3);
                            break;
                        case spv::Op::OpBitwiseOr:
                            EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kBitwiseOr, 3);
                            break;
                        case spv::Op::OpBitwiseXor:
                            EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kBitwiseXor, 3);
                            break;
                        case spv::Op::OpIEqual:
                            EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kEqual, 3);
                            break;
                        case spv::Op::OpINotEqual:
                            EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kNotEqual, 3);
                            break;
                        case spv::Op::OpSGreaterThan:
                            EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kSGreaterThan, 3);
                            break;
                        case spv::Op::OpSGreaterThanEqual:
                            EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kSGreaterThanEqual, 3);
                            break;
                        case spv::Op::OpSLessThan:
                            EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kSLessThan, 3);
                            break;
                        case spv::Op::OpSLessThanEqual:
                            EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kSLessThanEqual, 3);
                            break;
                        case spv::Op::OpUGreaterThan:
                            EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kUGreaterThan, 3);
                            break;
                        case spv::Op::OpUGreaterThanEqual:
                            EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kUGreaterThanEqual, 3);
                            break;
                        case spv::Op::OpULessThan:
                            EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kULessThan, 3);
                            break;
                        case spv::Op::OpULessThanEqual:
                            EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kULessThanEqual, 3);
                            break;
                        case spv::Op::OpLogicalAnd:
                            EmitBinary(inst, core::BinaryOp::kAnd, 3);
                            break;
                        case spv::Op::OpLogicalOr:
                            EmitBinary(inst, core::BinaryOp::kOr, 3);
                            break;
                        case spv::Op::OpLogicalNot:
                            EmitUnary(inst, core::UnaryOp::kNot, 3);
                            break;
                        case spv::Op::OpLogicalEqual:
                            EmitBinary(inst, core::BinaryOp::kEqual, 3);
                            break;
                        case spv::Op::OpLogicalNotEqual:
                            EmitBinary(inst, core::BinaryOp::kNotEqual, 3);
                            break;
                        case spv::Op::OpNot:
                            EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kNot, 3);
                            break;
                        case spv::Op::OpSConvert:
                            TINT_ICE() << "can't translate SConvert: WGSL does not have concrete "
                                          "integer types of different widths";
                        case spv::Op::OpUConvert:
                            TINT_ICE() << "can't translate UConvert: WGSL does not have concrete "
                                          "integer types of different widths";
                        case spv::Op::OpFConvert:
                            EmitOrAdd(b_.Convert(Type(inst.type_id()),
                                                 Value(inst.GetSingleWordInOperand(1))),
                                      inst.result_id());
                            break;
                        case spv::Op::OpSNegate:
                            EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kSNegate, 3);
                            break;
                        case spv::Op::OpIAdd:
                            EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kAdd, 3);
                            break;
                        case spv::Op::OpISub:
                            EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kSub, 3);
                            break;
                        case spv::Op::OpIMul:
                            EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kMul, 3);
                            break;
                        case spv::Op::OpSDiv:
                            EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kSDiv, 3);
                            break;
                        case spv::Op::OpUDiv:
                            EmitBinary(inst, core::BinaryOp::kDivide, 3);
                            break;
                        case spv::Op::OpUMod:
                            EmitBinary(inst, core::BinaryOp::kModulo, 3);
                            break;
                        case spv::Op::OpSMod:
                        case spv::Op::OpSRem:
                            EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kSMod, 3);
                            break;
                        case spv::Op::OpShiftLeftLogical:
                            EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kShiftLeftLogical,
                                                         3);
                            break;
                        case spv::Op::OpShiftRightLogical:
                            EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kShiftRightLogical,
                                                         3);
                            break;
                        case spv::Op::OpShiftRightArithmetic:
                            EmitSpirvExplicitBuiltinCall(
                                inst, spirv::BuiltinFn::kShiftRightArithmetic, 3);
                            break;
                        case spv::Op::OpCompositeExtract:
                            EmitCompositeExtract(inst, 3);
                            break;
                        case spv::Op::OpCompositeInsert:
                            TINT_ICE() << "can't translate OpSpecConstantOp with CompositeInsert: "
                                          "OpSpecConstantOp maps to a WGSL override declaration, "
                                          "but WGSL overrides must have scalar type";
                        case spv::Op::OpVectorShuffle:
                            TINT_ICE() << "can't translate OpSpecConstantOp with VectorShuffle: "
                                          "OpSpecConstantOp maps to a WGSL override declaration, "
                                          "but WGSL overrides must have scalar type";
                        case spv::Op::OpSelect:
                            TINT_ASSERT(Type(inst.type_id())->IsScalar())
                                << "can't translate OpSpecConstantOp with Select that returns "
                                   "a vector: "
                                   "OpSpecConstantOp maps to a WGSL override declaration, "
                                   "but WGSL overrides must have scalar type";
                            EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kSelect, 3);
                            break;
                        default:
                            TINT_ICE() << "Unknown spec constant operation: " << op;
                    }

                    // Restore the saved name, if any, in order to provide that
                    // name to the override.
                    if (!name.empty()) {
                        id_to_name_.insert({inst.result_id(), name});
                    }

                    CreateOverride(inst, Value(inst.result_id()), std::nullopt);
                    break;
                }
                case spv::Op::OpSpecConstantComposite: {
                    auto spec_id = GetSpecId(inst);
                    TINT_ASSERT(!spec_id.has_value())
                        << "OpSpecConstantCompositeOp not supported when set with a SpecId";

                    auto* cnst = SpvConstant(inst.result_id());
                    if (cnst != nullptr) {
                        // The spec constant is made of literals, so it's return as a constant from
                        // SPIR-V Tools Opt. We can just ignore it and let the normal constant
                        // handling take over.
                        break;
                    }

                    Vector<uint32_t, 4> args;
                    args.Reserve(inst.NumInOperands());

                    for (uint32_t i = 0; i < inst.NumInOperands(); ++i) {
                        uint32_t id = inst.GetSingleWordInOperand(i);
                        args.Push(id);
                    }

                    spec_composites_.insert({inst.result_id(), SpecComposite{
                                                                   .type = Type(inst.type_id()),
                                                                   .args = args,
                                                               }});
                    break;
                }
                default:
                    break;
            }
        }
    }

    void RegisterNames() {
        // Register names from OpName
        for (const auto& inst : spirv_context_->debugs2()) {
            switch (inst.opcode()) {
                case spv::Op::OpName: {
                    const auto name = inst.GetInOperand(1).AsString();
                    if (!name.empty()) {
                        id_to_name_[inst.GetSingleWordInOperand(0)] = name;
                    }
                    break;
                }
                case spv::Op::OpMemberName: {
                    const auto name = inst.GetInOperand(2).AsString();
                    if (!name.empty()) {
                        uint32_t struct_id = inst.GetSingleWordInOperand(0);
                        uint32_t member_idx = inst.GetSingleWordInOperand(1);
                        auto iter = struct_to_member_names_.insert({struct_id, {}});
                        auto& members = (*(iter.first)).second;

                        if (members.size() < (member_idx + 1)) {
                            members.resize(member_idx + 1);
                        }
                        members[member_idx] = name;
                    }
                    break;
                }
                default:
                    break;
            }
        }
    }

    /// @param sc a SPIR-V storage class
    /// @returns the Tint address space for a SPIR-V storage class
    core::AddressSpace AddressSpace(spv::StorageClass sc) {
        switch (sc) {
            case spv::StorageClass::Input:
                return core::AddressSpace::kIn;
            case spv::StorageClass::Output:
                return core::AddressSpace::kOut;
            case spv::StorageClass::Function:
                return core::AddressSpace::kFunction;
            case spv::StorageClass::Private:
                return core::AddressSpace::kPrivate;
            case spv::StorageClass::StorageBuffer:
                return core::AddressSpace::kStorage;
            case spv::StorageClass::Uniform:
                return core::AddressSpace::kUniform;
            case spv::StorageClass::UniformConstant:
                return core::AddressSpace::kHandle;
            case spv::StorageClass::Workgroup:
                return core::AddressSpace::kWorkgroup;
            case spv::StorageClass::PushConstant:
                return core::AddressSpace::kImmediate;
            default:
                TINT_UNIMPLEMENTED()
                    << "unhandled SPIR-V storage class: " << static_cast<uint32_t>(sc);
        }
    }

    /// @param b a SPIR-V BuiltIn
    /// @returns the Tint builtin value for a SPIR-V BuiltIn decoration
    Result<core::BuiltinValue> Builtin(spv::BuiltIn b) {
        switch (b) {
            case spv::BuiltIn::FragCoord:
                return core::BuiltinValue::kPosition;
            case spv::BuiltIn::FragDepth:
                return core::BuiltinValue::kFragDepth;
            case spv::BuiltIn::FrontFacing:
                return core::BuiltinValue::kFrontFacing;
            case spv::BuiltIn::GlobalInvocationId:
                return core::BuiltinValue::kGlobalInvocationId;
            case spv::BuiltIn::InstanceIndex:
                return core::BuiltinValue::kInstanceIndex;
            case spv::BuiltIn::LocalInvocationId:
                return core::BuiltinValue::kLocalInvocationId;
            case spv::BuiltIn::LocalInvocationIndex:
                return core::BuiltinValue::kLocalInvocationIndex;
            case spv::BuiltIn::NumWorkgroups:
                return core::BuiltinValue::kNumWorkgroups;
            case spv::BuiltIn::PointSize:
                return core::BuiltinValue::kPointSize;
            case spv::BuiltIn::Position:
                return core::BuiltinValue::kPosition;
            case spv::BuiltIn::SampleId:
                return core::BuiltinValue::kSampleIndex;
            case spv::BuiltIn::SampleMask:
                return core::BuiltinValue::kSampleMask;
            case spv::BuiltIn::SubgroupId:
                return core::BuiltinValue::kSubgroupId;
            case spv::BuiltIn::SubgroupSize:
                return core::BuiltinValue::kSubgroupSize;
            case spv::BuiltIn::SubgroupLocalInvocationId:
                return core::BuiltinValue::kSubgroupInvocationId;
            case spv::BuiltIn::NumSubgroups:
                return core::BuiltinValue::kNumSubgroups;
            case spv::BuiltIn::VertexIndex:
                return core::BuiltinValue::kVertexIndex;
            case spv::BuiltIn::WorkgroupId:
                return core::BuiltinValue::kWorkgroupId;
            case spv::BuiltIn::ClipDistance:
                return core::BuiltinValue::kClipDistances;
            case spv::BuiltIn::CullDistance:
                return core::BuiltinValue::kCullDistance;
            case spv::BuiltIn::PrimitiveId:
                return core::BuiltinValue::kPrimitiveIndex;
            default:
                return Failure("unhandled SPIR-V BuiltIn: " + std::string(spv::BuiltInToString(b)) +
                               " (val = " + std::to_string(static_cast<uint32_t>(b)) + ")");
        }
    }

    /// @param id a SPIR-V result ID for a type declaration instruction
    /// @param access_mode an optional access mode (for pointers)
    /// @returns a Tint type object
    const core::type::Type* Type(uint32_t id, core::Access access_mode = core::Access::kUndefined) {
        auto* type = spirv_context_->get_type_mgr()->GetType(id);

        // Only use the access mode for the map key if it is used as part of the type in Tint IR.
        auto key_mode = core::Access::kUndefined;
        if (type->kind() == spvtools::opt::analysis::Type::kImage ||
            type->kind() == spvtools::opt::analysis::Type::kPointer) {
            key_mode = access_mode;
        }

        return types_.GetOrAdd(TypeKey{id, key_mode}, [&]() -> const core::type::Type* {
            uint32_t array_stride = 0;
            bool set_as_storage_buffer = false;
            for (auto& deco : type->decorations()) {
                switch (spv::Decoration(deco[0])) {
                    case spv::Decoration::Block: {
                        // Ignore, just means it's a memory block.
                        break;
                    }
                    case spv::Decoration::BufferBlock: {
                        set_as_storage_buffer = true;
                        break;
                    }
                    case spv::Decoration::ArrayStride: {
                        array_stride = deco[1];
                        break;
                    }
                    default: {
                        TINT_UNIMPLEMENTED() << " unhandled type decoration " << deco[0];
                    }
                }
            }
            // Storage buffer is only set ons structs
            if (set_as_storage_buffer) {
                TINT_ASSERT(type->kind() == spvtools::opt::analysis::Type::kStruct);
            }
            // ArrayStride is only handled on the array type for now
            if (array_stride > 0) {
                if (type->kind() != spvtools::opt::analysis::Type::kArray &&
                    type->kind() != spvtools::opt::analysis::Type::kRuntimeArray) {
                    TINT_UNREACHABLE()
                        << "ArrayStride is only accepted on an Array or RuntimeArray";
                }
            }

            switch (type->kind()) {
                case spvtools::opt::analysis::Type::kVoid: {
                    return ty_.void_();
                }
                case spvtools::opt::analysis::Type::kBool: {
                    return ty_.bool_();
                }
                case spvtools::opt::analysis::Type::kInteger: {
                    auto* int_ty = type->AsInteger();
                    TINT_ASSERT(int_ty->width() == 32);
                    if (int_ty->IsSigned()) {
                        return ty_.i32();
                    } else {
                        return ty_.u32();
                    }
                }
                case spvtools::opt::analysis::Type::kFloat: {
                    auto* float_ty = type->AsFloat();
                    if (float_ty->width() == 16) {
                        return ty_.f16();
                    } else if (float_ty->width() == 32) {
                        return ty_.f32();
                    } else {
                        TINT_UNREACHABLE()
                            << "unsupported floating point type width: " << float_ty->width();
                    }
                }
                case spvtools::opt::analysis::Type::kVector: {
                    auto* vec_ty = type->AsVector();
                    TINT_ASSERT(vec_ty->element_count() <= 4);
                    return ty_.vec(
                        Type(spirv_context_->get_type_mgr()->GetId(vec_ty->element_type())),
                        vec_ty->element_count());
                }
                case spvtools::opt::analysis::Type::kMatrix: {
                    auto* mat_ty = type->AsMatrix();
                    TINT_ASSERT(mat_ty->element_count() <= 4);
                    return ty_.mat(
                        As<core::type::Vector>(
                            Type(spirv_context_->get_type_mgr()->GetId(mat_ty->element_type()))),
                        mat_ty->element_count());
                }
                case spvtools::opt::analysis::Type::kArray: {
                    return EmitArray(id, array_stride);
                }
                case spvtools::opt::analysis::Type::kRuntimeArray: {
                    return EmitRuntimeArray(id, array_stride);
                }
                case spvtools::opt::analysis::Type::kStruct: {
                    const core::type::Struct* str_ty = EmitStruct(id);
                    if (set_as_storage_buffer) {
                        storage_buffer_types_.insert(str_ty);
                    }
                    return str_ty;
                }
                case spvtools::opt::analysis::Type::kPointer: {
                    return EmitPointer(id, access_mode);
                }
                case spvtools::opt::analysis::Type::kSampler: {
                    return ty_.sampler();
                }
                case spvtools::opt::analysis::Type::kImage: {
                    auto* img = type->AsImage();

                    auto* sampled_ty =
                        Type(spirv_context_->get_type_mgr()->GetId(img->sampled_type()));
                    auto dim = static_cast<type::Dim>(img->dim());
                    auto depth = static_cast<type::Depth>(img->depth());
                    auto arrayed =
                        img->is_arrayed() ? type::Arrayed::kArrayed : type::Arrayed::kNonArrayed;
                    auto ms = img->is_multisampled() ? type::Multisampled::kMultisampled
                                                     : type::Multisampled::kSingleSampled;
                    auto sampled = static_cast<type::Sampled>(img->sampled());
                    auto texel_format = ToTexelFormat(img->format());

                    // If the access mode is undefined then default to read/write for the image
                    access_mode = access_mode == core::Access::kUndefined ? core::Access::kReadWrite
                                                                          : access_mode;

                    if (img->dim() != spv::Dim::Dim1D && img->dim() != spv::Dim::Dim2D &&
                        img->dim() != spv::Dim::Dim3D && img->dim() != spv::Dim::Cube &&
                        img->dim() != spv::Dim::SubpassData) {
                        TINT_ICE()
                            << "Unsupported texture dimension: " << spv::DimToString(img->dim())
                            << " (val = " << static_cast<uint32_t>(img->dim()) << ")";
                    }
                    TINT_ASSERT(img->sampled() != 0)
                        << "Unsupported texture sample setting: Known at Runtime";

                    if (depth == type::Depth::kDepth && !sampled_ty->Is<core::type::F32>()) {
                        TINT_ICE() << "Unsupported depth texture sampled type (must be f32)";
                    }

                    return ty_.Get<spirv::type::Image>(sampled_ty, dim, depth, arrayed, ms, sampled,
                                                       texel_format, access_mode);
                }
                case spvtools::opt::analysis::Type::kSampledImage: {
                    auto* sampled = type->AsSampledImage();
                    return ty_.Get<spirv::type::SampledImage>(
                        Type(spirv_context_->get_type_mgr()->GetId(sampled->image_type())));
                }
                default: {
                    TINT_UNIMPLEMENTED() << "unhandled SPIR-V type: " << type->str();
                }
            }
        });
    }

    core::TexelFormat ToTexelFormat(spv::ImageFormat fmt) {
        switch (fmt) {
            case spv::ImageFormat::Unknown:
                return core::TexelFormat::kUndefined;

            // 8 bit channels
            case spv::ImageFormat::Rgba8:
                return core::TexelFormat::kRgba8Unorm;
            case spv::ImageFormat::Rgba8Snorm:
                return core::TexelFormat::kRgba8Snorm;
            case spv::ImageFormat::Rgba8ui:
                return core::TexelFormat::kRgba8Uint;
            case spv::ImageFormat::Rgba8i:
                return core::TexelFormat::kRgba8Sint;
            case spv::ImageFormat::R8:
                return core::TexelFormat::kR8Unorm;
            case spv::ImageFormat::R8i:
                return core::TexelFormat::kR8Sint;
            case spv::ImageFormat::R8ui:
                return core::TexelFormat::kR8Uint;
            case spv::ImageFormat::R8Snorm:
                return core::TexelFormat::kR8Snorm;
            case spv::ImageFormat::Rg8:
                return core::TexelFormat::kRg8Unorm;
            case spv::ImageFormat::Rg8Snorm:
                return core::TexelFormat::kRg8Snorm;
            case spv::ImageFormat::Rg8i:
                return core::TexelFormat::kRg8Sint;
            case spv::ImageFormat::Rg8ui:
                return core::TexelFormat::kRg8Uint;

            // 16 bit channels
            case spv::ImageFormat::R16:
                return core::TexelFormat::kR16Unorm;
            case spv::ImageFormat::R16f:
                return core::TexelFormat::kR16Float;
            case spv::ImageFormat::R16i:
                return core::TexelFormat::kR16Sint;
            case spv::ImageFormat::R16ui:
                return core::TexelFormat::kR16Uint;
            case spv::ImageFormat::R16Snorm:
                return core::TexelFormat::kR16Snorm;
            case spv::ImageFormat::Rgba16:
                return core::TexelFormat::kRgba16Unorm;
            case spv::ImageFormat::Rgba16ui:
                return core::TexelFormat::kRgba16Uint;
            case spv::ImageFormat::Rgba16i:
                return core::TexelFormat::kRgba16Sint;
            case spv::ImageFormat::Rgba16f:
                return core::TexelFormat::kRgba16Float;
            case spv::ImageFormat::Rgba16Snorm:
                return core::TexelFormat::kRgba16Snorm;
            case spv::ImageFormat::Rg16:
                return core::TexelFormat::kRg16Unorm;
            case spv::ImageFormat::Rg16i:
                return core::TexelFormat::kRg16Sint;
            case spv::ImageFormat::Rg16ui:
                return core::TexelFormat::kRg16Uint;
            case spv::ImageFormat::Rg16f:
                return core::TexelFormat::kRg16Float;
            case spv::ImageFormat::Rg16Snorm:
                return core::TexelFormat::kRg16Snorm;

            // 32 bit channels
            case spv::ImageFormat::R32ui:
                return core::TexelFormat::kR32Uint;
            case spv::ImageFormat::R32i:
                return core::TexelFormat::kR32Sint;
            case spv::ImageFormat::R32f:
                return core::TexelFormat::kR32Float;
            case spv::ImageFormat::Rg32ui:
                return core::TexelFormat::kRg32Uint;
            case spv::ImageFormat::Rg32i:
                return core::TexelFormat::kRg32Sint;
            case spv::ImageFormat::Rg32f:
                return core::TexelFormat::kRg32Float;
            case spv::ImageFormat::Rgba32ui:
                return core::TexelFormat::kRgba32Uint;
            case spv::ImageFormat::Rgba32i:
                return core::TexelFormat::kRgba32Sint;
            case spv::ImageFormat::Rgba32f:
                return core::TexelFormat::kRgba32Float;
            case spv::ImageFormat::Rgb10A2:
                return core::TexelFormat::kRgb10A2Unorm;
            case spv::ImageFormat::Rgb10a2ui:
                return core::TexelFormat::kRgb10A2Uint;
            case spv::ImageFormat::R11fG11fB10f:
                return core::TexelFormat::kRg11B10Ufloat;
            default:
                break;
        }
        TINT_ICE() << "invalid image format: " << dawn::to_underlying(fmt);
    }

    /// @param type_id the pointer result_id
    /// @param access_mode the access mode
    /// @returns a Tint pointer object
    const core::type::Type* EmitPointer(uint32_t type_id, core::Access access_mode) {
        auto* inst = spirv_context_->get_def_use_mgr()->GetDef(type_id);

        auto* subtype = Type(inst->GetInOperand(1).AsId(), access_mode);

        // In a few cases we need to adjust the access mode.
        //
        // 1. Handle is always a read pointer
        // 2. If the SPIR-V type should be considered NonWritable
        if (subtype->IsHandle() || consider_non_writable_.contains(subtype)) {
            access_mode = core::Access::kRead;
        }

        // Using the deduplicated pointer should be fine because the storage classes must have
        // matched if it was a duplicate.
        auto* ptr_ty = spirv_context_->get_type_mgr()->GetType(type_id)->AsPointer();
        return ty_.ptr(AddressSpace(ptr_ty->storage_class()), subtype, access_mode);
    }

    /// @param type_id the spirv result_id
    /// @returns a Tint runtime array object
    const core::type::Type* EmitRuntimeArray(uint32_t type_id, uint32_t array_stride) {
        auto* inst = spirv_context_->get_def_use_mgr()->GetDef(type_id);

        auto* elem_ty = Type(inst->GetInOperand(0).AsId());
        uint32_t implicit_stride = tint::RoundUp(elem_ty->Align(), elem_ty->Size());
        if (array_stride == 0 || array_stride == implicit_stride) {
            return ty_.runtime_array(elem_ty);
        }

        return ty_.Get<spirv::type::ExplicitLayoutArray>(
            elem_ty, ty_.Get<core::type::RuntimeArrayCount>(), static_cast<uint32_t>(array_stride),
            array_stride);
    }

    /// @param type_id the spirv result_id for the type
    /// @param array_stride the stride
    /// @returns a Tint array object
    const core::type::Type* EmitArray(uint32_t type_id, uint32_t array_stride) {
        auto* inst = spirv_context_->get_def_use_mgr()->GetDef(type_id);

        // Even deduplicated the length info must match, so safe to use the type manager info here.
        auto* arr_ty = spirv_context_->get_type_mgr()->GetType(type_id)->AsArray();
        const auto& length = arr_ty->length_info();
        TINT_ASSERT(!length.words.empty());
        if (length.words[0] != spvtools::opt::analysis::Array::LengthInfo::kConstant) {
            TINT_UNIMPLEMENTED() << "specialized array lengths";
        }

        // Get the value from the constant used for the element count.
        const auto* count_const =
            spirv_context_->get_constant_mgr()->FindDeclaredConstant(length.id);
        TINT_ASSERT(count_const);
        const uint64_t count_val = count_const->GetZeroExtendedValue();
        TINT_ASSERT(count_val <= UINT32_MAX);

        auto* elem_ty = Type(inst->GetInOperand(0).AsId());
        uint32_t implicit_stride = tint::RoundUp(elem_ty->Align(), elem_ty->Size());
        if (array_stride == 0 || array_stride == implicit_stride) {
            return ty_.array(elem_ty, static_cast<uint32_t>(count_val));
        }

        return ty_.Get<spirv::type::ExplicitLayoutArray>(
            elem_ty, ty_.Get<core::type::ConstantArrayCount>(static_cast<uint32_t>(count_val)),
            static_cast<uint32_t>(array_stride * count_val), array_stride);
    }

    /// Calculate the size of a struct member type that has a matrix stride decoration.
    uint32_t GetSizeOfTypeWithMatrixStride(const core::type::Type* type,
                                           uint32_t stride,
                                           bool is_row_major) {
        return tint::Switch(
            type,
            [&](const core::type::Matrix* mat) {
                return stride * (is_row_major ? mat->Rows() : mat->Columns());
            },
            [&](const core::type::Array* arr) {
                auto size = GetSizeOfTypeWithMatrixStride(arr->ElemType(), stride, is_row_major);
                // The size of a runtime-sized array is the size of a single element, so we only
                // have to handle the fixed-sized array case here.
                if (auto count = arr->ConstantCount()) {
                    size *= count.value();
                }
                return size;
            },
            TINT_ICE_ON_NO_MATCH);
    }

    /// @param type_id the struct type id
    /// @returns a Tint struct object
    const core::type::Struct* EmitStruct(uint32_t type_id) {
        auto* inst = spirv_context_->get_def_use_mgr()->GetDef(type_id);

        uint32_t member_count = inst->NumInOperandWords();
        TINT_ASSERT(member_count != 0) << "empty structures are not supported";

        std::vector<std::string>* member_names = nullptr;
        auto struct_to_member_iter = struct_to_member_names_.find(type_id);
        if (struct_to_member_iter != struct_to_member_names_.end()) {
            member_names = &((*struct_to_member_iter).second);
        }

        // We can use the struct type for the decorations, since even if it was deduplicated then
        // the decorations must be the same.
        auto* struct_ty = spirv_context_->get_type_mgr()->GetType(type_id)->AsStruct();

        // Build a list of struct members.
        uint32_t current_size = 0u;
        uint32_t non_writable_members = 0;
        Vector<core::type::StructMember*, 4> members;
        for (uint32_t i = 0; i < member_count; i++) {
            auto* member_ty = Type(inst->GetInOperand(i).AsId());
            uint32_t align = std::max<uint32_t>(member_ty->Align(), 1u);
            uint32_t offset = tint::RoundUp(align, current_size);
            core::IOAttributes attributes;
            auto interpolation = [&]() -> core::Interpolation& {
                // Create the interpolation field with the default values on first call.
                if (!attributes.interpolation.has_value()) {
                    attributes.interpolation =
                        core::Interpolation{core::InterpolationType::kPerspective,
                                            core::InterpolationSampling::kUndefined};
                }
                return attributes.interpolation.value();
            };

            bool is_row_major = false;
            uint32_t matrix_stride = 0;
            // Handle member decorations that affect layout or attributes.
            if (struct_ty->element_decorations().count(i)) {
                for (auto& deco : struct_ty->element_decorations().at(i)) {
                    switch (spv::Decoration(deco[0])) {
                        case spv::Decoration::NonWritable:
                            // WGSL doesn't have a non-writable attribute on struct members, but, if
                            // the SPIR-V structure has NonWritable on all members then we treat the
                            // entire structure as non-writable.
                            non_writable_members += 1;
                            break;

                        case spv::Decoration::ColMajor:          // Do nothing, WGSL is column major
                        case spv::Decoration::NonReadable:       // Not supported in WGSL
                        case spv::Decoration::RelaxedPrecision:  // Not supported in WGSL
                            break;
                        case spv::Decoration::Coherent:
                            // Tint has coherent memory semantics, so this is a no-op.
                            break;
                        case spv::Decoration::Restrict:
                            // All Tint pointers are restrict. This is a no-op.
                            break;
                        case spv::Decoration::RowMajor:
                            is_row_major = true;
                            break;
                        case spv::Decoration::MatrixStride:
                            matrix_stride = deco[1];
                            break;
                        case spv::Decoration::Offset:
                            offset = deco[1];
                            break;
                        case spv::Decoration::BuiltIn: {
                            auto builtin_res = Builtin(spv::BuiltIn(deco[1]));
                            if (builtin_res != Success) {
                                TINT_ICE() << builtin_res.Failure().reason;
                            }
                            attributes.builtin = builtin_res.Get();
                            break;
                        }
                        case spv::Decoration::Invariant:
                            attributes.invariant = true;
                            break;
                        case spv::Decoration::Location:
                            attributes.location = deco[1];
                            break;
                        case spv::Decoration::NoPerspective:
                            interpolation().type = core::InterpolationType::kLinear;
                            break;
                        case spv::Decoration::Flat:
                            interpolation().type = core::InterpolationType::kFlat;
                            break;
                        case spv::Decoration::Centroid:
                            interpolation().sampling = core::InterpolationSampling::kCentroid;
                            break;
                        case spv::Decoration::Sample:
                            interpolation().sampling = core::InterpolationSampling::kSample;
                            break;

                        default:
                            TINT_UNIMPLEMENTED() << "unhandled member decoration: " << deco[0];
                    }
                }
            }

            if (member_ty->IsIntegerScalarOrVector() && attributes.location.has_value()) {
                interpolation().type = core::InterpolationType::kFlat;
            }

            Symbol name;
            if (member_names && member_names->size() > i) {
                auto n = (*member_names)[i];
                if (!n.empty()) {
                    name = ir_.symbols.Register(n);
                }
            }
            if (!name.IsValid()) {
                name = ir_.symbols.New();
            }

            uint32_t size = member_ty->Size();
            if (matrix_stride > 0) {
                size = GetSizeOfTypeWithMatrixStride(member_ty, matrix_stride, is_row_major);
            }

            core::type::StructMember* member = ty_.Get<core::type::StructMember>(
                name, member_ty, i, offset, align, size, std::move(attributes));
            if (is_row_major) {
                member->SetRowMajor();
            }
            if (matrix_stride > 0) {
                member->SetMatrixStride(matrix_stride);
            }

            members.Push(member);

            current_size = offset + size;
        }

        Symbol name = GetUniqueSymbolFor(type_id);
        if (!name.IsValid()) {
            name = ir_.symbols.New();
        }
        auto* strct = ty_.Struct(name, std::move(members));
        if (non_writable_members == member_count) {
            consider_non_writable_.insert(strct);
        }
        return strct;
    }

    Symbol GetUniqueSymbolFor(uint32_t id) {
        auto iter = id_to_name_.find(id);
        if (iter != id_to_name_.end()) {
            return ir_.symbols.New(iter->second);
        }
        return Symbol{};
    }

    Symbol GetSymbolFor(uint32_t id) {
        auto iter = id_to_name_.find(id);
        if (iter != id_to_name_.end()) {
            return ir_.symbols.Register(iter->second);
        }
        return Symbol{};
    }

    /// @param id a SPIR-V result ID for a function declaration instruction
    /// @returns a Tint function object
    core::ir::Function* Function(uint32_t id) {
        return functions_.GetOrAdd(id, [&] { return b_.Function(ty_.void_()); });
    }

    // Passes a value up through control flow to make it visible in an outer scope. Because SPIR-V
    // allows an id to be referenced as long as it's dominated, you can access a variable which is
    // defined inside an if branch for example. In order for that to be accessed in IR, we have to
    // propagate the value as a return of the control instruction (like the if).
    //
    // e.g. if the IR is similar to the following:
    // ```
    // if (b) {
    //    %a:i32 = let 4;
    //    exit_if
    // }
    // %c:i32 = %a + %a;
    // ```
    //
    // We propagate to something like:
    // ```
    // %d:i32 = if (b) {
    //   %a:i32 = let 4;  // The spir-v ID refers to %a at this point
    //   exit_if %a
    // }
    // %c:i32 = %d + %d  // The spir-v ID will now refer to %d instead of %a
    // ```
    //
    // We can end up propagating up through multiple levels, so we can end up with something like:
    // ```
    // %k:i32 = if (true) {
    //   %l:i32 = if (false) {
    //     %m:i32 = if (true) {
    //       %n:i32 = switch 4 {
    //         default: {
    //           %o:i32 = loop {
    //             %a:i32 = let 4;
    //             exit_loop %a
    //           }
    //           exit_switch %o
    //         }
    //       }
    //       exit_if %n
    //     }
    //     exit_if %m
    //   }
    //   exit_if %l
    // }
    // %b:i32 = %k + %k
    // ```
    //
    // @param id the spir-v ID to propagate up
    // @param src the source value being propagated
    core::ir::Value* Propagate(uint32_t id, core::ir::Value* src) {
        auto* blk = tint::Switch(
            src,  //
            [&](core::ir::BlockParam* bp) { return bp->Block(); },
            [&](core::ir::InstructionResult* res) { return res->Instruction()->Block(); },
            TINT_ICE_ON_NO_MATCH);

        // Walk up the set of control instructions from the current `blk`. We'll update the `src`
        // instruction as the new result which is to be used for the given SPIR-V `id`. At each
        // control instruction we'll add the current `src` as a result of each exit from the control
        // instruction, making a new result which is available in the parent scope.
        while (blk) {
            if (InBlock(blk)) {
                break;
            }

            core::ir::ControlInstruction* ctrl = nullptr;
            if (auto* mb = blk->As<core::ir::MultiInBlock>()) {
                ctrl = mb->Parent()->As<core::ir::ControlInstruction>();
                TINT_ASSERT(ctrl);

                for (auto exit : ctrl->Exits()) {
                    tint::Switch(
                        exit.Value(),  //
                        [&](core::ir::ExitLoop* el) { el->PushOperand(src); },
                        [&](core::ir::BreakIf* bi) { bi->PushOperand(src); },  //
                        TINT_ICE_ON_NO_MATCH);
                }
            } else {
                TINT_ASSERT(blk->Terminator());

                ctrl = tint::Switch(
                    blk->Terminator(),  //
                    [&](core::ir::ExitIf* ei) { return ei->If(); },
                    [&](core::ir::ExitSwitch* es) { return es->Switch(); },
                    [&](core::ir::ExitLoop* el) { return el->Loop(); },
                    [&](core::ir::NextIteration* ni) {
                        ni->PushOperand(src);
                        return nullptr;
                    },
                    [&](core::ir::Continue* cont) {
                        // The propagation is going through a `continue`. This means
                        // this is the only path to the continuing block, but it also
                        // means we're current in the continuing block. We can't do
                        // normal propagation here, we have to pass a block param
                        // instead.

                        auto* param = b_.BlockParam(src->Type());

                        // We're in the continuing block, so make the block param available in the
                        // scope.
                        id_stack_.back().insert(id);

                        auto* loop = cont->Loop();
                        loop->Continuing()->AddParam(param);
                        cont->PushOperand(src);

                        // Set `src` as the `param` so it's returned as the new value
                        src = param;
                        return nullptr;
                    },                                                      //
                    [&](core::ir::Unreachable*) { return blk->Parent(); },  //
                    TINT_ICE_ON_NO_MATCH);

                if (!ctrl) {
                    break;
                }

                for (auto& exit : ctrl->Exits()) {
                    exit->PushOperand(src);
                }
            }

            // If this control has no exits, then we don't need to add the result through the
            // control as we're jumping over the control to its parent control. (This is an
            // `if` inside a `loop` where the `if` is doing a `break`).
            if (ctrl->Exits().IsEmpty()) {
                if (ctrl->Is<core::ir::Loop>()) {
                    TINT_UNREACHABLE()
                        << "loop detected with no exits which means it's an infinite loop. "
                           "Infinite loops are not supported in WGSL";
                }

                TINT_ASSERT(ctrl->Is<core::ir::If>());
                blk = ctrl->Block();
                continue;
            }

            // Add a new result to the control instruction
            ctrl->AddResult(b_.InstructionResult(src->Type()));
            // The source instruction is now the control result we just inserted
            src = ctrl->Results().Back();
            // The SPIR-V ID now refers to the propagated value.
            values_.Replace(id, src);

            blk = ctrl->Block();
        }
        return src;
    }

    // Returns true if the `blk` is the  `parent_blk` or any of the ancestors of parent_blk
    bool IsContainedInBlock(core::ir::Block* parent_blk, core::ir::Block* blk) {
        while (parent_blk) {
            if (parent_blk == blk) {
                return true;
            }

            if (!parent_blk->Parent()) {
                break;
            }
            parent_blk = parent_blk->Parent()->Block();
        }
        return false;
    }

    // Propagate a value out of a control instruction. This isn't the same as the other
    // propagate as we only need to pull it out through a single blocks exit for the control
    // instruction.
    core::ir::Value* PropagateTerm(core::ir::Terminator* term,
                                   uint32_t spv_id_being_propagated,
                                   core::ir::Value* source_value,
                                   core::ir::Block* source_block) {
        auto* current_ctrl = source_block->Parent();
        core::ir::Block* current_blk = source_block;
        core::ir::Value* propagated_value = source_value;
        auto* type = source_value->Type();

        while (true) {
            if (IsContainedInBlock(term->Block(), current_blk)) {
                break;
            }
            TINT_ASSERT(current_ctrl);

            // If the terminator is an exit for this control instruction, we're done as the caller
            // will handle adding the result.
            bool done = false;
            for (auto exit : current_ctrl->Exits()) {
                if (exit.Value() == term) {
                    done = true;
                    break;
                }
            }
            if (done) {
                break;
            }

            auto* res = b_.InstructionResult(type);
            current_ctrl->AddResult(res);

            for (auto exit : current_ctrl->Exits()) {
                if (IsContainedInBlock(exit->Block(), current_blk)) {
                    exit->PushOperand(propagated_value);
                    continue;
                }

                // Special handling for loop-continuing blocks as the body is visible to the
                // continuing so any block params from the body can pass through the exit.
                if (auto* loop = current_ctrl->As<core::ir::Loop>()) {
                    if (exit->Block() == loop->Continuing() &&
                        propagated_value->Is<core::ir::BlockParam>()) {
                        exit->PushOperand(propagated_value);
                    }
                }
            }

            propagated_value = res;
            current_blk = current_ctrl->Block();
            current_ctrl = current_blk->Parent();
        }

        values_.Replace(spv_id_being_propagated, propagated_value);
        return propagated_value;
    }

    // Returns true if the value is a constant value
    bool IdIsConstant(uint32_t id) { return SpvConstant(id) || spec_composites_.contains(id); }

    // Returns true if this value is currently in scope
    bool IdIsInScope(uint32_t id) {
        for (auto iter = id_stack_.rbegin(); iter != id_stack_.rend(); ++iter) {
            if (iter->contains(id)) {
                return true;
            }
        }
        return false;
    }

    // Get the spirv constant for the given `id`. `nullptr` if no constant exists.
    const spvtools::opt::analysis::Constant* SpvConstant(uint32_t id) {
        return spirv_context_->get_constant_mgr()->FindDeclaredConstant(id);
    }

    /// Attempts to retrieve the current Tint IR value for `id`. This ignores scoping for the
    /// variable, if it exists it's returned (or if it's constant it's created). The value will not
    /// propagate up through control instructions.
    ///
    /// @param id a SPIR-V result ID
    /// @returns a Tint value object
    std::optional<core::ir::Value*> ValueNoPropagate(uint32_t id) {
        auto v = values_.Get(id);
        if (v) {
            return *v;
        }

        const spvtools::opt::Instruction* inst = spirv_context_->get_def_use_mgr()->GetDef(id);
        const core::type::Type* inst_ty = Type(inst->type_id());

        if (const spvtools::opt::analysis::Constant* c = SpvConstant(id)) {
            core::ir::Constant* val = b_.Constant(Constant(c));
            // SPIR-V opt will deduplicate structs with the same shape. We handle this in the type
            // code below by using the specific instructions type, not the spirv-opt type. But, when
            // we retrieve constants, then opt might have used the other type for the struct type.
            // So, check the instructions type, if it doesn't match what opt returns, then we
            // rebuild the struct below with our corrected type.
            if (val->Type() == inst_ty) {
                values_.Add(id, val);
                return val;
            }
        }

        // In the case of a deduplicated structure, we may need to re-create a null constant
        if (inst->opcode() == spv::Op::OpConstantNull) {
            TINT_ASSERT(inst_ty->Is<core::type::Struct>());
            core::ir::Value* val = b_.Zero(inst_ty);
            values_.Add(id, val);
            return val;
        }

        // If we didn't have a value already, and this instruction is a constructed constant, then
        // do the construction.
        if (inst->opcode() == spv::Op::OpConstantComposite) {
            Vector<const core::constant::Value*, 4> args;
            args.Reserve(inst->NumInOperands());

            for (uint32_t i = 0; i < inst->NumInOperands(); ++i) {
                auto* cnst = Value(inst->GetSingleWordInOperand(i))->As<core::ir::Constant>();
                TINT_ASSERT(cnst);
                args.Push(cnst->Value());
            }

            auto* composite = b_.Composite(inst_ty, args);
            AddValue(id, composite);
            return composite;
        }

        // If this was a spec composite, then it currently isn't in scope, so we construct
        // a new copy and assign the constant ID to the new construct in this scope.
        auto iter = spec_composites_.find(id);
        if (iter != spec_composites_.end()) {
            Vector<core::ir::Value*, 4> args;
            for (auto arg : iter->second.args) {
                args.Push(Value(arg));
            }

            core::ir::Value* construct = nullptr;
            b_.Append(current_block_, [&] { construct = b_.Construct(iter->second.type, args); });
            AddValue(id, construct);
            return construct;
        }

        return std::nullopt;
    }

    /// Attempts to retrieve the current Tint IR value for `id`. If the value exists and is not in
    /// scope it will propagate the value up through the control instructions.
    ///
    /// @param id a SPIR-V result ID
    /// @returns a Tint value object
    core::ir::Value* Value(uint32_t id, bool add_to_scope = true) {
        auto v = ValueNoPropagate(id);
        TINT_ASSERT(v.has_value());

        if (v.value()->Is<core::ir::Constant>() || v.value()->Is<core::ir::FunctionParam>() ||
            IdIsInScope(id)) {
            return v.value();
        }

        // A return values from a control instruction cannot be a pointer type
        // without supporting variable pointers. We regenerate the value so it
        // is in scope.
        if (v.value()->Type()->Is<core::type::Pointer>()) {
            return ReplicatePointer(id);
        }

        auto* new_v = Propagate(id, v.value());
        if (add_to_scope) {
            AddValue(id, new_v);
        }
        return new_v;
    }

    /// Replicates a pointer instruction that is defined inside a control flow construct
    /// but used outside of it.
    /// @param id the SPIR-V result ID of the pointer instruction
    /// @returns the replicated Tint IR value
    core::ir::Value* ReplicatePointer(uint32_t id) {
        auto* spv_inst = spirv_context_->get_def_use_mgr()->GetDef(id);
        TINT_ASSERT(spv_inst);
        switch (spv_inst->opcode()) {
            case spv::Op::OpAccessChain:
            case spv::Op::OpInBoundsAccessChain:
                EmitAccess(*spv_inst);
                break;
            case spv::Op::OpCopyObject:
                EmitCopyObject(*spv_inst);
                break;
            default:
                TINT_UNREACHABLE() << "unhandled instruction for pointer replication: "
                                   << spv::OpToString(spv_inst->opcode());
        }
        auto new_v = values_.Get(id);
        TINT_ASSERT(new_v);
        return *new_v;
    }

    /// Creates the Tint IR constant for the SPIR-V `constant` value.
    ///
    /// @param constant a SPIR-V constant object
    /// @returns a Tint constant value
    const core::constant::Value* Constant(const spvtools::opt::analysis::Constant* constant) {
        // Handle OpConstantNull for all types.
        if (constant->AsNullConstant()) {
            return ir_.constant_values.Zero(
                Type(spirv_context_->get_type_mgr()->GetId(constant->type())));
        }

        if (auto* bool_ = constant->AsBoolConstant()) {
            return b_.ConstantValue(bool_->value());
        }
        if (auto* i = constant->AsIntConstant()) {
            auto* int_ty = i->type()->AsInteger();
            TINT_ASSERT(int_ty->width() == 32);
            if (int_ty->IsSigned()) {
                return b_.ConstantValue(i32(i->GetS32BitValue()));
            } else {
                return b_.ConstantValue(u32(i->GetU32BitValue()));
            }
        }
        if (auto* f = constant->AsFloatConstant()) {
            auto* float_ty = f->type()->AsFloat();
            if (float_ty->width() == 16) {
                return b_.ConstantValue(f16::FromBits(static_cast<uint16_t>(f->words()[0])));
            } else if (float_ty->width() == 32) {
                return b_.ConstantValue(f32(f->GetFloat()));
            } else {
                TINT_UNREACHABLE()
                    << "unsupported floating point type width: " << float_ty->width();
            }
        }
        if (auto* v = constant->AsVectorConstant()) {
            Vector<const core::constant::Value*, 4> elements;
            for (auto& el : v->GetComponents()) {
                elements.Push(Constant(el));
            }
            return ir_.constant_values.Composite(
                Type(spirv_context_->get_type_mgr()->GetId(v->type())), std::move(elements));
        }
        if (auto* m = constant->AsMatrixConstant()) {
            Vector<const core::constant::Value*, 4> columns;
            for (auto& el : m->GetComponents()) {
                columns.Push(Constant(el));
            }
            return ir_.constant_values.Composite(
                Type(spirv_context_->get_type_mgr()->GetId(m->type())), std::move(columns));
        }
        if (auto* a = constant->AsArrayConstant()) {
            Vector<const core::constant::Value*, 16> elements;
            for (auto& el : a->GetComponents()) {
                elements.Push(Constant(el));
            }
            return ir_.constant_values.Composite(
                Type(spirv_context_->get_type_mgr()->GetId(a->type())), std::move(elements));
        }
        if (auto* s = constant->AsStructConstant()) {
            Vector<const core::constant::Value*, 16> elements;
            for (auto& el : s->GetComponents()) {
                elements.Push(Constant(el));
            }
            return ir_.constant_values.Composite(
                Type(spirv_context_->get_type_mgr()->GetId(s->type())), std::move(elements));
        }
        TINT_ICE() << "unhandled constant type: " << constant->type()->str();
    }

    /// @returns a literal operand with the given value
    core::ir::Value* Literal(uint32_t value) {
        return b_.Constant(ir_.constant_values.Get<core::constant::Scalar<u32>>(
            ty_.Get<type::Literal>(), u32(value)));
    }

    /// Register an IR value for a SPIR-V result ID.
    /// @param result_id the SPIR-V result ID
    /// @param value the IR value
    void AddValue(uint32_t result_id, core::ir::Value* value) {
        id_stack_.back().insert(result_id);
        values_.Replace(result_id, value);
    }

    /// Emit an instruction to the current block and associates the result to
    /// the spirv result id.
    /// @param inst the instruction to emit
    /// @param result_id the SPIR-V result ID to register the instruction result for
    void Emit(core::ir::Instruction* inst, uint32_t result_id) {
        current_block_->Append(inst);
        TINT_ASSERT(inst->Results().Length() == 1u);
        AddValue(result_id, inst->Result());

        Symbol name = GetSymbolFor(result_id);
        if (name.IsValid() && !inst->Result()->Type()->Is<core::type::Void>()) {
            ir_.SetName(inst, name);
        }
    }

    /// Emit an instruction to the current block.
    /// @param value the value to emit
    void EmitWithoutSpvResult(core::ir::Value* value) {
        if (auto* inst = value->AsInstruction()) {
            current_block_->Append(inst);
            TINT_ASSERT(inst->Results().Length() == 1u);
        }
    }

    /// Emit an instruction to the current block.
    /// @param value the value to emit
    void EmitWithoutResult(core::ir::Instruction* inst) {
        TINT_ASSERT(inst->Results().IsEmpty());
        current_block_->Append(inst);
    }

    /// Emit the module-scope variables.
    Result<SuccessType> EmitModuleScopeVariables() {
        for (auto& inst : spirv_context_->module()->types_values()) {
            switch (inst.opcode()) {
                case spv::Op::OpVariable:
                    TINT_CHECK_RESULT(EmitVar(inst));
                    break;
                case spv::Op::OpUndef: {
                    auto* ty = Type(inst.type_id());

                    TINT_ASSERT(!ty->Is<core::type::MemoryView>())
                        << "cannot create an undef memory view in WGSL";

                    AddValue(inst.result_id(), b_.Zero(ty));
                    break;
                }
                default:
                    break;
            }
        }
        return Success;
    }

    /// Emit the functions.
    Result<SuccessType> EmitFunctions() {
        // Add all the functions in a first pass and then fill in the function bodies. This means
        // the function will exist fixing an issues where calling a function that hasn't been seen
        // generates the wrong signature.
        for (auto& func : *spirv_context_->module()) {
            current_spirv_function_ = &func;

            Vector<core::ir::FunctionParam*, 4> params;
            func.ForEachParam([&](spvtools::opt::Instruction* spirv_param) {
                auto* param = b_.FunctionParam(Type(spirv_param->type_id()));
                values_.Add(spirv_param->result_id(), param);

                Symbol name = GetSymbolFor(spirv_param->result_id());
                if (name.IsValid()) {
                    ir_.SetName(param, name);
                }

                params.Push(param);
            });

            current_function_ = Function(func.result_id());
            current_function_->SetParams(std::move(params));
            current_function_->SetReturnType(Type(func.type_id()));

            Symbol name = GetSymbolFor(func.result_id());
            if (name.IsValid()) {
                ir_.SetName(current_function_, name);
            }

            functions_.Add(func.result_id(), current_function_);
            current_spirv_function_ = nullptr;
        }

        for (auto& func : *spirv_context_->module()) {
            current_spirv_function_ = &func;

            current_function_ = Function(func.result_id());
            TINT_CHECK_RESULT(EmitBlockParent(current_function_->Block(), *func.entry()));

            // No terminator was emitted, that means then end of block is
            // unreachable. Mark as such.
            if (!current_function_->Block()->Terminator()) {
                current_function_->Block()->Append(b_.Unreachable());
            }
            current_spirv_function_ = nullptr;
        }
        return Success;
    }

    /// Emit entry point attributes.
    Result<SuccessType> EmitEntryPointAttributes() {
        // Handle OpEntryPoint declarations.
        for (auto& entry_point : spirv_context_->module()->entry_points()) {
            auto model = entry_point.GetSingleWordInOperand(0);
            auto* func = Function(entry_point.GetSingleWordInOperand(1));

            // Set the pipeline stage.
            switch (spv::ExecutionModel(model)) {
                case spv::ExecutionModel::GLCompute:
                    func->SetStage(core::ir::Function::PipelineStage::kCompute);
                    break;
                case spv::ExecutionModel::Fragment:
                    func->SetStage(core::ir::Function::PipelineStage::kFragment);
                    break;
                case spv::ExecutionModel::Vertex:
                    func->SetStage(core::ir::Function::PipelineStage::kVertex);
                    break;
                default:
                    return Failure("unhandled execution model: " + std::to_string(model));
            }

            // Set the entry point name.
            ir_.SetName(func, entry_point.GetOperand(2).AsString());

            if (func->IsCompute()) {
                // Search for `WorkgroupSize` decorated Ids
                for (const spvtools::opt::Instruction& inst :
                     spirv_context_->module()->annotations()) {
                    if (inst.opcode() != spv::Op::OpDecorate ||
                        inst.GetSingleWordInOperand(1) !=
                            dawn::to_underlying(spv::Decoration::BuiltIn) ||
                        inst.GetSingleWordInOperand(2) !=
                            dawn::to_underlying(spv::BuiltIn::WorkgroupSize)) {
                        continue;
                    }
                    uint32_t id = inst.GetSingleWordInOperand(0);

                    Vector<core::ir::Value*, 3> args;
                    if (auto* c = SpvConstant(id)) {
                        auto* vals = c->AsVectorConstant();
                        TINT_ASSERT(vals);

                        for (auto& el : vals->GetComponents()) {
                            args.Push(b_.Constant(Constant(el)));
                        }
                    } else {
                        TINT_ASSERT(spec_composites_.contains(id));

                        auto info = spec_composites_[id];
                        TINT_ASSERT(info.args.Length() == 3);

                        for (auto arg : info.args) {
                            args.Push(Value(arg));
                        }
                    }
                    func->SetWorkgroupSize(args[0], args[1], args[2]);

                    break;
                }
            }
        }

        // Handle OpExecutionMode declarations.
        for (auto& execution_mode : spirv_context_->module()->execution_modes()) {
            auto* func = functions_.GetOr(execution_mode.GetSingleWordInOperand(0), nullptr);
            auto mode = execution_mode.GetSingleWordInOperand(1);
            TINT_ASSERT(func);

            switch (spv::ExecutionMode(mode)) {
                case spv::ExecutionMode::LocalSize:
                    func->SetWorkgroupSize(
                        b_.Constant(u32(execution_mode.GetSingleWordInOperand(2))),
                        b_.Constant(u32(execution_mode.GetSingleWordInOperand(3))),
                        b_.Constant(u32(execution_mode.GetSingleWordInOperand(4))));
                    break;
                case spv::ExecutionMode::DepthGreater:
                    return Failure("ExecutionMode DepthGreater is not supported in WGSL");
                case spv::ExecutionMode::DepthLess:
                    return Failure("ExecutionMode DepthLess is not supported in WGSL");
                case spv::ExecutionMode::DepthUnchanged:
                    return Failure("ExecutionMode DepthUnchanged is not supported in WGSL");
                case spv::ExecutionMode::EarlyFragmentTests:
                    return Failure("ExecutionMode EarlyFragmentTests is not supported in WGSL");
                case spv::ExecutionMode::DepthReplacing:
                case spv::ExecutionMode::OriginUpperLeft:
                    // These are ignored as they are implicitly supported by Tint IR.
                    break;
                default:
                    return Failure("unhandled execution mode: " + std::to_string(mode));
            }
        }
        return Success;
    }

    bool InBlock(core::ir::Block* blk) { return current_blocks_.contains(blk); }

    // A block parent is a container for a scope, like a `{}`d section in code. It controls the
    // block addition to the current blocks and the ID stack entry for the block.
    Result<SuccessType> EmitBlockParent(core::ir::Block* dst, spvtools::opt::BasicBlock& src) {
        TINT_ASSERT(!InBlock(dst));

        id_stack_.emplace_back();
        current_blocks_.insert(dst);

        auto res = EmitBlock(dst, src);

        current_blocks_.erase(dst);
        id_stack_.pop_back();

        return res;
    }

    /// Emit the contents of SPIR-V block @p src into Tint IR block @p dst.
    /// @param dst the Tint IR block to append to
    /// @param src the SPIR-V block to emit
    Result<SuccessType> EmitBlock(core::ir::Block* dst, spvtools::opt::BasicBlock& src) {
        TINT_SCOPED_ASSIGNMENT(current_block_, dst);

        // Register the merge if this is a header block
        auto* merge_inst = src.GetMergeInst();
        if (merge_inst) {
            auto merge_id = merge_inst->GetSingleWordInOperand(0);
            spirv_merge_id_to_header_id_.insert({merge_id, src.id()});
        }

        values_to_replace_.push_back({});

        // If this is a loop merge block, so we need to treat it as a Loop.
        auto* loop_merge_inst = src.GetLoopMergeInst();
        core::ir::Loop* loop = nullptr;
        if (loop_merge_inst) {
            // Emit the loop instruction into the current block.
            EmitLoop(src);

            // The loop header is a walk stop block, which was created in the emit loop method. Get
            // the loop back so we can change the current insertion block.
            loop = StopWalkingAt(src.id())->As<core::ir::Loop>();
            TINT_ASSERT(loop);

            id_stack_.emplace_back();
            current_blocks_.insert(loop->Body());

            // Now emit the remainder of the block into the loop body. We do this now so the loop
            // emitted above is in the parent block.
            current_block_ = loop->Body();
        }

        // Note, this comes after the loop code since the current block is set to the loop body
        spirv_id_to_block_.insert({src.id(), current_block_});

        TINT_CHECK_RESULT(ProcessInstructions(src));

        // Add the body terminator if necessary
        if (loop && !loop->Body()->Terminator()) {
            loop->Body()->Append(b_.Unreachable());
        }

        // For any `OpPhi` values we saw, insert their `Value` now. We do this at the end of the
        // processing of instructions because a phi can refer to instructions defined after it
        // in the block.
        auto replace = values_to_replace_.back();
        for (auto& val : replace) {
            auto v = ValueNoPropagate(val.value_id);
            TINT_ASSERT(v.has_value());
            val.terminator->SetOperand(val.idx, v.value());
        }

        values_to_replace_.pop_back();

        if (!loop) {
            return Success;
        }

        // Emit the continuing block. The continue block is within the scope of the body block,
        // so we don't pop the id stack yet.
        auto continue_id = loop_merge_inst->GetSingleWordInOperand(1);

        // Capture any continue PHi header values before emitting the continue because the value
        // will get re-written to be the continue block param, so we have to capture first.
        auto continue_loop_phi_ids = block_phi_values_[continue_id];
        std::vector<core::ir::Value*> continue_loop_phi_values;
        if (!continue_loop_phi_ids.empty()) {
            continue_loop_phi_values.reserve(continue_loop_phi_ids.size());
            for (auto& id : continue_loop_phi_ids) {
                auto v = ValueNoPropagate(id);
                if (v.has_value()) {
                    continue_loop_phi_values.push_back(v.value());
                }
            }
        }

        TINT_CHECK_RESULT(EmitContinueBlock(src.id(), continue_id, loop));

        // Remove the body block id stack before emitting the merge block.
        current_blocks_.erase(loop->Body());
        id_stack_.pop_back();

        // If we added phi's to the continuing block, we may have exits from the body which
        // aren't valid.
        if (loop->Continuing()->Params().Length() > 0) {
            for (auto incoming : loop->Continuing()->InboundSiblingBranches()) {
                TINT_ASSERT(incoming->Is<core::ir::Continue>());

                if (incoming->Args().size() == loop->Continuing()->Params().Length()) {
                    continue;
                }

                // Check if the block this instruction exists in has default phi result that we
                // can append.
                auto inst_to_blk_iter = inst_to_spirv_block_.find(incoming);
                if (inst_to_blk_iter != inst_to_spirv_block_.end()) {
                    uint32_t spirv_blk = inst_to_blk_iter->second;

                    auto phi_values_from_loop_header = block_phi_values_[spirv_blk];

                    // We require a PHI value, but the current block doesn't have any from the
                    // header. In this case, check the `continue` target to see if it has header
                    // provided phi values. If so, use that one.
                    if (phi_values_from_loop_header.empty()) {
                        TINT_ASSERT(!continue_loop_phi_values.empty());

                        for (auto* value : continue_loop_phi_values) {
                            incoming->PushOperand(value);
                        }

                    } else {
                        // If there were phi values, push them to this instruction
                        for (auto value_id : phi_values_from_loop_header) {
                            auto* value = Value(value_id);
                            incoming->PushOperand(value);
                        }
                    }
                } else {
                    TINT_UNREACHABLE() << "unable to provide needed continue arguments";
                }
            }
        }

        // Emit the merge block
        auto merge_id = loop_merge_inst->GetSingleWordInOperand(0);
        const auto& merge_bb = current_spirv_function_->FindBlock(merge_id);
        TINT_CHECK_RESULT(EmitBlock(dst, *merge_bb));
        return Success;
    }

    Result<SuccessType> EmitContinueBlock(uint32_t src_id,
                                          uint32_t continue_id,
                                          core::ir::Loop* loop) {
        // We're emitting the continue block, so remove it from the continue targets as it can no
        // longer be a target for this loop. This will allow it to be _reused_ as the continue
        // target for a single block loop if needed (which may have this same block as the
        // continue).
        continue_targets_.erase(continue_id);

        // Push id stack entry for the continuing block. We don't use EmitBlockParent to do this
        // because we need the scope to exist until after we process any `continue_blk_phis_`.
        id_stack_.emplace_back();

        // We only need to emit the continuing block if:
        //  a) It is not the loop header
        //  b) It has inbound branches. This works around a case where you can have a continuing
        //     where uses values which are very difficult to propagate, but the continuing is never
        //     reached anyway, so the propagation is useless.
        bool skipped_continue = true;
        if (continue_id != src_id && !loop->Continuing()->InboundSiblingBranches().IsEmpty()) {
            skipped_continue = false;

            const auto& bb_continue = current_spirv_function_->FindBlock(continue_id);

            current_blocks_.insert(loop->Continuing());
            TINT_CHECK_RESULT(EmitBlock(loop->Continuing(), *bb_continue));
            current_blocks_.erase(loop->Continuing());
        }

        if (!loop->Continuing()->Terminator()) {
            loop->Continuing()->Append(b_.NextIteration(loop));
        }

        // If this continue block needs to pass any `phi` instructions back to the main loop body.
        //
        // We have to do this here because we need to have emitted the loop body before we can get
        // the values used in the continue block.
        auto phis = continue_blk_phis_.find(continue_id);
        if (phis != continue_blk_phis_.end()) {
            for (auto value_id : phis->second) {
                auto* value = skipped_continue ? nullptr : Value(value_id, false);

                tint::Switch(
                    loop->Continuing()->Terminator(),  //
                    [&](core::ir::NextIteration* ni) { ni->PushOperand(value); },
                    [&](core::ir::BreakIf* bi) {
                        // TODO(dsinclair): Need to change the break-if insertion if there happens
                        // to be exit values, but those are rare, so leave this for when we have
                        // test case.
                        TINT_ASSERT(bi->ExitValues().empty());

                        auto len = bi->NextIterValues().size();
                        bi->PushOperand(value);
                        bi->SetNumNextIterValues(len + 1);
                    },
                    TINT_ICE_ON_NO_MATCH);
            }
        }

        id_stack_.pop_back();
        return Success;
    }

    Result<SuccessType> ProcessInstructions(spvtools::opt::BasicBlock& src) {
        for (auto& inst : src) {
            switch (inst.opcode()) {
                case spv::Op::OpNop:
                    break;
                case spv::Op::OpUndef:
                    AddValue(inst.result_id(), b_.Zero(Type(inst.type_id())));
                    break;
                case spv::Op::OpBranch:
                    TINT_CHECK_RESULT(EmitBranch(inst));
                    break;
                case spv::Op::OpBranchConditional:
                    TINT_CHECK_RESULT(EmitBranchConditional(src, inst));
                    break;
                case spv::Op::OpSwitch:
                    TINT_CHECK_RESULT(EmitSwitch(src, inst));
                    break;
                case spv::Op::OpLoopMerge:
                    EmitLoopMerge(src, inst);
                    break;
                case spv::Op::OpSelectionMerge:
                    // Do nothing, the selection merge will be handled in the following
                    // OpBranchCondition or OpSwitch instruction
                    break;
                case spv::Op::OpExtInst:
                    TINT_CHECK_RESULT(EmitExtInst(inst));
                    break;
                case spv::Op::OpCopyObject:
                    EmitCopyObject(inst);
                    break;
                case spv::Op::OpConvertFToS:
                    EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kConvertFToS);
                    break;
                case spv::Op::OpConvertFToU:
                    EmitOrAdd(b_.Convert(Type(inst.type_id()), Value(inst.GetSingleWordOperand(2))),
                              inst.result_id());
                    break;
                case spv::Op::OpConvertSToF:
                    EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kConvertSToF);
                    break;
                case spv::Op::OpConvertUToF:
                    EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kConvertUToF);
                    break;
                case spv::Op::OpFConvert:
                    EmitOrAdd(b_.Convert(Type(inst.type_id()), Value(inst.GetSingleWordOperand(2))),
                              inst.result_id());
                    break;
                case spv::Op::OpBitwiseAnd:
                    EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kBitwiseAnd);
                    break;
                case spv::Op::OpBitwiseOr:
                    EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kBitwiseOr);
                    break;
                case spv::Op::OpBitwiseXor:
                    EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kBitwiseXor);
                    break;
                case spv::Op::OpAccessChain:
                case spv::Op::OpInBoundsAccessChain:
                    EmitAccess(inst);
                    break;
                case spv::Op::OpCompositeInsert:
                    EmitCompositeInsert(inst);
                    break;
                case spv::Op::OpCompositeConstruct:
                    EmitConstruct(inst);
                    break;
                case spv::Op::OpCompositeExtract:
                    EmitCompositeExtract(inst);
                    break;
                case spv::Op::OpVectorInsertDynamic:
                    EmitVectorInsertDynamic(inst);
                    break;
                case spv::Op::OpFAdd:
                    EmitBinary(inst, core::BinaryOp::kAdd);
                    break;
                case spv::Op::OpIAdd:
                    EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kAdd);
                    break;
                case spv::Op::OpSDiv:
                    EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kSDiv);
                    break;
                case spv::Op::OpFDiv:
                case spv::Op::OpUDiv:
                    EmitBinary(inst, core::BinaryOp::kDivide);
                    break;
                case spv::Op::OpIMul:
                    EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kMul);
                    break;
                case spv::Op::OpFMul:
                case spv::Op::OpVectorTimesScalar:
                case spv::Op::OpMatrixTimesScalar:
                case spv::Op::OpVectorTimesMatrix:
                case spv::Op::OpMatrixTimesVector:
                case spv::Op::OpMatrixTimesMatrix:
                    EmitBinary(inst, core::BinaryOp::kMultiply);
                    break;
                case spv::Op::OpFRem:
                case spv::Op::OpUMod:
                    EmitBinary(inst, core::BinaryOp::kModulo);
                    break;
                case spv::Op::OpSMod:
                case spv::Op::OpSRem:
                    EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kSMod);
                    break;
                case spv::Op::OpFSub:
                    EmitBinary(inst, core::BinaryOp::kSubtract);
                    break;
                case spv::Op::OpFOrdEqual:
                    EmitBinary(inst, core::BinaryOp::kEqual);
                    break;
                case spv::Op::OpFOrdNotEqual:
                    EmitBinary(inst, core::BinaryOp::kNotEqual);
                    break;
                case spv::Op::OpFOrdGreaterThan:
                    EmitBinary(inst, core::BinaryOp::kGreaterThan);
                    break;
                case spv::Op::OpFOrdGreaterThanEqual:
                    EmitBinary(inst, core::BinaryOp::kGreaterThanEqual);
                    break;
                case spv::Op::OpFOrdLessThan:
                    EmitBinary(inst, core::BinaryOp::kLessThan);
                    break;
                case spv::Op::OpFOrdLessThanEqual:
                    EmitBinary(inst, core::BinaryOp::kLessThanEqual);
                    break;
                case spv::Op::OpFUnordEqual:
                    EmitInvertedBinary(inst, core::BinaryOp::kNotEqual);
                    break;
                case spv::Op::OpFUnordNotEqual:
                    EmitInvertedBinary(inst, core::BinaryOp::kEqual);
                    break;
                case spv::Op::OpFUnordGreaterThan:
                    EmitInvertedBinary(inst, core::BinaryOp::kLessThanEqual);
                    break;
                case spv::Op::OpFUnordGreaterThanEqual:
                    EmitInvertedBinary(inst, core::BinaryOp::kLessThan);
                    break;
                case spv::Op::OpFUnordLessThan:
                    EmitInvertedBinary(inst, core::BinaryOp::kGreaterThanEqual);
                    break;
                case spv::Op::OpFUnordLessThanEqual:
                    EmitInvertedBinary(inst, core::BinaryOp::kGreaterThan);
                    break;
                case spv::Op::OpIEqual:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kEqual);
                    break;
                case spv::Op::OpINotEqual:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kNotEqual);
                    break;
                case spv::Op::OpSGreaterThan:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kSGreaterThan);
                    break;
                case spv::Op::OpSGreaterThanEqual:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kSGreaterThanEqual);
                    break;
                case spv::Op::OpSLessThan:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kSLessThan);
                    break;
                case spv::Op::OpSLessThanEqual:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kSLessThanEqual);
                    break;
                case spv::Op::OpUGreaterThan:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kUGreaterThan);
                    break;
                case spv::Op::OpUGreaterThanEqual:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kUGreaterThanEqual);
                    break;
                case spv::Op::OpULessThan:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kULessThan);
                    break;
                case spv::Op::OpULessThanEqual:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kULessThanEqual);
                    break;
                case spv::Op::OpISub:
                    EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kSub);
                    break;
                case spv::Op::OpFunctionCall:
                    EmitFunctionCall(inst);
                    break;
                case spv::Op::OpLoad:
                    Emit(b_.Load(Value(inst.GetSingleWordOperand(2))), inst.result_id());
                    break;
                case spv::Op::OpReturn:
                    EmitWithoutResult(b_.Return(current_function_));
                    break;
                case spv::Op::OpReturnValue:
                    EmitWithoutResult(
                        b_.Return(current_function_, Value(inst.GetSingleWordOperand(0))));
                    break;
                case spv::Op::OpStore:
                    EmitWithoutResult(b_.Store(Value(inst.GetSingleWordOperand(0)),
                                               Value(inst.GetSingleWordOperand(1))));
                    break;
                case spv::Op::OpCopyMemory:
                    EmitCopyMemory(inst);
                    break;
                case spv::Op::OpVariable:
                    TINT_CHECK_RESULT(EmitVar(inst));
                    break;
                case spv::Op::OpUnreachable:
                    EmitWithoutResult(b_.Unreachable());
                    break;
                case spv::Op::OpKill:
                case spv::Op::OpTerminateInvocation:
                    EmitKill(inst);
                    break;
                case spv::Op::OpDot:
                    EmitBuiltinCall(inst, core::BuiltinFn::kDot);
                    break;
                case spv::Op::OpBitCount:
                    EmitBitCount(inst);
                    break;
                case spv::Op::OpBitFieldInsert:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kBitFieldInsert);
                    break;
                case spv::Op::OpBitFieldSExtract:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kBitFieldSExtract);
                    break;
                case spv::Op::OpBitFieldUExtract:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kBitFieldUExtract);
                    break;
                case spv::Op::OpBitReverse:
                    EmitBuiltinCall(inst, core::BuiltinFn::kReverseBits);
                    break;
                case spv::Op::OpAll:
                    EmitBuiltinCall(inst, core::BuiltinFn::kAll);
                    break;
                case spv::Op::OpAny:
                    EmitBuiltinCall(inst, core::BuiltinFn::kAny);
                    break;
                case spv::Op::OpDPdx:
                    EmitBuiltinCall(inst, core::BuiltinFn::kDpdx);
                    break;
                case spv::Op::OpDPdy:
                    EmitBuiltinCall(inst, core::BuiltinFn::kDpdy);
                    break;
                case spv::Op::OpFwidth:
                    EmitBuiltinCall(inst, core::BuiltinFn::kFwidth);
                    break;
                case spv::Op::OpDPdxFine:
                    EmitBuiltinCall(inst, core::BuiltinFn::kDpdxFine);
                    break;
                case spv::Op::OpDPdyFine:
                    EmitBuiltinCall(inst, core::BuiltinFn::kDpdyFine);
                    break;
                case spv::Op::OpFwidthFine:
                    EmitBuiltinCall(inst, core::BuiltinFn::kFwidthFine);
                    break;
                case spv::Op::OpDPdxCoarse:
                    EmitBuiltinCall(inst, core::BuiltinFn::kDpdxCoarse);
                    break;
                case spv::Op::OpDPdyCoarse:
                    EmitBuiltinCall(inst, core::BuiltinFn::kDpdyCoarse);
                    break;
                case spv::Op::OpFwidthCoarse:
                    EmitBuiltinCall(inst, core::BuiltinFn::kFwidthCoarse);
                    break;
                case spv::Op::OpLogicalAnd:
                    EmitBinary(inst, core::BinaryOp::kAnd);
                    break;
                case spv::Op::OpLogicalOr:
                    EmitBinary(inst, core::BinaryOp::kOr);
                    break;
                case spv::Op::OpLogicalEqual:
                    EmitBinary(inst, core::BinaryOp::kEqual);
                    break;
                case spv::Op::OpLogicalNotEqual:
                    EmitBinary(inst, core::BinaryOp::kNotEqual);
                    break;
                case spv::Op::OpLogicalNot:
                    EmitUnary(inst, core::UnaryOp::kNot);
                    break;
                case spv::Op::OpFNegate:
                    EmitUnary(inst, core::UnaryOp::kNegation);
                    break;
                case spv::Op::OpNot:
                    EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kNot);
                    break;
                case spv::Op::OpShiftLeftLogical:
                    EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kShiftLeftLogical);
                    break;
                case spv::Op::OpShiftRightLogical:
                    EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kShiftRightLogical);
                    break;
                case spv::Op::OpShiftRightArithmetic:
                    EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kShiftRightArithmetic);
                    break;
                case spv::Op::OpBitcast:
                    EmitBitcast(inst);
                    break;
                case spv::Op::OpQuantizeToF16:
                    EmitBuiltinCall(inst, core::BuiltinFn::kQuantizeToF16);
                    break;
                case spv::Op::OpTranspose:
                    EmitBuiltinCall(inst, core::BuiltinFn::kTranspose);
                    break;
                case spv::Op::OpSNegate:
                    EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kSNegate);
                    break;
                case spv::Op::OpFMod:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kFMod);
                    break;
                case spv::Op::OpSelect:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kSelect);
                    break;
                case spv::Op::OpVectorExtractDynamic:
                    EmitAccess(inst);
                    break;
                case spv::Op::OpOuterProduct:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kOuterProduct);
                    break;
                case spv::Op::OpVectorShuffle:
                    EmitVectorShuffle(inst);
                    break;
                case spv::Op::OpAtomicStore:
                    EmitAtomicStore(inst);
                    break;
                case spv::Op::OpAtomicLoad:
                    CheckAtomicNotFloat(inst);
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicLoad);
                    break;
                case spv::Op::OpAtomicIAdd:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicIAdd);
                    break;
                case spv::Op::OpAtomicISub:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicISub);
                    break;
                case spv::Op::OpAtomicAnd:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicAnd);
                    break;
                case spv::Op::OpAtomicOr:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicOr);
                    break;
                case spv::Op::OpAtomicXor:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicXor);
                    break;
                case spv::Op::OpAtomicSMin:
                    EmitAtomicSigned(inst, spirv::BuiltinFn::kAtomicSMin);
                    break;
                case spv::Op::OpAtomicUMin:
                    EmitAtomicUnsigned(inst, spirv::BuiltinFn::kAtomicUMin);
                    break;
                case spv::Op::OpAtomicSMax:
                    EmitAtomicSigned(inst, spirv::BuiltinFn::kAtomicSMax);
                    break;
                case spv::Op::OpAtomicUMax:
                    EmitAtomicUnsigned(inst, spirv::BuiltinFn::kAtomicUMax);
                    break;
                case spv::Op::OpAtomicExchange:
                    CheckAtomicNotFloat(inst);
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicExchange);
                    break;
                case spv::Op::OpAtomicCompareExchange:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicCompareExchange);
                    break;
                case spv::Op::OpAtomicIIncrement:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicIIncrement);
                    break;
                case spv::Op::OpAtomicIDecrement:
                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicIDecrement);
                    break;
                case spv::Op::OpControlBarrier:
                    EmitControlBarrier(inst);
                    break;
                case spv::Op::OpArrayLength:
                    EmitArrayLength(inst);
                    break;
                case spv::Op::OpSampledImage:
                    EmitSampledImage(inst);
                    break;
                case spv::Op::OpImage:
                    EmitImage(inst);
                    break;
                case spv::Op::OpImageFetch:
                    EmitImageFetchOrRead(inst, spirv::BuiltinFn::kImageFetch);
                    break;
                case spv::Op::OpImageRead:
                    EmitImageFetchOrRead(inst, spirv::BuiltinFn::kImageRead);
                    break;
                case spv::Op::OpImageGather:
                    EmitImageGather(inst);
                    break;
                case spv::Op::OpImageQueryLevels:
                    EmitImageQuery(inst, spirv::BuiltinFn::kImageQueryLevels);
                    break;
                case spv::Op::OpImageQuerySamples:
                    EmitImageQuery(inst, spirv::BuiltinFn::kImageQuerySamples);
                    break;
                case spv::Op::OpImageQuerySize:
                    EmitImageQuery(inst, spirv::BuiltinFn::kImageQuerySize);
                    break;
                case spv::Op::OpImageQuerySizeLod:
                    EmitImageQuerySizeLod(inst);
                    break;
                case spv::Op::OpImageSampleExplicitLod:
                    EmitImageSample(inst, spirv::BuiltinFn::kImageSampleExplicitLod);
                    break;
                case spv::Op::OpImageSampleImplicitLod:
                    EmitImageSample(inst, spirv::BuiltinFn::kImageSampleImplicitLod);
                    break;
                case spv::Op::OpImageSampleProjImplicitLod:
                    EmitImageSample(inst, spirv::BuiltinFn::kImageSampleProjImplicitLod);
                    break;
                case spv::Op::OpImageSampleProjExplicitLod:
                    EmitImageSample(inst, spirv::BuiltinFn::kImageSampleProjExplicitLod);
                    break;
                case spv::Op::OpImageWrite:
                    EmitImageWrite(inst);
                    break;
                case spv::Op::OpImageSampleDrefImplicitLod:
                    EmitImageSampleDepth(inst, spirv::BuiltinFn::kImageSampleDrefImplicitLod);
                    break;
                case spv::Op::OpImageSampleDrefExplicitLod:
                    EmitImageSampleDepth(inst, spirv::BuiltinFn::kImageSampleDrefExplicitLod);
                    break;
                case spv::Op::OpImageSampleProjDrefImplicitLod:
                    EmitImageSampleDepth(inst, spirv::BuiltinFn::kImageSampleProjDrefImplicitLod);
                    break;
                case spv::Op::OpImageSampleProjDrefExplicitLod:
                    EmitImageSampleDepth(inst, spirv::BuiltinFn::kImageSampleProjDrefExplicitLod);
                    break;
                case spv::Op::OpImageDrefGather:
                    EmitImageGatherDref(inst);
                    break;
                case spv::Op::OpPhi:
                    EmitPhi(inst);
                    break;

                case spv::Op::OpGroupNonUniformBroadcast:
                    EmitSubgroupBuiltinConstantId(inst,
                                                  spirv::BuiltinFn::kGroupNonUniformBroadcast);
                    break;
                case spv::Op::OpGroupNonUniformQuadBroadcast:
                    EmitSubgroupBuiltinConstantId(inst,
                                                  spirv::BuiltinFn::kGroupNonUniformQuadBroadcast);
                    break;
                case spv::Op::OpGroupNonUniformQuadSwap:
                    EmitSubgroupBuiltinConstantId(inst, spirv::BuiltinFn::kGroupNonUniformQuadSwap);
                    break;
                case spv::Op::OpGroupNonUniformAll:
                    EmitSubgroupBuiltin(inst, core::BuiltinFn::kSubgroupAll);
                    break;
                case spv::Op::OpGroupNonUniformAllEqual:
                    EmitSubgroupAllEqual(inst);
                    break;
                case spv::Op::OpGroupNonUniformAny:
                    EmitSubgroupBuiltin(inst, core::BuiltinFn::kSubgroupAny);
                    break;
                case spv::Op::OpGroupNonUniformElect:
                    EmitSubgroupBuiltin(inst, core::BuiltinFn::kSubgroupElect);
                    break;
                case spv::Op::OpGroupNonUniformBallot:
                    EmitSubgroupBuiltin(inst, core::BuiltinFn::kSubgroupBallot);
                    break;
                case spv::Op::OpGroupNonUniformBallotBitCount:
                    TINT_CHECK_RESULT(EmitSubgroupBallotBitCount(inst));
                    break;
                case spv::Op::OpGroupNonUniformBroadcastFirst:
                    EmitSubgroupBuiltin(inst, spirv::BuiltinFn::kGroupNonUniformBroadcastFirst);
                    break;
                case spv::Op::OpGroupNonUniformShuffle:
                    EmitSubgroupBuiltin(inst, spirv::BuiltinFn::kGroupNonUniformShuffle);
                    break;
                case spv::Op::OpGroupNonUniformShuffleXor:
                    EmitSubgroupBuiltin(inst, spirv::BuiltinFn::kGroupNonUniformShuffleXor);
                    break;
                case spv::Op::OpGroupNonUniformShuffleDown:
                    EmitSubgroupBuiltin(inst, spirv::BuiltinFn::kGroupNonUniformShuffleDown);
                    break;
                case spv::Op::OpGroupNonUniformShuffleUp:
                    EmitSubgroupBuiltin(inst, spirv::BuiltinFn::kGroupNonUniformShuffleUp);
                    break;
                case spv::Op::OpGroupNonUniformSMin:
                    EmitSubgroupMinMax(inst, spirv::BuiltinFn::kGroupNonUniformSMin);
                    break;
                case spv::Op::OpGroupNonUniformSMax:
                    EmitSubgroupMinMax(inst, spirv::BuiltinFn::kGroupNonUniformSMax);
                    break;
                case spv::Op::OpGroupNonUniformUMin:
                case spv::Op::OpGroupNonUniformFMin:
                    EmitSubgroupMinMax(inst, core::BuiltinFn::kSubgroupMin);
                    break;
                case spv::Op::OpGroupNonUniformUMax:
                case spv::Op::OpGroupNonUniformFMax:
                    EmitSubgroupMinMax(inst, core::BuiltinFn::kSubgroupMax);
                    break;
                case spv::Op::OpGroupNonUniformIAdd:
                case spv::Op::OpGroupNonUniformFAdd:
                    EmitSubgroupAdd(inst);
                    break;
                case spv::Op::OpGroupNonUniformIMul:
                case spv::Op::OpGroupNonUniformFMul:
                    EmitSubgroupMul(inst);
                    break;
                case spv::Op::OpGroupNonUniformBitwiseAnd:
                    EmitSubgroupBitwise(inst, core::BuiltinFn::kSubgroupAnd);
                    break;
                case spv::Op::OpGroupNonUniformBitwiseOr:
                    EmitSubgroupBitwise(inst, core::BuiltinFn::kSubgroupOr);
                    break;
                case spv::Op::OpGroupNonUniformBitwiseXor:
                    EmitSubgroupBitwise(inst, core::BuiltinFn::kSubgroupXor);
                    break;
                case spv::Op::OpIsNan:
                    return Failure(
                        "IsNan is not supported because NaNs cannot be represented in WGSL");
                case spv::Op::OpIsInf:
                    return Failure(
                        "IsInf is not supported because Infinities cannot be represented in WGSL");
                default:
                    return Failure("unhandled SPIR-V instruction: " +
                                   std::string(spv::OpToString(inst.opcode())) + " (val = " +
                                   std::to_string(static_cast<uint32_t>(inst.opcode())) + ")");
            }
        }
        return Success;
    }

    void ValidateScope(spvtools::opt::Instruction& inst) {
        auto scope_val = Value(inst.GetSingleWordInOperand(0));
        auto* cnst = scope_val->As<core::ir::Constant>();
        TINT_ASSERT(cnst);

        uint32_t scope = cnst->Value()->ValueAs<uint32_t>();
        TINT_ASSERT(static_cast<spv::Scope>(scope) == spv::Scope::Subgroup)
            << "subgroup scope required for GroupNonUniform instructions";
    }

    void EmitOrAdd(core::ir::Value* value, uint32_t result_id) {
        if (auto* inst = value->AsInstruction()) {
            Emit(inst, result_id);
        } else {
            AddValue(result_id, value);
        }
    }

    void EmitSubgroupBitwise(spvtools::opt::Instruction& inst, core::BuiltinFn fn) {
        ValidateScope(inst);

        auto group = inst.GetSingleWordInOperand(1);
        TINT_ASSERT(static_cast<spv::GroupOperation>(group) == spv::GroupOperation::Reduce)
            << "GroupNonUniformBitwise operations require a Reduce group operation";

        EmitOrAdd(b_.Call(Type(inst.type_id()), fn, Args(inst, 4)), inst.result_id());
    }

    void EmitSubgroupMul(spvtools::opt::Instruction& inst) {
        ValidateScope(inst);

        core::BuiltinFn fn = core::BuiltinFn::kNone;

        auto group = inst.GetSingleWordInOperand(1);
        if (static_cast<spv::GroupOperation>(group) == spv::GroupOperation::Reduce) {
            fn = core::BuiltinFn::kSubgroupMul;
        } else if (static_cast<spv::GroupOperation>(group) == spv::GroupOperation::InclusiveScan) {
            fn = core::BuiltinFn::kSubgroupInclusiveMul;
        } else if (static_cast<spv::GroupOperation>(group) == spv::GroupOperation::ExclusiveScan) {
            fn = core::BuiltinFn::kSubgroupExclusiveMul;
        } else {
            TINT_ICE() << "GroupNonUniform Mul instruction must have a group of `Reduce`, "
                          "`InclusiveScan`, or `ExclusiveScan`";
        }

        EmitOrAdd(b_.Call(Type(inst.type_id()), fn, Args(inst, 4)), inst.result_id());
    }

    void EmitSubgroupAdd(spvtools::opt::Instruction& inst) {
        ValidateScope(inst);

        core::BuiltinFn fn = core::BuiltinFn::kNone;

        auto group = inst.GetSingleWordInOperand(1);
        if (static_cast<spv::GroupOperation>(group) == spv::GroupOperation::Reduce) {
            fn = core::BuiltinFn::kSubgroupAdd;
        } else if (static_cast<spv::GroupOperation>(group) == spv::GroupOperation::InclusiveScan) {
            fn = core::BuiltinFn::kSubgroupInclusiveAdd;
        } else if (static_cast<spv::GroupOperation>(group) == spv::GroupOperation::ExclusiveScan) {
            fn = core::BuiltinFn::kSubgroupExclusiveAdd;
        } else {
            TINT_ICE() << "GroupNonUniform Add instruction must have a group of `Reduce`, "
                          "`InclusiveScan`, or `ExclusiveScan`";
        }

        EmitOrAdd(b_.Call(Type(inst.type_id()), fn, Args(inst, 4)), inst.result_id());
    }

    void EmitSubgroupMinMax(spvtools::opt::Instruction& inst, core::BuiltinFn fn) {
        ValidateScope(inst);

        auto group = inst.GetSingleWordInOperand(1);
        TINT_ASSERT(static_cast<spv::GroupOperation>(group) == spv::GroupOperation::Reduce)
            << "group operand Reduce required for `Min`/`Max` instructions";

        EmitOrAdd(b_.Call(Type(inst.type_id()), fn, Args(inst, 4)), inst.result_id());
    }

    void EmitSubgroupMinMax(spvtools::opt::Instruction& inst, spirv::BuiltinFn fn) {
        ValidateScope(inst);

        auto group = inst.GetSingleWordInOperand(1);
        TINT_ASSERT(static_cast<spv::GroupOperation>(group) == spv::GroupOperation::Reduce)
            << "group operand Reduce required for `Min`/`Max` instructions";

        Emit(
            b_.Call<spirv::ir::BuiltinCall>(Type(inst.type_id()), fn,                      //
                                            Vector{Value(inst.GetSingleWordInOperand(0)),  //
                                                   b_.Constant(u32(inst.GetSingleWordInOperand(1))),
                                                   Value(inst.GetSingleWordInOperand(2))}),
            inst.result_id());
    }

    void EmitSubgroupBuiltinConstantId(spvtools::opt::Instruction& inst, spirv::BuiltinFn fn) {
        auto id = Value(inst.GetSingleWordInOperand(2));

        // TODO(431054356): Convert core::BuiltinFn::kSubgroupBroadcast non-constant values into a
        // `subgroupShuffle` when we support SPIR-V >= 1.5 source.
        //
        // For QuadBroadcast this will remain an error as there is no WGSL equivalent.
        // For QuadSwap this will remain an error as there is no WGSL equivalent.
        TINT_ASSERT(id->Is<core::ir::Constant>())
            << "non-constant GroupNonUniform `Invocation Id` not supported";

        ValidateScope(inst);
        Emit(b_.Call<spirv::ir::BuiltinCall>(Type(inst.type_id()), fn, Args(inst, 2)),
             inst.result_id());
    }

    void EmitSubgroupBuiltin(spvtools::opt::Instruction& inst, spirv::BuiltinFn fn) {
        ValidateScope(inst);
        Emit(b_.Call<spirv::ir::BuiltinCall>(Type(inst.type_id()), fn, Args(inst, 2)),
             inst.result_id());
    }

    void EmitSubgroupBuiltin(spvtools::opt::Instruction& inst, core::BuiltinFn fn) {
        ValidateScope(inst);
        EmitOrAdd(b_.Call(Type(inst.type_id()), fn, Args(inst, 3)), inst.result_id());
    }

    Result<SuccessType> EmitSubgroupBallotBitCount(spvtools::opt::Instruction& inst) {
        ValidateScope(inst);

        auto ballot_id = inst.GetSingleWordInOperand(2);
        auto* ballot_inst = spirv_context_->get_def_use_mgr()->GetDef(ballot_id);
        if (!ballot_inst || ballot_inst->opcode() != spv::Op::OpGroupNonUniformBallot) {
            return Failure(
                "OpGroupNonUniformBallotBitCount is only supported when Value is from "
                "OpGroupNonUniformBallot");
        }

        auto group = inst.GetSingleWordInOperand(1);
        auto group_op = static_cast<spv::GroupOperation>(group);

        core::BuiltinFn fn = core::BuiltinFn::kNone;
        switch (group_op) {
            case spv::GroupOperation::Reduce:
                fn = core::BuiltinFn::kSubgroupAdd;
                break;
            case spv::GroupOperation::InclusiveScan:
                fn = core::BuiltinFn::kSubgroupInclusiveAdd;
                break;
            case spv::GroupOperation::ExclusiveScan:
                fn = core::BuiltinFn::kSubgroupExclusiveAdd;
                break;
            default:
                TINT_UNREACHABLE();
        }

        auto* pred_val = Value(ballot_inst->GetSingleWordInOperand(1));
        auto* conv = b_.Convert<u32>(pred_val);
        EmitWithoutSpvResult(conv);

        EmitOrAdd(b_.Call(Type(inst.type_id()), fn, conv), inst.result_id());
        return Success;
    }

    void EmitSubgroupAllEqual(spvtools::opt::Instruction& inst) {
        ValidateScope(inst);

        auto* val = Value(inst.GetSingleWordInOperand(1));
        auto* first = b_.Call<spirv::ir::BuiltinCall>(
            val->Type(), spirv::BuiltinFn::kGroupNonUniformBroadcastFirst,
            Vector{Value(inst.GetSingleWordInOperand(0)), val});
        EmitWithoutSpvResult(first->Result());

        // If NaNs and INFs are supported in the future, this lowering will remain correct as long
        // as floating-point equality comparisons use ordered-and-equal (OpFOrdEqual) semantics.
        auto* eq = b_.Equal(val, first);
        EmitWithoutSpvResult(eq);

        core::ir::Value* eq_val = eq;
        if (val->Type()->Is<core::type::Vector>()) {
            auto* all_call = b_.Call(ty_.bool_(), core::BuiltinFn::kAll, eq);
            EmitWithoutSpvResult(all_call);
            eq_val = all_call;
        }

        EmitOrAdd(b_.Call(ty_.bool_(), core::BuiltinFn::kSubgroupAll, eq_val), inst.result_id());
    }

    struct IfBranchValue {
        core::ir::Value* value;
        core::ir::If* if_;
    };

    void EmitPhi(spvtools::opt::Instruction& inst) {
        auto num_ops = inst.NumInOperands();

        // If there are no operands, then the phi is in a unreachable block, ignore it.
        if (num_ops == 0) {
            return;
        }

        // If there are only 2 arguments, that means we came directly from a block, so just emit the
        // value directly.
        if (num_ops == 2) {
            AddValue(inst.result_id(), Value(inst.GetSingleWordInOperand(0)));
            return;
        }

        auto* phi_containing_spirv_block = spirv_context_->get_instr_block(&inst);
        auto iter = spirv_merge_id_to_header_id_.find(phi_containing_spirv_block->id());

        // We're in a merge block for some construct which could be a loop, switch or if.
        if (iter != spirv_merge_id_to_header_id_.end()) {
            auto parent_blk_id = iter->second;
            auto* parent_blk = spirv_context_->get_instr_block(parent_blk_id);

            if (parent_blk->terminator()->opcode() == spv::Op::OpSwitch) {
                EmitPhiInSwitchMerge(inst, parent_blk_id);
                return;
            }
            if (!parent_blk->IsLoopHeader()) {
                EmitPhiInIfMerge(inst, parent_blk_id);
                return;
            }
        }

        // At this point, we must be dealing with an OpPhi in some kind of loop context, the loop
        // header, loop continuing or loop merge construct.
        EmitPhiInLoop(inst);
    }

    void EmitPhiInLoop(spvtools::opt::Instruction& inst) {
        auto* phi_containing_spirv_block = spirv_context_->get_instr_block(&inst);

        auto iter = spirv_merge_id_to_header_id_.find(phi_containing_spirv_block->id());
        // We're in the merge block for the loop
        if (iter != spirv_merge_id_to_header_id_.end()) {
            EmitPhiInLoopMerge(inst);
            return;
        }

        // The OpPhi is in the loop header, which means it's the body of the loop. The OpPhi can
        // receive values from the parent block, in which case we need to push them through the
        // initializer, or from the continuing block, which we will not have emitted yet.
        if (phi_containing_spirv_block->IsLoopHeader()) {
            EmitPhiInLoopHeader(inst, phi_containing_spirv_block);
            return;
        }

        auto containing_loop_header_id = spirv_context_->GetStructuredCFGAnalysis()->ContainingLoop(
            phi_containing_spirv_block->id());
        auto* loop_header_block = spirv_context_->get_instr_block(containing_loop_header_id);
        TINT_ASSERT(loop_header_block);

        auto* loop_merge_inst = loop_header_block->GetLoopMergeInst();
        auto continue_id = loop_merge_inst->GetSingleWordInOperand(1);

        // If the spirv-id to block table contains an entry for the continue id then we must have
        // started emitting the continue.
        bool has_continue_emitted = spirv_id_to_block_.contains(continue_id);
        if (!has_continue_emitted) {
            EmitPhiInLoopBody(inst, loop_merge_inst);
            return;
        }

        // The OpPhi is in the continue block of the loop.
        EmitPhiInLoopContinue(inst);
    }

    void AddOperandToTerminator(core::ir::Terminator* term, uint32_t id) {
        // If the ID is a constant, then we just directly emit it, it isn't an OpPhi value
        if (IdIsConstant(id)) {
            term->PushOperand(Value(id, false));
            return;
        }
        // If we've already seen the value, then we can emit it as this isn't referencing a later
        // value.
        auto val = values_.Get(id);
        if (val) {
            // If we've already seen the value, and it's still in scope, then we can just emit as it
            // isn't referencing a later value.
            if (IdIsInScope(id) || (*val)->Is<core::ir::FunctionParam>()) {
                term->PushOperand(Value(id, false));
                return;
            }

            // The value was a block param, that means it was a Phi which we've removed and
            // converted. We need to pass that Phi out of the control instruction, but we only want
            // to add it to exit instructions, not all terminators, so this isn't a full
            // Propagation.
            if (auto* bp = (*val)->As<core::ir::BlockParam>()) {
                auto* v = PropagateTerm(term, id, bp, bp->Block());
                term->PushOperand(v);
                return;
            }
            // The value is defined by an instruction inside an inner block. Propagate it out of
            // that block, then push that propagated value onto this terminator.
            if (auto* res = (*val)->As<core::ir::InstructionResult>()) {
                auto* v = PropagateTerm(term, id, *val, res->Instruction()->Block());
                term->PushOperand(v);
                return;
            }
        }

        // Value isn't known, or isn't in scope, push a placeholder for the operand value. We store
        // away the terminator/index pair along with the required value and then fill it in at the
        // end of the block emission.
        auto operand_idx = term->PushOperand(nullptr);
        values_to_replace_.back().push_back(ReplacementValue{
            .terminator = term,
            .idx = operand_idx,
            .value_id = id,
        });
    }

    void EmitPhiInLoopMerge(spvtools::opt::Instruction& inst) {
        // All of the source blocks should exist as they will either be the loop header, if we
        // happened to jump out early, the body if we break or the continuing if we break-if.
        auto* type = Type(inst.type_id());

        auto* phi_spirv_block = spirv_context_->get_instr_block(&inst);
        auto phi_blk_id = phi_spirv_block->id();

        // The merge target (which is the OpPhi SPIR-V block) is a walk stop block
        auto* loop = StopWalkingAt(phi_spirv_block->id())->As<core::ir::Loop>();
        TINT_ASSERT(loop);

        std::optional<uint32_t> default_value = std::nullopt;

        // The only way into the continue should be through `continue` calls out of the loop body,
        // which should all exist at this point as we emit the body first.
        for (uint32_t i = 0; i < inst.NumInOperands(); i += 2) {
            auto value_id = inst.GetSingleWordInOperand(i);
            auto blk_id = inst.GetSingleWordInOperand(i + 1);

            core::ir::Terminator* term = nullptr;

            // If the basic block ends in a branch conditional, then we really need to update the
            // branch which goes to the current block, not the terminator of the block we emitted
            // into. This difference is because the merge block will _also_ end up in the same IR
            // block and we can't tell the difference if we just get the terminator.
            const auto& bb = current_spirv_function_->FindBlock(blk_id);
            auto* terminator = (*bb).terminator();
            if (terminator->opcode() == spv::Op::OpBranchConditional) {
                uint32_t true_id = terminator->GetSingleWordInOperand(1);
                uint32_t false_id = terminator->GetSingleWordInOperand(2);

                auto iter = branch_conditional_to_if_.find(terminator);
                if (iter != branch_conditional_to_if_.end()) {
                    auto* if_ = iter->second;
                    if (true_id == phi_blk_id) {
                        term = if_->True()->Terminator();
                    } else if (false_id == phi_blk_id) {
                        term = if_->False()->Terminator();
                    }
                }
            }

            if (term == nullptr) {
                auto value_blk_iter = spirv_id_to_block_.find(blk_id);
                auto* value_ir_blk = value_blk_iter->second;
                term = value_ir_blk->Terminator();
            }

            if (term->Is<core::ir::Unreachable>()) {
                default_value = value_id;
                continue;
            }
            // Continue isn't a terminator into a merge. So, we must have had a branch conditional
            // where one branch continued and the other exited. We need to update the exiting block
            // as the terminator.
            if (term->Is<core::ir::Continue>()) {
                auto* if_ = term->prev->As<core::ir::If>();
                TINT_ASSERT(if_);

                if (if_->True()->Terminator()->Is<core::ir::ExitLoop>()) {
                    term = if_->True()->Terminator();
                } else {
                    term = if_->False()->Terminator();
                    TINT_ASSERT(term->Is<core::ir::ExitLoop>());
                }
            }

            AddOperandToTerminator(term, value_id);
        }

        auto* res = b_.InstructionResult(type);
        loop->AddResult(res);
        AddValue(inst.result_id(), res);

        // If there is a default value, then one of the blocks was an unreachable at the end. We
        // need to find exits where we haven't set all the params and add the default.
        if (default_value) {
            auto result_count = loop->Results().Length();
            for (auto iter : loop->Exits()) {
                if (iter->Operands().Length() >= result_count) {
                    continue;
                }

                // We haven't updated the exit yet
                auto* term = iter->As<core::ir::Terminator>();
                TINT_ASSERT(term);

                AddOperandToTerminator(term, default_value.value());
            }
        }
    }

    void EmitPhiInLoopContinue(spvtools::opt::Instruction& inst) {
        auto* type = Type(inst.type_id());

        auto* phi_spirv_block = spirv_context_->get_instr_block(&inst);

        // The continue target is a walk stop block
        auto* loop = StopWalkingAt(phi_spirv_block->id())->As<core::ir::Loop>();
        TINT_ASSERT(loop);

        std::optional<uint32_t> default_value = std::nullopt;

        // The only way into the continue should be through `continue` calls out of the loop body,
        // which should all exist at this point as we emit the body first.
        for (uint32_t i = 0; i < inst.NumInOperands(); i += 2) {
            auto value_id = inst.GetSingleWordInOperand(i);
            auto blk_id = inst.GetSingleWordInOperand(i + 1);

            auto value_blk_iter = spirv_id_to_block_.find(blk_id);
            auto* value_ir_blk = value_blk_iter->second;
            auto* term = value_ir_blk->Terminator();

            if (term->Is<core::ir::Unreachable>()) {
                default_value = value_id;
                continue;
            }

            AddOperandToTerminator(term, value_id);
        }

        // Add the block param to the continuing block
        auto* p = b_.BlockParam(type);
        loop->Continuing()->AddParam(p);
        AddValue(inst.result_id(), p);

        // If there is a default value, then one of the blocks was an unreachable at the end, this
        // can happen if the `OpBranchConditional` has one of the branches to the continue block. We
        // need to find incoming sibling branches where we haven't set all the params and add the
        // default.
        if (default_value) {
            auto param_count = loop->Continuing()->Params().Length();
            for (auto* sibling : loop->Continuing()->InboundSiblingBranches()) {
                if (sibling->Operands().Length() >= param_count) {
                    continue;
                }
                // We haven't updated the sibling yet
                auto* term = sibling->As<core::ir::Terminator>();
                TINT_ASSERT(term);

                AddOperandToTerminator(term, default_value.value());
            }
        }
    }

    void EmitPhiInLoopBody(spvtools::opt::Instruction& inst,
                           spvtools::opt::Instruction* loop_merge_inst) {
        auto continue_id = loop_merge_inst->GetSingleWordInOperand(1);

        auto* loop_header_block = spirv_context_->get_instr_block(loop_merge_inst);

        // The loop continue is a walk stop block. Since we're in the loop body itself we would have
        // added the continue target to the stop blocks when processing the header loop merge.
        auto* loop = StopWalkingAt(continue_id)->As<core::ir::Loop>();
        TINT_ASSERT(loop);

        // The only phi incoming block that makes sense on the body is from the loop header itself.
        // Any other incoming branches must be from unreachable blocks, otherwise it would have had
        // to have come from the loop header which is where the continue target will loop back too,
        // not the body label directly.
        std::optional<core::ir::Value*> value = std::nullopt;
        for (uint32_t i = 0; i < inst.NumInOperands(); i += 2) {
            auto value_id = inst.GetSingleWordInOperand(i);
            auto blk_id = inst.GetSingleWordInOperand(i + 1);

            if (blk_id != loop_header_block->id()) {
                continue;
            }

            value = Value(value_id);
        }
        TINT_ASSERT(value.has_value());
        AddValue(inst.result_id(), value.value());
    }

    void EmitPhiInLoopHeader(spvtools::opt::Instruction& inst,
                             spvtools::opt::BasicBlock* loop_header) {
        // Incoming branches should be from the parent block into the loop, and from the loop
        // continuing back into the header, each with a block_id and a value_id.
        TINT_ASSERT(inst.NumInOperands() == 4);

        auto* type = Type(inst.type_id());

        auto* phi_spirv_block = spirv_context_->get_instr_block(&inst);

        auto* loop_merge_inst = loop_header->GetLoopMergeInst();
        auto continue_id = loop_merge_inst->GetSingleWordInOperand(1);

        // The loop header is a walk stop block.
        auto* loop = StopWalkingAt(phi_spirv_block->id())->As<core::ir::Loop>();
        TINT_ASSERT(loop);

        for (uint32_t i = 0; i < inst.NumInOperands(); i += 2) {
            auto value_id = inst.GetSingleWordInOperand(i);
            auto blk_id = inst.GetSingleWordInOperand(i + 1);

            if (block_phi_values_.contains(blk_id)) {
                block_phi_values_[blk_id].push_back(value_id);
            } else {
                block_phi_values_[blk_id] = {value_id};
            }

            auto v = values_.Get(value_id);
            if (v) {
                // If the value exists, then try to get it to force the propagation. If it doesn't
                // exist, then it will come later in the header and we'll deal with it later.
                Value(value_id);
            }

            core::ir::Terminator* term = nullptr;
            // The referenced block hasn't been emitted yet (continue blocks have this
            // behaviour). So, store the fact that it needs to return a given value away for
            // when we do emit the block.
            //
            // We check both if we've seen the continue block, which if it's a separate block we
            // won't have seen, or if we have seen it (then it's the header itself) if the block is
            // the continue id.
            if (!spirv_id_to_block_.contains(blk_id) || blk_id == continue_id) {
                // If the continue is a separate target, we'll emit it later so just store this
                // value away to add to the next iteration.
                if (continue_id != phi_spirv_block->id()) {
                    continue_blk_phis_[continue_id].push_back(value_id);
                    continue;
                }

                // The loop header is the terminator, so synthesize a continue block and append
                // to that a next iteration.
                if (loop->Continuing()->IsEmpty()) {
                    b_.Append(loop->Continuing(), [&] { term = b_.NextIteration(loop); });
                } else {
                    // With multiple phis we may have already created the continuing
                    // block, so just get the terminator.
                    term = loop->Continuing()->Terminator();
                    TINT_ASSERT(term->Is<core::ir::NextIteration>());
                }

            } else {
                // This is the parent block, push this into the next iteration of the initializer.
                if (loop->Initializer()->IsEmpty()) {
                    b_.Append(loop->Initializer(), [&] { term = b_.NextIteration(loop); });
                } else {
                    term = loop->Initializer()->Terminator();
                    TINT_ASSERT(term->Is<core::ir::NextIteration>());
                }
            }

            AddOperandToTerminator(term, value_id);
        }

        // Add the block param to the body
        auto* p = b_.BlockParam(type);
        loop->Body()->AddParam(p);
        AddValue(inst.result_id(), p);
    }

    // Emit an OpPhi which is inside the merge block for a if.
    void EmitPhiInIfMerge(spvtools::opt::Instruction& inst, uint32_t header_id) {
        auto* type = Type(inst.type_id());
        core::ir::If* ctrl = nullptr;
        std::optional<core::ir::Value*> value_for_default_block = std::nullopt;

        for (uint32_t i = 0; i < inst.NumInOperands(); i += 2) {
            auto value_id = inst.GetSingleWordInOperand(i);
            auto blk_id = inst.GetSingleWordInOperand(i + 1);

            auto value_blk_iter = spirv_id_to_block_.find(blk_id);
            auto* value_ir_blk = value_blk_iter->second;

            // The block refers to the header itself, so it was the true or false branching directly
            // to the merge.
            //
            // We store this away as we may not know the if yet, we need to wait until we get the
            // control instruction and do the work later.
            if (blk_id == header_id) {
                value_for_default_block = Value(value_id);
                continue;
            }

            auto* term = value_ir_blk->Terminator();
            AddOperandToTerminator(term, value_id);

            if (auto* exit = term->As<core::ir::ExitIf>()) {
                if (ctrl) {
                    TINT_ASSERT(ctrl == exit->ControlInstruction());
                } else {
                    ctrl = exit->ControlInstruction()->As<core::ir::If>();
                    TINT_ASSERT(ctrl);
                }
            } else {
                TINT_UNREACHABLE();
            }
        }
        // No control instruction means that both true/false branches are the merge itself, so we
        // can just ignore the if, if we have a default then assign it straight through.
        if (!ctrl) {
            if (value_for_default_block) {
                AddValue(inst.result_id(), value_for_default_block.value());
            }
            return;
        }

        // If the default block needs to be assigned a value
        if (value_for_default_block) {
            core::ir::Terminator* term = nullptr;
            if (ctrl->True()->Terminator()->Operands().Length() <
                ctrl->False()->Terminator()->Operands().Length()) {
                term = ctrl->True()->Terminator();
            } else {
                term = ctrl->False()->Terminator();
            }
            term->PushOperand(value_for_default_block.value());
        }

        // Push the result into the parent
        auto* res = b_.InstructionResult(type);
        ctrl->AddResult(res);
        AddValue(inst.result_id(), res);
    }

    // Emit an OpPhi which is inside the merge block for a switch.
    void EmitPhiInSwitchMerge(spvtools::opt::Instruction& inst, uint32_t header_id) {
        auto* type = Type(inst.type_id());

        core::ir::Switch* ctrl = nullptr;
        std::optional<core::ir::Value*> value_for_default_block = std::nullopt;

        auto phi_blk_id = spirv_context_->get_instr_block(&inst)->id();

        for (uint32_t i = 0; i < inst.NumInOperands(); i += 2) {
            auto value_id = inst.GetSingleWordInOperand(i);
            auto blk_id = inst.GetSingleWordInOperand(i + 1);

            core::ir::Terminator* term = nullptr;

            // If the basic block ends in a branch conditional, then we really need to update the
            // branch which goes to the current block, not the terminator of the block we emitted
            // into. This difference is because the merge block will _also_ end up in the same IR
            // block and we can't tell the difference if we just get the terminator.
            const auto& bb = current_spirv_function_->FindBlock(blk_id);
            auto* terminator = (*bb).terminator();
            if (terminator->opcode() == spv::Op::OpBranchConditional) {
                uint32_t true_id = terminator->GetSingleWordInOperand(1);
                uint32_t false_id = terminator->GetSingleWordInOperand(2);

                auto iter = branch_conditional_to_if_.find(terminator);
                TINT_ASSERT(iter != branch_conditional_to_if_.end());

                auto* if_ = iter->second;
                if (true_id == phi_blk_id) {
                    term = if_->True()->Terminator();
                } else if (false_id == phi_blk_id) {
                    term = if_->False()->Terminator();
                }
            }

            if (term == nullptr) {
                auto value_blk_iter = spirv_id_to_block_.find(blk_id);
                auto* value_ir_blk = value_blk_iter->second;

                // In the case of a switch, the block can refer to the header of the switch, in this
                // case it means we don't have a default block and we jump over the switch itself,
                // so we need to insert this value into the terminator of the default block of the
                // switch.
                //
                // We store this away as we may not know the switch yet, we need to wait until we
                // get the control instruction and do the work later.
                if (blk_id == header_id) {
                    value_for_default_block = Value(value_id);
                    continue;
                }

                term = value_ir_blk->Terminator();
            }

            AddOperandToTerminator(term, value_id);

            if (auto* exit = term->As<core::ir::ExitSwitch>()) {
                if (ctrl) {
                    TINT_ASSERT(ctrl == exit->ControlInstruction());
                } else {
                    ctrl = exit->ControlInstruction()->As<core::ir::Switch>();
                    TINT_ASSERT(ctrl);
                }
            } else {
                TINT_UNREACHABLE();
            }
        }

        // No control instruction means there were no cases, so we can just ignore the switch, if we
        // have a default then assign it straight through.
        if (!ctrl) {
            if (value_for_default_block) {
                AddValue(inst.result_id(), value_for_default_block.value());
            }
            return;
        }

        // If the default block needs to be assigned a value
        if (value_for_default_block) {
            ctrl->DefaultBlock()->Terminator()->PushOperand(value_for_default_block.value());
        }

        // Push the result into the switch
        auto* res = b_.InstructionResult(type);
        ctrl->AddResult(res);
        AddValue(inst.result_id(), res);
    }

    void EmitImage(const spvtools::opt::Instruction& inst) {
        auto* si = Value(inst.GetSingleWordInOperand(0));
        Emit(b_.CallExplicit<spirv::ir::BuiltinCall>(
                 Type(inst.type_id()), spirv::BuiltinFn::kOpImage,
                 Vector<core::ir::TemplateParameter, 1>{
                     si->Type()->As<spirv::type::SampledImage>()->Image()},
                 Args(inst, 2)),
             inst.result_id());
    }

    void EmitSampledImage(const spvtools::opt::Instruction& inst) {
        auto* tex = Value(inst.GetSingleWordInOperand(0));
        auto* img_type = tex->Type()->As<type::Image>();
        TINT_ASSERT(img_type);
        TINT_ASSERT(img_type->GetMultisampled() != type::Multisampled::kMultisampled)
            << "Creating an OpTypeSampledImage from a multisampled image is not supported";
        Emit(b_.CallExplicit<spirv::ir::BuiltinCall>(
                 Type(inst.type_id()), spirv::BuiltinFn::kOpSampledImage,
                 Vector<core::ir::TemplateParameter, 1>{tex->Type()}, Args(inst, 2)),
             inst.result_id());
    }

    void EmitImageFetchOrRead(const spvtools::opt::Instruction& inst, spirv::BuiltinFn fn) {
        auto sampled_image = Value(inst.GetSingleWordInOperand(0));
        auto* coord = Value(inst.GetSingleWordInOperand(1));

        Vector<core::ir::Value*, 4> args = {sampled_image, coord};

        uint32_t literal_mask = inst.NumInOperands() > 2 ? inst.GetSingleWordInOperand(2) : 0u;
        args.Push(Literal(literal_mask));
        if (literal_mask != 0) {
            args.Push(Value(inst.GetSingleWordInOperand(3)));
        }

        Emit(b_.Call<spirv::ir::BuiltinCall>(Type(inst.type_id()), fn, args), inst.result_id());
    }

    void EmitImageGatherDref(const spvtools::opt::Instruction& inst) {
        auto sampled_image = Value(inst.GetSingleWordInOperand(0));
        auto* coord = Value(inst.GetSingleWordInOperand(1));
        auto* dref = Value(inst.GetSingleWordInOperand(2));

        Vector<core::ir::Value*, 4> args = {sampled_image, coord, dref};

        uint32_t literal_mask = inst.NumInOperands() > 3 ? inst.GetSingleWordInOperand(3) : 0u;
        args.Push(Literal(literal_mask));
        if (literal_mask != 0) {
            TINT_ASSERT(static_cast<spv::ImageOperandsMask>(literal_mask) ==
                        spv::ImageOperandsMask::ConstOffset);
            TINT_ASSERT(inst.NumInOperands() > 4);
            args.Push(Value(inst.GetSingleWordInOperand(4)));
        }

        Emit(b_.Call<spirv::ir::BuiltinCall>(Type(inst.type_id()),
                                             spirv::BuiltinFn::kImageDrefGather, args),
             inst.result_id());
    }

    void EmitImageGather(const spvtools::opt::Instruction& inst) {
        auto sampled_image = Value(inst.GetSingleWordInOperand(0));
        auto* coord = Value(inst.GetSingleWordInOperand(1));
        auto* comp = Value(inst.GetSingleWordInOperand(2));

        Vector<core::ir::Value*, 4> args = {sampled_image, coord, comp};

        uint32_t literal_mask = inst.NumInOperands() > 3 ? inst.GetSingleWordInOperand(3) : 0u;
        args.Push(Literal(literal_mask));
        if (literal_mask != 0) {
            TINT_ASSERT(static_cast<spv::ImageOperandsMask>(literal_mask) ==
                        spv::ImageOperandsMask::ConstOffset);
            TINT_ASSERT(inst.NumInOperands() > 4);
            args.Push(Value(inst.GetSingleWordInOperand(4)));
        }

        Emit(b_.Call<spirv::ir::BuiltinCall>(Type(inst.type_id()), spirv::BuiltinFn::kImageGather,
                                             args),
             inst.result_id());
    }

    void EmitImageSample(const spvtools::opt::Instruction& inst, spirv::BuiltinFn fn) {
        auto sampled_image = Value(inst.GetSingleWordInOperand(0));
        auto* coord = Value(inst.GetSingleWordInOperand(1));

        Vector<core::ir::Value*, 4> args = {sampled_image, coord};

        uint32_t literal_mask = inst.NumInOperands() > 2 ? inst.GetSingleWordInOperand(2) : 0u;
        args.Push(Literal(literal_mask));
        TINT_ASSERT(literal_mask == 0 || inst.NumInOperands() > 3);
        for (uint32_t i = 3; i < inst.NumInOperands(); ++i) {
            args.Push(Value(inst.GetSingleWordInOperand(i)));
        }

        Emit(b_.Call<spirv::ir::BuiltinCall>(Type(inst.type_id()), fn, args), inst.result_id());
    }

    bool HasLod(uint32_t mask) {
        return (mask & static_cast<uint32_t>(spv::ImageOperandsMask::Lod)) != 0;
    }

    void EmitImageSampleDepth(const spvtools::opt::Instruction& inst, spirv::BuiltinFn fn) {
        auto sampled_image = Value(inst.GetSingleWordInOperand(0));
        auto* coord = Value(inst.GetSingleWordInOperand(1));
        auto* dref = Value(inst.GetSingleWordInOperand(2));

        Vector<core::ir::Value*, 4> args = {sampled_image, coord, dref};

        uint32_t literal_mask = inst.NumInOperands() > 3 ? inst.GetSingleWordInOperand(3) : 0u;
        args.Push(Literal(literal_mask));
        TINT_ASSERT(literal_mask == 0 || inst.NumInOperands() > 4);
        for (uint32_t i = 4; i < inst.NumInOperands(); ++i) {
            args.Push(Value(inst.GetSingleWordInOperand(i)));
        }

        if (HasLod(literal_mask)) {
            core::ir::Value* lod = args[4];
            TINT_ASSERT(lod->Is<core::ir::Constant>());
            TINT_ASSERT(lod->Type()->As<core::type::F32>());

            auto v = lod->As<core::ir::Constant>()->Value()->ValueAs<float>();
            TINT_ASSERT(v == 0.0f) << "Dref LOD values must be 0.0";
        }

        Emit(b_.Call<spirv::ir::BuiltinCall>(Type(inst.type_id()), fn, args), inst.result_id());
    }

    void EmitImageWrite(const spvtools::opt::Instruction& inst) {
        auto* image = Value(inst.GetSingleWordInOperand(0));
        auto* coord = Value(inst.GetSingleWordInOperand(1));
        core::ir::Value* texel = Value(inst.GetSingleWordInOperand(2));

        // Our intrinsic has a vec4 type, which matches what WGSL expects. Instead of creating more
        // intrinsic entries, just turn the texel into a vec4.
        auto* texel_ty = texel->Type();
        if (texel_ty->IsScalar()) {
            auto* c = b_.Construct(ty_.vec4(texel_ty), texel);
            EmitWithoutSpvResult(c);
            texel = c;
        } else {
            auto* vec_ty = texel_ty->As<core::type::Vector>();
            TINT_ASSERT(vec_ty);

            core::ir::Value* c = nullptr;
            if (vec_ty->Width() == 2) {
                c = b_.Construct(ty_.vec4(vec_ty->Type()), texel, b_.Zero(vec_ty));
            } else if (vec_ty->Width() == 3) {
                c = b_.Construct(ty_.vec4(vec_ty->Type()), texel, b_.Zero(vec_ty->Type()));
            }
            if (c != nullptr) {
                EmitWithoutSpvResult(c);
                texel = c;
            }
        }

        uint32_t literal_mask = inst.NumInOperands() > 3 ? inst.GetSingleWordInOperand(3) : 0u;
        TINT_ASSERT(literal_mask == 0);
        Vector<core::ir::Value*, 4> args = {image, coord, texel, Literal(literal_mask)};
        Emit(b_.Call<spirv::ir::BuiltinCall>(ty_.void_(), spirv::BuiltinFn::kImageWrite, args),
             inst.result_id());
    }

    void EmitImageQuery(const spvtools::opt::Instruction& inst, spirv::BuiltinFn fn) {
        auto* image = Value(inst.GetSingleWordInOperand(0));

        auto* ty = Type(inst.type_id());
        Emit(b_.CallExplicit<spirv::ir::BuiltinCall>(
                 ty, fn, Vector<core::ir::TemplateParameter, 1>{ty->DeepestElement()}, image),
             inst.result_id());
    }

    void EmitImageQuerySizeLod(const spvtools::opt::Instruction& inst) {
        auto* image = Value(inst.GetSingleWordInOperand(0));
        auto* level = Value(inst.GetSingleWordInOperand(1));

        auto* ty = Type(inst.type_id());
        Emit(b_.CallExplicit<spirv::ir::BuiltinCall>(
                 ty, spirv::BuiltinFn::kImageQuerySizeLod,
                 Vector<core::ir::TemplateParameter, 1>{ty->DeepestElement()}, image, level),
             inst.result_id());
    }

    void EmitAtomicSigned(const spvtools::opt::Instruction& inst, spirv::BuiltinFn fn) {
        core::ir::Value* v = Value(inst.GetSingleWordOperand(2));
        TINT_ASSERT(v->Type()->UnwrapPtr()->Is<core::type::I32>());
        EmitSpirvBuiltinCall(inst, fn);
    }

    void EmitAtomicUnsigned(const spvtools::opt::Instruction& inst, spirv::BuiltinFn fn) {
        core::ir::Value* v = Value(inst.GetSingleWordOperand(2));
        TINT_ASSERT(v->Type()->UnwrapPtr()->Is<core::type::U32>());
        EmitSpirvBuiltinCall(inst, fn);
    }

    void EmitArrayLength(const spvtools::opt::Instruction& inst) {
        auto strct = Value(inst.GetSingleWordInOperand(0));
        auto field_index = inst.GetSingleWordInOperand(1);

        auto* ptr = strct->Type()->As<core::type::Pointer>();
        TINT_ASSERT(ptr);

        auto* ty = ptr->StoreType()->As<core::type::Struct>();
        TINT_ASSERT(ty);

        auto* access =
            b_.Access(ty_.ptr(ptr->AddressSpace(), ty->Members().Back()->Type(), ptr->Access()),
                      strct, u32(field_index));
        EmitWithoutSpvResult(access);

        EmitOrAdd(b_.Call(Type(inst.type_id()), core::BuiltinFn::kArrayLength, Vector{access}),
                  inst.result_id());
    }

    void EmitControlBarrier(const spvtools::opt::Instruction& inst) {
        auto get_constant = [&](uint32_t idx) {
            uint32_t id = inst.GetSingleWordOperand(idx);
            if (auto* constant = spirv_context_->get_constant_mgr()->FindDeclaredConstant(id)) {
                return constant->GetU32();
            }
            TINT_ICE() << "invalid or missing operands for control barrier";
        };

        uint32_t execution = get_constant(0);
        uint32_t memory = get_constant(1);
        uint32_t semantics = get_constant(2);

        TINT_ASSERT(execution == dawn::to_underlying(spv::Scope::Workgroup))
            << "unsupported control barrier execution scope: "
            << "expected Workgroup (2), got: " << execution;

        if (semantics & dawn::to_underlying(spv::MemorySemanticsMask::AcquireRelease)) {
            semantics &= ~dawn::to_underlying(spv::MemorySemanticsMask::AcquireRelease);
        } else {
            TINT_ICE() << "control barrier semantics requires acquire and release";
        }
        TINT_ASSERT(memory == dawn::to_underlying(spv::Scope::Workgroup))
            << "control barrier requires workgroup memory scope";

        if (semantics & dawn::to_underlying(spv::MemorySemanticsMask::WorkgroupMemory)) {
            EmitWithoutSpvResult(b_.Call(ty_.void_(), core::BuiltinFn::kWorkgroupBarrier));
            semantics &= ~dawn::to_underlying(spv::MemorySemanticsMask::WorkgroupMemory);
        }

        if (semantics & dawn::to_underlying(spv::MemorySemanticsMask::UniformMemory)) {
            EmitWithoutSpvResult(b_.Call(ty_.void_(), core::BuiltinFn::kStorageBarrier));
            semantics &= ~dawn::to_underlying(spv::MemorySemanticsMask::UniformMemory);
        }

        if (semantics & dawn::to_underlying(spv::MemorySemanticsMask::ImageMemory)) {
            EmitWithoutSpvResult(b_.Call(ty_.void_(), core::BuiltinFn::kTextureBarrier));
            semantics &= ~dawn::to_underlying(spv::MemorySemanticsMask::ImageMemory);
        }

        TINT_ASSERT(!semantics) << "unsupported control barrier semantics: " << semantics;
    }

    void CheckAtomicNotFloat(const spvtools::opt::Instruction& inst) {
        auto* ty = Type(inst.type_id());
        TINT_ASSERT(!ty->UnwrapPtr()->IsFloatScalar())
            << "Atomic operations on floating point values not supported.";
    }

    void EmitAtomicStore(const spvtools::opt::Instruction& inst) {
        auto* v = Value(inst.GetSingleWordInOperand(0));
        auto* ty = v->Type()->UnwrapPtr();
        TINT_ASSERT(!ty->IsFloatScalar())
            << "Atomic operations on floating point values not supported.";

        EmitWithoutSpvResult(b_.Call<spirv::ir::BuiltinCall>(
                                   ty_.void_(), spirv::BuiltinFn::kAtomicStore, Args(inst, 0))
                                 ->Result());
    }

    void EmitBitcast(const spvtools::opt::Instruction& inst) {
        auto val = Value(inst.GetSingleWordInOperand(0));
        auto ty = Type(inst.type_id());
        EmitOrAdd(b_.Bitcast(ty, val), inst.result_id());
    }

    core::ir::ControlInstruction* StopWalkingAt(uint32_t id) {
        auto iter = walk_stop_blocks_.find(id);
        if (iter != walk_stop_blocks_.end()) {
            return iter->second;
        }
        return nullptr;
    }

    core::ir::Loop* ContinueTarget(uint32_t id) {
        auto iter = continue_targets_.find(id);
        if (iter != continue_targets_.end()) {
            return iter->second;
        }
        return nullptr;
    }

    Result<SuccessType> EmitBranch(spvtools::opt::Instruction& inst) {
        auto dest_id = inst.GetSingleWordInOperand(0);

        // Disallow fallthrough
        for (auto& switch_blocks : current_switch_blocks_) {
            if (switch_blocks.count(dest_id) != 0) {
                return Failure("switch fallthrough not supported by the SPIR-V reader");
            }
        }

        // The destination is a continuing block, so insert a `continue`
        if (auto* loop = ContinueTarget(dest_id)) {
            auto* new_inst = b_.Continue(loop);
            auto id = spirv_context_->get_instr_block(&inst)->id();
            inst_to_spirv_block_[new_inst] = id;
            EmitWithoutResult(new_inst);
            return Success;
        }
        // If this is branching to a previous merge block then we're done. It can be a previous
        // merge block in the case of an `if` breaking out of a `switch` or `loop`.
        if (auto* ctrl_inst = StopWalkingAt(dest_id)) {
            if (auto* loop = ctrl_inst->As<core::ir::Loop>()) {
                // Going to the merge in a loop body has to be a break regardless of nesting level.

                if (InBlock(loop->Body()) && !InBlock(loop->Continuing())) {
                    EmitWithoutResult(b_.Exit(ctrl_inst));
                }
            } else if (ctrl_inst->Is<core::ir::Switch>()) {
                EmitWithoutResult(b_.Exit(ctrl_inst));
            }
            return Success;
        }

        TINT_ASSERT(current_spirv_function_);
        const auto& bb = current_spirv_function_->FindBlock(dest_id);

        TINT_CHECK_RESULT(EmitBlock(current_block_, *bb));
        return Success;
    }

    // Given a true and false branch find if there is a common convergence point before the merge
    // block.
    std::optional<uint32_t> FindPremergeId(uint32_t true_id,
                                           uint32_t false_id,
                                           std::optional<uint32_t> merge_id) {
        auto* cfg = spirv_context_->cfg();

        // We need a merge block, the true and false to be unique and the true and false to not be
        // the merge.
        if (!merge_id || true_id == false_id || true_id == merge_id || false_id == merge_id) {
            return std::nullopt;
        }

        // Get the list of blocks from the true branch to the merge
        std::list<spvtools::opt::BasicBlock*> true_blocks;
        cfg->ComputeStructuredOrder(
            current_spirv_function_, &*(current_spirv_function_->FindBlock(true_id)),
            &*(current_spirv_function_->FindBlock(merge_id.value())), &true_blocks);

        // Get the list of blocks from the false branch to the merge
        std::list<spvtools::opt::BasicBlock*> false_blocks;
        cfg->ComputeStructuredOrder(
            current_spirv_function_, &*(current_spirv_function_->FindBlock(false_id)),
            &*(current_spirv_function_->FindBlock(merge_id.value())), &false_blocks);

        auto& true_end = true_blocks.back();
        auto& false_end = false_blocks.back();

        // We only consider the block as returning if it didn't return through
        // the merge block. (I.e. it's a direct exit from inside the branch
        // itself.
        bool true_returns = true_end->id() != merge_id && true_end->IsReturn();
        bool false_returns = false_end->id() != merge_id && false_end->IsReturn();
        // If one of the blocks returns but the other doesn't, then we can't
        // have a premerge block.
        if (true_returns != false_returns) {
            return std::nullopt;
        }

        // If they don't return, both blocks must merge to the same place.
        if (!true_returns && (true_end->id() != false_end->id())) {
            return std::nullopt;
        }

        // If these aren't returns, then remove the merge blocks.
        if (!true_returns) {
            true_blocks.pop_back();
            false_blocks.pop_back();
        }

        std::optional<uint32_t> id = std::nullopt;
        while (!true_blocks.empty() && !false_blocks.empty()) {
            auto* tb = true_blocks.back();
            if (tb != false_blocks.back()) {
                break;
            }

            id = tb->id();

            true_blocks.pop_back();
            false_blocks.pop_back();
        }

        // If this is already a stop block, so it can't be a premerge
        if (id.has_value() && walk_stop_blocks_.contains(id.value())) {
            return std::nullopt;
        }
        return id;
    }

    core::ir::ControlInstruction* ExitFor(core::ir::ControlInstruction* ctrl,
                                          core::ir::ControlInstruction* parent) {
        // If you have a BranchConditional inside a BranchConditional where
        // the inner does not have a merge block, it can branch out to the
        // merge of the outer conditional. But, WGSL doesn't allow that, so
        // just treat it as an exit of the inner block.
        if (ctrl->Is<core::ir::If>() && parent->Is<core::ir::If>()) {
            return parent;
        }
        return ctrl;
    }

    core::ir::Instruction* EmitBranchStopBlock(core::ir::ControlInstruction* ctrl,
                                               core::ir::If* if_,
                                               core::ir::Block* blk,
                                               uint32_t target) {
        if (auto* loop = ContinueTarget(target)) {
            auto* cont = b_.Continue(loop);
            blk->Append(cont);
            return cont;
        }

        auto iter = merge_to_premerge_.find(target);
        if (iter != merge_to_premerge_.end()) {
            // Branch to a merge block, but skipping over an expected premerge block
            // so we need a guard.
            if (!iter->second.condition) {
                b_.InsertBefore(iter->second.parent,
                                [&] { iter->second.condition = b_.Var("execute_premerge", true); });
            }
            b_.Append(blk, [&] { b_.Store(iter->second.condition, false); });
        }

        auto* exit = b_.Exit(ExitFor(ctrl, if_));
        blk->Append(exit);
        return exit;
    }

    bool ProcessBranchAsLoopHeader(core::ir::Value* cond, uint32_t true_id, uint32_t false_id) {
        bool true_is_header = loop_headers_.count(true_id) > 0;
        bool false_is_header = loop_headers_.count(false_id) > 0;

        if (!true_is_header && !false_is_header) {
            return false;
        }

        core::ir::Loop* loop = nullptr;
        uint32_t merge_id = 0;

        if (true_is_header) {
            const auto& bb_header = current_spirv_function_->FindBlock(true_id);
            merge_id = (*bb_header).MergeBlockIdIfAny();

            loop = loop_headers_[true_id];

        } else {
            const auto& bb_header = current_spirv_function_->FindBlock(false_id);
            merge_id = (*bb_header).MergeBlockIdIfAny();

            loop = loop_headers_[false_id];
        }
        TINT_ASSERT(merge_id > 0);

        // The only time a loop continuing will be in current blocks is if
        // we're inside the continuing block itself.
        //
        // Note, we may _not_ be in the IR continuing block. This can happen
        // in the case of a SPIR-V loop where the header_id and continue_id
        // are the same. We'll be emitting into the IR body, but branch to
        // the header because that's also the continuing in SPIR-V.
        if (current_blocks_.count(loop->Continuing()) != 0u) {
            if (true_id == merge_id && false_is_header) {
                EmitWithoutResult(b_.BreakIf(loop, cond));
                return true;
            }
            if (false_id == merge_id && true_is_header) {
                auto* val = b_.Not(cond);
                if (auto* inst = val->AsInstruction()) {
                    EmitWithoutSpvResult(inst->Result());
                }
                EmitWithoutResult(b_.BreakIf(loop, val));
                return true;
            }
        }
        return false;
    }

    Result<SuccessType> EmitPremergeBlock(uint32_t merge_id,
                                          uint32_t premerge_start_id,
                                          core::ir::If* premerge_if_) {
        auto iter = merge_to_premerge_.find(merge_id);
        TINT_ASSERT(iter != merge_to_premerge_.end());

        // If we created a condition guard, we need to swap the premerge `true` condition with
        // the condition variable.
        if (iter->second.condition) {
            auto* premerge_cond = b_.Load(iter->second.condition);
            EmitWithoutSpvResult(premerge_cond->Result());
            premerge_if_->SetOperand(core::ir::If::kConditionOperandOffset,
                                     premerge_cond->Result());
        }
        merge_to_premerge_.erase(iter);

        EmitWithoutResult(premerge_if_);

        const auto& bb_premerge = current_spirv_function_->FindBlock(premerge_start_id);
        TINT_CHECK_RESULT(EmitBlockParent(premerge_if_->True(), *bb_premerge));
        if (!premerge_if_->True()->Terminator()) {
            premerge_if_->True()->Append(b_.Exit(premerge_if_));
        }

        premerge_if_->False()->Append(b_.Unreachable());
        return Success;
    }

    Result<SuccessType> EmitIfBranch(uint32_t id, core::ir::If* if_, core::ir::Block* blk) {
        const auto& bb = current_spirv_function_->FindBlock(id);
        TINT_CHECK_RESULT(EmitBlockParent(blk, *bb));
        if (!blk->Terminator()) {
            blk->Append(b_.Exit(if_));
        }
        return Success;
    }

    Result<SuccessType> EmitBranchConditional(const spvtools::opt::BasicBlock& bb,
                                              const spvtools::opt::Instruction& inst) {
        auto cond = Value(inst.GetSingleWordInOperand(0));
        auto true_id = inst.GetSingleWordInOperand(1);
        auto false_id = inst.GetSingleWordInOperand(2);

        if (ProcessBranchAsLoopHeader(cond, true_id, false_id)) {
            return Success;
        }

        // If the true and false block are the same, then we change the condition into
        // `cond || true` so that we always take the true block, the false block will be marked
        // unreachable.
        if (true_id == false_id) {
            auto* binary = b_.Binary(core::BinaryOp::kOr, cond->Type(), cond, b_.Constant(true));
            EmitWithoutSpvResult(binary);
            cond = binary;
        }

        auto* if_ = b_.If(cond);
        EmitWithoutResult(if_);

        branch_conditional_to_if_.insert({&inst, if_});

        std::optional<uint32_t> merge_id = std::nullopt;

        auto* merge_inst = bb.GetMergeInst();
        if (bb.GetLoopMergeInst()) {
            // If this is a loop merge block, then the merge instruction is for
            // the loop, not the branch conditional.
            merge_inst = nullptr;
        } else if (merge_inst != nullptr) {
            merge_id = merge_inst->GetSingleWordInOperand(0);
            walk_stop_blocks_.insert({merge_id.value(), if_});
        }

        TINT_ASSERT(current_spirv_function_);

        // Determine if there is a premerge block to handle
        std::optional<uint32_t> premerge_start_id = FindPremergeId(true_id, false_id, merge_id);

        // If we found the start of a premerge, push it onto the merge stack so this ends up being a
        // temporary merge block for the if branches.
        core::ir::If* premerge_if_ = nullptr;
        if (premerge_start_id.has_value()) {
            // Must have a merge to have a premerge
            merge_to_premerge_.insert({merge_id.value(), PremergeInfo{if_, {}}});
            premerge_if_ = b_.If(b_.Constant(true));
            walk_stop_blocks_.insert({premerge_start_id.value(), premerge_if_});
        }
        if (auto* ctrl = StopWalkingAt(true_id)) {
            auto* new_inst = EmitBranchStopBlock(ctrl, if_, if_->True(), true_id);
            inst_to_spirv_block_[new_inst] = bb.id();
        } else {
            TINT_CHECK_RESULT(EmitIfBranch(true_id, if_, if_->True()));
        }

        // Pre-SPIRV 1.6 the true and false blocks could be the same. If that's the case then we
        // will have changed the condition and the false block is now unreachable.
        if (false_id == true_id) {
            if_->False()->Append(b_.Unreachable());
        } else if (auto* ctrl = StopWalkingAt(false_id)) {
            auto* new_inst = EmitBranchStopBlock(ctrl, if_, if_->False(), false_id);
            inst_to_spirv_block_[new_inst] = bb.id();
        } else {
            TINT_CHECK_RESULT(EmitIfBranch(false_id, if_, if_->False()));
        }

        // There was a premerge, remove it from the merge stack and then emit the premerge into an
        // `if true` block in order to maintain re-convergence guarantees. The premerge will contain
        // all the blocks up to the merge block.
        if (premerge_start_id.has_value()) {
            TINT_CHECK_RESULT(
                EmitPremergeBlock(merge_id.value(), premerge_start_id.value(), premerge_if_));
        }

        // Emit the merge block if it exists.
        if (merge_id.has_value()) {
            const auto& bb_merge = current_spirv_function_->FindBlock(merge_id.value());
            TINT_CHECK_RESULT(EmitBlock(current_block_, *bb_merge));
        }
        return Success;
    }

    void EmitLoop(const spvtools::opt::BasicBlock& bb) {
        // This just handles creating the loop itself, the rest of the processing
        // of the continue and merge blocks will be handled when we deal with the
        // LoopMerge instruction itself. We have to setup the loop early in order
        // to capture instructions which come in the header before the LoopMerge.
        auto* loop = b_.Loop();
        EmitWithoutResult(loop);

        // A `loop` header block can also be the merge block for an `if`. In that the case, replace
        // the `if` information in the stop blocks with the loop as this must be the `if` merge
        // block and the `if` is complete.
        walk_stop_blocks_[bb.id()] = loop;
    }

    void EmitLoopMerge(const spvtools::opt::BasicBlock& bb,
                       const spvtools::opt::Instruction& inst) {
        auto merge_id = inst.GetSingleWordInOperand(0);
        auto continue_id = inst.GetSingleWordInOperand(1);
        auto header_id = bb.id();

        // The loop was created in `EmitLoop` and set as the stop block value for
        // the header block. Retrieve the loop from the stop list.
        auto* loop = StopWalkingAt(header_id)->As<core::ir::Loop>();
        TINT_ASSERT(loop);

        loop_headers_.insert({header_id, loop});
        continue_targets_.insert({continue_id, loop});

        // Insert the stop blocks
        walk_stop_blocks_.insert({merge_id, loop});
        if (continue_id != header_id) {
            walk_stop_blocks_.insert({continue_id, loop});
        }

        // The remainder of the loop body will process when we hit the
        // BranchConditional or Branch after the LoopMerge. We're already
        // processing into the loop body from the `EmitLoop` code above so just
        // continue emitting.

        // The merge block will be emitted by the `EmitBlock` code after the
        // instructions in the loop header are emitted.
    }

    Result<SuccessType> EmitSwitch(const spvtools::opt::BasicBlock& bb,
                                   const spvtools::opt::Instruction& inst) {
        auto* selector = Value(inst.GetSingleWordInOperand(0));
        auto default_id = inst.GetSingleWordInOperand(1);

        auto* switch_ = b_.Switch(selector);
        EmitWithoutResult(switch_);

        auto* merge_inst = bb.GetMergeInst();
        TINT_ASSERT(merge_inst);

        auto merge_id = merge_inst->GetSingleWordInOperand(0);
        walk_stop_blocks_.insert({merge_id, switch_});

        size_t switch_blocks_id = current_switch_blocks_.size();
        current_switch_blocks_.push_back({});

        auto* default_blk = b_.DefaultCase(switch_);
        if (default_id != merge_id) {
            current_switch_blocks_[switch_blocks_id].emplace(default_id);

            const auto& bb_default = current_spirv_function_->FindBlock(default_id);
            TINT_CHECK_RESULT(EmitBlockParent(default_blk, *bb_default));
        }
        if (!default_blk->Terminator()) {
            default_blk->Append(b_.ExitSwitch(switch_));
        }

        std::unordered_map<uint32_t, size_t> block_id_to_case_index;
        block_id_to_case_index[default_id] = switch_->Cases().Length() - 1;

        for (uint32_t i = 2; i < inst.NumInOperandWords(); i += 2) {
            auto blk_id = inst.GetSingleWordInOperand(i + 1);

            if (blk_id != merge_id) {
                current_switch_blocks_[switch_blocks_id].emplace(blk_id);
            }
        }

        // For each selector.
        for (uint32_t i = 2; i < inst.NumInOperandWords(); i += 2) {
            auto literal = inst.GetSingleWordInOperand(i);
            auto blk_id = inst.GetSingleWordInOperand(i + 1);

            core::ir::Constant* sel = nullptr;
            if (selector->Type()->Is<core::type::I32>()) {
                sel = b_.Constant(i32(literal));
            } else {
                sel = b_.Constant(u32(literal));
            }

            // Determine if we've seen this block and should combine selectors
            auto case_index_iter = block_id_to_case_index.find(blk_id);
            if (case_index_iter != block_id_to_case_index.end()) {
                switch_->Cases()[case_index_iter->second].selectors.Push(
                    core::ir::Switch::CaseSelector{sel});
                continue;
            }

            core::ir::Block* blk = b_.Case(switch_, Vector{sel});
            if (blk_id != merge_id) {
                const auto& basic_block = current_spirv_function_->FindBlock(blk_id);
                TINT_CHECK_RESULT(EmitBlockParent(blk, *basic_block));
            }
            if (!blk->Terminator()) {
                blk->Append(b_.ExitSwitch(switch_));
            }
            block_id_to_case_index[blk_id] = switch_->Cases().Length() - 1;
        }

        current_switch_blocks_.pop_back();

        const auto& bb_merge = current_spirv_function_->FindBlock(merge_id);
        TINT_CHECK_RESULT(EmitBlock(current_block_, *bb_merge));
        return Success;
    }

    Vector<core::ir::Value*, 4> Args(const spvtools::opt::Instruction& inst, uint32_t start) {
        Vector<core::ir::Value*, 4> args;
        for (uint32_t i = start; i < inst.NumOperandWords(); i++) {
            args.Push(Value(inst.GetSingleWordOperand(i)));
        }
        return args;
    }

    void EmitBuiltinCall(const spvtools::opt::Instruction& inst, core::BuiltinFn fn) {
        EmitOrAdd(b_.Call(Type(inst.type_id()), fn, Args(inst, 2)), inst.result_id());
    }

    void EmitSpirvExplicitBuiltinCall(const spvtools::opt::Instruction& inst,
                                      spirv::BuiltinFn fn,
                                      uint32_t first_operand_idx = 2) {
        Emit(b_.CallExplicit<spirv::ir::BuiltinCall>(
                 Type(inst.type_id()), fn,
                 Vector<core::ir::TemplateParameter, 1>{Type(inst.type_id())->DeepestElement()},
                 Args(inst, first_operand_idx)),
             inst.result_id());
    }

    void EmitSpirvBuiltinCall(const spvtools::opt::Instruction& inst,
                              spirv::BuiltinFn fn,
                              uint32_t first_operand_idx = 2) {
        Emit(b_.Call<spirv::ir::BuiltinCall>(Type(inst.type_id()), fn,
                                             Args(inst, first_operand_idx)),
             inst.result_id());
    }

    void EmitBitCount(const spvtools::opt::Instruction& inst) {
        auto* res_ty = Type(inst.type_id());
        Emit(b_.CallExplicit<spirv::ir::BuiltinCall>(
                 res_ty, spirv::BuiltinFn::kBitCount,
                 Vector<core::ir::TemplateParameter, 1>{res_ty->DeepestElement()}, Args(inst, 2)),
             inst.result_id());
    }

    /// @param inst the SPIR-V instruction
    /// Note: This isn't technically correct, but there is no `kill` equivalent in WGSL. The closets
    /// we have is `discard` which maps to `OpDemoteToHelperInvocation` in SPIR-V.
    void EmitKill([[maybe_unused]] const spvtools::opt::Instruction& inst) {
        // TODO(430084563): Log a warning that the `OpKill` or `OpTerminateInvocation` will not have
        // the same semantics as the original SPIR-V.
        EmitWithoutResult(b_.Discard());

        // An `OpKill` is a terminator in SPIR-V. `discard` is not a terminator in WGSL. After the
        // `discard` we inject a `return` for the current function. This is similar in spirit to
        // what `OpKill` does although not totally correct (i.e. we don't early return from calling
        // functions, just the function where `OpKill` was emitted. There are also limited places in
        // which `OpKill` can be used. So, we don't have to worry about it in a `continuing` block
        // because the continuing must end with a branching terminator which `OpKill` does not
        // branch.
        if (current_function_->ReturnType()->Is<core::type::Void>()) {
            EmitWithoutResult(b_.Return(current_function_));
        } else {
            EmitWithoutResult(
                b_.Return(current_function_, b_.Zero(current_function_->ReturnType())));
        }
    }

    /// @param inst the SPIR-V instruction for OpCopyObject
    void EmitCopyObject(const spvtools::opt::Instruction& inst) {
        // Make the result Id a pointer to the original copied value.
        auto* v = Value(inst.GetSingleWordOperand(2));

        if (v->Type()->IsHandle() || v->Type()->Is<spirv::type::SampledImage>()) {
            values_.Add(inst.result_id(), v);
        } else {
            auto* l = b_.Let(v);
            Emit(l, inst.result_id());
        }
    }

    /// @param inst the SPIR-V instruction for OpCopyMemory
    void EmitCopyMemory(const spvtools::opt::Instruction& inst) {
        auto load = b_.Load(Value(inst.GetSingleWordOperand(1)));
        EmitWithoutSpvResult(load->Result());
        EmitWithoutResult(b_.Store(Value(inst.GetSingleWordOperand(0)), load));
    }

    /// @param inst the SPIR-V instruction for OpExtInst
    Result<SuccessType> EmitExtInst(const spvtools::opt::Instruction& inst) {
        auto inst_set = inst.GetSingleWordInOperand(0);
        if (ignored_imports_.count(inst_set) > 0) {
            // Ignore it but don't error out.
            return Success;
        }
        if (glsl_std_450_imports_.count(inst_set) > 0) {
            return EmitGlslStd450ExtInst(inst);
        }
        TINT_UNREACHABLE()
            << "unrecognized extended instruction set should have been caught during registration";
    }

    // Returns the WGSL standard library function for the given GLSL.std.450 extended instruction
    // operation code. This handles GLSL functions which directly translate to the WGSL equivalent.
    // Any non-direct translation is returned as `kNone`.
    core::BuiltinFn GetGlslStd450WgslEquivalentFuncName(uint32_t ext_opcode) {
        switch (ext_opcode) {
            case GLSLstd450Acos:
                return core::BuiltinFn::kAcos;
            case GLSLstd450Acosh:
                return core::BuiltinFn::kAcosh;
            case GLSLstd450Asin:
                return core::BuiltinFn::kAsin;
            case GLSLstd450Asinh:
                return core::BuiltinFn::kAsinh;
            case GLSLstd450Atan:
                return core::BuiltinFn::kAtan;
            case GLSLstd450Atanh:
                return core::BuiltinFn::kAtanh;
            case GLSLstd450Atan2:
                return core::BuiltinFn::kAtan2;
            case GLSLstd450Ceil:
                return core::BuiltinFn::kCeil;
            case GLSLstd450Cos:
                return core::BuiltinFn::kCos;
            case GLSLstd450Cosh:
                return core::BuiltinFn::kCosh;
            case GLSLstd450Cross:
                return core::BuiltinFn::kCross;
            case GLSLstd450Degrees:
                return core::BuiltinFn::kDegrees;
            case GLSLstd450Determinant:
                return core::BuiltinFn::kDeterminant;
            case GLSLstd450Distance:
                return core::BuiltinFn::kDistance;
            case GLSLstd450Exp:
                return core::BuiltinFn::kExp;
            case GLSLstd450Exp2:
                return core::BuiltinFn::kExp2;
            case GLSLstd450FAbs:
                return core::BuiltinFn::kAbs;
            case GLSLstd450FSign:
                return core::BuiltinFn::kSign;
            case GLSLstd450Floor:
                return core::BuiltinFn::kFloor;
            case GLSLstd450Fract:
                return core::BuiltinFn::kFract;
            case GLSLstd450Fma:
                return core::BuiltinFn::kFma;
            case GLSLstd450InverseSqrt:
                return core::BuiltinFn::kInverseSqrt;
            case GLSLstd450Length:
                return core::BuiltinFn::kLength;
            case GLSLstd450Log:
                return core::BuiltinFn::kLog;
            case GLSLstd450Log2:
                return core::BuiltinFn::kLog2;
            case GLSLstd450NClamp:
            case GLSLstd450FClamp:  // FClamp is less prescriptive about NaN operands
                return core::BuiltinFn::kClamp;
            case GLSLstd450ModfStruct:
                return core::BuiltinFn::kModf;
            case GLSLstd450FrexpStruct:
                return core::BuiltinFn::kFrexp;
            case GLSLstd450NMin:
            case GLSLstd450FMin:  // FMin is less prescriptive about NaN operands
                return core::BuiltinFn::kMin;
            case GLSLstd450NMax:
            case GLSLstd450FMax:  // FMax is less prescriptive about NaN operands
                return core::BuiltinFn::kMax;
            case GLSLstd450FMix:
                return core::BuiltinFn::kMix;
            case GLSLstd450PackSnorm4x8:
                return core::BuiltinFn::kPack4X8Snorm;
            case GLSLstd450PackUnorm4x8:
                return core::BuiltinFn::kPack4X8Unorm;
            case GLSLstd450PackSnorm2x16:
                return core::BuiltinFn::kPack2X16Snorm;
            case GLSLstd450PackUnorm2x16:
                return core::BuiltinFn::kPack2X16Unorm;
            case GLSLstd450PackHalf2x16:
                return core::BuiltinFn::kPack2X16Float;
            case GLSLstd450Pow:
                return core::BuiltinFn::kPow;
            case GLSLstd450Radians:
                return core::BuiltinFn::kRadians;
            case GLSLstd450Round:
            case GLSLstd450RoundEven:
                return core::BuiltinFn::kRound;
            case GLSLstd450Sin:
                return core::BuiltinFn::kSin;
            case GLSLstd450Sinh:
                return core::BuiltinFn::kSinh;
            case GLSLstd450SmoothStep:
                return core::BuiltinFn::kSmoothstep;
            case GLSLstd450Sqrt:
                return core::BuiltinFn::kSqrt;
            case GLSLstd450Step:
                return core::BuiltinFn::kStep;
            case GLSLstd450Tan:
                return core::BuiltinFn::kTan;
            case GLSLstd450Tanh:
                return core::BuiltinFn::kTanh;
            case GLSLstd450Trunc:
                return core::BuiltinFn::kTrunc;
            case GLSLstd450UnpackSnorm4x8:
                return core::BuiltinFn::kUnpack4X8Snorm;
            case GLSLstd450UnpackUnorm4x8:
                return core::BuiltinFn::kUnpack4X8Unorm;
            case GLSLstd450UnpackSnorm2x16:
                return core::BuiltinFn::kUnpack2X16Snorm;
            case GLSLstd450UnpackUnorm2x16:
                return core::BuiltinFn::kUnpack2X16Unorm;
            case GLSLstd450UnpackHalf2x16:
                return core::BuiltinFn::kUnpack2X16Float;

            default:
                break;
        }
        return core::BuiltinFn::kNone;
    }

    spirv::BuiltinFn GetGlslStd450SpirvEquivalentFuncName(uint32_t ext_opcode) {
        switch (ext_opcode) {
            case GLSLstd450SAbs:
                return spirv::BuiltinFn::kAbs;
            case GLSLstd450SSign:
                return spirv::BuiltinFn::kSign;
            case GLSLstd450Normalize:
                return spirv::BuiltinFn::kNormalize;
            case GLSLstd450MatrixInverse:
                return spirv::BuiltinFn::kInverse;
            case GLSLstd450SMax:
                return spirv::BuiltinFn::kSMax;
            case GLSLstd450SMin:
                return spirv::BuiltinFn::kSMin;
            case GLSLstd450SClamp:
                return spirv::BuiltinFn::kSClamp;
            case GLSLstd450UMax:
                return spirv::BuiltinFn::kUMax;
            case GLSLstd450UMin:
                return spirv::BuiltinFn::kUMin;
            case GLSLstd450UClamp:
                return spirv::BuiltinFn::kUClamp;
            case GLSLstd450FindILsb:
                return spirv::BuiltinFn::kFindILsb;
            case GLSLstd450FindSMsb:
                return spirv::BuiltinFn::kFindSMsb;
            case GLSLstd450FindUMsb:
                return spirv::BuiltinFn::kFindUMsb;
            case GLSLstd450Refract:
                return spirv::BuiltinFn::kRefract;
            case GLSLstd450Reflect:
                return spirv::BuiltinFn::kReflect;
            case GLSLstd450FaceForward:
                return spirv::BuiltinFn::kFaceForward;
            case GLSLstd450Ldexp:
                return spirv::BuiltinFn::kLdexp;
            case GLSLstd450Modf:
                return spirv::BuiltinFn::kModf;
            case GLSLstd450Frexp:
                return spirv::BuiltinFn::kFrexp;
            default:
                break;
        }
        return spirv::BuiltinFn::kNone;
    }

    Vector<core::ir::TemplateParameter, 1> GlslStd450ExplicitParams(
        uint32_t ext_opcode,
        const core::type::Type* result_ty) {
        if (ext_opcode == GLSLstd450SSign || ext_opcode == GLSLstd450SAbs ||
            ext_opcode == GLSLstd450SMax || ext_opcode == GLSLstd450SMin ||
            ext_opcode == GLSLstd450SClamp || ext_opcode == GLSLstd450UMax ||
            ext_opcode == GLSLstd450UMin || ext_opcode == GLSLstd450UClamp ||
            ext_opcode == GLSLstd450FindILsb || ext_opcode == GLSLstd450FindSMsb ||
            ext_opcode == GLSLstd450FindUMsb) {
            return {result_ty->DeepestElement()};
        }
        return {};
    }

    /// @param inst the SPIR-V instruction for OpAccessChain
    Result<SuccessType> EmitGlslStd450ExtInst(const spvtools::opt::Instruction& inst) {
        const auto ext_opcode = inst.GetSingleWordInOperand(1);
        auto* spv_ty = Type(inst.type_id());

        Vector<core::ir::Value*, 4> operands;
        // All parameters to GLSL.std.450 extended instructions are IDs.
        for (uint32_t idx = 2; idx < inst.NumInOperands(); ++idx) {
            operands.Push(Value(inst.GetSingleWordInOperand(idx)));
        }

        const auto wgsl_fn = GetGlslStd450WgslEquivalentFuncName(ext_opcode);
        if (wgsl_fn == core::BuiltinFn::kModf) {
            // For `ModfStruct`, which is, essentially, a WGSL `modf` instruction
            // we need some special handling. The result type that we produce
            // must be the SPIR-V type as we don't know how the result is used
            // later. So, we need to make the WGSL query and re-construct an
            // object of the right SPIR-V type. We can't, easily, do this later
            // as we lose the SPIR-V type as soon as we replace the result of the
            // `modf`. So, inline the work here to generate the correct results.

            auto* mem_ty = operands[0]->Type();
            auto* result_ty = core::type::CreateModfResult(ty_, ir_.symbols, mem_ty);

            auto* call = b_.Call(result_ty, wgsl_fn, operands);
            auto* fract = b_.Access(mem_ty, call, 0_u);
            auto* whole = b_.Access(mem_ty, call, 1_u);

            EmitWithoutSpvResult(call);
            EmitWithoutSpvResult(fract);
            EmitWithoutSpvResult(whole);
            EmitOrAdd(b_.Construct(spv_ty, fract, whole), inst.result_id());
            return Success;
        }
        if (wgsl_fn == core::BuiltinFn::kFrexp) {
            // For `FrexpStruct`, which is, essentially, a WGSL `frexp`
            // instruction we need some special handling. The result type that we
            // produce must be the SPIR-V type as we don't know how the result is
            // used later. So, we need to make the WGSL query and re-construct an
            // object of the right SPIR-V type. We can't, easily, do this later
            // as we lose the SPIR-V type as soon as we replace the result of the
            // `frexp`. So, inline the work here to generate the correct results.

            auto* mem_ty = operands[0]->Type();
            auto* result_ty = core::type::CreateFrexpResult(ty_, ir_.symbols, mem_ty);

            auto* call = b_.Call(result_ty, wgsl_fn, operands);
            auto* fract = b_.Access(mem_ty, call, 0_u);
            auto* exp = b_.Access(ty_.MatchWidth(ty_.i32(), mem_ty), call, 1_u);
            core::ir::Value* exp_res = exp;

            EmitWithoutSpvResult(call);
            EmitWithoutSpvResult(fract);
            EmitWithoutSpvResult(exp);

            if (auto* str = spv_ty->As<core::type::Struct>()) {
                auto* exp_ty = str->Members()[1]->Type();
                if (exp_ty->DeepestElement()->IsUnsignedIntegerScalar()) {
                    exp_res = b_.Bitcast(exp_ty, exp);
                    EmitWithoutSpvResult(exp_res);
                }
            }

            EmitOrAdd(b_.Construct(spv_ty, fract, exp_res), inst.result_id());
            return Success;
        }
        if (wgsl_fn != core::BuiltinFn::kNone) {
            EmitOrAdd(b_.Call(spv_ty, wgsl_fn, operands), inst.result_id());
            return Success;
        }

        const auto spv_fn = GetGlslStd450SpirvEquivalentFuncName(ext_opcode);
        if (spv_fn != spirv::BuiltinFn::kNone) {
            auto explicit_params = GlslStd450ExplicitParams(ext_opcode, spv_ty);
            Emit(b_.CallExplicit<spirv::ir::BuiltinCall>(spv_ty, spv_fn, explicit_params, operands),
                 inst.result_id());
            return Success;
        }

        TINT_UNREACHABLE() << "unhandled GLSL.std.450 instruction " << ext_opcode;
    }

    /// @param inst the SPIR-V instruction for OpAccessChain
    void EmitAccess(const spvtools::opt::Instruction& inst) {
        Vector indices = Args(inst, 3);
        auto* base = Value(inst.GetSingleWordOperand(2));

        if (indices.IsEmpty()) {
            // There are no indices, so just forward the base object.
            AddValue(inst.result_id(), base);
            return;
        }

        // Propagate the access mode of the base object.
        auto access_mode = core::Access::kUndefined;
        if (auto* ptr = base->Type()->As<core::type::Pointer>()) {
            access_mode = ptr->Access();
        }

        auto* access = b_.Access(Type(inst.type_id(), access_mode), base, std::move(indices));
        EmitOrAdd(access, inst.result_id());
    }

    /// @param inst the SPIR-V instruction
    /// @param op the unary operator to use
    void EmitUnary(const spvtools::opt::Instruction& inst,
                   core::UnaryOp op,
                   uint32_t first_operand_idx = 2) {
        auto* val = Value(inst.GetSingleWordOperand(first_operand_idx));
        auto* unary = b_.Unary(op, val);
        if (auto* unary_inst = unary->AsInstruction()) {
            Emit(unary_inst, inst.result_id());
        } else {
            AddValue(inst.result_id(), unary);
        }
    }

    /// @param inst the SPIR-V instruction
    /// @param op the binary operator to use
    void EmitBinary(const spvtools::opt::Instruction& inst,
                    core::BinaryOp op,
                    uint32_t first_operand_idx = 2) {
        auto* lhs = Value(inst.GetSingleWordOperand(first_operand_idx));
        auto* rhs = Value(inst.GetSingleWordOperand(first_operand_idx + 1));
        auto* binary = b_.Binary(op, Type(inst.type_id()), lhs, rhs);
        if (auto* res = binary->AsInstruction()) {
            Emit(res, inst.result_id());
        } else {
            AddValue(inst.result_id(), binary);
        }
    }

    /// Emits the logical negation of the result of the given SPIR-V instruction.
    /// @param inst the SPIR-V instruction
    /// @param op the binary operator to use
    void EmitInvertedBinary(const spvtools::opt::Instruction& inst, core::BinaryOp op) {
        auto* lhs = Value(inst.GetSingleWordOperand(2));
        auto* rhs = Value(inst.GetSingleWordOperand(3));
        auto* binary = b_.Binary(op, Type(inst.type_id()), lhs, rhs);
        EmitWithoutSpvResult(binary);

        auto* inv = b_.Not(binary);
        if (auto* inv_inst = inv->AsInstruction()) {
            Emit(inv_inst, inst.result_id());
        } else {
            AddValue(inst.result_id(), inv);
        }
    }

    /// @param inst the SPIR-V instruction for OpCompositeExtract
    void EmitCompositeExtract(const spvtools::opt::Instruction& inst,
                              uint32_t composite_index = 2) {
        Vector<core::ir::Value*, 4> indices;
        for (uint32_t i = composite_index + 1; i < inst.NumOperandWords(); i++) {
            indices.Push(b_.Constant(u32(inst.GetSingleWordOperand(i))));
        }
        auto* object = Value(inst.GetSingleWordOperand(composite_index));
        auto* access = b_.Access(Type(inst.type_id()), object, std::move(indices));
        EmitOrAdd(access, inst.result_id());
    }

    /// @param inst the SPIR-V instruction for OpCompositeInsert
    void EmitCompositeInsert(const spvtools::opt::Instruction& inst) {
        auto* object = Value(inst.GetSingleWordOperand(2));
        auto* composite = Value(inst.GetSingleWordOperand(3));
        Vector<core::ir::Value*, 4> indices;
        for (uint32_t i = 4; i < inst.NumOperandWords(); i++) {
            indices.Push(b_.Constant(u32(inst.GetSingleWordOperand(i))));
        }

        auto* tmp = b_.Var(ty_.ptr(function, Type(inst.type_id())));
        tmp->SetInitializer(composite);
        auto* ptr_ty = ty_.ptr(function, object->Type());
        auto* access = b_.Access(ptr_ty, tmp, std::move(indices));

        EmitWithoutSpvResult(tmp->Result());
        EmitWithoutSpvResult(access);
        EmitWithoutResult(b_.Store(access, object));
        Emit(b_.Load(tmp), inst.result_id());
    }

    /// @param inst the SPIR-V instruction for OpCompositeConstruct
    void EmitConstruct(const spvtools::opt::Instruction& inst) {
        auto* construct = b_.Construct(Type(inst.type_id()), Args(inst, 2));
        EmitOrAdd(construct, inst.result_id());
    }

    /// @param inst the SPIR-V instruction for OpVectorInsertDynamic
    void EmitVectorInsertDynamic(const spvtools::opt::Instruction& inst) {
        auto vector = Value(inst.GetSingleWordOperand(2));
        auto component = Value(inst.GetSingleWordOperand(3));
        auto index = Value(inst.GetSingleWordOperand(4));
        auto* tmp = b_.Var(
            ty_.ptr(core::AddressSpace::kFunction, Type(inst.type_id()), core::Access::kReadWrite));
        tmp->SetInitializer(vector);
        EmitWithoutSpvResult(tmp->Result());
        EmitWithoutResult(b_.StoreVectorElement(tmp, index, component));
        Emit(b_.Load(tmp), inst.result_id());
    }

    /// @param inst the SPIR-V instruction for OpVectorShuffle
    void EmitVectorShuffle(const spvtools::opt::Instruction& inst) {
        auto* vector1 = Value(inst.GetSingleWordOperand(2));
        auto* vector2 = Value(inst.GetSingleWordOperand(3));
        auto* result_ty = Type(inst.type_id());
        auto* el_ty = result_ty->DeepestElement();

        uint32_t n1 = vector1->Type()->As<core::type::Vector>()->Width();
        uint32_t n2 = vector2->Type()->As<core::type::Vector>()->Width();

        Vector<core::ir::Value*, 4> swizzles;

        // Track the current swizzle that we are building from consecutive indices that fall within
        // the same vector.
        Vector<uint32_t, 4> current_indices;
        core::ir::Value* current_vector = nullptr;

        // Emit the current swizzle that we have constructed so far, and add it to the list.
        auto flush_swizzle = [&] {
            if (current_vector == nullptr) {
                return;
            }
            auto* swizzle_type = ty_.MatchWidth(el_ty, current_indices.Length());
            auto* swizzle = b_.Swizzle(swizzle_type, current_vector, current_indices);
            EmitWithoutSpvResult(swizzle);
            swizzles.Push(swizzle);
            current_indices.Clear();
        };

        for (uint32_t i = 4; i < inst.NumOperandWords(); i++) {
            uint32_t literal = inst.GetSingleWordOperand(i);

            // Determine which vector this index falls within.
            uint32_t next_index;
            core::ir::Value* next_vector = nullptr;
            if (literal == 0xFFFFFFFF) {
                // Undefined component, so just use the first component of the first vector.
                next_vector = vector1;
                next_index = 0;
            } else if (literal < n1) {
                next_vector = vector1;
                next_index = literal;
            } else if (literal < n1 + n2) {
                next_vector = vector2;
                next_index = literal - n1;
            } else {
                TINT_ICE() << "invalid vector shuffle index";
            }

            // If the vector has changed from the previous index, flush the swizzle.
            if (next_vector != current_vector) {
                flush_swizzle();
            }
            current_vector = next_vector;
            current_indices.Push(next_index);
        }

        flush_swizzle();

        if (swizzles.Length() == 1) {
            // There was only one swizzle, so we can just use it directly.
            AddValue(inst.result_id(), swizzles[0]);
        } else {
            // There were multiple swizzles, so we combine them all to produce the final result.
            EmitOrAdd(b_.Construct(result_ty, swizzles), inst.result_id());
        }
    }

    /// @param inst the SPIR-V instruction for OpFunctionCall
    void EmitFunctionCall(const spvtools::opt::Instruction& inst) {
        Emit(b_.Call(Function(inst.GetSingleWordInOperand(0)), Args(inst, 3)), inst.result_id());
    }

    /// @param inst the SPIR-V instruction for OpVariable
    Result<SuccessType> EmitVar(const spvtools::opt::Instruction& inst) {
        // Handle decorations.
        std::optional<uint32_t> group;
        std::optional<uint32_t> binding;
        core::Access access_mode = core::Access::kUndefined;
        core::IOAttributes io_attributes;
        auto interpolation = [&]() -> core::Interpolation& {
            // Create the interpolation field with the default values on first call.
            if (!io_attributes.interpolation.has_value()) {
                io_attributes.interpolation = core::Interpolation{
                    .type = core::InterpolationType::kPerspective,
                    .sampling = core::InterpolationSampling::kUndefined,
                };
            }
            return io_attributes.interpolation.value();
        };
        for (auto* deco :
             spirv_context_->get_decoration_mgr()->GetDecorationsFor(inst.result_id(), false)) {
            auto d = deco->GetSingleWordOperand(1);
            switch (spv::Decoration(d)) {
                case spv::Decoration::RelaxedPrecision:  // WGSL is relaxed precision by default
                    break;
                case spv::Decoration::NonReadable:
                    access_mode = core::Access::kWrite;
                    break;
                case spv::Decoration::NonWritable:
                    access_mode = core::Access::kRead;
                    break;
                case spv::Decoration::DescriptorSet:
                    group = deco->GetSingleWordOperand(2);
                    break;
                case spv::Decoration::Binding:
                    binding = deco->GetSingleWordOperand(2);
                    break;
                case spv::Decoration::BuiltIn: {
                    TINT_CHECK_RESULT_UNWRAP(builtin_val,
                                             Builtin(spv::BuiltIn(deco->GetSingleWordOperand(2))));
                    io_attributes.builtin = builtin_val;
                    break;
                }
                case spv::Decoration::Invariant:
                    io_attributes.invariant = true;
                    break;
                case spv::Decoration::Location:
                    io_attributes.location = deco->GetSingleWordOperand(2);
                    break;
                case spv::Decoration::NoPerspective:
                    interpolation().type = core::InterpolationType::kLinear;
                    break;
                case spv::Decoration::Flat:
                    interpolation().type = core::InterpolationType::kFlat;
                    break;
                case spv::Decoration::Centroid:
                    interpolation().sampling = core::InterpolationSampling::kCentroid;
                    break;
                case spv::Decoration::Sample:
                    interpolation().sampling = core::InterpolationSampling::kSample;
                    break;
                case spv::Decoration::Index:
                    io_attributes.blend_src = deco->GetSingleWordOperand(2);
                    break;
                case spv::Decoration::Coherent:
                    // Tint has coherent memory semantics, so this is a no-op.
                    break;
                case spv::Decoration::Restrict:
                    // Hint to the compiler that it may compile as if there is no aliasing. Ignore.
                    break;
                default:
                    return Failure("unhandled decoration " + std::to_string(d));
            }
        }

        if (io_attributes.interpolation.has_value()) {
            // WGSL requires that '@interpolate(flat)' needs to be paired with '@location', however
            // SPIR-V requires all fragment shader integer Inputs are 'flat'. If the decorations do
            // not contain a spv::Decoration::Location, then remove the interpolation decoration.
            //
            // The `perspective,center` interpolation is the default value if one isn't provided.
            // Just strip it off. This keeps us from accidentally applying interpolation where it
            // isn't permitted, and it isn't necessary.
            if ((io_attributes.interpolation->type == core::InterpolationType::kFlat &&
                 !io_attributes.location.has_value()) ||
                (io_attributes.interpolation->type == core::InterpolationType::kPerspective &&
                 io_attributes.interpolation->sampling == core::InterpolationSampling::kCenter)) {
                io_attributes.interpolation = std::nullopt;
            }
        }

        auto* element_ty = Type(inst.type_id(), access_mode)->As<core::type::Pointer>();
        if (element_ty->AddressSpace() == core::AddressSpace::kOut) {
            if (element_ty->StoreType()->IsIntegerScalarOrVector()) {
                io_attributes.interpolation = {
                    .type = core::InterpolationType::kFlat,
                    .sampling = core::InterpolationSampling::kUndefined,
                };
            } else if (auto* str = element_ty->StoreType()->As<core::type::Struct>()) {
                for (auto* member : str->Members()) {
                    if (member->Type()->IsIntegerScalarOrVector()) {
                        const_cast<core::type::StructMember*>(member)->SetInterpolation(
                            core::Interpolation{core::InterpolationType::kFlat,
                                                core::InterpolationSampling::kUndefined});
                    }
                }
            }
        }

        auto* var = b_.Var(element_ty);
        if (inst.NumOperands() > 3) {
            var->SetInitializer(Value(inst.GetSingleWordOperand(3)));
        }

        if (group || binding) {
            TINT_ASSERT(group && binding);

            // Remap any samplers which match an entry in the sampler mappings
            // table.
            if (element_ty->StoreType()->Is<core::type::Sampler>()) {
                auto it =
                    options_.sampler_mappings.find(BindingPoint{group.value(), binding.value()});
                if (it != options_.sampler_mappings.end()) {
                    auto bp = it->second;
                    group = bp.group;
                    binding = bp.binding;
                }
            }

            auto& grp = max_binding.GetOrAddZero(group.value());
            grp = std::max(grp, binding.value());

            auto& used = used_bindings.GetOrAddZero(BindingPoint{group.value(), binding.value()});
            used += 1;

            io_attributes.binding_point = {group.value(), binding.value()};
        }
        var->SetAttributes(std::move(io_attributes));
        var_to_original_access_mode_.insert({var, access_mode});

        Emit(var, inst.result_id());
        return Success;
    }

  private:
    /// TypeKey describes a SPIR-V type with an access mode.
    struct TypeKey {
        /// The SPIR-V type object.
        uint32_t type_id;
        /// The access mode.
        core::Access access_mode;

        // Equality operator for TypeKey.
        bool operator==(const TypeKey& other) const {
            return type_id == other.type_id && access_mode == other.access_mode;
        }

        /// @returns the hash code of the TypeKey
        tint::HashCode HashCode() const { return Hash(type_id, access_mode); }
    };

    /// The parser options
    const Options& options_;

    /// The generated IR module.
    core::ir::Module ir_;
    /// The Tint IR builder.
    core::ir::Builder b_{ir_};
    /// The Tint type manager.
    core::type::Manager& ty_{ir_.Types()};

    /// The Tint IR function that is currently being emitted.
    core::ir::Function* current_function_ = nullptr;
    /// The Tint IR block that is currently being emitted.
    core::ir::Block* current_block_ = nullptr;
    /// A map from a SPIR-V type declaration to the corresponding Tint type object.
    Hashmap<TypeKey, const core::type::Type*, 16> types_;
    /// A map from a SPIR-V function definition result ID to the corresponding Tint function object.
    Hashmap<uint32_t, core::ir::Function*, 8> functions_;
    /// A map from a SPIR-V result ID to the corresponding Tint value object.
    Hashmap<uint32_t, core::ir::Value*, 8> values_;
    /// Maps a `group` number to the largest seen `binding` value for that group
    Hashmap<uint32_t, uint32_t, 4> max_binding;
    /// A map of binding point to the count of usages
    Hashmap<BindingPoint, uint32_t, 4> used_bindings;

    /// The SPIR-V context containing the SPIR-V tools intermediate representation.
    std::unique_ptr<spvtools::opt::IRContext> spirv_context_;
    /// The current SPIR-V function being emitted
    spvtools::opt::Function* current_spirv_function_ = nullptr;

    // The set of IDs that are imports of the GLSL.std.450 extended instruction sets.
    std::unordered_set<uint32_t> glsl_std_450_imports_;
    // The set of IDs of imports that are ignored. For example, any "NonSemanticInfo." import is
    // ignored.
    std::unordered_set<uint32_t> ignored_imports_;

    // Map of SPIR-V IDs to string names
    std::unordered_map<uint32_t, std::string> id_to_name_;
    // Map of SPIR-V Struct IDs to a list of member string names
    std::unordered_map<uint32_t, std::vector<std::string>> struct_to_member_names_;

    // Set of types which should be considered `NonWritable` even if no decoration is present
    std::unordered_set<const core::type::Type*> consider_non_writable_;

    // Set of SPIR-V block ids where we'll stop a `Branch` instruction walk. These could be merge
    // blocks, premerge blocks, continuing blocks, etc.
    std::unordered_map<uint32_t, core::ir::ControlInstruction*> walk_stop_blocks_;
    // Map of continue target ID to the controlling IR loop.
    std::unordered_map<uint32_t, core::ir::Loop*> continue_targets_;
    // Map of header target ID to the controlling IR loop.
    std::unordered_map<uint32_t, core::ir::Loop*> loop_headers_;

    struct PremergeInfo {
        core::ir::If* parent = nullptr;
        core::ir::Var* condition = nullptr;
    };
    // Map of merge ID to an associated premerge_id, if any
    std::unordered_map<uint32_t, PremergeInfo> merge_to_premerge_;

    std::unordered_set<core::ir::Block*> current_blocks_;

    // For each block, we keep a set of SPIR-V `id`s which are known in that scope.
    std::vector<std::unordered_set<uint32_t>> id_stack_;

    // If we're in a switch, is populated with the IDs of the blocks for each of the switch
    // selectors. This lets us watch for fallthrough when emitting branch instructions.
    std::vector<std::unordered_set<uint32_t>> current_switch_blocks_;

    /// Maps from a spirv-v block id to the corresponding block in the IR
    std::unordered_map<uint32_t, core::ir::Block*> spirv_id_to_block_;

    // Map of continue block id to the phi types which need to be returned by
    // the continue target
    std::unordered_map<uint32_t, std::vector<uint32_t>> continue_blk_phis_;

    // A stack of values which need to be replaced as we finish processing a
    // block. Used to store `phi` information so we can retrieve values which
    // are defined after the `OpPhi` instruction.
    std::vector<std::vector<ReplacementValue>> values_to_replace_;

    // A map of block to phi values returned by the loop header
    std::unordered_map<uint32_t, std::vector<uint32_t>> block_phi_values_;

    // Map of certain instructions back to their originating spirv block
    std::unordered_map<core::ir::Instruction*, uint32_t> inst_to_spirv_block_;

    // Map of merge block id's back to the block which contains the header
    std::unordered_map<uint32_t, uint32_t> spirv_merge_id_to_header_id_;

    // Structure hold spec composite information
    struct SpecComposite {
        // The composite type
        const core::type::Type* type = nullptr;
        // The composite arguments
        Vector<uint32_t, 4> args;
    };

    // The set of SPIR-V IDs which map to `OpSpecConstantComposite` information
    std::unordered_map<uint32_t, SpecComposite> spec_composites_;

    // Structures which are marked with `BufferBlock` and need to be reported as `Storage` address
    // space
    std::unordered_set<const core::type::Struct*> storage_buffer_types_;

    // Map of `var` to the access mode it was originally created with. This may be different from
    // the current mode if we needed to set a default mode.
    std::unordered_map<core::ir::Var*, core::Access> var_to_original_access_mode_;

    // Map of spir-v branch conditional instructions to the related IR if instruction.
    std::unordered_map<const spvtools::opt::Instruction*, core::ir::If*> branch_conditional_to_if_;
};

}  // namespace

Result<core::ir::Module> Parse(std::span<const uint32_t> spirv, const Options& options) {
    return Parser(options).Run(spirv);
}

}  // namespace tint::spirv::reader
