// 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;
      // The abort message is always packed with scalar rules
      // See https://gitlab.khronos.org/vulkan/vulkan/-/work_items/4954
      reference->layout = LayoutMode::kScalar;
      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
