17d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Copyright 2014 the V8 project authors. All rights reserved.
27d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Use of this source code is governed by a BSD-style license that can be
37d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// found in the LICENSE file.
47d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
57d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#ifndef V8_CCTEST_COMPILER_CODEGEN_TESTER_H_
67d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#define V8_CCTEST_COMPILER_CODEGEN_TESTER_H_
77d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
87d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/v8.h"
97d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/pipeline.h"
117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/raw-machine-assembler.h"
127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/simulator.h"
137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "test/cctest/compiler/call-tester.h"
147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace v8 {
167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace internal {
177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace compiler {
187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgtemplate <typename MachineAssembler>
207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgclass MachineAssemblerTester : public HandleAndZoneScope,
217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                               public CallHelper,
227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                               public MachineAssembler {
237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
2431c0e32e19ad3df48525fa9e7b2d1c0c07496d00machenbach@chromium.org  MachineAssemblerTester(MachineType return_type, MachineType p0,
2531c0e32e19ad3df48525fa9e7b2d1c0c07496d00machenbach@chromium.org                         MachineType p1, MachineType p2, MachineType p3,
2631c0e32e19ad3df48525fa9e7b2d1c0c07496d00machenbach@chromium.org                         MachineType p4)
277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      : HandleAndZoneScope(),
289aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org        CallHelper(
299aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org            main_isolate(),
309aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org            MakeMachineSignature(main_zone(), return_type, p0, p1, p2, p3, p4)),
319aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org        MachineAssembler(
329aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org            new (main_zone()) Graph(main_zone()),
339aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org            MakeMachineSignature(main_zone(), return_type, p0, p1, p2, p3, p4),
349aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org            kMachPtr) {}
357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3631c0e32e19ad3df48525fa9e7b2d1c0c07496d00machenbach@chromium.org  Node* LoadFromPointer(void* address, MachineType rep, int32_t offset = 0) {
377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return this->Load(rep, this->PointerConstant(address),
387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                      this->Int32Constant(offset));
397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4131c0e32e19ad3df48525fa9e7b2d1c0c07496d00machenbach@chromium.org  void StoreToPointer(void* address, MachineType rep, Node* node) {
427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    this->Store(rep, this->PointerConstant(address), node);
437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* StringConstant(const char* string) {
467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return this->HeapConstant(
477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        this->isolate()->factory()->InternalizeUtf8String(string));
487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void CheckNumber(double expected, Object* number) {
517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CHECK(this->isolate()->factory()->NewNumber(expected)->SameValue(number));
527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void CheckString(const char* expected, Object* string) {
557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CHECK(
567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        this->isolate()->factory()->InternalizeUtf8String(expected)->SameValue(
577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org            string));
587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void GenerateCode() { Generate(); }
617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org protected:
637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  virtual byte* Generate() {
647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (code_.is_null()) {
657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Schedule* schedule = this->Export();
667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      CallDescriptor* call_descriptor = this->call_descriptor();
677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Graph* graph = this->graph();
687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      CompilationInfo info(graph->zone()->isolate(), graph->zone());
697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Linkage linkage(&info, call_descriptor);
707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Pipeline pipeline(&info);
717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      code_ = pipeline.GenerateCodeForMachineGraph(&linkage, graph, schedule);
727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return this->code_.ToHandleChecked()->entry();
747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org private:
777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  MaybeHandle<Code> code_;
787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgtemplate <typename ReturnType>
827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgclass RawMachineAssemblerTester
837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    : public MachineAssemblerTester<RawMachineAssembler>,
847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      public CallHelper2<ReturnType, RawMachineAssemblerTester<ReturnType> > {
857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
865e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  RawMachineAssemblerTester(MachineType p0 = kMachNone,
875e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org                            MachineType p1 = kMachNone,
885e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org                            MachineType p2 = kMachNone,
895e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org                            MachineType p3 = kMachNone,
905e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org                            MachineType p4 = kMachNone)
917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      : MachineAssemblerTester<RawMachineAssembler>(
927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org            ReturnValueTraits<ReturnType>::Representation(), p0, p1, p2, p3,
937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org            p4) {}
947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  template <typename Ci, typename Fn>
967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void Run(const Ci& ci, const Fn& fn) {
977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    typename Ci::const_iterator i;
987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    for (i = ci.begin(); i != ci.end(); ++i) {
997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      CHECK_EQ(fn(*i), this->Call(*i));
1007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
1017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  template <typename Ci, typename Cj, typename Fn>
1047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void Run(const Ci& ci, const Cj& cj, const Fn& fn) {
1057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    typename Ci::const_iterator i;
1067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    typename Cj::const_iterator j;
1077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    for (i = ci.begin(); i != ci.end(); ++i) {
1087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      for (j = cj.begin(); j != cj.end(); ++j) {
1097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        CHECK_EQ(fn(*i, *j), this->Call(*i, *j));
1107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
1117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
1127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
1147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic const bool USE_RESULT_BUFFER = true;
1177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic const bool USE_RETURN_REGISTER = false;
1187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic const int32_t CHECK_VALUE = 0x99BEEDCE;
1197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// TODO(titzer): use the C-style calling convention, or any register-based
1227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// calling convention for binop tests.
12331c0e32e19ad3df48525fa9e7b2d1c0c07496d00machenbach@chromium.orgtemplate <typename CType, MachineType rep, bool use_result_buffer>
1247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgclass BinopTester {
1257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
1267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit BinopTester(RawMachineAssemblerTester<int32_t>* tester)
1277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      : T(tester),
1287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        param0(T->LoadFromPointer(&p0, rep)),
1297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        param1(T->LoadFromPointer(&p1, rep)),
1307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        p0(static_cast<CType>(0)),
1317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        p1(static_cast<CType>(0)),
1327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        result(static_cast<CType>(0)) {}
1337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  RawMachineAssemblerTester<int32_t>* T;
1357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* param0;
1367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* param1;
1377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  CType call(CType a0, CType a1) {
1397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    p0 = a0;
1407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    p1 = a1;
1417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (use_result_buffer) {
1427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      CHECK_EQ(CHECK_VALUE, T->Call());
1437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return result;
1447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    } else {
1457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return T->Call();
1467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
1477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void AddReturn(Node* val) {
1507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (use_result_buffer) {
1517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      T->Store(rep, T->PointerConstant(&result), T->Int32Constant(0), val);
1527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      T->Return(T->Int32Constant(CHECK_VALUE));
1537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    } else {
1547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      T->Return(val);
1557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
1567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  template <typename Ci, typename Cj, typename Fn>
1597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void Run(const Ci& ci, const Cj& cj, const Fn& fn) {
1607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    typename Ci::const_iterator i;
1617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    typename Cj::const_iterator j;
1627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    for (i = ci.begin(); i != ci.end(); ++i) {
1637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      for (j = cj.begin(); j != cj.end(); ++j) {
1647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        CHECK_EQ(fn(*i, *j), this->call(*i, *j));
1657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
1667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
1677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org protected:
1707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  CType p0;
1717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  CType p1;
1727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  CType result;
1737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
1747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// A helper class for testing code sequences that take two int parameters and
1777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// return an int value.
1787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgclass Int32BinopTester
1795e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    : public BinopTester<int32_t, kMachInt32, USE_RETURN_REGISTER> {
1807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
1817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit Int32BinopTester(RawMachineAssemblerTester<int32_t>* tester)
1825e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      : BinopTester<int32_t, kMachInt32, USE_RETURN_REGISTER>(tester) {}
1835e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org};
1845e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
1855e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
1865e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org// A helper class for testing code sequences that take two uint parameters and
1875e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org// return an uint value.
1885e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.orgclass Uint32BinopTester
1895e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    : public BinopTester<uint32_t, kMachUint32, USE_RETURN_REGISTER> {
1905e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org public:
1915e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  explicit Uint32BinopTester(RawMachineAssemblerTester<int32_t>* tester)
1925e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      : BinopTester<uint32_t, kMachUint32, USE_RETURN_REGISTER>(tester) {}
1937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1945e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  uint32_t call(uint32_t a0, uint32_t a1) {
1955e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    p0 = a0;
1965e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    p1 = a1;
1975e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    return static_cast<uint32_t>(T->Call());
1987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
2007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// A helper class for testing code sequences that take two double parameters and
2037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// return a double value.
2047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// TODO(titzer): figure out how to return doubles correctly on ia32.
2057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgclass Float64BinopTester
2065e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    : public BinopTester<double, kMachFloat64, USE_RESULT_BUFFER> {
2077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
2087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit Float64BinopTester(RawMachineAssemblerTester<int32_t>* tester)
2095e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      : BinopTester<double, kMachFloat64, USE_RESULT_BUFFER>(tester) {}
2107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
2117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// A helper class for testing code sequences that take two pointer parameters
2147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// and return a pointer value.
2157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// TODO(titzer): pick word size of pointers based on V8_TARGET.
2167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgtemplate <typename Type>
2177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgclass PointerBinopTester
2185e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    : public BinopTester<Type*, kMachPtr, USE_RETURN_REGISTER> {
2197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
2207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit PointerBinopTester(RawMachineAssemblerTester<int32_t>* tester)
2215e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      : BinopTester<Type*, kMachPtr, USE_RETURN_REGISTER>(tester) {}
2227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
2237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// A helper class for testing code sequences that take two tagged parameters and
2267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// return a tagged value.
2277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgtemplate <typename Type>
2287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgclass TaggedBinopTester
2295e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    : public BinopTester<Type*, kMachAnyTagged, USE_RETURN_REGISTER> {
2307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
2317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit TaggedBinopTester(RawMachineAssemblerTester<int32_t>* tester)
2325e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      : BinopTester<Type*, kMachAnyTagged, USE_RETURN_REGISTER>(tester) {}
2337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
2347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// A helper class for testing compares. Wraps a machine opcode and provides
2367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// evaluation routines and the operators.
2377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgclass CompareWrapper {
2387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
2397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit CompareWrapper(IrOpcode::Value op) : opcode(op) {}
2407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* MakeNode(RawMachineAssemblerTester<int32_t>* m, Node* a, Node* b) {
2427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return m->NewNode(op(m->machine()), a, b);
2437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2452c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  const Operator* op(MachineOperatorBuilder* machine) {
2467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    switch (opcode) {
2477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kWord32Equal:
2487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return machine->Word32Equal();
2497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kInt32LessThan:
2507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return machine->Int32LessThan();
2517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kInt32LessThanOrEqual:
2527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return machine->Int32LessThanOrEqual();
2537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kUint32LessThan:
2547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return machine->Uint32LessThan();
2557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kUint32LessThanOrEqual:
2567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return machine->Uint32LessThanOrEqual();
2577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kFloat64Equal:
2587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return machine->Float64Equal();
2597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kFloat64LessThan:
2607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return machine->Float64LessThan();
2617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kFloat64LessThanOrEqual:
2627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return machine->Float64LessThanOrEqual();
2637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      default:
2647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        UNREACHABLE();
2657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
2667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return NULL;
2677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool Int32Compare(int32_t a, int32_t b) {
2707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    switch (opcode) {
2717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kWord32Equal:
2727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return a == b;
2737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kInt32LessThan:
2747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return a < b;
2757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kInt32LessThanOrEqual:
2767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return a <= b;
2777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kUint32LessThan:
2787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return static_cast<uint32_t>(a) < static_cast<uint32_t>(b);
2797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kUint32LessThanOrEqual:
2807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return static_cast<uint32_t>(a) <= static_cast<uint32_t>(b);
2817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      default:
2827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        UNREACHABLE();
2837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
2847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return false;
2857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool Float64Compare(double a, double b) {
2887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    switch (opcode) {
2897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kFloat64Equal:
2907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return a == b;
2917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kFloat64LessThan:
2927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return a < b;
2937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kFloat64LessThanOrEqual:
2947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return a <= b;
2957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      default:
2967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        UNREACHABLE();
2977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
2987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return false;
2997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IrOpcode::Value opcode;
3027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
3037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// A small closure class to generate code for a function of two inputs that
3067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// produces a single output so that it can be used in many different contexts.
3077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// The {expected()} method should compute the expected output for a given
3087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// pair of inputs.
3097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgtemplate <typename T>
3107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgclass BinopGen {
3117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
3127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  virtual void gen(RawMachineAssemblerTester<int32_t>* m, Node* a, Node* b) = 0;
3137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  virtual T expected(T a, T b) = 0;
3147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  virtual ~BinopGen() {}
3157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
3167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// A helper class to generate various combination of input shape combinations
3187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// and run the generated code to ensure it produces the correct results.
3197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgclass Int32BinopInputShapeTester {
3207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
3217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit Int32BinopInputShapeTester(BinopGen<int32_t>* g) : gen(g) {}
3227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void TestAllInputShapes();
3247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org private:
3267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  BinopGen<int32_t>* gen;
3277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int32_t input_a;
3287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int32_t input_b;
3297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void Run(RawMachineAssemblerTester<int32_t>* m);
3317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void RunLeft(RawMachineAssemblerTester<int32_t>* m);
3327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void RunRight(RawMachineAssemblerTester<int32_t>* m);
3337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
3347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}  // namespace compiler
3357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}  // namespace internal
3367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}  // namespace v8
3377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#endif  // V8_CCTEST_COMPILER_CODEGEN_TESTER_H_
339