blob: 4e12dabbe1898d6a1a54911f86bae5d0a47b69c6 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_
6#define V8_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_
7
8#include <deque>
9#include <set>
10
11#include "src/base/utils/random-number-generator.h"
12#include "src/compiler/instruction-selector.h"
13#include "src/compiler/raw-machine-assembler.h"
14#include "src/test/test-utils.h"
15
16namespace v8 {
17namespace internal {
18namespace compiler {
19
20class InstructionSelectorTest : public TestWithContext, public TestWithZone {
21 public:
22 InstructionSelectorTest();
23 virtual ~InstructionSelectorTest();
24
25 base::RandomNumberGenerator* rng() { return &rng_; }
26
27 class Stream;
28
29 enum StreamBuilderMode {
30 kAllInstructions,
31 kTargetInstructions,
32 kAllExceptNopInstructions
33 };
34
35 class StreamBuilder FINAL : public RawMachineAssembler {
36 public:
37 StreamBuilder(InstructionSelectorTest* test, MachineType return_type)
38 : RawMachineAssembler(new (test->zone()) Graph(test->zone()),
39 MakeMachineSignature(test->zone(), return_type)),
40 test_(test) {}
41 StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
42 MachineType parameter0_type)
43 : RawMachineAssembler(
44 new (test->zone()) Graph(test->zone()),
45 MakeMachineSignature(test->zone(), return_type, parameter0_type)),
46 test_(test) {}
47 StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
48 MachineType parameter0_type, MachineType parameter1_type)
49 : RawMachineAssembler(
50 new (test->zone()) Graph(test->zone()),
51 MakeMachineSignature(test->zone(), return_type, parameter0_type,
52 parameter1_type)),
53 test_(test) {}
54 StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
55 MachineType parameter0_type, MachineType parameter1_type,
56 MachineType parameter2_type)
57 : RawMachineAssembler(
58 new (test->zone()) Graph(test->zone()),
59 MakeMachineSignature(test->zone(), return_type, parameter0_type,
60 parameter1_type, parameter2_type)),
61 test_(test) {}
62
63 Stream Build(CpuFeature feature) {
64 return Build(InstructionSelector::Features(feature));
65 }
66 Stream Build(CpuFeature feature1, CpuFeature feature2) {
67 return Build(InstructionSelector::Features(feature1, feature2));
68 }
69 Stream Build(StreamBuilderMode mode = kTargetInstructions) {
70 return Build(InstructionSelector::Features(), mode);
71 }
72 Stream Build(InstructionSelector::Features features,
73 StreamBuilderMode mode = kTargetInstructions);
74
75 private:
76 MachineSignature* MakeMachineSignature(Zone* zone,
77 MachineType return_type) {
78 MachineSignature::Builder builder(zone, 1, 0);
79 builder.AddReturn(return_type);
80 return builder.Build();
81 }
82
83 MachineSignature* MakeMachineSignature(Zone* zone, MachineType return_type,
84 MachineType parameter0_type) {
85 MachineSignature::Builder builder(zone, 1, 1);
86 builder.AddReturn(return_type);
87 builder.AddParam(parameter0_type);
88 return builder.Build();
89 }
90
91 MachineSignature* MakeMachineSignature(Zone* zone, MachineType return_type,
92 MachineType parameter0_type,
93 MachineType parameter1_type) {
94 MachineSignature::Builder builder(zone, 1, 2);
95 builder.AddReturn(return_type);
96 builder.AddParam(parameter0_type);
97 builder.AddParam(parameter1_type);
98 return builder.Build();
99 }
100
101 MachineSignature* MakeMachineSignature(Zone* zone, MachineType return_type,
102 MachineType parameter0_type,
103 MachineType parameter1_type,
104 MachineType parameter2_type) {
105 MachineSignature::Builder builder(zone, 1, 3);
106 builder.AddReturn(return_type);
107 builder.AddParam(parameter0_type);
108 builder.AddParam(parameter1_type);
109 builder.AddParam(parameter2_type);
110 return builder.Build();
111 }
112
113 private:
114 InstructionSelectorTest* test_;
115 };
116
117 class Stream FINAL {
118 public:
119 size_t size() const { return instructions_.size(); }
120 const Instruction* operator[](size_t index) const {
121 EXPECT_LT(index, size());
122 return instructions_[index];
123 }
124
125 bool IsDouble(const InstructionOperand* operand) const {
126 return IsDouble(ToVreg(operand));
127 }
128 bool IsDouble(int virtual_register) const {
129 return doubles_.find(virtual_register) != doubles_.end();
130 }
131
132 bool IsInteger(const InstructionOperand* operand) const {
133 return IsInteger(ToVreg(operand));
134 }
135 bool IsInteger(int virtual_register) const {
136 return !IsDouble(virtual_register) && !IsReference(virtual_register);
137 }
138
139 bool IsReference(const InstructionOperand* operand) const {
140 return IsReference(ToVreg(operand));
141 }
142 bool IsReference(int virtual_register) const {
143 return references_.find(virtual_register) != references_.end();
144 }
145
146 int32_t ToInt32(const InstructionOperand* operand) const {
147 return ToConstant(operand).ToInt32();
148 }
149
150 int64_t ToInt64(const InstructionOperand* operand) const {
151 return ToConstant(operand).ToInt64();
152 }
153
154 int ToVreg(const InstructionOperand* operand) const {
155 if (operand->IsConstant()) return operand->index();
156 EXPECT_EQ(InstructionOperand::UNALLOCATED, operand->kind());
157 return UnallocatedOperand::cast(operand)->virtual_register();
158 }
159
160 FrameStateDescriptor* GetFrameStateDescriptor(int deoptimization_id) {
161 EXPECT_LT(deoptimization_id, GetFrameStateDescriptorCount());
162 return deoptimization_entries_[deoptimization_id];
163 }
164
165 int GetFrameStateDescriptorCount() {
166 return static_cast<int>(deoptimization_entries_.size());
167 }
168
169 private:
170 Constant ToConstant(const InstructionOperand* operand) const {
171 ConstantMap::const_iterator i;
172 if (operand->IsConstant()) {
173 i = constants_.find(operand->index());
174 EXPECT_FALSE(constants_.end() == i);
175 } else {
176 EXPECT_EQ(InstructionOperand::IMMEDIATE, operand->kind());
177 i = immediates_.find(operand->index());
178 EXPECT_FALSE(immediates_.end() == i);
179 }
180 EXPECT_EQ(operand->index(), i->first);
181 return i->second;
182 }
183
184 friend class StreamBuilder;
185
186 typedef std::map<int, Constant> ConstantMap;
187
188 ConstantMap constants_;
189 ConstantMap immediates_;
190 std::deque<Instruction*> instructions_;
191 std::set<int> doubles_;
192 std::set<int> references_;
193 std::deque<FrameStateDescriptor*> deoptimization_entries_;
194 };
195
196 base::RandomNumberGenerator rng_;
197};
198
199
200template <typename T>
201class InstructionSelectorTestWithParam
202 : public InstructionSelectorTest,
203 public ::testing::WithParamInterface<T> {};
204
205} // namespace compiler
206} // namespace internal
207} // namespace v8
208
209#endif // V8_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_