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

#include <algorithm>
#include <cassert>
#include <ostream>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#include "source/spirv_constant.h"
#include "source/spirv_target_env.h"
#include "source/util/hash_combine.h"
#include "source/val/validation_state.h"

namespace spvtools {
namespace val {
namespace {

enum class LayoutMode : uint8_t {
  // Vulkan scalar block rules
  kScalar,
  // Vulkan standard alignment rules (i.e. std430)
  kStandard,
  // Vulkan extended alignment rules (i.e. std140)
  kExtended,
};

std::ostream& operator<<(std::ostream& str, const LayoutMode& mode) {
  switch (mode) {
    case LayoutMode::kScalar:
      str << "scalar";
      break;
    case LayoutMode::kStandard:
      str << "standard";
      break;
    case LayoutMode::kExtended:
      str << "extended";
      break;
  }
  return str;
}

enum class LayoutRequirement : uint8_t {
  // Must be laid out
  kRequired,
  // Must not be laid out
  kProhibited,
  // Either laid or not
  kAllowed,
};

struct Impl {
  ValidationState_t& vstate;

  // Relevant information to describe a memory instruction for the purposes of
  // layout validation.
  struct MemoryReference {
    // The data type of the memory instruction (after stripping any descriptor
    // array).
    uint32_t type_id = 0;
    // The descriptor array type id (if there is one).
    uint32_t descriptor_array_id = 0;
    // The storage class for the memory instruction.
    // Only used for error messages
    spv::StorageClass storage_class;
    // The layout mode (only relevant if a layout is required).
    LayoutMode layout;
    // The layout requirement for the instruction.
    LayoutRequirement requirement;
    // Whether it is an untyped pointer base.
    bool untyped = false;
  };

  // Matrix constraints from a struct member to carry to the actual matrix type.
  struct MatrixConstraints {
    uint32_t stride = 0;
    bool col_major = true;
  };

  // Cache valid checks for types that should have no layout.
  std::unordered_set<uint32_t> no_layout_cache_;

  // Struct member info
  struct MemberInfo {
    // Structure member index (note: index + 1 is instruction index).
    uint32_t index;
    // Whether or not an Offset/OffsetIdEXT decoration is present.
    bool has_offset = false;
    // Offset value. Max uint32_t is used for no evaluation (e.g. spec
    // constant).
    uint32_t offset = std::numeric_limits<uint32_t>::max();
    // Whether or not RowMajor or ColMajor decoration is present.
    bool has_matrix = false;
    // Matrix constraints (stride and majorness).
    MatrixConstraints matrix_constraints;
  };

  // Cache of structure member information.
  std::unordered_map<uint32_t, std::vector<MemberInfo>> struct_members_;

  struct LayoutKey {
    uint32_t type_id = 0;
    LayoutMode layout;
    uint32_t incoming_offset = 0;
    MatrixConstraints matrix_constraints{};

    bool operator==(const LayoutKey& other) const {
      return type_id == other.type_id && layout == other.layout &&
             incoming_offset == other.incoming_offset &&
             matrix_constraints.stride == other.matrix_constraints.stride &&
             matrix_constraints.col_major == other.matrix_constraints.col_major;
    }
  };
  struct LayoutKeyHash {
    size_t operator()(const LayoutKey& key) const noexcept {
      return spvtools::utils::hash_combine(
          0, key.type_id, static_cast<uint32_t>(key.layout),
          key.incoming_offset, key.matrix_constraints.stride,
          key.matrix_constraints.col_major);
    }
  };

  // Caches valid results of CheckLayout calls.
  std::unordered_set<LayoutKey, LayoutKeyHash> layout_cache_;

  // Returns the layout requirements for `sc`.
  // Workgroup is expected to be explicitly laid out if `is_block` is true.
  // UniformConstant is expected to be explicitly laid out if `descriptor_heap`
  // is true.
  LayoutRequirement GetStorageClassRequirement(spv::StorageClass sc,
                                               bool is_block,
                                               bool descriptor_heap) {
    switch (sc) {
      case spv::StorageClass::Workgroup:
        return is_block ? LayoutRequirement::kRequired
                        : LayoutRequirement::kProhibited;
      case spv::StorageClass::StorageBuffer:
      case spv::StorageClass::Uniform:
      case spv::StorageClass::PushConstant:
      case spv::StorageClass::PhysicalStorageBuffer:
        return LayoutRequirement::kRequired;
      case spv::StorageClass::UniformConstant:
        return descriptor_heap ? LayoutRequirement::kRequired
                               : LayoutRequirement::kProhibited;
      case spv::StorageClass::Function:
      case spv::StorageClass::Private:
        return vstate.version() <= SPV_SPIRV_VERSION_WORD(1, 4)
                   ? LayoutRequirement::kAllowed
                   : LayoutRequirement::kProhibited;
      case spv::StorageClass::Input:
      case spv::StorageClass::Output:
        // Block is used generally and mesh shaders use Offset.
        // TODO: This is a little over permissive.
        return LayoutRequirement::kAllowed;
      default:
        // TODO: Some storage classes in ray tracing use explicit layout
        // decorations, but it is not well documented which. For now treat
        // other storage classes as allowed to be laid out. See Vulkan
        // internal issue 4192.
        return LayoutRequirement::kAllowed;
    }
  }

