// Copyright (c) 2019 Google LLC
//
// 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.

// This pass injects code in a graphics shader to implement guarantees
// satisfying Vulkan's robustBufferAcces rules.  Robust access rules permit
// an out-of-bounds access to be redirected to an access of the same type
// (load, store, etc.) but within the same root object.
//
// We assume baseline functionality in Vulkan, i.e. the module uses
// logical addressing mode, without VK_KHR_variable_pointers.
//
//    - Logical addressing mode implies:
//      - Each root pointer (a pointer that exists other than by the
//        execution of a shader instruction) is the result of an OpVariable.
//
//      - Instructions that result in pointers are:
//          OpVariable
//          OpAccessChain
//          OpInBoundsAccessChain
//          OpFunctionParameter
//          OpImageTexelPointer
//          OpCopyObject
//
//      - Instructions that use a pointer are:
//          OpLoad
//          OpStore
//          OpAccessChain
//          OpInBoundsAccessChain
//          OpFunctionCall
//          OpImageTexelPointer
//          OpCopyMemory
//          OpCopyObject
//          all OpAtomic* instructions
//
// We classify pointer-users into:
//  - Accesses:
//    - OpLoad
//    - OpStore
//    - OpAtomic*
//    - OpCopyMemory
//
//  - Address calculations:
//    - OpAccessChain
//    - OpInBoundsAccessChain
//
//  - Pass-through:
//    - OpFunctionCall
//    - OpFunctionParameter
//    - OpCopyObject
//
// The strategy is:
//
//  - Handle only logical addressing mode. In particular, don't handle a module
//    if it uses one of the variable-pointers capabilities.
//
//  - Don't handle modules using capability RuntimeDescriptorArrayEXT.  So the
//    only runtime arrays are those that are the last member in a
//    Block-decorated struct.  This allows us to feasibly/easily compute the
//    length of the runtime array. See below.
//
//  - The memory locations accessed by OpLoad, OpStore, OpCopyMemory, and
//    OpAtomic* are determined by their pointer parameter or parameters.
//    Pointers are always (correctly) typed and so the address and number of
//    consecutive locations are fully determined by the pointer.
//
//  - A pointer value orginates as one of few cases:
//
//    - OpVariable for an interface object or an array of them: image,
//      buffer (UBO or SSBO), sampler, sampled-image, push-constant, input
//      variable, output variable. The execution environment is responsible for
//      allocating the correct amount of storage for these, and for ensuring
//      each resource bound to such a variable is big enough to contain the
//      SPIR-V pointee type of the variable.
//
//    - OpVariable for a non-interface object.  These are variables in
//      Workgroup, Private, and Function storage classes.  The compiler ensures
//      the underlying allocation is big enough to store the entire SPIR-V
//      pointee type of the variable.
//
//    - An OpFunctionParameter. This always maps to a pointer parameter to an
//      OpFunctionCall.
//
//      - In logical addressing mode, these are severely limited:
//        "Any pointer operand to an OpFunctionCall must be:
//          - a memory object declaration, or
//          - a pointer to an element in an array that is a memory object
//          declaration, where the element type is OpTypeSampler or OpTypeImage"
//
//      - This has an important simplifying consequence:
//
//        - When looking for a pointer to the structure containing a runtime
//          array, you begin with a pointer to the runtime array and trace
//          backward in the function.  You never have to trace back beyond
//          your function call boundary.  So you can't take a partial access
//          chain into an SSBO, then pass that pointer into a function.  So
//          we don't resort to using fat pointers to compute array length.
//          We can trace back to a pointer to the containing structure,
//          and use that in an OpArrayLength instruction. (The structure type
//          gives us the member index of the runtime array.)
//
//        - Otherwise, the pointer type fully encodes the range of valid
//          addresses. In particular, the type of a pointer to an aggregate
//          value fully encodes the range of indices when indexing into
//          that aggregate.
//
//    - The pointer is the result of an access chain instruction.  We clamp
//      indices contributing to address calculations.  As noted above, the
//      valid ranges are either bound by the length of a runtime array, or
//      by the type of the base pointer.  The length of a runtime array is
//      the result of an OpArrayLength instruction acting on the pointer of
//      the containing structure as noted above.
//
//      - Access chain indices are always treated as signed, so:
//        - Clamp the upper bound at the signed integer maximum.
//        - Use SClamp for all clamping.
//
//    - TODO(dneto): OpImageTexelPointer:
//      - Clamp coordinate to the image size returned by OpImageQuerySize
//      - If multi-sampled, clamp the sample index to the count returned by
//        OpImageQuerySamples.
//      - If not multi-sampled, set the sample index to 0.
//
//  - Rely on the external validator to check that pointers are only
//    used by the instructions as above.
//
//  - Handles OpTypeRuntimeArray
//    Track pointer back to original resource (pointer to struct), so we can
//    query the runtime array size.
//

#include "graphics_robust_access_pass.h"

#include <algorithm>
#include <cstring>
#include <functional>
#include <initializer_list>
#include <limits>
#include <utility>

#include "constants.h"
#include "def_use_manager.h"
#include "function.h"
#include "ir_context.h"
#include "module.h"
#include "pass.h"
#include "source/diagnostic.h"
#include "source/util/make_unique.h"
#include "spirv-tools/libspirv.h"
#include "spirv/unified1/GLSL.std.450.h"
#include "spirv/unified1/spirv.h"
#include "type_manager.h"
#include "types.h"

