// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_CCTEST_COMPILER_CODEGEN_TESTER_H_
#define V8_CCTEST_COMPILER_CODEGEN_TESTER_H_

#include "src/compiler/instruction-selector.h"
#include "src/compiler/pipeline.h"
#include "src/compiler/raw-machine-assembler.h"
#include "src/simulator.h"
#include "test/cctest/compiler/call-tester.h"

namespace v8 {
namespace internal {
namespace compiler {

template <typename ReturnType>
class RawMachineAssemblerTester : public HandleAndZoneScope,
                                  public CallHelper<ReturnType>,
                                  public RawMachineAssembler {
 public:
  RawMachineAssemblerTester(MachineType p0 = MachineType::None(),
                            MachineType p1 = MachineType::None(),
                            MachineType p2 = MachineType::None(),
                            MachineType p3 = MachineType::None(),
                            MachineType p4 = MachineType::None())
      : HandleAndZoneScope(),
        CallHelper<ReturnType>(
            main_isolate(),
            CSignature::New(main_zone(), MachineTypeForC<ReturnType>(), p0, p1,
                            p2, p3, p4)),
        RawMachineAssembler(
            main_isolate(), new (main_zone()) Graph(main_zone()),
            Linkage::GetSimplifiedCDescriptor(
                main_zone(),
                CSignature::New(main_zone(), MachineTypeForC<ReturnType>(), p0,
                                p1, p2, p3, p4)),
            MachineType::PointerRepresentation(),
            InstructionSelector::SupportedMachineOperatorFlags()) {}

  void CheckNumber(double expected, Object* number) {
    CHECK(this->isolate()->factory()->NewNumber(expected)->SameValue(number));
  }

  void CheckString(const char* expected, Object* string) {
    CHECK(
        this->isolate()->factory()->InternalizeUtf8String(expected)->SameValue(
            string));
  }

  void GenerateCode() { Generate(); }

  Handle<Code> GetCode() {
    Generate();
    return code_.ToHandleChecked();
  }

 protected:
  virtual byte* Generate() {
    if (code_.is_null()) {
      Schedule* schedule = this->Export();
      CallDescriptor* call_descriptor = this->call_descriptor();
      Graph* graph = this->graph();
      CompilationInfo info("testing", main_isolate(), main_zone());
      code_ = Pipeline::GenerateCodeForTesting(&info, call_descriptor, graph,
                                               schedule);
    }
    return this->code_.ToHandleChecked()->entry();
  }

 private:
  MaybeHandle<Code> code_;
};


template <typename ReturnType>
class BufferedRawMachineAssemblerTester
    : public RawMachineAssemblerTester<int32_t> {
 public:
  BufferedRawMachineAssemblerTester(MachineType p0 = MachineType::None(),
                                    MachineType p1 = MachineType::None(),
                                    MachineType p2 = MachineType::None(),
                                    MachineType p3 = MachineType::None())
      : BufferedRawMachineAssemblerTester(ComputeParameterCount(p0, p1, p2, p3),
                                          p0, p1, p2, p3) {}


  // The BufferedRawMachineAssemblerTester does not pass parameters directly
  // to the constructed IR graph. Instead it passes a pointer to the parameter
  // to the IR graph, and adds Load nodes to the IR graph to load the
  // parameters from memory. Thereby it is possible to pass 64 bit parameters
  // to the IR graph.
  Node* Parameter(size_t index) {
    CHECK(index >= 0 && index < 4);
    return parameter_nodes_[index];
  }


  // The BufferedRawMachineAssemblerTester adds a Store node to the IR graph
  // to store the graph's return value in memory. The memory address for the
  // Store node is provided as a parameter. By storing the return value in
  // memory it is possible to return 64 bit values.
  void Return(Node* input) {
    Store(MachineTypeForC<ReturnType>().representation(),
          RawMachineAssembler::Parameter(return_parameter_index_), input,
          kNoWriteBarrier);
    RawMachineAssembler::Return(Int32Constant(1234));
  }

  ReturnType Call() {
    ReturnType return_value;
    test_graph_signature_->VerifyParams();
    CallHelper<int32_t>::Call(reinterpret_cast<void*>(&return_value));
    return return_value;
  }

  template <typename P0>
  ReturnType Call(P0 p0) {
    ReturnType return_value;
    test_graph_signature_->VerifyParams<P0>();
    CallHelper<int32_t>::Call(reinterpret_cast<void*>(&p0),
                              reinterpret_cast<void*>(&return_value));
    return return_value;
  }

  template <typename P0, typename P1>
  ReturnType Call(P0 p0, P1 p1) {
    ReturnType return_value;
    test_graph_signature_->VerifyParams<P0, P1>();
    CallHelper<int32_t>::Call(reinterpret_cast<void*>(&p0),
                              reinterpret_cast<void*>(&p1),
                              reinterpret_cast<void*>(&return_value));
    return return_value;
  }

  template <typename P0, typename P1, typename P2>
  ReturnType Call(P0 p0, P1 p1, P2 p2) {
    ReturnType return_value;
    test_graph_signature_->VerifyParams<P0, P1, P2>();
    CallHelper<int32_t>::Call(
        reinterpret_cast<void*>(&p0), reinterpret_cast<void*>(&p1),
        reinterpret_cast<void*>(&p2), reinterpret_cast<void*>(&return_value));
    return return_value;
  }

  template <typename P0, typename P1, typename P2, typename P3>
  ReturnType Call(P0 p0, P1 p1, P2 p2, P3 p3) {
    ReturnType return_value;
    test_graph_signature_->VerifyParams<P0, P1, P2, P3>();
    CallHelper<int32_t>::Call(
        reinterpret_cast<void*>(&p0), reinterpret_cast<void*>(&p1),
        reinterpret_cast<void*>(&p2), reinterpret_cast<void*>(&p3),
        reinterpret_cast<void*>(&return_value));
    return return_value;
  }

 private:
  BufferedRawMachineAssemblerTester(uint32_t return_parameter_index,
                                    MachineType p0, MachineType p1,
                                    MachineType p2, MachineType p3)
      : RawMachineAssemblerTester<int32_t>(
            MachineType::Pointer(),
            p0 == MachineType::None() ? MachineType::None()
                                      : MachineType::Pointer(),
            p1 == MachineType::None() ? MachineType::None()
                                      : MachineType::Pointer(),
            p2 == MachineType::None() ? MachineType::None()
                                      : MachineType::Pointer(),
            p3 == MachineType::None() ? MachineType::None()
                                      : MachineType::Pointer()),
        test_graph_signature_(
            CSignature::New(main_zone(), MachineType::Int32(), p0, p1, p2, p3)),
        return_parameter_index_(return_parameter_index) {
    parameter_nodes_[0] = p0 == MachineType::None()
                              ? nullptr
                              : Load(p0, RawMachineAssembler::Parameter(0));
    parameter_nodes_[1] = p1 == MachineType::None()
                              ? nullptr
                              : Load(p1, RawMachineAssembler::Parameter(1));
    parameter_nodes_[2] = p2 == MachineType::None()
                              ? nullptr
                              : Load(p2, RawMachineAssembler::Parameter(2));
    parameter_nodes_[3] = p3 == MachineType::None()
                              ? nullptr
                              : Load(p3, RawMachineAssembler::Parameter(3));
  }


  static uint32_t ComputeParameterCount(MachineType p0, MachineType p1,
                                        MachineType p2, MachineType p3) {
    if (p0 == MachineType::None()) {
      return 0;
    }
    if (p1 == MachineType::None()) {
      return 1;
    }
    if (p2 == MachineType::None()) {
      return 2;
    }
    if (p3 == MachineType::None()) {
      return 3;
    }
    return 4;
  }


  CSignature* test_graph_signature_;
  Node* parameter_nodes_[4];
  uint32_t return_parameter_index_;
};


template <>
class BufferedRawMachineAssemblerTester<void>
    : public RawMachineAssemblerTester<void> {
 public:
  BufferedRawMachineAssemblerTester(MachineType p0 = MachineType::None(),
                                    MachineType p1 = MachineType::None(),
                                    MachineType p2 = MachineType::None(),
                                    MachineType p3 = MachineType::None())
      : RawMachineAssemblerTester<void>(
            p0 == MachineType::None() ? MachineType::None()
                                      : MachineType::Pointer(),
            p1 == MachineType::None() ? MachineType::None()
                                      : MachineType::Pointer(),
            p2 == MachineType::None() ? MachineType::None()
                                      : MachineType::Pointer(),
            p3 == MachineType::None() ? MachineType::None()
                                      : MachineType::Pointer()),
        test_graph_signature_(
            CSignature::New(RawMachineAssemblerTester<void>::main_zone(),
                            MachineType::None(), p0, p1, p2, p3)) {
    parameter_nodes_[0] = p0 == MachineType::None()
                              ? nullptr
                              : Load(p0, RawMachineAssembler::Parameter(0));
    parameter_nodes_[1] = p1 == MachineType::None()
                              ? nullptr
                              : Load(p1, RawMachineAssembler::Parameter(1));
    parameter_nodes_[2] = p2 == MachineType::None()
                              ? nullptr
                              : Load(p2, RawMachineAssembler::Parameter(2));
    parameter_nodes_[3] = p3 == MachineType::None()
                              ? nullptr
                              : Load(p3, RawMachineAssembler::Parameter(3));
  }


  // The BufferedRawMachineAssemblerTester does not pass parameters directly
  // to the constructed IR graph. Instead it passes a pointer to the parameter
  // to the IR graph, and adds Load nodes to the IR graph to load the
  // parameters from memory. Thereby it is possible to pass 64 bit parameters
  // to the IR graph.
  Node* Parameter(size_t index) {
    CHECK(index >= 0 && index < 4);
    return parameter_nodes_[index];
  }


  void Call() {
    test_graph_signature_->VerifyParams();
    CallHelper<void>::Call();
  }

  template <typename P0>
  void Call(P0 p0) {
    test_graph_signature_->VerifyParams<P0>();
    CallHelper<void>::Call(reinterpret_cast<void*>(&p0));
  }

  template <typename P0, typename P1>
  void Call(P0 p0, P1 p1) {
    test_graph_signature_->VerifyParams<P0, P1>();
    CallHelper<void>::Call(reinterpret_cast<void*>(&p0),
                           reinterpret_cast<void*>(&p1));
  }

  template <typename P0, typename P1, typename P2>
  void Call(P0 p0, P1 p1, P2 p2) {
    test_graph_signature_->VerifyParams<P0, P1, P2>();
    CallHelper<void>::Call(reinterpret_cast<void*>(&p0),
                           reinterpret_cast<void*>(&p1),
                           reinterpret_cast<void*>(&p2));
  }

  template <typename P0, typename P1, typename P2, typename P3>
  void Call(P0 p0, P1 p1, P2 p2, P3 p3) {
    test_graph_signature_->VerifyParams<P0, P1, P2, P3>();
    CallHelper<void>::Call(
        reinterpret_cast<void*>(&p0), reinterpret_cast<void*>(&p1),
        reinterpret_cast<void*>(&p2), reinterpret_cast<void*>(&p3));
  }

 private:
  CSignature* test_graph_signature_;
  Node* parameter_nodes_[4];
};
static const bool USE_RESULT_BUFFER = true;
static const bool USE_RETURN_REGISTER = false;
static const int32_t CHECK_VALUE = 0x99BEEDCE;


// TODO(titzer): use the C-style calling convention, or any register-based
// calling convention for binop tests.
template <typename CType, bool use_result_buffer>
class BinopTester {
 public:
  explicit BinopTester(RawMachineAssemblerTester<int32_t>* tester,
                       MachineType rep)
      : T(tester),
        param0(T->LoadFromPointer(&p0, rep)),
        param1(T->LoadFromPointer(&p1, rep)),
        rep(rep),
        p0(static_cast<CType>(0)),
        p1(static_cast<CType>(0)),
        result(static_cast<CType>(0)) {}