  // Returns the layout rules for `sc`.
  LayoutMode GetStorageClassLayout(spv::StorageClass sc, bool is_buffer_block) {
    switch (sc) {
      case spv::StorageClass::Workgroup:
        return vstate.options()->workgroup_scalar_block_layout
                   ? LayoutMode::kScalar
                   : LayoutMode::kStandard;
        break;
      case spv::StorageClass::StorageBuffer:
      case spv::StorageClass::PushConstant:
      case spv::StorageClass::UniformConstant:
      case spv::StorageClass::PhysicalStorageBuffer:
        return vstate.options()->scalar_block_layout ? LayoutMode::kScalar
                                                     : LayoutMode::kStandard;
        break;
      case spv::StorageClass::Uniform:
        return vstate.options()->scalar_block_layout
                   ? LayoutMode::kScalar
                   : ((is_buffer_block ||
                       vstate.options()->uniform_buffer_standard_layout)
                          ? LayoutMode::kStandard
                          : LayoutMode::kExtended);
        break;
      default:
        break;
    }
    return LayoutMode::kStandard;
  }

  // Returns true if `inst` is a memory reference instruction
  // Populates `reference` with the necessary information.
  //
  // The following are interesting memory references:
  // For typed pointers:
  //  * OpVariable
  //  * Memory instructions on PhysicalStorageBuffer
  //  * OpBufferPointerEXT
  // For untyped pointers:
  //  * All memory instructions
  bool GetMemoryReference(const Instruction* inst, MemoryReference* reference) {
    auto* type_inst = vstate.FindDef(inst->type_id());
    if (inst->opcode() == spv::Op::OpVariable) {
      auto sc = type_inst->GetOperandAs<spv::StorageClass>(1u);
      const bool is_descriptor_heap = vstate.IsDescriptorHeapBaseVariable(inst);
      reference->storage_class = sc;
      reference->type_id = type_inst->GetOperandAs<uint32_t>(2u);
      const bool is_block_decorated =
          vstate.GetIdOpcode(reference->type_id) == spv::Op::OpTypeStruct &&
          vstate.HasDecoration(reference->type_id, spv::Decoration::Block);
      reference->requirement = GetStorageClassRequirement(
          sc, is_block_decorated, is_descriptor_heap);

      // Unwrap the descriptor array.
      if (sc == spv::StorageClass::StorageBuffer ||
          sc == spv::StorageClass::Uniform ||
          sc == spv::StorageClass::UniformConstant) {
        const auto* data_type = vstate.FindDef(reference->type_id);
        if (data_type->opcode() == spv::Op::OpTypeArray ||
            data_type->opcode() == spv::Op::OpTypeRuntimeArray) {
          reference->descriptor_array_id = reference->type_id;
          reference->type_id = data_type->GetOperandAs<uint32_t>(1u);
        }
      }

      const bool buffer_block =
          vstate.GetIdOpcode(reference->type_id) == spv::Op::OpTypeStruct &&
          vstate.HasDecoration(reference->type_id,
                               spv::Decoration::BufferBlock);
      reference->layout = GetStorageClassLayout(sc, buffer_block);

      return true;
    } else if (type_inst && type_inst->opcode() == spv::Op::OpTypePointer &&
               type_inst->GetOperandAs<spv::StorageClass>(1u) ==
                   spv::StorageClass::PhysicalStorageBuffer) {
      reference->storage_class = spv::StorageClass::PhysicalStorageBuffer;
      reference->type_id = type_inst->GetOperandAs<uint32_t>(2u);
      reference->layout = GetStorageClassLayout(
          spv::StorageClass::PhysicalStorageBuffer, false);
      reference->requirement = LayoutRequirement::kRequired;

      return true;
    } else if (inst->opcode() == spv::Op::OpBufferPointerEXT &&
               type_inst->opcode() == spv::Op::OpTypePointer) {
      auto sc = type_inst->GetOperandAs<spv::StorageClass>(1u);
      reference->storage_class = sc;
      uint32_t pointee_ty_id = type_inst->GetOperandAs<uint32_t>(2u);
      const bool buffer_block =
          vstate.GetIdOpcode(pointee_ty_id) == spv::Op::OpTypeStruct &&
          vstate.HasDecoration(pointee_ty_id, spv::Decoration::BufferBlock);
      reference->layout = GetStorageClassLayout(sc, buffer_block);
      reference->requirement = LayoutRequirement::kRequired;
      reference->type_id = pointee_ty_id;

      return true;
    } else if (vstate.HasCapability(spv::Capability::UntypedPointersKHR) &&
               spvIsVulkanEnv(vstate.context()->target_env)) {
      uint32_t ptr_ty_id = 0;
      uint32_t data_ty_id = 0;
      switch (inst->opcode()) {
        case spv::Op::OpUntypedVariableKHR:
          if (inst->operands().size() > 3) {
            ptr_ty_id = inst->type_id();
            data_ty_id = inst->GetOperandAs<uint32_t>(3u);
          } else {
            return false;
          }
          break;
        case spv::Op::OpUntypedAccessChainKHR:
        case spv::Op::OpUntypedInBoundsAccessChainKHR:
        case spv::Op::OpUntypedPtrAccessChainKHR:
        case spv::Op::OpUntypedInBoundsPtrAccessChainKHR:
          ptr_ty_id = inst->type_id();
          data_ty_id = inst->GetOperandAs<uint32_t>(2);
          break;
        case spv::Op::OpLoad:
          if (vstate.GetIdOpcode(vstate.GetOperandTypeId(inst, 2)) ==
              spv::Op::OpTypeUntypedPointerKHR) {
            const auto ptr_id = inst->GetOperandAs<uint32_t>(2);
            ptr_ty_id = vstate.FindDef(ptr_id)->type_id();
            data_ty_id = inst->type_id();
          } else {
            return false;
          }
          break;
        case spv::Op::OpStore:
          if (vstate.GetIdOpcode(vstate.GetOperandTypeId(inst, 0)) ==
              spv::Op::OpTypeUntypedPointerKHR) {
            const auto ptr_id = inst->GetOperandAs<uint32_t>(0);
            ptr_ty_id = vstate.FindDef(ptr_id)->type_id();
            data_ty_id = vstate.GetOperandTypeId(inst, 1);
          } else {
            return false;
          }
          break;
        case spv::Op::OpUntypedArrayLengthKHR:
          ptr_ty_id =
              vstate.FindDef(inst->GetOperandAs<uint32_t>(3))->type_id();
          data_ty_id = inst->GetOperandAs<uint32_t>(2);
          break;
        default:
          return false;
      }

      // If the data type is an array that contains a Block- or
      // BufferBlock-decorated struct, then use the struct for layout checks
      // instead of the array. In this case, the array represents a descriptor
      // array which should not have an explicit layout.
      const auto* data_type = vstate.FindDef(data_ty_id);
      if (data_type->opcode() == spv::Op::OpTypeArray ||
          data_type->opcode() == spv::Op::OpTypeRuntimeArray) {
        uint32_t ele_ty_id = data_type->GetOperandAs<uint32_t>(1u);
        if (vstate.HasDecoration(ele_ty_id, spv::Decoration::Block) ||
            vstate.HasDecoration(ele_ty_id, spv::Decoration::BufferBlock)) {
          reference->descriptor_array_id = data_ty_id;
          data_ty_id = ele_ty_id;
        }
      }

      auto sc = vstate.FindDef(ptr_ty_id)->GetOperandAs<spv::StorageClass>(1u);
      reference->storage_class = sc;
      reference->type_id = data_ty_id;
      reference->requirement = LayoutRequirement::kRequired;
      reference->untyped = true;
      const bool buffer_block =
          vstate.GetIdOpcode(data_ty_id) == spv::Op::OpTypeStruct &&
          vstate.HasDecoration(data_ty_id, spv::Decoration::BufferBlock);
      reference->layout = GetStorageClassLayout(sc, buffer_block);

      return true;
    } else if (inst->opcode() == spv::Op::OpAbortKHR) {
      reference->type_id = inst->GetOperandAs<uint32_t>(0u);
      // Abort messages doesn't have a storage class
      reference->storage_class = spv::StorageClass::Max;
      // Currently not specified well
      // https://gitlab.khronos.org/spirv/SPIR-V/-/work_items/962
      reference->layout = vstate.options()->scalar_block_layout
                              ? LayoutMode::kScalar
                              : LayoutMode::kStandard;
      reference->requirement = LayoutRequirement::kRequired;
      return true;
    }

    // Not a memory reference.
    return false;
  }

