1 // 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.
5 #ifndef V8_UNITTESTS_COMPILER_INSTRUCTION_SEQUENCE_UNITTEST_H_
6 #define V8_UNITTESTS_COMPILER_INSTRUCTION_SEQUENCE_UNITTEST_H_
8 #include "src/compiler/instruction.h"
9 #include "test/unittests/test-utils.h"
10 #include "testing/gmock/include/gmock/gmock.h"
16 class InstructionSequenceTest : public TestWithIsolateAndZone {
18 static const int kDefaultNRegs = 4;
19 static const int kNoValue = kMinInt;
21 typedef RpoNumber Rpo;
24 VReg() : value_(kNoValue) {}
25 VReg(PhiInstruction* phi) : value_(phi->virtual_register()) {} // NOLINT
26 explicit VReg(int value) : value_(value) {}
30 typedef std::pair<VReg, VReg> VRegPair;
32 enum TestOperandType {
47 TestOperand() : type_(kInvalid), vreg_(), value_(kNoValue) {}
48 TestOperand(TestOperandType type, int imm)
49 : type_(type), vreg_(), value_(imm) {}
50 TestOperand(TestOperandType type, VReg vreg, int value = kNoValue)
51 : type_(type), vreg_(vreg), value_(value) {}
53 TestOperandType type_;
58 static TestOperand Same() { return TestOperand(kSameAsFirst, VReg()); }
60 static TestOperand Reg(VReg vreg, int index = kNoValue) {
61 TestOperandType type = kRegister;
62 if (index != kNoValue) type = kFixedRegister;
63 return TestOperand(type, vreg, index);
66 static TestOperand Reg(int index = kNoValue) { return Reg(VReg(), index); }
68 static TestOperand Slot(VReg vreg, int index = kNoValue) {
69 TestOperandType type = kSlot;
70 if (index != kNoValue) type = kFixedSlot;
71 return TestOperand(type, vreg, index);
74 static TestOperand Slot(int index = kNoValue) { return Slot(VReg(), index); }
76 static TestOperand Const(int index) {
77 CHECK_NE(kNoValue, index);
78 return TestOperand(kConstant, VReg(), index);
81 static TestOperand Use(VReg vreg) { return TestOperand(kNone, vreg); }
83 static TestOperand Use() { return Use(VReg()); }
85 static TestOperand Unique(VReg vreg) { return TestOperand(kUnique, vreg); }
87 static TestOperand UniqueReg(VReg vreg) {
88 return TestOperand(kUniqueRegister, vreg);
91 enum BlockCompletionType { kBlockEnd, kFallThrough, kBranch, kJump };
93 struct BlockCompletion {
94 BlockCompletionType type_;
100 static BlockCompletion FallThrough() {
101 BlockCompletion completion = {kFallThrough, TestOperand(), 1, kNoValue};
105 static BlockCompletion Jump(int offset) {
106 BlockCompletion completion = {kJump, TestOperand(), offset, kNoValue};
110 static BlockCompletion Branch(TestOperand op, int left_offset,
112 BlockCompletion completion = {kBranch, op, left_offset, right_offset};
116 static BlockCompletion Last() {
117 BlockCompletion completion = {kBlockEnd, TestOperand(), kNoValue, kNoValue};
121 InstructionSequenceTest();
123 void SetNumRegs(int num_general_registers, int num_double_registers);
124 RegisterConfiguration* config();
125 InstructionSequence* sequence();
127 void StartLoop(int loop_blocks);
130 Instruction* EndBlock(BlockCompletion completion = FallThrough());
132 TestOperand Imm(int32_t imm = 0);
133 VReg Define(TestOperand output_op);
134 VReg Parameter(TestOperand output_op = Reg()) { return Define(output_op); }
136 Instruction* Return(TestOperand input_op_0);
137 Instruction* Return(VReg vreg) { return Return(Reg(vreg, 0)); }
139 PhiInstruction* Phi(VReg incoming_vreg_0 = VReg(),
140 VReg incoming_vreg_1 = VReg(),
141 VReg incoming_vreg_2 = VReg(),
142 VReg incoming_vreg_3 = VReg());
143 PhiInstruction* Phi(VReg incoming_vreg_0, size_t input_count);
144 void SetInput(PhiInstruction* phi, size_t input, VReg vreg);
146 VReg DefineConstant(int32_t imm = 0);
147 Instruction* EmitNop();
148 Instruction* EmitI(size_t input_size, TestOperand* inputs);
149 Instruction* EmitI(TestOperand input_op_0 = TestOperand(),
150 TestOperand input_op_1 = TestOperand(),
151 TestOperand input_op_2 = TestOperand(),
152 TestOperand input_op_3 = TestOperand());
153 VReg EmitOI(TestOperand output_op, size_t input_size, TestOperand* inputs);
154 VReg EmitOI(TestOperand output_op, TestOperand input_op_0 = TestOperand(),
155 TestOperand input_op_1 = TestOperand(),
156 TestOperand input_op_2 = TestOperand(),
157 TestOperand input_op_3 = TestOperand());
158 VRegPair EmitOOI(TestOperand output_op_0, TestOperand output_op_1,
159 size_t input_size, TestOperand* inputs);
160 VRegPair EmitOOI(TestOperand output_op_0, TestOperand output_op_1,
161 TestOperand input_op_0 = TestOperand(),
162 TestOperand input_op_1 = TestOperand(),
163 TestOperand input_op_2 = TestOperand(),
164 TestOperand input_op_3 = TestOperand());
165 VReg EmitCall(TestOperand output_op, size_t input_size, TestOperand* inputs);
166 VReg EmitCall(TestOperand output_op, TestOperand input_op_0 = TestOperand(),
167 TestOperand input_op_1 = TestOperand(),
168 TestOperand input_op_2 = TestOperand(),
169 TestOperand input_op_3 = TestOperand());
171 InstructionBlock* current_block() const { return current_block_; }
172 int num_general_registers() const { return num_general_registers_; }
173 int num_double_registers() const { return num_double_registers_; }
175 // Called after all instructions have been inserted.
179 VReg NewReg() { return VReg(sequence()->NextVirtualRegister()); }
181 static TestOperand Invalid() { return TestOperand(kInvalid, VReg()); }
183 Instruction* EmitBranch(TestOperand input_op);
184 Instruction* EmitFallThrough();
185 Instruction* EmitJump();
186 Instruction* NewInstruction(InstructionCode code, size_t outputs_size,
187 InstructionOperand* outputs,
188 size_t inputs_size = 0,
189 InstructionOperand* inputs = nullptr,
190 size_t temps_size = 0,
191 InstructionOperand* temps = nullptr);
192 InstructionOperand Unallocated(TestOperand op,
193 UnallocatedOperand::ExtendedPolicy policy);
194 InstructionOperand Unallocated(TestOperand op,
195 UnallocatedOperand::ExtendedPolicy policy,
196 UnallocatedOperand::Lifetime lifetime);
197 InstructionOperand Unallocated(TestOperand op,
198 UnallocatedOperand::ExtendedPolicy policy,
200 InstructionOperand Unallocated(TestOperand op,
201 UnallocatedOperand::BasicPolicy policy,
203 InstructionOperand* ConvertInputs(size_t input_size, TestOperand* inputs);
204 InstructionOperand ConvertInputOp(TestOperand op);
205 InstructionOperand ConvertOutputOp(VReg vreg, TestOperand op);
206 InstructionBlock* NewBlock();
207 void WireBlock(size_t block_offset, int jump_offset);
209 Instruction* Emit(InstructionCode code, size_t outputs_size = 0,
210 InstructionOperand* outputs = nullptr,
211 size_t inputs_size = 0,
212 InstructionOperand* inputs = nullptr, size_t temps_size = 0,
213 InstructionOperand* temps = nullptr, bool is_call = false);
215 Instruction* AddInstruction(Instruction* instruction);
219 int expected_blocks_;
222 typedef std::vector<LoopData> LoopBlocks;
223 typedef std::map<int, const Instruction*> Instructions;
224 typedef std::vector<BlockCompletion> Completions;
226 SmartPointer<RegisterConfiguration> config_;
227 InstructionSequence* sequence_;
228 int num_general_registers_;
229 int num_double_registers_;
231 // Block building state.
232 InstructionBlocks instruction_blocks_;
233 Instructions instructions_;
234 Completions completions_;
235 LoopBlocks loop_blocks_;
236 InstructionBlock* current_block_;
240 } // namespace compiler
241 } // namespace internal
244 #endif // V8_UNITTESTS_COMPILER_INSTRUCTION_SEQUENCE_UNITTEST_H_