  RawMachineAssemblerTester<int32_t>* T;
  Node* param0;
  Node* param1;

  CType call(CType a0, CType a1) {
    p0 = a0;
    p1 = a1;
    if (use_result_buffer) {
      CHECK_EQ(CHECK_VALUE, T->Call());
      return result;
    } else {
      return static_cast<CType>(T->Call());
    }
  }

  void AddReturn(Node* val) {
    if (use_result_buffer) {
      T->Store(rep.representation(), T->PointerConstant(&result),
               T->Int32Constant(0), val, kNoWriteBarrier);
      T->Return(T->Int32Constant(CHECK_VALUE));
    } else {
      T->Return(val);
    }
  }

  template <typename Ci, typename Cj, typename Fn>
  void Run(const Ci& ci, const Cj& cj, const Fn& fn) {
    typename Ci::const_iterator i;
    typename Cj::const_iterator j;
    for (i = ci.begin(); i != ci.end(); ++i) {
      for (j = cj.begin(); j != cj.end(); ++j) {
        CHECK_EQ(fn(*i, *j), this->call(*i, *j));
      }
    }
  }

 protected:
  MachineType rep;
  CType p0;
  CType p1;
  CType result;
};


// A helper class for testing code sequences that take two int parameters and
// return an int value.
class Int32BinopTester : public BinopTester<int32_t, USE_RETURN_REGISTER> {
 public:
  explicit Int32BinopTester(RawMachineAssemblerTester<int32_t>* tester)
      : BinopTester<int32_t, USE_RETURN_REGISTER>(tester,
                                                  MachineType::Int32()) {}
};


// A helper class for testing code sequences that take two int parameters and
// return an int value.
class Int64BinopTester : public BinopTester<int64_t, USE_RETURN_REGISTER> {
 public:
  explicit Int64BinopTester(RawMachineAssemblerTester<int32_t>* tester)
      : BinopTester<int64_t, USE_RETURN_REGISTER>(tester,
                                                  MachineType::Int64()) {}
};


// A helper class for testing code sequences that take two uint parameters and
// return an uint value.
class Uint32BinopTester : public BinopTester<uint32_t, USE_RETURN_REGISTER> {
 public:
  explicit Uint32BinopTester(RawMachineAssemblerTester<int32_t>* tester)
      : BinopTester<uint32_t, USE_RETURN_REGISTER>(tester,
                                                   MachineType::Uint32()) {}