  // Checks that no instruction in the type tree of `type_id` has any explicit
  // layout decorations.
  spv_result_t CheckNoLayout(const Instruction* inst, uint32_t type_id,
                             spv::StorageClass sc) {
    if (no_layout_cache_.count(type_id)) {
      return SPV_SUCCESS;
    }

    const auto* type_inst = vstate.FindDef(type_id);
    if (type_inst->opcode() == spv::Op::OpTypePointer) {
      // PhysicalStorageBuffer and variable pointers can have ArrayStride
      // decorations even if they are stored in a non-laid storage class (e.g.
      // Function).
      auto ptr_sc = type_inst->GetOperandAs<spv::StorageClass>(1u);
      if (GetStorageClassRequirement(ptr_sc, true, false) !=
          LayoutRequirement::kProhibited) {
        return SPV_SUCCESS;
      }
    }

    const auto& id_decs = vstate.id_decorations();
    const auto iter = id_decs.find(type_id);
    if (iter != id_decs.end()) {
      for (const auto& d : iter->second) {
        const spv::Decoration dec = d.dec_type();
        if (dec == spv::Decoration::Block ||
            dec == spv::Decoration::BufferBlock ||
            dec == spv::Decoration::Offset ||
            dec == spv::Decoration::OffsetIdEXT ||
            dec == spv::Decoration::ArrayStride ||
            dec == spv::Decoration::ArrayStrideIdEXT ||
            dec == spv::Decoration::MatrixStride ||
            dec == spv::Decoration::RowMajor ||
            dec == spv::Decoration::ColMajor) {
          return vstate.diag(SPV_ERROR_INVALID_ID, inst)
                 << vstate.VkErrorID(10684)
                 << "Invalid explicit layout decorations on type "
                 << vstate.getIdName(type_id) << ", the "
                 << spvtools::StorageClassToString(sc)
                 << " storage class has an explicit layout from the "
                 << vstate.SpvDecorationString(dec) << " decoration";
        }
      }
    }

    switch (type_inst->opcode()) {
      case spv::Op::OpTypeStruct:
        for (uint32_t i = 1; i < type_inst->operands().size(); i++) {
          if (auto error = CheckNoLayout(
                  inst, type_inst->GetOperandAs<uint32_t>(i), sc)) {
            return error;
          }
        }
        break;
      case spv::Op::OpTypeRuntimeArray:
      case spv::Op::OpTypeArray:
        if (auto error = CheckNoLayout(
                inst, type_inst->GetOperandAs<uint32_t>(1u), sc)) {
          return error;
        }
        break;
      case spv::Op::OpTypePointer: {
        auto ptr_sc = type_inst->GetOperandAs<spv::StorageClass>(1u);
        if (auto error = CheckNoLayout(
                inst, type_inst->GetOperandAs<uint32_t>(2u), ptr_sc)) {
          return error;
        }
        break;
      }
      default:
        break;
    }

    no_layout_cache_.insert(type_id);

    return SPV_SUCCESS;
  }

  // Returns true if type_id contains a matrix. Only looks through arrays.
  bool ContainsMatrix(uint32_t type_id) {
    const auto* type_inst = vstate.FindDef(type_id);
    switch (type_inst->opcode()) {
      case spv::Op::OpTypeMatrix:
        return true;
      case spv::Op::OpTypeArray:
      case spv::Op::OpTypeRuntimeArray:
        return ContainsMatrix(type_inst->GetOperandAs<uint32_t>(1u));
      default:
        break;
    }

    return false;
  }

