/*
 * Copyright (C) 2016 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_OPTIMIZING_NODES_MIPS_H_
#define ART_COMPILER_OPTIMIZING_NODES_MIPS_H_

namespace art {

// Compute the address of the method for MIPS Constant area support.
class HMipsComputeBaseMethodAddress : public HExpression<0> {
 public:
  // Treat the value as an int32_t, but it is really a 32 bit native pointer.
  HMipsComputeBaseMethodAddress()
      : HExpression(DataType::Type::kInt32, SideEffects::None(), kNoDexPc) {}

  bool CanBeMoved() const OVERRIDE { return true; }

  DECLARE_INSTRUCTION(MipsComputeBaseMethodAddress);

 protected:
  DEFAULT_COPY_CONSTRUCTOR(MipsComputeBaseMethodAddress);
};

// Mips version of HPackedSwitch that holds a pointer to the base method address.
class HMipsPackedSwitch FINAL : public HTemplateInstruction<2> {
 public:
  HMipsPackedSwitch(int32_t start_value,
                    int32_t num_entries,
                    HInstruction* input,
                    HMipsComputeBaseMethodAddress* method_base,
                    uint32_t dex_pc)
    : HTemplateInstruction(SideEffects::None(), dex_pc),
      start_value_(start_value),
      num_entries_(num_entries) {
    SetRawInputAt(0, input);
    SetRawInputAt(1, method_base);
  }

  bool IsControlFlow() const OVERRIDE { return true; }

  int32_t GetStartValue() const { return start_value_; }

  int32_t GetNumEntries() const { return num_entries_; }

  HBasicBlock* GetDefaultBlock() const {
    // Last entry is the default block.
    return GetBlock()->GetSuccessors()[num_entries_];
  }

  DECLARE_INSTRUCTION(MipsPackedSwitch);

 protected:
  DEFAULT_COPY_CONSTRUCTOR(MipsPackedSwitch);

 private:
  const int32_t start_value_;
  const int32_t num_entries_;
};

// This instruction computes part of the array access offset (index offset).
//
// For array accesses the element address has the following structure:
// Address = CONST_OFFSET + base_addr + index << ELEM_SHIFT. The address part
// (index << ELEM_SHIFT) can be shared across array accesses with
// the same data type and index. For example, in the following loop 5 accesses can share address
// computation:
//
// void foo(int[] a, int[] b, int[] c) {
//   for (i...) {
//     a[i] = a[i] + 5;
//     b[i] = b[i] + c[i];
//   }
// }
//
// Note: as the instruction doesn't involve base array address into computations it has no side
// effects.
class HIntermediateArrayAddressIndex FINAL : public HExpression<2> {
 public:
  HIntermediateArrayAddressIndex(HInstruction* index, HInstruction* shift, uint32_t dex_pc)
      : HExpression(DataType::Type::kInt32, SideEffects::None(), dex_pc) {
    SetRawInputAt(0, index);
    SetRawInputAt(1, shift);
  }

  bool CanBeMoved() const OVERRIDE { return true; }
  bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
    return true;
  }
  bool IsActualObject() const OVERRIDE { return false; }

  HInstruction* GetIndex() const { return InputAt(0); }
  HInstruction* GetShift() const { return InputAt(1); }

  DECLARE_INSTRUCTION(IntermediateArrayAddressIndex);

 protected:
  DEFAULT_COPY_CONSTRUCTOR(IntermediateArrayAddressIndex);
};

}  // namespace art

#endif  // ART_COMPILER_OPTIMIZING_NODES_MIPS_H_
