blob: eb86bd9174985c883234e468a3ce73c995b75143 [file] [log] [blame]
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001// 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_UNITTESTS_COMPILER_INSTRUCTION_SEQUENCE_UNITTEST_H_
6#define V8_UNITTESTS_COMPILER_INSTRUCTION_SEQUENCE_UNITTEST_H_
7
8#include "src/compiler/instruction.h"
9#include "test/unittests/test-utils.h"
10#include "testing/gmock/include/gmock/gmock.h"
11
12namespace v8 {
13namespace internal {
14namespace compiler {
15
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016class InstructionSequenceTest : public TestWithIsolateAndZone {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018 static const int kDefaultNRegs = 8;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040019 static const int kNoValue = kMinInt;
20
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021 typedef RpoNumber Rpo;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022
23 struct VReg {
24 VReg() : value_(kNoValue) {}
25 VReg(PhiInstruction* phi) : value_(phi->virtual_register()) {} // NOLINT
26 explicit VReg(int value) : value_(value) {}
27 int value_;
28 };
29
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000030 typedef std::pair<VReg, VReg> VRegPair;
31
Emily Bernierd0a1eb72015-03-24 16:35:39 -040032 enum TestOperandType {
33 kInvalid,
34 kSameAsFirst,
35 kRegister,
36 kFixedRegister,
37 kSlot,
38 kFixedSlot,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000039 kExplicit,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040040 kImmediate,
41 kNone,
42 kConstant,
43 kUnique,
44 kUniqueRegister
45 };
46
47 struct TestOperand {
48 TestOperand() : type_(kInvalid), vreg_(), value_(kNoValue) {}
49 TestOperand(TestOperandType type, int imm)
50 : type_(type), vreg_(), value_(imm) {}
51 TestOperand(TestOperandType type, VReg vreg, int value = kNoValue)
52 : type_(type), vreg_(vreg), value_(value) {}
53
54 TestOperandType type_;
55 VReg vreg_;
56 int value_;
57 };
58
59 static TestOperand Same() { return TestOperand(kSameAsFirst, VReg()); }
60
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000061 static TestOperand ExplicitReg(int index) {
62 TestOperandType type = kExplicit;
63 return TestOperand(type, VReg(), index);
64 }
65
Emily Bernierd0a1eb72015-03-24 16:35:39 -040066 static TestOperand Reg(VReg vreg, int index = kNoValue) {
67 TestOperandType type = kRegister;
68 if (index != kNoValue) type = kFixedRegister;
69 return TestOperand(type, vreg, index);
70 }
71
72 static TestOperand Reg(int index = kNoValue) { return Reg(VReg(), index); }
73
74 static TestOperand Slot(VReg vreg, int index = kNoValue) {
75 TestOperandType type = kSlot;
76 if (index != kNoValue) type = kFixedSlot;
77 return TestOperand(type, vreg, index);
78 }
79
80 static TestOperand Slot(int index = kNoValue) { return Slot(VReg(), index); }
81
82 static TestOperand Const(int index) {
83 CHECK_NE(kNoValue, index);
84 return TestOperand(kConstant, VReg(), index);
85 }
86
87 static TestOperand Use(VReg vreg) { return TestOperand(kNone, vreg); }
88
89 static TestOperand Use() { return Use(VReg()); }
90
91 static TestOperand Unique(VReg vreg) { return TestOperand(kUnique, vreg); }
92
93 static TestOperand UniqueReg(VReg vreg) {
94 return TestOperand(kUniqueRegister, vreg);
95 }
96
97 enum BlockCompletionType { kBlockEnd, kFallThrough, kBranch, kJump };
98
99 struct BlockCompletion {
100 BlockCompletionType type_;
101 TestOperand op_;
102 int offset_0_;
103 int offset_1_;
104 };
105
106 static BlockCompletion FallThrough() {
107 BlockCompletion completion = {kFallThrough, TestOperand(), 1, kNoValue};
108 return completion;
109 }
110
111 static BlockCompletion Jump(int offset) {
112 BlockCompletion completion = {kJump, TestOperand(), offset, kNoValue};
113 return completion;
114 }
115
116 static BlockCompletion Branch(TestOperand op, int left_offset,
117 int right_offset) {
118 BlockCompletion completion = {kBranch, op, left_offset, right_offset};
119 return completion;
120 }
121
122 static BlockCompletion Last() {
123 BlockCompletion completion = {kBlockEnd, TestOperand(), kNoValue, kNoValue};
124 return completion;
125 }
126
127 InstructionSequenceTest();
128
129 void SetNumRegs(int num_general_registers, int num_double_registers);
130 RegisterConfiguration* config();
131 InstructionSequence* sequence();
132
133 void StartLoop(int loop_blocks);
134 void EndLoop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000135 void StartBlock(bool deferred = false);
136 Instruction* EndBlock(BlockCompletion completion = FallThrough());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400137
138 TestOperand Imm(int32_t imm = 0);
139 VReg Define(TestOperand output_op);
140 VReg Parameter(TestOperand output_op = Reg()) { return Define(output_op); }
141
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000142 Instruction* Return(TestOperand input_op_0);
143 Instruction* Return(VReg vreg) { return Return(Reg(vreg, 0)); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400144
145 PhiInstruction* Phi(VReg incoming_vreg_0 = VReg(),
146 VReg incoming_vreg_1 = VReg(),
147 VReg incoming_vreg_2 = VReg(),
148 VReg incoming_vreg_3 = VReg());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000149 PhiInstruction* Phi(VReg incoming_vreg_0, size_t input_count);
150 void SetInput(PhiInstruction* phi, size_t input, VReg vreg);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400151
152 VReg DefineConstant(int32_t imm = 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000153 Instruction* EmitNop();
154 Instruction* EmitI(size_t input_size, TestOperand* inputs);
155 Instruction* EmitI(TestOperand input_op_0 = TestOperand(),
156 TestOperand input_op_1 = TestOperand(),
157 TestOperand input_op_2 = TestOperand(),
158 TestOperand input_op_3 = TestOperand());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400159 VReg EmitOI(TestOperand output_op, size_t input_size, TestOperand* inputs);
160 VReg EmitOI(TestOperand output_op, TestOperand input_op_0 = TestOperand(),
161 TestOperand input_op_1 = TestOperand(),
162 TestOperand input_op_2 = TestOperand(),
163 TestOperand input_op_3 = TestOperand());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000164 VRegPair EmitOOI(TestOperand output_op_0, TestOperand output_op_1,
165 size_t input_size, TestOperand* inputs);
166 VRegPair EmitOOI(TestOperand output_op_0, TestOperand output_op_1,
167 TestOperand input_op_0 = TestOperand(),
168 TestOperand input_op_1 = TestOperand(),
169 TestOperand input_op_2 = TestOperand(),
170 TestOperand input_op_3 = TestOperand());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400171 VReg EmitCall(TestOperand output_op, size_t input_size, TestOperand* inputs);
172 VReg EmitCall(TestOperand output_op, TestOperand input_op_0 = TestOperand(),
173 TestOperand input_op_1 = TestOperand(),
174 TestOperand input_op_2 = TestOperand(),
175 TestOperand input_op_3 = TestOperand());
176
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400177 InstructionBlock* current_block() const { return current_block_; }
178 int num_general_registers() const { return num_general_registers_; }
179 int num_double_registers() const { return num_double_registers_; }
180
181 // Called after all instructions have been inserted.
182 void WireBlocks();
183
184 private:
185 VReg NewReg() { return VReg(sequence()->NextVirtualRegister()); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400186
187 static TestOperand Invalid() { return TestOperand(kInvalid, VReg()); }
188
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000189 Instruction* EmitBranch(TestOperand input_op);
190 Instruction* EmitFallThrough();
191 Instruction* EmitJump();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400192 Instruction* NewInstruction(InstructionCode code, size_t outputs_size,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193 InstructionOperand* outputs,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400194 size_t inputs_size = 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000195 InstructionOperand* inputs = nullptr,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400196 size_t temps_size = 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000197 InstructionOperand* temps = nullptr);
198 InstructionOperand Unallocated(TestOperand op,
199 UnallocatedOperand::ExtendedPolicy policy);
200 InstructionOperand Unallocated(TestOperand op,
201 UnallocatedOperand::ExtendedPolicy policy,
202 UnallocatedOperand::Lifetime lifetime);
203 InstructionOperand Unallocated(TestOperand op,
204 UnallocatedOperand::ExtendedPolicy policy,
205 int index);
206 InstructionOperand Unallocated(TestOperand op,
207 UnallocatedOperand::BasicPolicy policy,
208 int index);
209 InstructionOperand* ConvertInputs(size_t input_size, TestOperand* inputs);
210 InstructionOperand ConvertInputOp(TestOperand op);
211 InstructionOperand ConvertOutputOp(VReg vreg, TestOperand op);
212 InstructionBlock* NewBlock(bool deferred = false);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400213 void WireBlock(size_t block_offset, int jump_offset);
214
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000215 Instruction* Emit(InstructionCode code, size_t outputs_size = 0,
216 InstructionOperand* outputs = nullptr,
217 size_t inputs_size = 0,
218 InstructionOperand* inputs = nullptr, size_t temps_size = 0,
219 InstructionOperand* temps = nullptr, bool is_call = false);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400220
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000221 Instruction* AddInstruction(Instruction* instruction);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400222
223 struct LoopData {
224 Rpo loop_header_;
225 int expected_blocks_;
226 };
227
228 typedef std::vector<LoopData> LoopBlocks;
229 typedef std::map<int, const Instruction*> Instructions;
230 typedef std::vector<BlockCompletion> Completions;
231
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000232 base::SmartPointer<RegisterConfiguration> config_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400233 InstructionSequence* sequence_;
234 int num_general_registers_;
235 int num_double_registers_;
236
237 // Block building state.
238 InstructionBlocks instruction_blocks_;
239 Instructions instructions_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400240 Completions completions_;
241 LoopBlocks loop_blocks_;
242 InstructionBlock* current_block_;
243 bool block_returns_;
244};
245
246} // namespace compiler
247} // namespace internal
248} // namespace v8
249
250#endif // V8_UNITTESTS_COMPILER_INSTRUCTION_SEQUENCE_UNITTEST_H_