  // Gets the value for an id-based layout decoration (e.g. ArrayStrideIdEXT and
  // OffsetIdEXT). Returns max uint32_t if the value cannot be evaluated (e.g.
  // spec constant).
  uint32_t GetIdDecorationValue(uint32_t id) {
    const auto* inst = vstate.FindDef(id);
    if (!spvOpcodeIsConstant(inst->opcode())) {
      return std::numeric_limits<uint32_t>::max();
    }
    uint64_t value = 0;
    if (vstate.EvalConstantValUint64(id, &value)) {
      return static_cast<uint32_t>(value);
    }
    return std::numeric_limits<uint32_t>::max();
  }

  // Returns whether an array stride decoration is present on the array and its
  // value.
  std::pair<bool, uint32_t> GetArrayStride(uint32_t array_id) {
    uint32_t stride = std::numeric_limits<uint32_t>::max();
    bool has_stride = false;
    for (auto& d : vstate.id_decorations(array_id)) {
      if (d.dec_type() == spv::Decoration::ArrayStride) {
        stride = d.params()[0];
        has_stride = true;
        break;
      } else if (d.dec_type() == spv::Decoration::ArrayStrideIdEXT) {
        stride = GetIdDecorationValue(d.params()[0]);
        has_stride = true;
        break;
      }
    }
    return std::make_pair(has_stride, stride);
  }

  // Gets the offset value from an offset decoration.
  uint32_t GetOffset(spv::Decoration dec, uint32_t param) {
    // param is a literal value
    if (dec == spv::Decoration::Offset) {
      return param;
    }
    // param is an id
    return GetIdDecorationValue(param);
  }

  // Returns true if value is aligned to align.
  bool IsAlignedTo(uint32_t value, uint32_t align) {
    if (align == 0) return value == 0;
    return (value % align) == 0;
  }

  // Rounds up value to next multiple of align.
  uint32_t AlignTo(uint32_t value, uint32_t align) {
    return (value + align - 1) & ~(align - 1);
  }

  // A member is defined to improperly straddle if either of the following are
  // true:
  // - It is a vector with total size less than or equal to 16 bytes, and has
  // Offset decorations placing its first byte at F and its last byte at L,
  // where floor(F / 16) != floor(L / 16).
  // - It is a vector with total size greater than 16 bytes and has its Offset
  // decorations placing its first byte at a non-integer multiple of 16.
  bool HasImproperStraddle(uint32_t offset, uint32_t size) {
    const auto F = offset;
    const auto L = offset + size - 1;
    if (size <= 16) {
      if ((F >> 4) != (L >> 4)) return true;
    } else {
      if (F % 16 != 0) return true;
    }
    return false;
  }

  // Used to map the option alignment to the Vulkan VUID
  uint32_t GetAlignVkErrorId(spv::Op opcode) {
    if (opcode == spv::Op::OpTypeSampler) {
      return 11476;
    } else if (opcode == spv::Op::OpTypeSampledImage ||
               opcode == spv::Op::OpTypeImage) {
      return 11477;
    } else if (opcode == spv::Op::OpTypeBufferEXT) {
      return 11478;
    } else if (opcode == spv::Op::OpTypeAccelerationStructureKHR) {
      return 11479;
    } else if (opcode == spv::Op::OpTypeTensorARM) {
      return 11480;
    }
    return 0;
  }

  // Returns the alignment for type_id for the given layout rules.
  uint32_t GetAlign(uint32_t type_id, LayoutMode mode,
                    const MatrixConstraints& matrix_constraints,
                    bool allow_relaxed = true) {
    const auto* type_inst = vstate.FindDef(type_id);
    uint32_t align = 1;
    switch (type_inst->opcode()) {
      case spv::Op::OpTypeSampledImage:
      case spv::Op::OpTypeSampler:
      case spv::Op::OpTypeImage:
        if (vstate.HasCapability(spv::Capability::BindlessTextureNV)) {
          return vstate.samplerimage_variable_address_mode() / 8;
        }
        if (type_inst->opcode() == spv::Op::OpTypeSampler) {
          return vstate.options()->sampler_descriptor_layout.alignment;
        }
        if (type_inst->opcode() == spv::Op::OpTypeImage) {
          return vstate.options()->image_descriptor_layout.alignment;
        }
        break;
      case spv::Op::OpTypeBufferEXT:
      case spv::Op::OpTypeAccelerationStructureKHR:
        return vstate.options()->buffer_descriptor_layout.alignment;
      case spv::Op::OpTypeInt:
      case spv::Op::OpTypeFloat:
        return type_inst->GetOperandAs<uint32_t>(1u) / 8;
      case spv::Op::OpTypeVector:
      case spv::Op::OpTypeVectorIdEXT: {
        const auto ele_id = type_inst->GetOperandAs<uint32_t>(1u);
        const auto num_eles = vstate.GetDimension(type_id);
        align = GetAlign(ele_id, mode, {});
        // Relaxed layout only applies to vectors as direct members of structs.
        // Arrays and matrices are not relaxed.
        if (mode == LayoutMode::kScalar ||
            (allow_relaxed && vstate.IsRelaxedBlockLayout())) {
          return align;
        }
        return align * ((num_eles == 3 || num_eles > 4) ? 4 : num_eles);
      }
      case spv::Op::OpTypeMatrix:
        if (mode == LayoutMode::kScalar) {
          const auto* vec_inst =
              vstate.FindDef(type_inst->GetOperandAs<uint32_t>(1u));
          const auto ele_id = vec_inst->GetOperandAs<uint32_t>(1u);
          return GetAlign(ele_id, mode, {});
        }

        if (matrix_constraints.col_major) {
          align = GetAlign(type_inst->GetOperandAs<uint32_t>(1u), mode, {},
                           /* allow_relaxed = */ false);
        } else {
          // A row-major matrix of C columns has a base alignment equal to the
          // base alignment of a vector of C matrix components.
          const auto num_cols = type_inst->GetOperandAs<uint32_t>(2u);
          const auto* col_inst =
              vstate.FindDef(type_inst->GetOperandAs<uint32_t>(1u));
          const auto ele_id = col_inst->GetOperandAs<uint32_t>(1u);
          align = GetAlign(ele_id, mode, {});
          // The equivalent vector may not exist so we replicate the vector rule
          // here.
          if (mode != LayoutMode::kScalar) {
            align = align * (num_cols == 3 ? 4 : num_cols);
          }
        }
        if (mode == LayoutMode::kExtended) {
          align = AlignTo(align, 16u);
        }
        return align;
      case spv::Op::OpTypeArray:
      case spv::Op::OpTypeRuntimeArray:
        align = GetAlign(type_inst->GetOperandAs<uint32_t>(1u), mode,
                         matrix_constraints, /* allow_relaxed = */ false);
        if (mode == LayoutMode::kExtended) {
          align = AlignTo(align, 16u);
        }
        return align;
      case spv::Op::OpTypeStruct:
        for (uint32_t i = 1; i < type_inst->operands().size(); i++) {
          const auto member_id = type_inst->GetOperandAs<uint32_t>(i);
          MatrixConstraints mat_constraints;
          GetMatrixConstraints(type_id, i - 1, &mat_constraints);
          align = std::max(align, GetAlign(member_id, mode, mat_constraints));
          if (mode == LayoutMode::kExtended) {
            align = AlignTo(align, 16u);
          }
        }
        return align;
      case spv::Op::OpTypePointer:
      case spv::Op::OpTypeUntypedPointerKHR:
        return vstate.pointer_size_and_alignment();
      default:
        break;
    }
    assert(0 && "unhandled type");
    return 1;
  }