  uint32_t call(uint32_t a0, uint32_t a1) {
    p0 = a0;
    p1 = a1;
    return static_cast<uint32_t>(T->Call());
  }
};


// A helper class for testing code sequences that take two float parameters and
// return a float value.
// TODO(titzer): figure out how to return floats correctly on ia32.
class Float32BinopTester : public BinopTester<float, USE_RESULT_BUFFER> {
 public:
  explicit Float32BinopTester(RawMachineAssemblerTester<int32_t>* tester)
      : BinopTester<float, USE_RESULT_BUFFER>(tester, MachineType::Float32()) {}
};


// A helper class for testing code sequences that take two double parameters and
// return a double value.
// TODO(titzer): figure out how to return doubles correctly on ia32.
class Float64BinopTester : public BinopTester<double, USE_RESULT_BUFFER> {
 public:
  explicit Float64BinopTester(RawMachineAssemblerTester<int32_t>* tester)
      : BinopTester<double, USE_RESULT_BUFFER>(tester, MachineType::Float64()) {
  }
};


// A helper class for testing code sequences that take two pointer parameters
// and return a pointer value.
// TODO(titzer): pick word size of pointers based on V8_TARGET.
template <typename Type>
class PointerBinopTester : public BinopTester<Type*, USE_RETURN_REGISTER> {
 public:
  explicit PointerBinopTester(RawMachineAssemblerTester<int32_t>* tester)
      : BinopTester<Type*, USE_RETURN_REGISTER>(tester,
                                                MachineType::Pointer()) {}
};


// A helper class for testing code sequences that take two tagged parameters and
// return a tagged value.
template <typename Type>
class TaggedBinopTester : public BinopTester<Type*, USE_RETURN_REGISTER> {
 public:
  explicit TaggedBinopTester(RawMachineAssemblerTester<int32_t>* tester)
      : BinopTester<Type*, USE_RETURN_REGISTER>(tester,
                                                MachineType::AnyTagged()) {}
};

// A helper class for testing compares. Wraps a machine opcode and provides
// evaluation routines and the operators.
class CompareWrapper {
 public:
  explicit CompareWrapper(IrOpcode::Value op) : opcode(op) {}

