// 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.

#ifndef SOURCE_OPT_GRAPHICS_ROBUST_ACCESS_PASS_H_
#define SOURCE_OPT_GRAPHICS_ROBUST_ACCESS_PASS_H_

#include <map>
#include <unordered_map>

#include "source/diagnostic.h"

#include "constants.h"
#include "def_use_manager.h"
#include "instruction.h"
#include "module.h"
#include "pass.h"

namespace spvtools {
namespace opt {

// See optimizer.hpp for documentation.
class GraphicsRobustAccessPass : public Pass {
 public:
  GraphicsRobustAccessPass();
  const char* name() const override { return "graphics-robust-access"; }
  Status Process() override;

  IRContext::Analysis GetPreservedAnalyses() override {
    return IRContext::kAnalysisDefUse |
           IRContext::kAnalysisInstrToBlockMapping |
           IRContext::kAnalysisConstants | IRContext::kAnalysisTypes |
           IRContext::kAnalysisIdToFuncMapping;
  }

 private:
  // Records failure for the current module, and returns a stream
  // that can be used to provide user error information to the message
  // consumer.
  spvtools::DiagnosticStream Fail();

  // Returns SPV_SUCCESS if this pass can correctly process the module.
  // Otherwise logs a message and returns a failure code.
  spv_result_t IsCompatibleModule();

  // Transform the current module, if possible. Failure and modification
  // status is recorded in the |_| member. On failure, error information is
  // posted to the message consumer.  The return value has no significance.
  spv_result_t ProcessCurrentModule();

  // Process the given function.  Updates the state value |_|.  Returns true
  // if the module was modified.
  bool ProcessAFunction(opt::Function*);

  // Clamps indices in the OpAccessChain or OpInBoundsAccessChain instruction
  // |access_chain|. Inserts instructions before the given instruction.  Updates
  // analyses and records that the module is modified.
  void ClampIndicesForAccessChain(Instruction* access_chain);

  // Returns the id of the instruction importing the "GLSL.std.450" extended
  // instruction set. If it does not yet exist, the import instruction is
  // created and inserted into the module, and updates |_.modified| and
  // |_.glsl_insts_id|.
  uint32_t GetGlslInsts();

  // Returns an instruction which is constant with the given value of the given
  // type. Ignores any value bits beyond the width of the type.
  Instruction* GetValueForType(uint64_t value, const analysis::Integer* type);

  // Returns the unsigned value for the given constant.  Assumes it's at most
  // 64 bits wide.
  uint64_t GetUnsignedValueForConstant(const analysis::Constant* c);

  // Converts an integer value to an unsigned wider integer type, using either
  // sign extension or zero extension.  The new instruction is inserted
  // immediately before |before_inst|, and is analyzed for definitions and uses.
  // Returns the newly inserted instruction.  Assumes the |value| is an integer
  // scalar of a narrower type than |bitwidth| bits.
  Instruction* WidenInteger(bool sign_extend, uint32_t bitwidth,
                            Instruction* value, Instruction* before_inst);

  // Returns a new instruction that invokes the UClamp GLSL.std.450 extended
  // instruction with the three given operands.  That is, the result of the
  // instruction is:
  //  - |min| if |x| is unsigned-less than |min|
  //  - |max| if |x| is unsigned-more than |max|
  //  - |x| otherwise.
  // We assume that |min| is unsigned-less-or-equal to |max|, and that the
  // operands all have the same scalar integer type.  The instruction is
  // inserted before |where|.
  opt::Instruction* MakeClampInst(Instruction* x, Instruction* min,
                                  Instruction* max, Instruction* where);

  // Returns a new instruction which evaluates to the length the runtime array
  // referenced by the access chain at the specfied index.  The instruction is
  // inserted before the access chain instruction.  Returns a null pointer in
  // some cases if assumptions are violated (rather than asserting out).
  opt::Instruction* MakeRuntimeArrayLengthInst(Instruction* access_chain,
                                               uint32_t operand_index);

  // Clamps the coordinate for an OpImageTexelPointer so it stays within
  // the bounds of the size of the image.  Updates analyses and records that
  // the module is modified.  Returns a status code to indicate success
  // or failure.  If assumptions are not met, returns an error status code
  // and emits a diagnostic.
  spv_result_t ClampCoordinateForImageTexelPointer(opt::Instruction* itp);

  // Gets the instruction that defines the given id.
  opt::Instruction* GetDef(uint32_t id) {
    return context()->get_def_use_mgr()->GetDef(id);
  }

  // Returns a new instruction inserted before |where_inst|, and created from
  // the remaining arguments. Registers the definitions and uses of the new
  // instruction and also records its block.
  opt::Instruction* InsertInst(opt::Instruction* where_inst, SpvOp opcode,
                               uint32_t type_id, uint32_t result_id,
                               const Instruction::OperandList& operands);

  // State required for the current module.
  struct PerModuleState {
    // This pass modified the module.
    bool modified = false;
    // True if there is an error processing the current module, e.g. if
    // preconditions are not met.
    bool failed = false;
    // The id of the GLSL.std.450 extended instruction set.  Zero if it does
    // not exist.
    uint32_t glsl_insts_id = 0;
  } module_status_;
};

}  // namespace opt
}  // namespace spvtools

#endif  // SOURCE_OPT_GRAPHICS_ROBUST_ACCESS_PASS_H_
