
// Copyright (c) 2017 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.

#ifndef SOURCE_OPT_INSTRUCTION_LIST_H_
#define SOURCE_OPT_INSTRUCTION_LIST_H_

#include <cassert>
#include <functional>
#include <memory>
#include <utility>
#include <vector>

#include "source/latest_version_spirv_header.h"
#include "source/operand.h"
#include "source/opt/instruction.h"
#include "source/util/ilist.h"
#include "spirv-tools/libspirv.h"

namespace spvtools {
namespace opt {

// This class is intended to be the container for Instructions.  This container
// owns the instructions that are in it.  When removing an Instruction from the
// list, the caller is assuming responsibility for deleting the storage.
//
// TODO: Because there are a number of other data structures that will want
// pointers to instruction, ownership should probably be moved to the module.
// Because of that I have not made the ownership passing in this class fully
// explicit.  For example, RemoveFromList takes ownership from the list, but
// does not return an std::unique_ptr to signal that.  When we fully decide on
// ownership, this will have to be fixed up one way or the other.
class InstructionList : public utils::IntrusiveList<Instruction> {
 public:
  InstructionList() = default;
  InstructionList(InstructionList&& that)
      : utils::IntrusiveList<Instruction>(std::move(that)) {}
  InstructionList& operator=(InstructionList&& that) {
    auto p = static_cast<utils::IntrusiveList<Instruction>*>(this);
    *p = std::move(that);
    return *this;
  }

  // Destroy this list and any instructions in the list.
  inline virtual ~InstructionList();

  class iterator : public utils::IntrusiveList<Instruction>::iterator {
   public:
    iterator(const utils::IntrusiveList<Instruction>::iterator& i)
        : utils::IntrusiveList<Instruction>::iterator(i) {}
    iterator(Instruction* i) : utils::IntrusiveList<Instruction>::iterator(i) {}

    // DEPRECATED: Please use MoveBefore with an InstructionList instead.
    //
    // Moves the nodes in |list| to the list that |this| points to.  The
    // positions of the nodes will be immediately before the element pointed to
    // by the iterator.  The return value will be an iterator pointing to the
    // first of the newly inserted elements.  Ownership of the elements in
    // |list| is now passed on to |*this|.
    iterator InsertBefore(std::vector<std::unique_ptr<Instruction>>&& list);

    // The node |i| will be inserted immediately before |this|. The return value
    // will be an iterator pointing to the newly inserted node.  The owner of
    // |*i| becomes |*this|
    iterator InsertBefore(std::unique_ptr<Instruction>&& i);

    // Removes the node from the list, and deletes the storage.  Returns a valid
    // iterator to the next node.
    iterator Erase() {
      iterator_template next_node = *this;
      ++next_node;
      node_->RemoveFromList();
      delete node_;
      return next_node;
    }
  };

  iterator begin() { return utils::IntrusiveList<Instruction>::begin(); }
  iterator end() { return utils::IntrusiveList<Instruction>::end(); }
  const_iterator begin() const {
    return utils::IntrusiveList<Instruction>::begin();
  }
  const_iterator end() const {
    return utils::IntrusiveList<Instruction>::end();
  }

  void push_back(std::unique_ptr<Instruction>&& inst) {
    utils::IntrusiveList<Instruction>::push_back(inst.release());
  }

  // Same as in the base class, except it will delete the data as well.
  inline void clear();

  // Runs the given function |f| on the instructions in the list and optionally
  // on the preceding debug line instructions.
  inline void ForEachInst(const std::function<void(Instruction*)>& f,
                          bool run_on_debug_line_insts) {
    auto next = begin();
    for (auto i = next; i != end(); i = next) {
      ++next;
      i->ForEachInst(f, run_on_debug_line_insts);
    }
  }
};

InstructionList::~InstructionList() { clear(); }

void InstructionList::clear() {
  while (!empty()) {
    Instruction* inst = &front();
    inst->RemoveFromList();
    delete inst;
  }
}

}  // namespace opt
}  // namespace spvtools

#endif  // SOURCE_OPT_INSTRUCTION_LIST_H_