  Node* MakeNode(RawMachineAssemblerTester<int32_t>* m, Node* a, Node* b) {
    return m->AddNode(op(m->machine()), a, b);
  }

  const Operator* op(MachineOperatorBuilder* machine) {
    switch (opcode) {
      case IrOpcode::kWord32Equal:
        return machine->Word32Equal();
      case IrOpcode::kInt32LessThan:
        return machine->Int32LessThan();
      case IrOpcode::kInt32LessThanOrEqual:
        return machine->Int32LessThanOrEqual();
      case IrOpcode::kUint32LessThan:
        return machine->Uint32LessThan();
      case IrOpcode::kUint32LessThanOrEqual:
        return machine->Uint32LessThanOrEqual();
      case IrOpcode::kFloat64Equal:
        return machine->Float64Equal();
      case IrOpcode::kFloat64LessThan:
        return machine->Float64LessThan();
      case IrOpcode::kFloat64LessThanOrEqual:
        return machine->Float64LessThanOrEqual();
      default:
        UNREACHABLE();
    }
    return NULL;
  }

  bool Int32Compare(int32_t a, int32_t b) {
    switch (opcode) {
      case IrOpcode::kWord32Equal:
        return a == b;
      case IrOpcode::kInt32LessThan:
        return a < b;
      case IrOpcode::kInt32LessThanOrEqual:
        return a <= b;
      case IrOpcode::kUint32LessThan:
        return static_cast<uint32_t>(a) < static_cast<uint32_t>(b);
      case IrOpcode::kUint32LessThanOrEqual:
        return static_cast<uint32_t>(a) <= static_cast<uint32_t>(b);
      default:
        UNREACHABLE();
    }
    return false;
  }