namespace spvtools {
namespace opt {

using opt::Instruction;
using opt::Operand;
using spvtools::MakeUnique;

GraphicsRobustAccessPass::GraphicsRobustAccessPass() : module_status_() {}

Pass::Status GraphicsRobustAccessPass::Process() {
  module_status_ = PerModuleState();

  ProcessCurrentModule();

  auto result = module_status_.failed
                    ? Status::Failure
                    : (module_status_.modified ? Status::SuccessWithChange
                                               : Status::SuccessWithoutChange);

  return result;
}

spvtools::DiagnosticStream GraphicsRobustAccessPass::Fail() {
  module_status_.failed = true;
  // We don't really have a position, and we'll ignore the result.
  return std::move(
      spvtools::DiagnosticStream({}, consumer(), "", SPV_ERROR_INVALID_BINARY)
      << name() << ": ");
}

spv_result_t GraphicsRobustAccessPass::IsCompatibleModule() {
  auto* feature_mgr = context()->get_feature_mgr();
  if (!feature_mgr->HasCapability(SpvCapabilityShader))
    return Fail() << "Can only process Shader modules";
  if (feature_mgr->HasCapability(SpvCapabilityVariablePointers))
    return Fail() << "Can't process modules with VariablePointers capability";
  if (feature_mgr->HasCapability(SpvCapabilityVariablePointersStorageBuffer))
    return Fail() << "Can't process modules with VariablePointersStorageBuffer "
                     "capability";
  if (feature_mgr->HasCapability(SpvCapabilityRuntimeDescriptorArrayEXT)) {
    // These have a RuntimeArray outside of Block-decorated struct.  There
    // is no way to compute the array length from within SPIR-V.
    return Fail() << "Can't process modules with RuntimeDescriptorArrayEXT "
                     "capability";
  }

  {
    auto* inst = context()->module()->GetMemoryModel();
    const auto addressing_model = inst->GetSingleWordOperand(0);
    if (addressing_model != SpvAddressingModelLogical)
      return Fail() << "Addressing model must be Logical.  Found "
                    << inst->PrettyPrint();
  }
  return SPV_SUCCESS;
}

spv_result_t GraphicsRobustAccessPass::ProcessCurrentModule() {
  auto err = IsCompatibleModule();
  if (err != SPV_SUCCESS) return err;

  ProcessFunction fn = [this](opt::Function* f) { return ProcessAFunction(f); };
  module_status_.modified |= context()->ProcessReachableCallTree(fn);

  // Need something here.  It's the price we pay for easier failure paths.
  return SPV_SUCCESS;
}

bool GraphicsRobustAccessPass::ProcessAFunction(opt::Function* function) {
  // Ensure that all pointers computed inside a function are within bounds.
  // Find the access chains in this block before trying to modify them.
  std::vector<Instruction*> access_chains;
  std::vector<Instruction*> image_texel_pointers;
  for (auto& block : *function) {
    for (auto& inst : block) {
      switch (inst.opcode()) {
        case SpvOpAccessChain:
        case SpvOpInBoundsAccessChain:
          access_chains.push_back(&inst);
          break;
        case SpvOpImageTexelPointer:
          image_texel_pointers.push_back(&inst);
          break;
        default:
          break;
      }
    }
  }
  for (auto* inst : access_chains) {
    ClampIndicesForAccessChain(inst);
    if (module_status_.failed) return module_status_.modified;
  }

  for (auto* inst : image_texel_pointers) {
    if (SPV_SUCCESS != ClampCoordinateForImageTexelPointer(inst)) break;
  }
  return module_status_.modified;
}

void GraphicsRobustAccessPass::ClampIndicesForAccessChain(
    Instruction* access_chain) {
  Instruction& inst = *access_chain;

  auto* constant_mgr = context()->get_constant_mgr();
  auto* def_use_mgr = context()->get_def_use_mgr();
  auto* type_mgr = context()->get_type_mgr();
  const bool have_int64_cap =
      context()->get_feature_mgr()->HasCapability(SpvCapabilityInt64);

  // Replaces one of the OpAccessChain index operands with a new value.
  // Updates def-use analysis.
  auto replace_index = [this, &inst, def_use_mgr](uint32_t operand_index,
                                                  Instruction* new_value) {
    inst.SetOperand(operand_index, {new_value->result_id()});
    def_use_mgr->AnalyzeInstUse(&inst);
    module_status_.modified = true;
    return SPV_SUCCESS;
  };

  // Replaces one of the OpAccesssChain index operands with a clamped value.
  // Replace the operand at |operand_index| with the value computed from
  // signed_clamp(%old_value, %min_value, %max_value).  It also analyzes
  // the new instruction and records that them module is modified.
  // Assumes %min_value is signed-less-or-equal than %max_value. (All callees
  // use 0 for %min_value).
  auto clamp_index = [&inst, type_mgr, this, &replace_index](
                         uint32_t operand_index, Instruction* old_value,
                         Instruction* min_value, Instruction* max_value) {
    auto* clamp_inst =
        MakeSClampInst(*type_mgr, old_value, min_value, max_value, &inst);
    return replace_index(operand_index, clamp_inst);
  };

  // Ensures the specified index of access chain |inst| has a value that is
  // at most |count| - 1.  If the index is already a constant value less than
  // |count| then no change is made.
  auto clamp_to_literal_count =
      [&inst, this, &constant_mgr, &type_mgr, have_int64_cap, &replace_index,
       &clamp_index](uint32_t operand_index, uint64_t count) -> spv_result_t {
    Instruction* index_inst =
        this->GetDef(inst.GetSingleWordOperand(operand_index));
    const auto* index_type =
        type_mgr->GetType(index_inst->type_id())->AsInteger();
    assert(index_type);
    const auto index_width = index_type->width();

    if (count <= 1) {
      // Replace the index with 0.
      return replace_index(operand_index, GetValueForType(0, index_type));
    }

    uint64_t maxval = count - 1;

    // Compute the bit width of a viable type to hold |maxval|.
    // Look for a bit width, up to 64 bits wide, to fit maxval.
    uint32_t maxval_width = index_width;
    while ((maxval_width < 64) && (0 != (maxval >> maxval_width))) {
      maxval_width *= 2;
    }
    // Determine the type for |maxval|.
    uint32_t next_id = context()->module()->IdBound();
    analysis::Integer signed_type_for_query(maxval_width, true);
    auto* maxval_type =
        type_mgr->GetRegisteredType(&signed_type_for_query)->AsInteger();
    if (next_id != context()->module()->IdBound()) {
      module_status_.modified = true;
    }
    // Access chain indices are treated as signed, so limit the maximum value
    // of the index so it will always be positive for a signed clamp operation.
    maxval = std::min(maxval, ((uint64_t(1) << (maxval_width - 1)) - 1));

    if (index_width > 64) {
      return this->Fail() << "Can't handle indices wider than 64 bits, found "
                             "constant index with "
                          << index_width << " bits as index number "
                          << operand_index << " of access chain "
                          << inst.PrettyPrint();
    }

    // Split into two cases: the current index is a constant, or not.

    // If the index is a constant then |index_constant| will not be a null
    // pointer.  (If index is an |OpConstantNull| then it |index_constant| will
    // not be a null pointer.)  Since access chain indices must be scalar
    // integers, this can't be a spec constant.
    if (auto* index_constant = constant_mgr->GetConstantFromInst(index_inst)) {
      auto* int_index_constant = index_constant->AsIntConstant();
      int64_t value = 0;
      // OpAccessChain indices are treated as signed.  So get the signed
      // constant value here.
      if (index_width <= 32) {
        value = int64_t(int_index_constant->GetS32BitValue());
      } else if (index_width <= 64) {
        value = int_index_constant->GetS64BitValue();
      }
      if (value < 0) {
        return replace_index(operand_index, GetValueForType(0, index_type));
      } else if (uint64_t(value) <= maxval) {
        // Nothing to do.
        return SPV_SUCCESS;
      } else {
        // Replace with maxval.
        assert(count > 0);  // Already took care of this case above.
        return replace_index(operand_index,
                             GetValueForType(maxval, maxval_type));
      }
    } else {
      // Generate a clamp instruction.
      assert(maxval >= 1);
      assert(index_width <= 64);  // Otherwise, already returned above.
      if (index_width >= 64 && !have_int64_cap) {
        // An inconsistent module.
        return Fail() << "Access chain index is wider than 64 bits, but Int64 "
                         "is not declared: "
                      << index_inst->PrettyPrint();
      }
      // Widen the index value if necessary
      if (maxval_width > index_width) {
        // Find the wider type.  We only need this case if a constant array
        // bound is too big.

        // From how we calculated maxval_width, widening won't require adding
        // the Int64 capability.
        assert(have_int64_cap || maxval_width <= 32);
        if (!have_int64_cap && maxval_width >= 64) {
          // Be defensive, but this shouldn't happen.
          return this->Fail()
                 << "Clamping index would require adding Int64 capability. "
                 << "Can't clamp 32-bit index " << operand_index
                 << " of access chain " << inst.PrettyPrint();
        }
        index_inst = WidenInteger(index_type->IsSigned(), maxval_width,
                                  index_inst, &inst);
      }

      // Finally, clamp the index.
      return clamp_index(operand_index, index_inst,
                         GetValueForType(0, maxval_type),
                         GetValueForType(maxval, maxval_type));
    }
    return SPV_SUCCESS;
  };

  // Ensures the specified index of access chain |inst| has a value that is at
  // most the value of |count_inst| minus 1, where |count_inst| is treated as an
  // unsigned integer. This can log a failure.
  auto clamp_to_count = [&inst, this, &constant_mgr, &clamp_to_literal_count,
                         &clamp_index,
                         &type_mgr](uint32_t operand_index,
                                    Instruction* count_inst) -> spv_result_t {
    Instruction* index_inst =
        this->GetDef(inst.GetSingleWordOperand(operand_index));
    const auto* index_type =
        type_mgr->GetType(index_inst->type_id())->AsInteger();
    const auto* count_type =
        type_mgr->GetType(count_inst->type_id())->AsInteger();
    assert(index_type);
    if (const auto* count_constant =
            constant_mgr->GetConstantFromInst(count_inst)) {
      uint64_t value = 0;
      const auto width = count_constant->type()->AsInteger()->width();
      if (width <= 32) {
        value = count_constant->AsIntConstant()->GetU32BitValue();
      } else if (width <= 64) {
        value = count_constant->AsIntConstant()->GetU64BitValue();
      } else {
        return this->Fail() << "Can't handle indices wider than 64 bits, found "
                               "constant index with "
                            << index_type->width() << "bits";
      }
      return clamp_to_literal_count(operand_index, value);
    } else {
      // Widen them to the same width.
      const auto index_width = index_type->width();
      const auto count_width = count_type->width();
      const auto target_width = std::max(index_width, count_width);
      // UConvert requires the result type to have 0 signedness.  So enforce
      // that here.
      auto* wider_type = index_width < count_width ? count_type : index_type;
      if (index_type->width() < target_width) {
        // Access chain indices are treated as signed integers.
        index_inst = WidenInteger(true, target_width, index_inst, &inst);
      } else if (count_type->width() < target_width) {
        // Assume type sizes are treated as unsigned.
        count_inst = WidenInteger(false, target_width, count_inst, &inst);
      }
      // Compute count - 1.
      // It doesn't matter if 1 is signed or unsigned.
      auto* one = GetValueForType(1, wider_type);
      auto* count_minus_1 = InsertInst(
          &inst, SpvOpISub, type_mgr->GetId(wider_type), TakeNextId(),
          {{SPV_OPERAND_TYPE_ID, {count_inst->result_id()}},
           {SPV_OPERAND_TYPE_ID, {one->result_id()}}});
      auto* zero = GetValueForType(0, wider_type);
      // Make sure we clamp to an upper bound that is at most the signed max
      // for the target type.
      const uint64_t max_signed_value =
          ((uint64_t(1) << (target_width - 1)) - 1);
      // Use unsigned-min to ensure that the result is always non-negative.
      // That ensures we satisfy the invariant for SClamp, where the "min"
      // argument we give it (zero), is no larger than the third argument.
      auto* upper_bound =
          MakeUMinInst(*type_mgr, count_minus_1,
                       GetValueForType(max_signed_value, wider_type), &inst);
      // Now clamp the index to this upper bound.
      return clamp_index(operand_index, index_inst, zero, upper_bound);
    }
    return SPV_SUCCESS;
  };

  const Instruction* base_inst = GetDef(inst.GetSingleWordInOperand(0));
  const Instruction* base_type = GetDef(base_inst->type_id());
  Instruction* pointee_type = GetDef(base_type->GetSingleWordInOperand(1));

  // Walk the indices from earliest to latest, replacing indices with a
  // clamped value, and updating the pointee_type.  The order matters for
  // the case when we have to compute the length of a runtime array.  In
  // that the algorithm relies on the fact that that the earlier indices
  // have already been clamped.
  const uint32_t num_operands = inst.NumOperands();
  for (uint32_t idx = 3; !module_status_.failed && idx < num_operands; ++idx) {
    const uint32_t index_id = inst.GetSingleWordOperand(idx);
    Instruction* index_inst = GetDef(index_id);

    switch (pointee_type->opcode()) {
      case SpvOpTypeMatrix:  // Use column count
      case SpvOpTypeVector:  // Use component count
      {
        const uint32_t count = pointee_type->GetSingleWordOperand(2);
        clamp_to_literal_count(idx, count);
        pointee_type = GetDef(pointee_type->GetSingleWordOperand(1));
      } break;

      case SpvOpTypeArray: {
        // The array length can be a spec constant, so go through the general
        // case.
        Instruction* array_len = GetDef(pointee_type->GetSingleWordOperand(2));
        clamp_to_count(idx, array_len);
        pointee_type = GetDef(pointee_type->GetSingleWordOperand(1));
      } break;

      case SpvOpTypeStruct: {
        // SPIR-V requires the index to be an OpConstant.
        // We need to know the index literal value so we can compute the next
        // pointee type.
        if (index_inst->opcode() != SpvOpConstant ||
            !constant_mgr->GetConstantFromInst(index_inst)
                 ->type()
                 ->AsInteger()) {
          Fail() << "Member index into struct is not a constant integer: "
                 << index_inst->PrettyPrint(
                        SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES)
                 << "\nin access chain: "
                 << inst.PrettyPrint(SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
          return;
        }
        const auto num_members = pointee_type->NumInOperands();
        const auto* index_constant =
            constant_mgr->GetConstantFromInst(index_inst);
        // Get the sign-extended value, since access index is always treated as
        // signed.
        const auto index_value = index_constant->GetSignExtendedValue();
        if (index_value < 0 || index_value >= num_members) {
          Fail() << "Member index " << index_value
                 << " is out of bounds for struct type: "
                 << pointee_type->PrettyPrint(
                        SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES)
                 << "\nin access chain: "
                 << inst.PrettyPrint(SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
          return;
        }
        pointee_type = GetDef(pointee_type->GetSingleWordInOperand(
            static_cast<uint32_t>(index_value)));
        // No need to clamp this index.  We just checked that it's valid.
      } break;

      case SpvOpTypeRuntimeArray: {
        auto* array_len = MakeRuntimeArrayLengthInst(&inst, idx);
        if (!array_len) {  // We've already signaled an error.
          return;
        }
        clamp_to_count(idx, array_len);
        if (module_status_.failed) return;
        pointee_type = GetDef(pointee_type->GetSingleWordOperand(1));
      } break;

      default:
        Fail() << " Unhandled pointee type for access chain "
               << pointee_type->PrettyPrint(
                      SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
    }
  }
}

uint32_t GraphicsRobustAccessPass::GetGlslInsts() {
  if (module_status_.glsl_insts_id == 0) {
    // This string serves double-duty as raw data for a string and for a vector
    // of 32-bit words
    const char glsl[] = "GLSL.std.450\0\0\0\0";
    const size_t glsl_str_byte_len = 16;
    // Use an existing import if we can.
    for (auto& inst : context()->module()->ext_inst_imports()) {
      const auto& name_words = inst.GetInOperand(0).words;
      if (0 == std::strncmp(reinterpret_cast<const char*>(name_words.data()),
                            glsl, glsl_str_byte_len)) {
        module_status_.glsl_insts_id = inst.result_id();
      }
    }
    if (module_status_.glsl_insts_id == 0) {
      // Make a new import instruction.
      module_status_.glsl_insts_id = TakeNextId();
      std::vector<uint32_t> words(glsl_str_byte_len / sizeof(uint32_t));
      std::memcpy(words.data(), glsl, glsl_str_byte_len);
      auto import_inst = MakeUnique<Instruction>(
          context(), SpvOpExtInstImport, 0, module_status_.glsl_insts_id,
          std::initializer_list<Operand>{
              Operand{SPV_OPERAND_TYPE_LITERAL_STRING, std::move(words)}});
      Instruction* inst = import_inst.get();
      context()->module()->AddExtInstImport(std::move(import_inst));
      module_status_.modified = true;
      context()->AnalyzeDefUse(inst);
      // Reanalyze the feature list, since we added an extended instruction
      // set improt.
      context()->get_feature_mgr()->Analyze(context()->module());
    }
  }
  return module_status_.glsl_insts_id;
}

opt::Instruction* opt::GraphicsRobustAccessPass::GetValueForType(
    uint64_t value, const analysis::Integer* type) {
  auto* mgr = context()->get_constant_mgr();
  assert(type->width() <= 64);
  std::vector<uint32_t> words;
  words.push_back(uint32_t(value));
  if (type->width() > 32) {
    words.push_back(uint32_t(value >> 32u));
  }
  const auto* constant = mgr->GetConstant(type, words);
  return mgr->GetDefiningInstruction(
      constant, context()->get_type_mgr()->GetTypeInstruction(type));
}

opt::Instruction* opt::GraphicsRobustAccessPass::WidenInteger(
    bool sign_extend, uint32_t bit_width, Instruction* value,
    Instruction* before_inst) {
  analysis::Integer unsigned_type_for_query(bit_width, false);
  auto* type_mgr = context()->get_type_mgr();
  auto* unsigned_type = type_mgr->GetRegisteredType(&unsigned_type_for_query);
  auto type_id = context()->get_type_mgr()->GetId(unsigned_type);
  auto conversion_id = TakeNextId();
  auto* conversion = InsertInst(
      before_inst, (sign_extend ? SpvOpSConvert : SpvOpUConvert), type_id,
      conversion_id, {{SPV_OPERAND_TYPE_ID, {value->result_id()}}});
  return conversion;
}

Instruction* GraphicsRobustAccessPass::MakeUMinInst(
    const analysis::TypeManager& tm, Instruction* x, Instruction* y,
    Instruction* where) {
  // Get IDs of instructions we'll be referencing. Evaluate them before calling
  // the function so we force a deterministic ordering in case both of them need
  // to take a new ID.
  const uint32_t glsl_insts_id = GetGlslInsts();
  uint32_t smin_id = TakeNextId();
  const auto xwidth = tm.GetType(x->type_id())->AsInteger()->width();
  const auto ywidth = tm.GetType(y->type_id())->AsInteger()->width();
  assert(xwidth == ywidth);
  (void)xwidth;
  (void)ywidth;
  auto* smin_inst = InsertInst(
      where, SpvOpExtInst, x->type_id(), smin_id,
      {
          {SPV_OPERAND_TYPE_ID, {glsl_insts_id}},
          {SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER, {GLSLstd450UMin}},
          {SPV_OPERAND_TYPE_ID, {x->result_id()}},
          {SPV_OPERAND_TYPE_ID, {y->result_id()}},
      });
  return smin_inst;
}

Instruction* GraphicsRobustAccessPass::MakeSClampInst(
    const analysis::TypeManager& tm, Instruction* x, Instruction* min,
    Instruction* max, Instruction* where) {
  // Get IDs of instructions we'll be referencing. Evaluate them before calling
  // the function so we force a deterministic ordering in case both of them need
  // to take a new ID.
  const uint32_t glsl_insts_id = GetGlslInsts();
  uint32_t clamp_id = TakeNextId();
  const auto xwidth = tm.GetType(x->type_id())->AsInteger()->width();
  const auto minwidth = tm.GetType(min->type_id())->AsInteger()->width();
  const auto maxwidth = tm.GetType(max->type_id())->AsInteger()->width();
  assert(xwidth == minwidth);
  assert(xwidth == maxwidth);
  (void)xwidth;
  (void)minwidth;
  (void)maxwidth;
  auto* clamp_inst = InsertInst(
      where, SpvOpExtInst, x->type_id(), clamp_id,
      {
          {SPV_OPERAND_TYPE_ID, {glsl_insts_id}},
          {SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER, {GLSLstd450SClamp}},
          {SPV_OPERAND_TYPE_ID, {x->result_id()}},
          {SPV_OPERAND_TYPE_ID, {min->result_id()}},
          {SPV_OPERAND_TYPE_ID, {max->result_id()}},
      });
  return clamp_inst;
}

Instruction* GraphicsRobustAccessPass::MakeRuntimeArrayLengthInst(
    Instruction* access_chain, uint32_t operand_index) {
  // The Index parameter to the access chain at |operand_index| is indexing
  // *into* the runtime-array.  To get the number of elements in the runtime
  // array we need a pointer to the Block-decorated struct that contains the
  // runtime array. So conceptually we have to go 2 steps backward in the
  // access chain.  The two steps backward might forces us to traverse backward
  // across multiple dominating instructions.
  auto* type_mgr = context()->get_type_mgr();

  // How many access chain indices do we have to unwind to find the pointer
  // to the struct containing the runtime array?
  uint32_t steps_remaining = 2;
  // Find or create an instruction computing the pointer to the structure
  // containing the runtime array.
  // Walk backward through pointer address calculations until we either get
  // to exactly the right base pointer, or to an access chain instruction
  // that we can replicate but truncate to compute the address of the right
  // struct.
  Instruction* current_access_chain = access_chain;
  Instruction* pointer_to_containing_struct = nullptr;
  while (steps_remaining > 0) {
    switch (current_access_chain->opcode()) {
      case SpvOpCopyObject:
        // Whoops. Walk right through this one.
        current_access_chain =
            GetDef(current_access_chain->GetSingleWordInOperand(0));
        break;
      case SpvOpAccessChain:
      case SpvOpInBoundsAccessChain: {
        const int first_index_operand = 3;
        // How many indices in this access chain contribute to getting us
        // to an element in the runtime array?
        const auto num_contributing_indices =
            current_access_chain == access_chain
                ? operand_index - (first_index_operand - 1)
                : current_access_chain->NumInOperands() - 1 /* skip the base */;
        Instruction* base =
            GetDef(current_access_chain->GetSingleWordInOperand(0));
        if (num_contributing_indices == steps_remaining) {
          // The base pointer points to the structure.
          pointer_to_containing_struct = base;
          steps_remaining = 0;
          break;
        } else if (num_contributing_indices < steps_remaining) {
          // Peel off the index and keep going backward.
          steps_remaining -= num_contributing_indices;
          current_access_chain = base;
        } else {
          // This access chain has more indices than needed.  Generate a new
          // access chain instruction, but truncating the list of indices.
          const int base_operand = 2;
          // We'll use the base pointer and the indices up to but not including
          // the one indexing into the runtime array.
          Instruction::OperandList ops;
          // Use the base pointer
          ops.push_back(current_access_chain->GetOperand(base_operand));
          const uint32_t num_indices_to_keep =
              num_contributing_indices - steps_remaining - 1;
          for (uint32_t i = 0; i <= num_indices_to_keep; i++) {
            ops.push_back(
                current_access_chain->GetOperand(first_index_operand + i));
          }
          // Compute the type of the result of the new access chain.  Start at
          // the base and walk the indices in a forward direction.
          auto* constant_mgr = context()->get_constant_mgr();
          std::vector<uint32_t> indices_for_type;
          for (uint32_t i = 0; i < ops.size() - 1; i++) {
            uint32_t index_for_type_calculation = 0;
            Instruction* index =
                GetDef(current_access_chain->GetSingleWordOperand(
                    first_index_operand + i));
            if (auto* index_constant =
                    constant_mgr->GetConstantFromInst(index)) {
              // We only need 32 bits. For the type calculation, it's sufficient
              // to take the zero-extended value. It only matters for the struct
              // case, and struct member indices are unsigned.
              index_for_type_calculation =
                  uint32_t(index_constant->GetZeroExtendedValue());
            } else {
              // Indexing into a variably-sized thing like an array.  Use 0.
              index_for_type_calculation = 0;
            }
            indices_for_type.push_back(index_for_type_calculation);
          }
          auto* base_ptr_type = type_mgr->GetType(base->type_id())->AsPointer();
          auto* base_pointee_type = base_ptr_type->pointee_type();
          auto* new_access_chain_result_pointee_type =
              type_mgr->GetMemberType(base_pointee_type, indices_for_type);
          const uint32_t new_access_chain_type_id = type_mgr->FindPointerToType(
              type_mgr->GetId(new_access_chain_result_pointee_type),
              base_ptr_type->storage_class());

          // Create the instruction and insert it.
          const auto new_access_chain_id = TakeNextId();
          auto* new_access_chain =
              InsertInst(current_access_chain, current_access_chain->opcode(),
                         new_access_chain_type_id, new_access_chain_id, ops);
          pointer_to_containing_struct = new_access_chain;
          steps_remaining = 0;
          break;
        }
      } break;
      default:
        Fail() << "Unhandled access chain in logical addressing mode passes "
                  "through "
               << current_access_chain->PrettyPrint(
                      SPV_BINARY_TO_TEXT_OPTION_SHOW_BYTE_OFFSET |
                      SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
        return nullptr;
    }
  }
  assert(pointer_to_containing_struct);
  auto* pointee_type =
      type_mgr->GetType(pointer_to_containing_struct->type_id())
          ->AsPointer()
          ->pointee_type();

  auto* struct_type = pointee_type->AsStruct();
  const uint32_t member_index_of_runtime_array =
      uint32_t(struct_type->element_types().size() - 1);
  // Create the length-of-array instruction before the original access chain,
  // but after the generation of the pointer to the struct.
  const auto array_len_id = TakeNextId();
  analysis::Integer uint_type_for_query(32, false);
  auto* uint_type = type_mgr->GetRegisteredType(&uint_type_for_query);
  auto* array_len = InsertInst(
      access_chain, SpvOpArrayLength, type_mgr->GetId(uint_type), array_len_id,
      {{SPV_OPERAND_TYPE_ID, {pointer_to_containing_struct->result_id()}},
       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {member_index_of_runtime_array}}});
  return array_len;
}

spv_result_t GraphicsRobustAccessPass::ClampCoordinateForImageTexelPointer(
    opt::Instruction* image_texel_pointer) {
  // TODO(dneto): Write tests for this code.
  // TODO(dneto): Use signed-clamp
  (void)(image_texel_pointer);
  return SPV_SUCCESS;

  // Do not compile this code until it is ready to be used.
#if 0
  // Example:
  //   %texel_ptr = OpImageTexelPointer %texel_ptr_type %image_ptr %coord
  //   %sample
  //
  // We want to clamp %coord components between vector-0 and the result
  // of OpImageQuerySize acting on the underlying image.  So insert:
  //     %image = OpLoad %image_type %image_ptr
  //     %query_size = OpImageQuerySize %query_size_type %image
  //
  // For a multi-sampled image, %sample is the sample index, and we need
  // to clamp it between zero and the number of samples in the image.
  //     %sample_count = OpImageQuerySamples %uint %image
  //     %max_sample_index = OpISub %uint %sample_count %uint_1
  // For non-multi-sampled images, the sample index must be constant zero.

  auto* def_use_mgr = context()->get_def_use_mgr();
  auto* type_mgr = context()->get_type_mgr();
  auto* constant_mgr = context()->get_constant_mgr();

  auto* image_ptr = GetDef(image_texel_pointer->GetSingleWordInOperand(0));
  auto* image_ptr_type = GetDef(image_ptr->type_id());
  auto image_type_id = image_ptr_type->GetSingleWordInOperand(1);
  auto* image_type = GetDef(image_type_id);
  auto* coord = GetDef(image_texel_pointer->GetSingleWordInOperand(1));
  auto* samples = GetDef(image_texel_pointer->GetSingleWordInOperand(2));

  // We will modify the module, at least by adding image query instructions.
  module_status_.modified = true;

  // Declare the ImageQuery capability if the module doesn't already have it.
  auto* feature_mgr = context()->get_feature_mgr();
  if (!feature_mgr->HasCapability(SpvCapabilityImageQuery)) {
    auto cap = MakeUnique<Instruction>(
        context(), SpvOpCapability, 0, 0,
        std::initializer_list<Operand>{
            {SPV_OPERAND_TYPE_CAPABILITY, {SpvCapabilityImageQuery}}});
    def_use_mgr->AnalyzeInstDefUse(cap.get());
    context()->AddCapability(std::move(cap));
    feature_mgr->Analyze(context()->module());
  }

  // OpImageTexelPointer is used to translate a coordinate and sample index
  // into an address for use with an atomic operation.  That is, it may only
  // used with what Vulkan calls a "storage image"
  // (OpTypeImage parameter Sampled=2).
  // Note: A storage image never has a level-of-detail associated with it.

  // Constraints on the sample id:
  //  - Only 2D images can be multi-sampled: OpTypeImage parameter MS=1
  //    only if Dim=2D.
  //  - Non-multi-sampled images (OpTypeImage parameter MS=0) must use
  //    sample ID to a constant 0.

  // The coordinate is treated as unsigned, and should be clamped against the
  // image "size", returned by OpImageQuerySize. (Note: OpImageQuerySizeLod
  // is only usable with a sampled image, i.e. its image type has Sampled=1).

  // Determine the result type for the OpImageQuerySize.
  // For non-arrayed images:
  //   non-Cube:
  //     - Always the same as the coordinate type
  //   Cube:
  //     - Use all but the last component of the coordinate (which is the face
  //       index from 0 to 5).
  // For arrayed images (in Vulkan the Dim is 1D, 2D, or Cube):
  //   non-Cube:
  //     - A vector with the components in the coordinate, and one more for
  //       the layer index.
  //   Cube:
  //     - The same as the coordinate type: 3-element integer vector.
  //     - The third component from the size query is the layer count.
  //     - The third component in the texel pointer calculation is
  //       6 * layer + face, where 0 <= face < 6.
  //   Cube: Use all but the last component of the coordinate (which is the face
  //   index from 0 to 5).
  const auto dim = SpvDim(image_type->GetSingleWordInOperand(1));
  const bool arrayed = image_type->GetSingleWordInOperand(3) == 1;
  const bool multisampled = image_type->GetSingleWordInOperand(4) != 0;
  const auto query_num_components = [dim, arrayed, this]() -> int {
    const int arrayness_bonus = arrayed ? 1 : 0;
    int num_coords = 0;
    switch (dim) {
      case SpvDimBuffer:
      case SpvDim1D:
        num_coords = 1;
        break;
      case SpvDimCube:
        // For cube, we need bounds for x, y, but not face.
      case SpvDimRect:
      case SpvDim2D:
        num_coords = 2;
        break;
      case SpvDim3D:
        num_coords = 3;
        break;
      case SpvDimSubpassData:
      case SpvDimMax:
        return Fail() << "Invalid image dimension for OpImageTexelPointer: "
                      << int(dim);
        break;
    }
    return num_coords + arrayness_bonus;
  }();
  const auto* coord_component_type = [type_mgr, coord]() {
    const analysis::Type* coord_type = type_mgr->GetType(coord->type_id());
    if (auto* vector_type = coord_type->AsVector()) {
      return vector_type->element_type()->AsInteger();
    }
    return coord_type->AsInteger();
  }();
  // For now, only handle 32-bit case for coordinates.
  if (!coord_component_type) {
    return Fail() << " Coordinates for OpImageTexelPointer are not integral: "
                  << image_texel_pointer->PrettyPrint(
                         SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  }
  if (coord_component_type->width() != 32) {
    return Fail() << " Expected OpImageTexelPointer coordinate components to "
                     "be 32-bits wide. They are "
                  << coord_component_type->width() << " bits. "
                  << image_texel_pointer->PrettyPrint(
                         SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  }
  const auto* query_size_type =
      [type_mgr, coord_component_type,
       query_num_components]() -> const analysis::Type* {
    if (query_num_components == 1) return coord_component_type;
    analysis::Vector proposed(coord_component_type, query_num_components);
    return type_mgr->GetRegisteredType(&proposed);
  }();

  const uint32_t image_id = TakeNextId();
  auto* image =
      InsertInst(image_texel_pointer, SpvOpLoad, image_type_id, image_id,
                 {{SPV_OPERAND_TYPE_ID, {image_ptr->result_id()}}});

  const uint32_t query_size_id = TakeNextId();
  auto* query_size =
      InsertInst(image_texel_pointer, SpvOpImageQuerySize,
                 type_mgr->GetTypeInstruction(query_size_type), query_size_id,
                 {{SPV_OPERAND_TYPE_ID, {image->result_id()}}});

  auto* component_1 = constant_mgr->GetConstant(coord_component_type, {1});
  const uint32_t component_1_id =
      constant_mgr->GetDefiningInstruction(component_1)->result_id();
  auto* component_0 = constant_mgr->GetConstant(coord_component_type, {0});
  const uint32_t component_0_id =
      constant_mgr->GetDefiningInstruction(component_0)->result_id();

  // If the image is a cube array, then the last component of the queried
  // size is the layer count.  In the query, we have to accomodate folding
  // in the face index ranging from 0 through 5. The inclusive upper bound
  // on the third coordinate therefore is multiplied by 6.
  auto* query_size_including_faces = query_size;
  if (arrayed && (dim == SpvDimCube)) {
    // Multiply the last coordinate by 6.
    auto* component_6 = constant_mgr->GetConstant(coord_component_type, {6});
    const uint32_t component_6_id =
        constant_mgr->GetDefiningInstruction(component_6)->result_id();
    assert(query_num_components == 3);
    auto* multiplicand = constant_mgr->GetConstant(
        query_size_type, {component_1_id, component_1_id, component_6_id});
    auto* multiplicand_inst =
        constant_mgr->GetDefiningInstruction(multiplicand);
    const auto query_size_including_faces_id = TakeNextId();
    query_size_including_faces = InsertInst(
        image_texel_pointer, SpvOpIMul,
        type_mgr->GetTypeInstruction(query_size_type),
        query_size_including_faces_id,
        {{SPV_OPERAND_TYPE_ID, {query_size_including_faces->result_id()}},
         {SPV_OPERAND_TYPE_ID, {multiplicand_inst->result_id()}}});
  }

  // Make a coordinate-type with all 1 components.
  auto* coordinate_1 =
      query_num_components == 1
          ? component_1
          : constant_mgr->GetConstant(
                query_size_type,
                std::vector<uint32_t>(query_num_components, component_1_id));
  // Make a coordinate-type with all 1 components.
  auto* coordinate_0 =
      query_num_components == 0
          ? component_0
          : constant_mgr->GetConstant(
                query_size_type,
                std::vector<uint32_t>(query_num_components, component_0_id));

  const uint32_t query_max_including_faces_id = TakeNextId();
  auto* query_max_including_faces = InsertInst(
      image_texel_pointer, SpvOpISub,
      type_mgr->GetTypeInstruction(query_size_type),
      query_max_including_faces_id,
      {{SPV_OPERAND_TYPE_ID, {query_size_including_faces->result_id()}},
       {SPV_OPERAND_TYPE_ID,
        {constant_mgr->GetDefiningInstruction(coordinate_1)->result_id()}}});

  // Clamp the coordinate
  auto* clamp_coord = MakeSClampInst(
      *type_mgr, coord, constant_mgr->GetDefiningInstruction(coordinate_0),
      query_max_including_faces, image_texel_pointer);
  image_texel_pointer->SetInOperand(1, {clamp_coord->result_id()});

  // Clamp the sample index
  if (multisampled) {
    // Get the sample count via OpImageQuerySamples
    const auto query_samples_id = TakeNextId();
    auto* query_samples = InsertInst(
        image_texel_pointer, SpvOpImageQuerySamples,
        constant_mgr->GetDefiningInstruction(component_0)->type_id(),
        query_samples_id, {{SPV_OPERAND_TYPE_ID, {image->result_id()}}});

    const auto max_samples_id = TakeNextId();
    auto* max_samples = InsertInst(image_texel_pointer, SpvOpImageQuerySamples,
                                   query_samples->type_id(), max_samples_id,
                                   {{SPV_OPERAND_TYPE_ID, {query_samples_id}},
                                    {SPV_OPERAND_TYPE_ID, {component_1_id}}});

    auto* clamp_samples = MakeSClampInst(
        *type_mgr, samples, constant_mgr->GetDefiningInstruction(coordinate_0),
        max_samples, image_texel_pointer);
    image_texel_pointer->SetInOperand(2, {clamp_samples->result_id()});

  } else {
    // Just replace it with 0.  Don't even check what was there before.
    image_texel_pointer->SetInOperand(2, {component_0_id});
  }

  def_use_mgr->AnalyzeInstUse(image_texel_pointer);

  return SPV_SUCCESS;
#endif
}

opt::Instruction* GraphicsRobustAccessPass::InsertInst(
    opt::Instruction* where_inst, SpvOp opcode, uint32_t type_id,
    uint32_t result_id, const Instruction::OperandList& operands) {
  module_status_.modified = true;
  auto* result = where_inst->InsertBefore(
      MakeUnique<Instruction>(context(), opcode, type_id, result_id, operands));
  context()->get_def_use_mgr()->AnalyzeInstDefUse(result);
  auto* basic_block = context()->get_instr_block(where_inst);
  context()->set_instr_block(result, basic_block);
  return result;
}

}  // namespace opt
}  // namespace spvtools
