/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * 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 ART_COMPILER_SEA_IR_IR_INSTRUCTION_NODES_H_
#define ART_COMPILER_SEA_IR_IR_INSTRUCTION_NODES_H_
#include "dex_instruction-inl.h"
#include "sea_ir/ir/sea_node.h"
#include "sea_ir/ir/visitor.h"


namespace sea_ir {

enum SpecialRegisters {
  NO_REGISTER = -1,             // Usually signifies that there is no register
                                // that respects the condition you asked for.
  RETURN_REGISTER = -2,         // Written by the invoke* instructions, read by move-results.
  UNNAMED_CONST_REGISTER = -3   // Written by UnnamedConst* instructions, read by *Lit* instruction.
};

class IRVisitor;

// This class represents an instruction in SEA IR.
// As we add support for specific classes of instructions,
// the number of InstructionNode objects should dwindle, while the
// number of subclasses and instances of subclasses will go up.
class InstructionNode: public SeaNode {
 public:
  static std::vector<sea_ir::InstructionNode*> Create(const art::Instruction* in);
  // Returns the Dalvik instruction around which this InstructionNode is wrapped.
  const art::Instruction* GetInstruction() const {
    DCHECK(NULL != instruction_) << "Tried to access NULL instruction in an InstructionNode.";
    return instruction_;
  }
  // Returns the register that is defined by the current instruction, or NO_REGISTER otherwise.
  virtual int GetResultRegister() const;
  // Returns the set of registers defined by the current instruction.
  virtual std::vector<int> GetDefinitions() const;
  // Returns the set of register numbers that are used by the instruction.
  virtual std::vector<int> GetUses() const;
  // Mark the current instruction as a downward exposed definition.
  void MarkAsDEDef();
  // Rename the use of @reg_no to refer to the instruction @definition,
  // essentially creating SSA form.
  void RenameToSSA(int reg_no, InstructionNode* definition) {
    definition_edges_.insert(std::pair<int, InstructionNode*>(reg_no, definition));
    definition->AddSSAUse(this);
  }
  // Returns the ordered set of Instructions that define the input operands of this instruction.
  // Precondition: SeaGraph.ConvertToSSA().
  virtual std::vector<InstructionNode*> GetSSAProducers() {
    std::vector<int> uses = GetUses();
    std::vector<InstructionNode*> ssa_uses;
    for (std::vector<int>::const_iterator cit = uses.begin(); cit != uses.end(); cit++) {
      ssa_uses.push_back((*definition_edges_.find(*cit)).second);
    }
    return ssa_uses;
  }
  std::map<int, InstructionNode* >* GetSSAProducersMap() {
    return &definition_edges_;
  }
  std::vector<InstructionNode*>* GetSSAConsumers() {
    return &used_in_;
  }
  virtual void AddSSAUse(InstructionNode* use) {
    used_in_.push_back(use);
  }
  void Accept(IRVisitor* v) {
    v->Visit(this);
    v->Traverse(this);
  }
  // Set the region to which this instruction belongs.
  Region* GetRegion() {
    DCHECK(NULL != region_);
    return region_;
  }
  // Get the region to which this instruction belongs.
  void SetRegion(Region* region) {
    region_ = region;
  }

 protected:
  explicit InstructionNode(const art::Instruction* in):
      SeaNode(), instruction_(in), used_in_(), de_def_(false), region_(NULL) { }

 protected:
  const art::Instruction* const instruction_;
  std::map<int, InstructionNode* > definition_edges_;  // Maps used registers to their definitions.
  // Stores pointers to instructions that use the result of the current instruction.
  std::vector<InstructionNode*> used_in_;
  bool de_def_;
  Region* region_;
};

class ConstInstructionNode: public InstructionNode {
 public:
  explicit ConstInstructionNode(const art::Instruction* inst):
      InstructionNode(inst) { }

  void Accept(IRVisitor* v) {
    v->Visit(this);
    v->Traverse(this);
  }

  virtual int32_t GetConstValue() const {
    return GetInstruction()->VRegB_11n();
  }
};

class UnnamedConstInstructionNode: public ConstInstructionNode {
 public:
  explicit UnnamedConstInstructionNode(const art::Instruction* inst, int32_t value):
      ConstInstructionNode(inst), value_(value) { }

  void Accept(IRVisitor* v) {
    v->Visit(this);
    v->Traverse(this);
  }

  int GetResultRegister() const {
    return UNNAMED_CONST_REGISTER;
  }

  int32_t GetConstValue() const {
    return value_;
  }

 private:
  const int32_t value_;
};

class ReturnInstructionNode: public InstructionNode {
 public:
  explicit ReturnInstructionNode(const art::Instruction* inst): InstructionNode(inst) { }
  void Accept(IRVisitor* v) {
    v->Visit(this);
    v->Traverse(this);
  }
};

class IfNeInstructionNode: public InstructionNode {
 public:
  explicit IfNeInstructionNode(const art::Instruction* inst): InstructionNode(inst) {
    DCHECK(InstructionTools::IsDefinition(inst) == false);
  }
  void Accept(IRVisitor* v) {
    v->Visit(this);
    v->Traverse(this);
  }
};



class MoveResultInstructionNode: public InstructionNode {
 public:
  explicit MoveResultInstructionNode(const art::Instruction* inst): InstructionNode(inst) { }
  std::vector<int> GetUses() const {
    std::vector<int> uses;  // Using vector<> instead of set<> because order matters.
    uses.push_back(RETURN_REGISTER);
    return uses;
  }
  void Accept(IRVisitor* v) {
    v->Visit(this);
    v->Traverse(this);
  }
};

class InvokeStaticInstructionNode: public InstructionNode {
 public:
  explicit InvokeStaticInstructionNode(const art::Instruction* inst): InstructionNode(inst) { }
  int GetResultRegister() const {
    return RETURN_REGISTER;
  }
  void Accept(IRVisitor* v) {
    v->Visit(this);
    v->Traverse(this);
  }
};

class AddIntInstructionNode: public InstructionNode {
 public:
  explicit AddIntInstructionNode(const art::Instruction* inst): InstructionNode(inst) { }
  void Accept(IRVisitor* v) {
    v->Visit(this);
    v->Traverse(this);
  }
};

class AddIntLitInstructionNode: public AddIntInstructionNode {
 public:
  explicit AddIntLitInstructionNode(const art::Instruction* inst):
      AddIntInstructionNode(inst) { }

  std::vector<int> GetUses() const {
    std::vector<int> uses =  AddIntInstructionNode::GetUses();
    uses.push_back(UNNAMED_CONST_REGISTER);
    return uses;
    }

  void Accept(IRVisitor* v) {
    v->Visit(this);
    v->Traverse(this);
  }
};

class GotoInstructionNode: public InstructionNode {
 public:
  explicit GotoInstructionNode(const art::Instruction* inst): InstructionNode(inst) { }
  void Accept(IRVisitor* v) {
    v->Visit(this);
    v->Traverse(this);
  }
};

class IfEqzInstructionNode: public InstructionNode {
 public:
  explicit IfEqzInstructionNode(const art::Instruction* inst): InstructionNode(inst) {
    DCHECK(InstructionTools::IsDefinition(inst) == false);
  }
  void Accept(IRVisitor* v) {
    v->Visit(this);
    v->Traverse(this);
  }
};
}  // namespace sea_ir
#endif  // ART_COMPILER_SEA_IR_IR_INSTRUCTION_NODES_H_