  bool Float64Compare(double a, double b) {
    switch (opcode) {
      case IrOpcode::kFloat64Equal:
        return a == b;
      case IrOpcode::kFloat64LessThan:
        return a < b;
      case IrOpcode::kFloat64LessThanOrEqual:
        return a <= b;
      default:
        UNREACHABLE();
    }
    return false;
  }

  IrOpcode::Value opcode;
};


// A small closure class to generate code for a function of two inputs that
// produces a single output so that it can be used in many different contexts.
// The {expected()} method should compute the expected output for a given
// pair of inputs.
template <typename T>
class BinopGen {
 public:
  virtual void gen(RawMachineAssemblerTester<int32_t>* m, Node* a, Node* b) = 0;
  virtual T expected(T a, T b) = 0;
  virtual ~BinopGen() {}
};

// A helper class to generate various combination of input shape combinations
// and run the generated code to ensure it produces the correct results.
class Int32BinopInputShapeTester {
 public:
  explicit Int32BinopInputShapeTester(BinopGen<int32_t>* g) : gen(g) {}

  void TestAllInputShapes();

 private:
  BinopGen<int32_t>* gen;
  int32_t input_a;
  int32_t input_b;

  void Run(RawMachineAssemblerTester<int32_t>* m);
  void RunLeft(RawMachineAssemblerTester<int32_t>* m);
  void RunRight(RawMachineAssemblerTester<int32_t>* m);
};

// TODO(bmeurer): Drop this crap once we switch to GTest/Gmock.
static inline void CheckFloatEq(volatile float x, volatile float y) {
  if (std::isnan(x)) {
    CHECK(std::isnan(y));
  } else {
    CHECK_EQ(x, y);
  }
}

static inline void CheckDoubleEq(volatile double x, volatile double y) {
  if (std::isnan(x)) {
    CHECK(std::isnan(y));
  } else {
    CHECK_EQ(x, y);
  }
}

}  // namespace compiler
}  // namespace internal
}  // namespace v8

#endif  // V8_CCTEST_COMPILER_CODEGEN_TESTER_H_