  // Returns the size of the given type.
  uint32_t GetSize(uint32_t type_id,
                   const MatrixConstraints& matrix_constraints) {
    const auto* type_inst = vstate.FindDef(type_id);
    switch (type_inst->opcode()) {
      case spv::Op::OpTypeSampledImage:
      case spv::Op::OpTypeSampler:
      case spv::Op::OpTypeImage:
        if (vstate.HasCapability(spv::Capability::BindlessTextureNV)) {
          return vstate.samplerimage_variable_address_mode() / 8;
        }
        if (type_inst->opcode() == spv::Op::OpTypeSampler) {
          return vstate.options()->sampler_descriptor_layout.size;
        }
        if (type_inst->opcode() == spv::Op::OpTypeImage) {
          return vstate.options()->image_descriptor_layout.size;
        }
        break;
      case spv::Op::OpTypeBufferEXT:
      case spv::Op::OpTypeAccelerationStructureKHR:
        return vstate.options()->buffer_descriptor_layout.size;
      case spv::Op::OpTypeInt:
      case spv::Op::OpTypeFloat:
        return type_inst->GetOperandAs<uint32_t>(1u) / 8;
      case spv::Op::OpTypeVector:
      case spv::Op::OpTypeVectorIdEXT: {
        const auto ele_id = type_inst->GetOperandAs<uint32_t>(1u);
        const auto num_eles = vstate.GetDimension(type_id);
        return GetSize(ele_id, {}) * num_eles;
      }
      case spv::Op::OpTypeArray: {
        const auto count_id = type_inst->GetOperandAs<uint32_t>(2u);
        uint64_t count = 0;
        if (!vstate.EvalConstantValUint64(count_id, &count)) {
          return 0;
        }
        const auto [has_stride, stride] = GetArrayStride(type_id);
        const auto ele_size =
            GetSize(type_inst->GetOperandAs<uint32_t>(1u), matrix_constraints);
        // uint32 max is a marker for unevaluatable.
        if (stride == std::numeric_limits<uint32_t>::max()) {
          return ele_size;
        }
        return (static_cast<uint32_t>(count) - 1) * stride + ele_size;
      }
      case spv::Op::OpTypeRuntimeArray:
        return 0;
      case spv::Op::OpTypeMatrix: {
        const auto num_cols = type_inst->GetOperandAs<uint32_t>(2u);
        if (matrix_constraints.col_major) {
          return num_cols * matrix_constraints.stride;
        } else {
          const auto* col_inst =
              vstate.FindDef(type_inst->GetOperandAs<uint32_t>(1u));
          const auto ele_id = col_inst->GetOperandAs<uint32_t>(1u);
          const auto num_rows = col_inst->GetOperandAs<uint32_t>(2u);
          return (num_rows - 1) * matrix_constraints.stride +
                 num_cols * GetSize(ele_id, {});
        }
      }
      case spv::Op::OpTypeStruct: {
        const auto& members = GetStructMembers(type_id);
        if (members.empty()) return 0;
        const auto& last = members.back();
        if (last.offset == std::numeric_limits<uint32_t>::max()) {
          return 0;
        }
        return last.offset +
               GetSize(type_inst->GetOperandAs<uint32_t>(last.index + 1),
                       last.matrix_constraints);
      }
      case spv::Op::OpTypePointer:
      case spv::Op::OpTypeUntypedPointerKHR:
        return vstate.pointer_size_and_alignment();
      default:
        break;
    }
    assert(0 && "unhandled type");
    return 0;
  }

  // Returns true if type_id has a matrix and populates matrix_constraints.
  bool GetMatrixConstraints(uint32_t type_id, uint32_t index,
                            MatrixConstraints* matrix_constraints) {
    bool has_matrix = false;
    auto member_decorations = vstate.id_member_decorations(type_id, index);
    for (auto decoration = member_decorations.begin;
         decoration != member_decorations.end; ++decoration) {
      if (decoration->dec_type() == spv::Decoration::ColMajor ||
          decoration->dec_type() == spv::Decoration::RowMajor) {
        has_matrix = true;
        matrix_constraints->col_major =
            decoration->dec_type() == spv::Decoration::ColMajor;
      }
      if (decoration->dec_type() == spv::Decoration::MatrixStride) {
        matrix_constraints->stride = decoration->params()[0];
      }
    }
    return has_matrix;
  }

