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 BasicBlock::RpoNumber Rpo;
24 VReg() : value_(kNoValue) {}
25 VReg(PhiInstruction* phi) : value_(phi->virtual_register()) {} // NOLINT
26 explicit VReg(int value) : value_(value) {}
30 enum TestOperandType {
45 TestOperand() : type_(kInvalid), vreg_(), value_(kNoValue) {}
46 TestOperand(TestOperandType type, int imm)
47 : type_(type), vreg_(), value_(imm) {}
48 TestOperand(TestOperandType type, VReg vreg, int value = kNoValue)
49 : type_(type), vreg_(vreg), value_(value) {}
51 TestOperandType type_;
56 static TestOperand Same() { return TestOperand(kSameAsFirst, VReg()); }
58 static TestOperand Reg(VReg vreg, int index = kNoValue) {
59 TestOperandType type = kRegister;
60 if (index != kNoValue) type = kFixedRegister;
61 return TestOperand(type, vreg, index);
64 static TestOperand Reg(int index = kNoValue) { return Reg(VReg(), index); }
66 static TestOperand Slot(VReg vreg, int index = kNoValue) {
67 TestOperandType type = kSlot;
68 if (index != kNoValue) type = kFixedSlot;
69 return TestOperand(type, vreg, index);
72 static TestOperand Slot(int index = kNoValue) { return Slot(VReg(), index); }
74 static TestOperand Const(int index) {
75 CHECK_NE(kNoValue, index);
76 return TestOperand(kConstant, VReg(), index);
79 static TestOperand Use(VReg vreg) { return TestOperand(kNone, vreg); }
81 static TestOperand Use() { return Use(VReg()); }
83 static TestOperand Unique(VReg vreg) { return TestOperand(kUnique, vreg); }
85 static TestOperand UniqueReg(VReg vreg) {
86 return TestOperand(kUniqueRegister, vreg);
89 enum BlockCompletionType { kBlockEnd, kFallThrough, kBranch, kJump };
91 struct BlockCompletion {
92 BlockCompletionType type_;
98 static BlockCompletion FallThrough() {
99 BlockCompletion completion = {kFallThrough, TestOperand(), 1, kNoValue};
103 static BlockCompletion Jump(int offset) {
104 BlockCompletion completion = {kJump, TestOperand(), offset, kNoValue};
108 static BlockCompletion Branch(TestOperand op, int left_offset,
110 BlockCompletion completion = {kBranch, op, left_offset, right_offset};
114 static BlockCompletion Last() {
115 BlockCompletion completion = {kBlockEnd, TestOperand(), kNoValue, kNoValue};
119 InstructionSequenceTest();
121 void SetNumRegs(int num_general_registers, int num_double_registers);
122 RegisterConfiguration* config();
123 InstructionSequence* sequence();
125 void StartLoop(int loop_blocks);
128 int EndBlock(BlockCompletion completion = FallThrough());
130 TestOperand Imm(int32_t imm = 0);
131 VReg Define(TestOperand output_op);
132 VReg Parameter(TestOperand output_op = Reg()) { return Define(output_op); }
134 int Return(TestOperand input_op_0);
135 int Return(VReg vreg) { return Return(Reg(vreg, 0)); }
137 PhiInstruction* Phi(VReg incoming_vreg_0 = VReg(),
138 VReg incoming_vreg_1 = VReg(),
139 VReg incoming_vreg_2 = VReg(),
140 VReg incoming_vreg_3 = VReg());
141 PhiInstruction* Phi(VReg incoming_vreg_0, size_t input_count);
142 void SetInput(PhiInstruction* phi, size_t input, VReg vreg);
144 VReg DefineConstant(int32_t imm = 0);
146 int EmitI(size_t input_size, TestOperand* inputs);
147 int EmitI(TestOperand input_op_0 = TestOperand(),
148 TestOperand input_op_1 = TestOperand(),
149 TestOperand input_op_2 = TestOperand(),
150 TestOperand input_op_3 = TestOperand());
151 VReg EmitOI(TestOperand output_op, size_t input_size, TestOperand* inputs);
152 VReg EmitOI(TestOperand output_op, TestOperand input_op_0 = TestOperand(),
153 TestOperand input_op_1 = TestOperand(),
154 TestOperand input_op_2 = TestOperand(),
155 TestOperand input_op_3 = TestOperand());
156 VReg EmitCall(TestOperand output_op, size_t input_size, TestOperand* inputs);
157 VReg EmitCall(TestOperand output_op, TestOperand input_op_0 = TestOperand(),
158 TestOperand input_op_1 = TestOperand(),
159 TestOperand input_op_2 = TestOperand(),
160 TestOperand input_op_3 = TestOperand());
162 // Get defining instruction vreg or value returned at instruction creation
163 // time when there is no return value.
164 const Instruction* GetInstruction(int instruction_index);
166 InstructionBlock* current_block() const { return current_block_; }
167 int num_general_registers() const { return num_general_registers_; }
168 int num_double_registers() const { return num_double_registers_; }
170 // Called after all instructions have been inserted.
174 VReg NewReg() { return VReg(sequence()->NextVirtualRegister()); }
175 int NewIndex() { return current_instruction_index_--; }
177 static TestOperand Invalid() { return TestOperand(kInvalid, VReg()); }
179 int EmitBranch(TestOperand input_op);
180 int EmitFallThrough();
182 Instruction* NewInstruction(InstructionCode code, size_t outputs_size,
183 InstructionOperand* outputs,
184 size_t inputs_size = 0,
185 InstructionOperand* inputs = nullptr,
186 size_t temps_size = 0,
187 InstructionOperand* temps = nullptr);
188 InstructionOperand Unallocated(TestOperand op,
189 UnallocatedOperand::ExtendedPolicy policy);
190 InstructionOperand Unallocated(TestOperand op,
191 UnallocatedOperand::ExtendedPolicy policy,
192 UnallocatedOperand::Lifetime lifetime);
193 InstructionOperand Unallocated(TestOperand op,
194 UnallocatedOperand::ExtendedPolicy policy,
196 InstructionOperand Unallocated(TestOperand op,
197 UnallocatedOperand::BasicPolicy policy,
199 InstructionOperand* ConvertInputs(size_t input_size, TestOperand* inputs);
200 InstructionOperand ConvertInputOp(TestOperand op);
201 InstructionOperand ConvertOutputOp(VReg vreg, TestOperand op);
202 InstructionBlock* NewBlock();
203 void WireBlock(size_t block_offset, int jump_offset);
205 int Emit(int instruction_index, InstructionCode code, size_t outputs_size = 0,
206 InstructionOperand* outputs = nullptr, size_t inputs_size = 0,
207 InstructionOperand* inputs = nullptr, size_t temps_size = 0,
208 InstructionOperand* temps = nullptr, bool is_call = false);
210 int AddInstruction(int instruction_index, Instruction* instruction);
214 int expected_blocks_;
217 typedef std::vector<LoopData> LoopBlocks;
218 typedef std::map<int, const Instruction*> Instructions;
219 typedef std::vector<BlockCompletion> Completions;
221 SmartPointer<RegisterConfiguration> config_;
222 InstructionSequence* sequence_;
223 int num_general_registers_;
224 int num_double_registers_;
226 // Block building state.
227 InstructionBlocks instruction_blocks_;
228 Instructions instructions_;
229 int current_instruction_index_;
230 Completions completions_;
231 LoopBlocks loop_blocks_;
232 InstructionBlock* current_block_;
236 } // namespace compiler
237 } // namespace internal
240 #endif // V8_UNITTESTS_COMPILER_INSTRUCTION_SEQUENCE_UNITTEST_H_