1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2014 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_CCTEST_COMPILER_CODEGEN_TESTER_H_
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define V8_CCTEST_COMPILER_CODEGEN_TESTER_H_
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/compiler/instruction-selector.h"
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/pipeline.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/raw-machine-assembler.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/simulator.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "test/cctest/compiler/call-tester.h"
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace compiler {
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtemplate <typename ReturnType>
19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass RawMachineAssemblerTester : public HandleAndZoneScope,
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  public CallHelper<ReturnType>,
21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  public RawMachineAssembler {
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  RawMachineAssemblerTester(MachineType p0 = MachineType::None(),
24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                            MachineType p1 = MachineType::None(),
25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                            MachineType p2 = MachineType::None(),
26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                            MachineType p3 = MachineType::None(),
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                            MachineType p4 = MachineType::None())
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : HandleAndZoneScope(),
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        CallHelper<ReturnType>(
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            main_isolate(),
31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            CSignature::New(main_zone(), MachineTypeForC<ReturnType>(), p0, p1,
32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                            p2, p3, p4)),
33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        RawMachineAssembler(
34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            main_isolate(), new (main_zone()) Graph(main_zone()),
35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Linkage::GetSimplifiedCDescriptor(
36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                main_zone(),
37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                CSignature::New(main_zone(), MachineTypeForC<ReturnType>(), p0,
38342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch                                p1, p2, p3, p4),
39342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch                true),
40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            MachineType::PointerRepresentation(),
41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            InstructionSelector::SupportedMachineOperatorFlags()) {}
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
43342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  virtual ~RawMachineAssemblerTester() {}
44342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CheckNumber(double expected, Object* number) {
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(this->isolate()->factory()->NewNumber(expected)->SameValue(number));
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CheckString(const char* expected, Object* string) {
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        this->isolate()->factory()->InternalizeUtf8String(expected)->SameValue(
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            string));
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void GenerateCode() { Generate(); }
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<Code> GetCode() {
58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Generate();
59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return code_.ToHandleChecked();
60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch protected:
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual byte* Generate() {
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (code_.is_null()) {
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Schedule* schedule = this->Export();
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallDescriptor* call_descriptor = this->call_descriptor();
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Graph* graph = this->graph();
68537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch      CompilationInfo info(ArrayVector("testing"), main_isolate(), main_zone());
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      code_ = Pipeline::GenerateCodeForTesting(&info, call_descriptor, graph,
70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                               schedule);
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return this->code_.ToHandleChecked()->entry();
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MaybeHandle<Code> code_;
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename ReturnType>
81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass BufferedRawMachineAssemblerTester
82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    : public RawMachineAssemblerTester<int32_t> {
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BufferedRawMachineAssemblerTester(MachineType p0 = MachineType::None(),
85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    MachineType p1 = MachineType::None(),
86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    MachineType p2 = MachineType::None(),
87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    MachineType p3 = MachineType::None())
88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : BufferedRawMachineAssemblerTester(ComputeParameterCount(p0, p1, p2, p3),
89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                          p0, p1, p2, p3) {}
90014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
91342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  virtual byte* Generate() { return RawMachineAssemblerTester::Generate(); }
92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // The BufferedRawMachineAssemblerTester does not pass parameters directly
94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // to the constructed IR graph. Instead it passes a pointer to the parameter
95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // to the IR graph, and adds Load nodes to the IR graph to load the
96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // parameters from memory. Thereby it is possible to pass 64 bit parameters
97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // to the IR graph.
98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* Parameter(size_t index) {
99342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch    CHECK(index < 4);
100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return parameter_nodes_[index];
101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // The BufferedRawMachineAssemblerTester adds a Store node to the IR graph
104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // to store the graph's return value in memory. The memory address for the
105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Store node is provided as a parameter. By storing the return value in
106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // memory it is possible to return 64 bit values.
107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Return(Node* input) {
108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Store(MachineTypeForC<ReturnType>().representation(),
109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          RawMachineAssembler::Parameter(return_parameter_index_), input,
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          kNoWriteBarrier);
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    RawMachineAssembler::Return(Int32Constant(1234));
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ReturnType Call() {
115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ReturnType return_value;
116342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch    CSignature::VerifyParams(test_graph_signature_);
117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallHelper<int32_t>::Call(reinterpret_cast<void*>(&return_value));
118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return return_value;
119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  template <typename P0>
122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ReturnType Call(P0 p0) {
123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ReturnType return_value;
124342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch    CSignature::VerifyParams<P0>(test_graph_signature_);
125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallHelper<int32_t>::Call(reinterpret_cast<void*>(&p0),
126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              reinterpret_cast<void*>(&return_value));
127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return return_value;
128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  template <typename P0, typename P1>
131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ReturnType Call(P0 p0, P1 p1) {
132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ReturnType return_value;
133342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch    CSignature::VerifyParams<P0, P1>(test_graph_signature_);
134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallHelper<int32_t>::Call(reinterpret_cast<void*>(&p0),
135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              reinterpret_cast<void*>(&p1),
136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              reinterpret_cast<void*>(&return_value));
137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return return_value;
138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  template <typename P0, typename P1, typename P2>
141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ReturnType Call(P0 p0, P1 p1, P2 p2) {
142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ReturnType return_value;
143342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch    CSignature::VerifyParams<P0, P1, P2>(test_graph_signature_);
144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallHelper<int32_t>::Call(
145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        reinterpret_cast<void*>(&p0), reinterpret_cast<void*>(&p1),
146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        reinterpret_cast<void*>(&p2), reinterpret_cast<void*>(&return_value));
147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return return_value;
148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  template <typename P0, typename P1, typename P2, typename P3>
151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ReturnType Call(P0 p0, P1 p1, P2 p2, P3 p3) {
152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ReturnType return_value;
153342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch    CSignature::VerifyParams<P0, P1, P2, P3>(test_graph_signature_);
154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallHelper<int32_t>::Call(
155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        reinterpret_cast<void*>(&p0), reinterpret_cast<void*>(&p1),
156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        reinterpret_cast<void*>(&p2), reinterpret_cast<void*>(&p3),
157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        reinterpret_cast<void*>(&return_value));
158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return return_value;
159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private:
162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BufferedRawMachineAssemblerTester(uint32_t return_parameter_index,
163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    MachineType p0, MachineType p1,
164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    MachineType p2, MachineType p3)
165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : RawMachineAssemblerTester<int32_t>(
166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            MachineType::Pointer(),
167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            p0 == MachineType::None() ? MachineType::None()
168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                      : MachineType::Pointer(),
169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            p1 == MachineType::None() ? MachineType::None()
170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                      : MachineType::Pointer(),
171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            p2 == MachineType::None() ? MachineType::None()
172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                      : MachineType::Pointer(),
173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            p3 == MachineType::None() ? MachineType::None()
174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                      : MachineType::Pointer()),
175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        test_graph_signature_(
176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            CSignature::New(main_zone(), MachineType::Int32(), p0, p1, p2, p3)),
177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return_parameter_index_(return_parameter_index) {
178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    parameter_nodes_[0] = p0 == MachineType::None()
179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              ? nullptr
180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              : Load(p0, RawMachineAssembler::Parameter(0));
181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    parameter_nodes_[1] = p1 == MachineType::None()
182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              ? nullptr
183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              : Load(p1, RawMachineAssembler::Parameter(1));
184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    parameter_nodes_[2] = p2 == MachineType::None()
185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              ? nullptr
186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              : Load(p2, RawMachineAssembler::Parameter(2));
187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    parameter_nodes_[3] = p3 == MachineType::None()
188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              ? nullptr
189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              : Load(p3, RawMachineAssembler::Parameter(3));
190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static uint32_t ComputeParameterCount(MachineType p0, MachineType p1,
194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        MachineType p2, MachineType p3) {
195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (p0 == MachineType::None()) {
196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return 0;
197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (p1 == MachineType::None()) {
199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return 1;
200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (p2 == MachineType::None()) {
202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return 2;
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (p3 == MachineType::None()) {
205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return 3;
206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return 4;
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CSignature* test_graph_signature_;
212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* parameter_nodes_[4];
213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t return_parameter_index_;
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtemplate <>
218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass BufferedRawMachineAssemblerTester<void>
219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    : public RawMachineAssemblerTester<void> {
220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public:
221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BufferedRawMachineAssemblerTester(MachineType p0 = MachineType::None(),
222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    MachineType p1 = MachineType::None(),
223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    MachineType p2 = MachineType::None(),
224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    MachineType p3 = MachineType::None())
225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : RawMachineAssemblerTester<void>(
226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            p0 == MachineType::None() ? MachineType::None()
227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                      : MachineType::Pointer(),
228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            p1 == MachineType::None() ? MachineType::None()
229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                      : MachineType::Pointer(),
230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            p2 == MachineType::None() ? MachineType::None()
231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                      : MachineType::Pointer(),
232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            p3 == MachineType::None() ? MachineType::None()
233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                      : MachineType::Pointer()),
234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        test_graph_signature_(
235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            CSignature::New(RawMachineAssemblerTester<void>::main_zone(),
236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                            MachineType::None(), p0, p1, p2, p3)) {
237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    parameter_nodes_[0] = p0 == MachineType::None()
238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              ? nullptr
239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              : Load(p0, RawMachineAssembler::Parameter(0));
240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    parameter_nodes_[1] = p1 == MachineType::None()
241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              ? nullptr
242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              : Load(p1, RawMachineAssembler::Parameter(1));
243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    parameter_nodes_[2] = p2 == MachineType::None()
244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              ? nullptr
245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              : Load(p2, RawMachineAssembler::Parameter(2));
246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    parameter_nodes_[3] = p3 == MachineType::None()
247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              ? nullptr
248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              : Load(p3, RawMachineAssembler::Parameter(3));
249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
251342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  virtual byte* Generate() { return RawMachineAssemblerTester::Generate(); }
252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // The BufferedRawMachineAssemblerTester does not pass parameters directly
254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // to the constructed IR graph. Instead it passes a pointer to the parameter
255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // to the IR graph, and adds Load nodes to the IR graph to load the
256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // parameters from memory. Thereby it is possible to pass 64 bit parameters
257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // to the IR graph.
258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* Parameter(size_t index) {
25921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    CHECK(index < 4);
260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return parameter_nodes_[index];
261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Call() {
265342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch    CSignature::VerifyParams(test_graph_signature_);
266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallHelper<void>::Call();
267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  template <typename P0>
270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Call(P0 p0) {
271342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch    CSignature::VerifyParams<P0>(test_graph_signature_);
272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallHelper<void>::Call(reinterpret_cast<void*>(&p0));
273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  template <typename P0, typename P1>
276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Call(P0 p0, P1 p1) {
277342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch    CSignature::VerifyParams<P0, P1>(test_graph_signature_);
278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallHelper<void>::Call(reinterpret_cast<void*>(&p0),
279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                           reinterpret_cast<void*>(&p1));
280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  template <typename P0, typename P1, typename P2>
283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Call(P0 p0, P1 p1, P2 p2) {
284342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch    CSignature::VerifyParams<P0, P1, P2>(test_graph_signature_);
285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallHelper<void>::Call(reinterpret_cast<void*>(&p0),
286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                           reinterpret_cast<void*>(&p1),
287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                           reinterpret_cast<void*>(&p2));
288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  template <typename P0, typename P1, typename P2, typename P3>
291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Call(P0 p0, P1 p1, P2 p2, P3 p3) {
292342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch    CSignature::VerifyParams<P0, P1, P2, P3>(test_graph_signature_);
293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallHelper<void>::Call(
294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        reinterpret_cast<void*>(&p0), reinterpret_cast<void*>(&p1),
295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        reinterpret_cast<void*>(&p2), reinterpret_cast<void*>(&p3));
296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private:
299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CSignature* test_graph_signature_;
300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* parameter_nodes_[4];
301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const bool USE_RESULT_BUFFER = true;
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const bool USE_RETURN_REGISTER = false;
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const int32_t CHECK_VALUE = 0x99BEEDCE;
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(titzer): use the C-style calling convention, or any register-based
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// calling convention for binop tests.
309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtemplate <typename CType, bool use_result_buffer>
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass BinopTester {
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit BinopTester(RawMachineAssemblerTester<int32_t>* tester,
313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       MachineType rep)
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : T(tester),
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        param0(T->LoadFromPointer(&p0, rep)),
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        param1(T->LoadFromPointer(&p1, rep)),
317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        rep(rep),
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        p0(static_cast<CType>(0)),
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        p1(static_cast<CType>(0)),
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        result(static_cast<CType>(0)) {}
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RawMachineAssemblerTester<int32_t>* T;
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* param0;
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* param1;
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CType call(CType a0, CType a1) {
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    p0 = a0;
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    p1 = a1;
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (use_result_buffer) {
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(CHECK_VALUE, T->Call());
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return result;
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return static_cast<CType>(T->Call());
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AddReturn(Node* val) {
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (use_result_buffer) {
339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      T->Store(rep.representation(), T->PointerConstant(&result),
340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch               T->Int32Constant(0), val, kNoWriteBarrier);
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      T->Return(T->Int32Constant(CHECK_VALUE));
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      T->Return(val);
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template <typename Ci, typename Cj, typename Fn>
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Run(const Ci& ci, const Cj& cj, const Fn& fn) {
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    typename Ci::const_iterator i;
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    typename Cj::const_iterator j;
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (i = ci.begin(); i != ci.end(); ++i) {
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      for (j = cj.begin(); j != cj.end(); ++j) {
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK_EQ(fn(*i, *j), this->call(*i, *j));
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch protected:
359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MachineType rep;
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CType p0;
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CType p1;
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CType result;
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A helper class for testing code sequences that take two int parameters and
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// return an int value.
368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass Int32BinopTester : public BinopTester<int32_t, USE_RETURN_REGISTER> {
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit Int32BinopTester(RawMachineAssemblerTester<int32_t>* tester)
371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : BinopTester<int32_t, USE_RETURN_REGISTER>(tester,
372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                  MachineType::Int32()) {}
373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// A helper class for testing code sequences that take two int parameters and
377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// return an int value.
378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass Int64BinopTester : public BinopTester<int64_t, USE_RETURN_REGISTER> {
379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public:
380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit Int64BinopTester(RawMachineAssemblerTester<int32_t>* tester)
381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : BinopTester<int64_t, USE_RETURN_REGISTER>(tester,
382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                  MachineType::Int64()) {}
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A helper class for testing code sequences that take two uint parameters and
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// return an uint value.
388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass Uint32BinopTester : public BinopTester<uint32_t, USE_RETURN_REGISTER> {
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit Uint32BinopTester(RawMachineAssemblerTester<int32_t>* tester)
391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : BinopTester<uint32_t, USE_RETURN_REGISTER>(tester,
392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                   MachineType::Uint32()) {}
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint32_t call(uint32_t a0, uint32_t a1) {
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    p0 = a0;
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    p1 = a1;
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return static_cast<uint32_t>(T->Call());
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// A helper class for testing code sequences that take two float parameters and
403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// return a float value.
404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass Float32BinopTester : public BinopTester<float, USE_RESULT_BUFFER> {
405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public:
406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit Float32BinopTester(RawMachineAssemblerTester<int32_t>* tester)
407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : BinopTester<float, USE_RESULT_BUFFER>(tester, MachineType::Float32()) {}
408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A helper class for testing code sequences that take two double parameters and
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// return a double value.
413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass Float64BinopTester : public BinopTester<double, USE_RESULT_BUFFER> {
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit Float64BinopTester(RawMachineAssemblerTester<int32_t>* tester)
416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : BinopTester<double, USE_RESULT_BUFFER>(tester, MachineType::Float64()) {
417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A helper class for testing code sequences that take two pointer parameters
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// and return a pointer value.
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(titzer): pick word size of pointers based on V8_TARGET.
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename Type>
425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass PointerBinopTester : public BinopTester<Type*, USE_RETURN_REGISTER> {
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit PointerBinopTester(RawMachineAssemblerTester<int32_t>* tester)
428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : BinopTester<Type*, USE_RETURN_REGISTER>(tester,
429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                MachineType::Pointer()) {}
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A helper class for testing code sequences that take two tagged parameters and
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// return a tagged value.
435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename Type>
436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass TaggedBinopTester : public BinopTester<Type*, USE_RETURN_REGISTER> {
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit TaggedBinopTester(RawMachineAssemblerTester<int32_t>* tester)
439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : BinopTester<Type*, USE_RETURN_REGISTER>(tester,
440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                MachineType::AnyTagged()) {}
441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A helper class for testing compares. Wraps a machine opcode and provides
444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// evaluation routines and the operators.
445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass CompareWrapper {
446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit CompareWrapper(IrOpcode::Value op) : opcode(op) {}
448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* MakeNode(RawMachineAssemblerTester<int32_t>* m, Node* a, Node* b) {
450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return m->AddNode(op(m->machine()), a, b);
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const Operator* op(MachineOperatorBuilder* machine) {
454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (opcode) {
455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kWord32Equal:
456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return machine->Word32Equal();
457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt32LessThan:
458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return machine->Int32LessThan();
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt32LessThanOrEqual:
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return machine->Int32LessThanOrEqual();
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kUint32LessThan:
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return machine->Uint32LessThan();
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kUint32LessThanOrEqual:
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return machine->Uint32LessThanOrEqual();
465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kFloat64Equal:
466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return machine->Float64Equal();
467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kFloat64LessThan:
468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return machine->Float64LessThan();
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kFloat64LessThanOrEqual:
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return machine->Float64LessThanOrEqual();
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      default:
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        UNREACHABLE();
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return NULL;
475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool Int32Compare(int32_t a, int32_t b) {
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (opcode) {
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kWord32Equal:
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return a == b;
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt32LessThan:
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return a < b;
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt32LessThanOrEqual:
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return a <= b;
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kUint32LessThan:
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return static_cast<uint32_t>(a) < static_cast<uint32_t>(b);
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kUint32LessThanOrEqual:
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return static_cast<uint32_t>(a) <= static_cast<uint32_t>(b);
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      default:
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        UNREACHABLE();
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return false;
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool Float64Compare(double a, double b) {
496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (opcode) {
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kFloat64Equal:
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return a == b;
499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kFloat64LessThan:
500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return a < b;
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kFloat64LessThanOrEqual:
502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return a <= b;
503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      default:
504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        UNREACHABLE();
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return false;
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IrOpcode::Value opcode;
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A small closure class to generate code for a function of two inputs that
514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// produces a single output so that it can be used in many different contexts.
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The {expected()} method should compute the expected output for a given
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// pair of inputs.
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename T>
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass BinopGen {
519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual void gen(RawMachineAssemblerTester<int32_t>* m, Node* a, Node* b) = 0;
521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual T expected(T a, T b) = 0;
522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual ~BinopGen() {}
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A helper class to generate various combination of input shape combinations
526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// and run the generated code to ensure it produces the correct results.
527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass Int32BinopInputShapeTester {
528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
529342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  explicit Int32BinopInputShapeTester(BinopGen<int32_t>* g)
530342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch      : gen(g), input_a(0), input_b(0) {}
531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TestAllInputShapes();
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BinopGen<int32_t>* gen;
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t input_a;
537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t input_b;
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Run(RawMachineAssemblerTester<int32_t>* m);
540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RunLeft(RawMachineAssemblerTester<int32_t>* m);
541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RunRight(RawMachineAssemblerTester<int32_t>* m);
542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace compiler
544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace internal
545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace v8
546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_CCTEST_COMPILER_CODEGEN_TESTER_H_
548