  // Gathers (and caches) structure members and their decorations.
  const std::vector<MemberInfo>& GetStructMembers(uint32_t type_id) {
    if (struct_members_.count(type_id)) {
      return struct_members_[type_id];
    }

    const auto* type_inst = vstate.FindDef(type_id);
    std::vector<MemberInfo> member_info;
    member_info.reserve(type_inst->operands().size() - 1);
    for (uint32_t i = 1; i < type_inst->operands().size(); i++) {
      auto member_idx = i - 1;
      auto member_decorations =
          vstate.id_member_decorations(type_id, member_idx);
      member_info.push_back(MemberInfo{member_idx});
      auto& member = member_info.back();
      member.has_matrix =
          GetMatrixConstraints(type_id, member_idx, &member.matrix_constraints);
      for (auto decoration = member_decorations.begin;
           decoration != member_decorations.end; ++decoration) {
        switch (decoration->dec_type()) {
          case spv::Decoration::Offset:
          case spv::Decoration::OffsetIdEXT:
            member.has_offset = true;
            member.offset =
                GetOffset(decoration->dec_type(), decoration->params()[0]);
            break;
          default:
            break;
        }
      }
    }
    // Sort by offset value.
    std::stable_sort(member_info.begin(), member_info.end(),
                     [](const MemberInfo& lhs, const MemberInfo& rhs) {
                       return lhs.offset < rhs.offset;
                     });
    struct_members_[type_id] = std::move(member_info);
    return struct_members_[type_id];
  }

  // Returns some common messaging to improve diagnostics.
  std::string CommonError(const Instruction* inst,
                          spv::StorageClass storage_class, LayoutMode mode) {
    std::string s;
    std::ostringstream str(s);
    str << " Instantiated via " << vstate.getIdName(inst->id());
    // OpAbortKHR is an example where there is not storage class
    if (storage_class != spv::StorageClass::Max) {
      str << " in the " << spvtools::StorageClassToString(storage_class)
          << " storage class";
    }
    str << " using " << mode << " layout rules.";
    if (mode != LayoutMode::kScalar) {
      if (storage_class == spv::StorageClass::Workgroup) {
        str << vstate.MissingFeature(
            "workgroupMemoryExplicitLayoutScalarBlockLayout feature",
            "--workgroup-scalar-block-layout", true);
      } else if (!vstate.IsRelaxedBlockLayout()) {
        str << vstate.MissingFeature("VK_KHR_relaxed_block_layout extension",
                                     "--relax-block-layout", true);
      } else if (storage_class == spv::StorageClass::Uniform &&
                 mode != LayoutMode::kStandard) {
        str << vstate.MissingFeature("uniformBufferStandardLayout feature",
                                     "--uniform-buffer-standard-layout", true);
      } else {
        str << vstate.MissingFeature("scalarBlockLayout feature",
                                     "--scalar-block-layout", true);
      }
    }
    return str.str();
  }

