/*
 * Copyright (C) 2015 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_X86_H_
#define ART_COMPILER_OPTIMIZING_NODES_X86_H_

namespace art HIDDEN {

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

  bool CanBeMoved() const override { return true; }

  DECLARE_INSTRUCTION(X86ComputeBaseMethodAddress);

 protected:
  DEFAULT_COPY_CONSTRUCTOR(X86ComputeBaseMethodAddress);
};

// Load a constant value from the constant table.
class HX86LoadFromConstantTable final : public HExpression<2> {
 public:
  HX86LoadFromConstantTable(HX86ComputeBaseMethodAddress* method_base,
                            HConstant* constant)
      : HExpression(kX86LoadFromConstantTable,
                    constant->GetType(),
                    SideEffects::None(),
                    kNoDexPc) {
    SetRawInputAt(0, method_base);
    SetRawInputAt(1, constant);
  }

  HX86ComputeBaseMethodAddress* GetBaseMethodAddress() const {
    return InputAt(0)->AsX86ComputeBaseMethodAddress();
  }

  HConstant* GetConstant() const {
    return InputAt(1)->AsConstant();
  }

  DECLARE_INSTRUCTION(X86LoadFromConstantTable);

 protected:
  DEFAULT_COPY_CONSTRUCTOR(X86LoadFromConstantTable);
};

// Version of HNeg with access to the constant table for FP types.
class HX86FPNeg final : public HExpression<2> {
 public:
  HX86FPNeg(DataType::Type result_type,
            HInstruction* input,
            HX86ComputeBaseMethodAddress* method_base,
            uint32_t dex_pc)
      : HExpression(kX86FPNeg, result_type, SideEffects::None(), dex_pc) {
    DCHECK(DataType::IsFloatingPointType(result_type));
    SetRawInputAt(0, input);
    SetRawInputAt(1, method_base);
  }

  HX86ComputeBaseMethodAddress* GetBaseMethodAddress() const {
    return InputAt(1)->AsX86ComputeBaseMethodAddress();
  }

  DECLARE_INSTRUCTION(X86FPNeg);

 protected:
  DEFAULT_COPY_CONSTRUCTOR(X86FPNeg);
};

// X86 version of HPackedSwitch that holds a pointer to the base method address.
class HX86PackedSwitch final : public HExpression<2> {
 public:
  HX86PackedSwitch(int32_t start_value,
                   int32_t num_entries,
                   HInstruction* input,
                   HX86ComputeBaseMethodAddress* method_base,
                   uint32_t dex_pc)
    : HExpression(kX86PackedSwitch, 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_; }

  HX86ComputeBaseMethodAddress* GetBaseMethodAddress() const {
    return InputAt(1)->AsX86ComputeBaseMethodAddress();
  }

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

  DECLARE_INSTRUCTION(X86PackedSwitch);

 protected:
  DEFAULT_COPY_CONSTRUCTOR(X86PackedSwitch);

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

class HX86AndNot final : public HBinaryOperation {
 public:
  HX86AndNot(DataType::Type result_type,
       HInstruction* left,
       HInstruction* right,
       uint32_t dex_pc = kNoDexPc)
      : HBinaryOperation(kX86AndNot, result_type, left, right, SideEffects::None(), dex_pc) {
  }

  bool IsCommutative() const override { return false; }

  template <typename T> static T Compute(T x, T y) { return ~x & y; }

  HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
    return GetBlock()->GetGraph()->GetIntConstant(
        Compute(x->GetValue(), y->GetValue()), GetDexPc());
  }
  HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
    return GetBlock()->GetGraph()->GetLongConstant(
        Compute(x->GetValue(), y->GetValue()), GetDexPc());
  }
  HConstant* Evaluate([[maybe_unused]] HFloatConstant* x,
                      [[maybe_unused]] HFloatConstant* y) const override {
    LOG(FATAL) << DebugName() << " is not defined for float values";
    UNREACHABLE();
  }
  HConstant* Evaluate([[maybe_unused]] HDoubleConstant* x,
                      [[maybe_unused]] HDoubleConstant* y) const override {
    LOG(FATAL) << DebugName() << " is not defined for double values";
    UNREACHABLE();
  }

  DECLARE_INSTRUCTION(X86AndNot);

 protected:
  DEFAULT_COPY_CONSTRUCTOR(X86AndNot);
};

class HX86MaskOrResetLeastSetBit final : public HUnaryOperation {
 public:
  HX86MaskOrResetLeastSetBit(DataType::Type result_type, InstructionKind op,
                             HInstruction* input, uint32_t dex_pc = kNoDexPc)
      : HUnaryOperation(kX86MaskOrResetLeastSetBit, result_type, input, dex_pc),
        op_kind_(op) {
    DCHECK_EQ(result_type, DataType::Kind(input->GetType()));
    DCHECK(op == HInstruction::kAnd || op == HInstruction::kXor) << op;
  }
  template <typename T>
  auto Compute(T x) const -> decltype(x & (x-1)) {
    static_assert(std::is_same<decltype(x & (x-1)), decltype(x ^(x-1))>::value,
                  "Inconsistent  bitwise types");
    switch (op_kind_) {
      case HInstruction::kAnd:
        return x & (x-1);
      case HInstruction::kXor:
        return x ^ (x-1);
      default:
        LOG(FATAL) << "Unreachable";
        UNREACHABLE();
    }
  }

  HConstant* Evaluate(HIntConstant* x) const override {
    return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()), GetDexPc());
  }
  HConstant* Evaluate(HLongConstant* x) const override {
    return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue()), GetDexPc());
  }
  HConstant* Evaluate([[maybe_unused]] HFloatConstant* x) const override {
    LOG(FATAL) << DebugName() << "is not defined for float values";
    UNREACHABLE();
  }
  HConstant* Evaluate([[maybe_unused]] HDoubleConstant* x) const override {
    LOG(FATAL) << DebugName() << "is not defined for double values";
    UNREACHABLE();
  }
  InstructionKind GetOpKind() const { return op_kind_; }

  DECLARE_INSTRUCTION(X86MaskOrResetLeastSetBit);

 protected:
  const InstructionKind op_kind_;

  DEFAULT_COPY_CONSTRUCTOR(X86MaskOrResetLeastSetBit);
};

}  // namespace art

#endif  // ART_COMPILER_OPTIMIZING_NODES_X86_H_