  // Checks struct layouts
  // * Each member must
  //   * Have an offset decoration
  //   * If the member is a matrix or array(s) of matrices
  //     * Must have majorness and matrix stride decorations
  //   * If member is a runtime array, it must be last by offset
  //   * Offset must be aligned
  //   * Total offset must be aligned
  //   * Offset + size < next elements offset
  //   * If member is a vector, it must have a valid straddle
  //   * The member has a valid layout
  spv_result_t CheckStructLayout(const Instruction* inst, uint32_t type_id,
                                 spv::StorageClass storage_class,
                                 LayoutMode mode, uint32_t incoming_offset,
                                 const MatrixConstraints& matrix_constraints) {
    const auto* type_inst = vstate.FindDef(type_id);
    const auto& member_info = GetStructMembers(type_id);
    for (auto& member : member_info) {
      const auto member_id =
          type_inst->GetOperandAs<uint32_t>(member.index + 1);
      if (!member.has_offset) {
        return vstate.diag(SPV_ERROR_INVALID_ID, type_inst)
               << "Structure member " << member.index
               << " must be explicitly laid out with Offset or OffsetIdEXT "
                  "decorations."
               << CommonError(inst, storage_class, mode);
      }
      if (ContainsMatrix(member_id)) {
        if (!member.has_matrix) {
          return vstate.diag(SPV_ERROR_INVALID_ID, type_inst)
                 << "Structure member " << member.index
                 << " containing a matrix must be explicitly laid out "
                    "with RowMajor or ColMajor decorations."
                 << CommonError(inst, storage_class, mode);
        } else if (member.matrix_constraints.stride == 0) {
          return vstate.diag(SPV_ERROR_INVALID_ID, type_inst)
                 << "Structure member " << member.index
                 << " containing a matrix must be explicitly laid out "
                    "with MatrixStride decorations."
                 << CommonError(inst, storage_class, mode);
        }
      }
    }

    uint32_t next_offset = 0;
    uint32_t ordered_index = 0;
    for (const auto& member : member_info) {
      auto member_idx = member.index;
      auto offset = member.offset;
      // We have no information
      if (offset == std::numeric_limits<uint32_t>::max()) {
        continue;
      }
      auto member_id = type_inst->GetOperandAs<uint32_t>(member_idx + 1);
      auto member_inst = vstate.FindDef(member_id);
      if (member_inst->opcode() == spv::Op::OpTypeRuntimeArray &&
          ordered_index != member_info.size() - 1) {
        return vstate.diag(SPV_ERROR_INVALID_ID, type_inst)
               << vstate.VkErrorID(4680)
               << "Structure has a runtime array at offset " << offset
               << ", but other members at larger offsets."
               << CommonError(inst, storage_class, mode);
      }
      ordered_index++;

      MatrixConstraints mat_constraints = matrix_constraints;
      if (member.has_matrix) {
        mat_constraints = member.matrix_constraints;
      }
      uint32_t align = GetAlign(member_id, mode, mat_constraints);
      if (!IsAlignedTo(offset, align)) {
        return vstate.diag(SPV_ERROR_INVALID_ID, type_inst)
               << vstate.VkErrorID(GetAlignVkErrorId(member_inst->opcode()))
               << "Structure member " << member_idx << " at offset " << offset
               << " is not aligned to " << align << "."
               << CommonError(inst, storage_class, mode);
      }
      if (!IsAlignedTo(offset + incoming_offset, align)) {
        return vstate.diag(SPV_ERROR_INVALID_ID, type_inst)
               << vstate.VkErrorID(GetAlignVkErrorId(member_inst->opcode()))
               << "Structure member " << member_idx << " at offset " << offset
               << " plus incoming offset " << incoming_offset
               << " is not aligned to " << align << "."
               << CommonError(inst, storage_class, mode);
      }
      if (offset < next_offset) {
        return vstate.diag(SPV_ERROR_INVALID_ID, type_inst)
               << "Structure member " << member_idx << " at offset " << offset
               << " overlaps previous member ending at offset "
               << next_offset - 1 << "."
               << CommonError(inst, storage_class, mode);
      }
      if (mode != LayoutMode::kScalar && vstate.IsRelaxedBlockLayout()) {
        if (member_inst->opcode() == spv::Op::OpTypeVector ||
            member_inst->opcode() == spv::Op::OpTypeVectorIdEXT) {
          uint32_t size = GetSize(member_id, {});
          if (HasImproperStraddle(incoming_offset + offset, size)) {
            return vstate.diag(SPV_ERROR_INVALID_ID, type_inst)
                   << "Structure member " << member_idx
                   << ": Vector has improper straddle due to offset "
                   << incoming_offset + offset << "."
                   << CommonError(inst, storage_class, mode);
          }
        }
      }
      if (auto error = CheckLayout(inst, member_id, storage_class, mode,
                                   incoming_offset + offset, mat_constraints)) {
        return error;
      }

      uint32_t size = GetSize(member_id, mat_constraints);
      next_offset = size + offset;
      if (mode != LayoutMode::kScalar &&
          (member_inst->opcode() == spv::Op::OpTypeArray ||
           member_inst->opcode() == spv::Op::OpTypeStruct)) {
        next_offset = AlignTo(next_offset, align);
      }
    }

    return SPV_SUCCESS;
  }

  // Checks array layouts
  // * Arrays must have stride decoration
  // * Stride must be non-zero
  // * Stride must be aligned
  // * Stride must be greater or equal to element size
  // * Elements have valid layout
  spv_result_t CheckArrayLayout(const Instruction* inst, uint32_t type_id,
                                spv::StorageClass storage_class,
                                LayoutMode mode, uint32_t incoming_offset,
                                const MatrixConstraints& matrix_constraints) {
    const auto* type_inst = vstate.FindDef(type_id);
    auto [has_stride, stride] = GetArrayStride(type_id);
    if (!has_stride) {
      return vstate.diag(SPV_ERROR_INVALID_ID, type_inst)
             << "Array must be explicitly laid out with ArrayStride or "
                "ArrayStrideIdEXT decorations."
             << CommonError(inst, storage_class, mode);
    }
    uint32_t ele_id = type_inst->GetOperandAs<uint32_t>(1u);
    uint32_t ele_size = GetSize(ele_id, matrix_constraints);
    uint32_t align = GetAlign(type_id, mode, matrix_constraints);
    if (stride == 0) {
      return vstate.diag(SPV_ERROR_INVALID_ID, type_inst)
             << "Array must not have a stride of 0."
             << CommonError(inst, storage_class, mode);
    }

    // uint32 max stride is unevaluatable (e.g. spec constant).
    if (stride == std::numeric_limits<uint32_t>::max()) {
      return SPV_SUCCESS;
    }

    if (!IsAlignedTo(stride, align)) {
      return vstate.diag(SPV_ERROR_INVALID_ID, type_inst)
             << "Array stride " << stride << " must satisfy alignment " << align
             << "." << CommonError(inst, storage_class, mode);
    }
    if (stride != std::numeric_limits<uint32_t>::max() && stride < ele_size) {
      return vstate.diag(SPV_ERROR_INVALID_ID, type_inst)
             << "Array stride " << stride
             << " is smaller than element type size " << ele_size << "."
             << CommonError(inst, storage_class, mode);
    }

    uint32_t num_elements = 0;
    if (type_inst->opcode() == spv::Op::OpTypeArray) {
      uint64_t count = 0;
      if (vstate.EvalConstantValUint64(type_inst->GetOperandAs<uint32_t>(2u),
                                       &count)) {
        num_elements = static_cast<uint32_t>(count);
      }
    }
    num_elements = std::max(1u, num_elements);
    std::vector<bool> seen(16, false);
    for (uint32_t i = 0; i < num_elements; ++i) {
      uint32_t next_offset = i * stride + incoming_offset;
      // Stop checking if offsets repeat in terms of 16-byte multiples.
      if (seen[next_offset % 16]) {
        break;
      }

      if (auto error = CheckLayout(inst, ele_id, storage_class, mode,
                                   next_offset, matrix_constraints)) {
        return error;
      }

      seen[next_offset % 16] = true;
    }
    return SPV_SUCCESS;
  }

  // Checks the layout matrices
  // * Stride must be a multiple of align
  // * Stride must be greater or equal to minor size
  spv_result_t CheckMatrixLayout(const Instruction* inst, uint32_t type_id,
                                 spv::StorageClass storage_class,
                                 LayoutMode mode,
                                 const MatrixConstraints& matrix_constraints) {
    // We already checked that any struct containing a matrix has a non-zero
    // stride so if we have 0 stride here then it will come from the result
    // of an access chain or other instruction. Other rules are meant to
    // catch any misuse we can skip it here.
    if (matrix_constraints.stride == 0) {
      return SPV_SUCCESS;
    }
    const auto* type_inst = vstate.FindDef(type_id);
    const auto align = GetAlign(type_id, mode, matrix_constraints);
    if (!IsAlignedTo(matrix_constraints.stride, align)) {
      return vstate.diag(SPV_ERROR_INVALID_ID, type_inst)
             << "Matrix with a stride " << matrix_constraints.stride
             << " not satisfying alignment to " << align << "."
             << CommonError(inst, storage_class, mode) << "\n";
    }
    const auto ele_id = type_inst->GetOperandAs<uint32_t>(1u);
    uint32_t size = 0;
    if (matrix_constraints.col_major) {
      size = GetSize(ele_id, {});
    } else {
      // Element size is # cols * ele size.
      const auto* ele_inst = vstate.FindDef(ele_id);
      const auto scalar_id = ele_inst->GetOperandAs<uint32_t>(1u);
      size = GetSize(scalar_id, {}) * type_inst->GetOperandAs<uint32_t>(2u);
    }
    if (matrix_constraints.stride < size) {
      return vstate.diag(SPV_ERROR_INVALID_ID, type_inst)
             << "Matrix stride " << matrix_constraints.stride
             << " is smaller than column size " << size << "."
             << CommonError(inst, storage_class, mode);
    }
    return SPV_SUCCESS;
  }

  // Returns true if type_id satisfies the given layout rules.
  spv_result_t CheckLayout(const Instruction* inst, uint32_t type_id,
                           spv::StorageClass storage_class, LayoutMode mode,
                           uint32_t incoming_offset,
                           const MatrixConstraints& matrix_constraints) {
    if (vstate.options()->skip_block_layout) {
      return SPV_SUCCESS;
    }

    LayoutKey key{type_id, mode, incoming_offset, matrix_constraints};
    if (layout_cache_.count(key)) {
      return SPV_SUCCESS;
    }

    const auto* type_inst = vstate.FindDef(type_id);
    switch (type_inst->opcode()) {
      case spv::Op::OpTypeStruct:
        if (auto error =
                CheckStructLayout(inst, type_id, storage_class, mode,
                                  incoming_offset, matrix_constraints)) {
          return error;
        }
        break;
      case spv::Op::OpTypeArray:
      case spv::Op::OpTypeRuntimeArray:
        if (auto error =
                CheckArrayLayout(inst, type_id, storage_class, mode,
                                 incoming_offset, matrix_constraints)) {
          return error;
        }
        break;
      case spv::Op::OpTypeMatrix:
        if (auto error = CheckMatrixLayout(inst, type_id, storage_class, mode,
                                           matrix_constraints)) {
          return error;
        }
        break;
      default:
        break;
    }

    layout_cache_.insert(key);

    return SPV_SUCCESS;
  }

  // Performs a single pass over the IR and for each memory reference determines
  // what validation is necessary.
  spv_result_t Run() {
    if (!spvIsVulkanEnv(vstate.context()->target_env)) {
      return SPV_SUCCESS;
    }

    for (const auto& inst : vstate.ordered_instructions()) {
      MemoryReference reference;
      if (!GetMemoryReference(&inst, &reference)) {
        continue;
      }

      // Descriptor arrays shouldn't have a stride. Check for that here since
      // most descriptors require a layout.
      if (reference.descriptor_array_id != 0) {
        const bool array_stride = vstate.HasDecoration(
            reference.descriptor_array_id, spv::Decoration::ArrayStride);
        const bool array_stride_id = vstate.HasDecoration(
            reference.descriptor_array_id, spv::Decoration::ArrayStrideIdEXT);
        if (array_stride || array_stride_id) {
          return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
                 << vstate.VkErrorID(10684)
                 << "Invalid explicit layout decorations on type "
                 << vstate.getIdName(reference.descriptor_array_id) << ", the "
                 << spvtools::StorageClassToString(reference.storage_class)
                 << " storage class has an explicit layout from the "
                 << vstate.SpvDecorationString(
                        array_stride ? spv::Decoration::ArrayStride
                                     : spv::Decoration::ArrayStrideIdEXT)
                 << " decoration";
        }
      }

      // Untyped pointers require a layout. Workgroup variables must be blocks
      // to have a layout.
      if (reference.untyped &&
          reference.storage_class == spv::StorageClass::Workgroup &&
          inst.opcode() == spv::Op::OpUntypedVariableKHR &&
          (vstate.GetIdOpcode(reference.type_id) != spv::Op::OpTypeStruct ||
           !vstate.HasDecoration(reference.type_id, spv::Decoration::Block))) {
        return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
               << vstate.VkErrorID(10684)
               << "Untyped variables in Workgroup storage class must be "
                  "block-decorated structs";
      }

      if (reference.requirement == LayoutRequirement::kRequired) {
        if (auto error =
                CheckLayout(&inst, reference.type_id, reference.storage_class,
                            reference.layout, 0, {})) {
          return error;
        }
      } else if (reference.requirement == LayoutRequirement::kProhibited) {
        if (auto error = CheckNoLayout(&inst, reference.type_id,
                                       reference.storage_class)) {
          return error;
        }
      }
    }
    return SPV_SUCCESS;
  }
};

}  // namespace

spv_result_t ValidateExplicitLayout(ValidationState_t& vstate) {
  return Impl{vstate}.Run();
}

}  // namespace val
}  // namespace spvtools
