613e25883ebb0e21b7e37eaca607a86583d62807
[platform/upstream/nodejs.git] / deps / v8 / test / unittests / compiler / instruction-sequence-unittest.h
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.
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
12 namespace v8 {
13 namespace internal {
14 namespace compiler {
15
16 class InstructionSequenceTest : public TestWithIsolateAndZone {
17  public:
18   static const int kDefaultNRegs = 4;
19   static const int kNoValue = kMinInt;
20
21   typedef BasicBlock::RpoNumber Rpo;
22
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
30   enum TestOperandType {
31     kInvalid,
32     kSameAsFirst,
33     kRegister,
34     kFixedRegister,
35     kSlot,
36     kFixedSlot,
37     kImmediate,
38     kNone,
39     kConstant,
40     kUnique,
41     kUniqueRegister
42   };
43
44   struct TestOperand {
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) {}
50
51     TestOperandType type_;
52     VReg vreg_;
53     int value_;
54   };
55
56   static TestOperand Same() { return TestOperand(kSameAsFirst, VReg()); }
57
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);
62   }
63
64   static TestOperand Reg(int index = kNoValue) { return Reg(VReg(), index); }
65
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);
70   }
71
72   static TestOperand Slot(int index = kNoValue) { return Slot(VReg(), index); }
73
74   static TestOperand Const(int index) {
75     CHECK_NE(kNoValue, index);
76     return TestOperand(kConstant, VReg(), index);
77   }
78
79   static TestOperand Use(VReg vreg) { return TestOperand(kNone, vreg); }
80
81   static TestOperand Use() { return Use(VReg()); }
82
83   static TestOperand Unique(VReg vreg) { return TestOperand(kUnique, vreg); }
84
85   static TestOperand UniqueReg(VReg vreg) {
86     return TestOperand(kUniqueRegister, vreg);
87   }
88
89   enum BlockCompletionType { kBlockEnd, kFallThrough, kBranch, kJump };
90
91   struct BlockCompletion {
92     BlockCompletionType type_;
93     TestOperand op_;
94     int offset_0_;
95     int offset_1_;
96   };
97
98   static BlockCompletion FallThrough() {
99     BlockCompletion completion = {kFallThrough, TestOperand(), 1, kNoValue};
100     return completion;
101   }
102
103   static BlockCompletion Jump(int offset) {
104     BlockCompletion completion = {kJump, TestOperand(), offset, kNoValue};
105     return completion;
106   }
107
108   static BlockCompletion Branch(TestOperand op, int left_offset,
109                                 int right_offset) {
110     BlockCompletion completion = {kBranch, op, left_offset, right_offset};
111     return completion;
112   }
113
114   static BlockCompletion Last() {
115     BlockCompletion completion = {kBlockEnd, TestOperand(), kNoValue, kNoValue};
116     return completion;
117   }
118
119   InstructionSequenceTest();
120
121   void SetNumRegs(int num_general_registers, int num_double_registers);
122   RegisterConfiguration* config();
123   InstructionSequence* sequence();
124
125   void StartLoop(int loop_blocks);
126   void EndLoop();
127   void StartBlock();
128   int EndBlock(BlockCompletion completion = FallThrough());
129
130   TestOperand Imm(int32_t imm = 0);
131   VReg Define(TestOperand output_op);
132   VReg Parameter(TestOperand output_op = Reg()) { return Define(output_op); }
133
134   int Return(TestOperand input_op_0);
135   int Return(VReg vreg) { return Return(Reg(vreg, 0)); }
136
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);
143
144   VReg DefineConstant(int32_t imm = 0);
145   int EmitNop();
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());
161
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);
165
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_; }
169
170   // Called after all instructions have been inserted.
171   void WireBlocks();
172
173  private:
174   VReg NewReg() { return VReg(sequence()->NextVirtualRegister()); }
175   int NewIndex() { return current_instruction_index_--; }
176
177   static TestOperand Invalid() { return TestOperand(kInvalid, VReg()); }
178
179   int EmitBranch(TestOperand input_op);
180   int EmitFallThrough();
181   int EmitJump();
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,
195                                  int index);
196   InstructionOperand Unallocated(TestOperand op,
197                                  UnallocatedOperand::BasicPolicy policy,
198                                  int index);
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);
204
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);
209
210   int AddInstruction(int instruction_index, Instruction* instruction);
211
212   struct LoopData {
213     Rpo loop_header_;
214     int expected_blocks_;
215   };
216
217   typedef std::vector<LoopData> LoopBlocks;
218   typedef std::map<int, const Instruction*> Instructions;
219   typedef std::vector<BlockCompletion> Completions;
220
221   SmartPointer<RegisterConfiguration> config_;
222   InstructionSequence* sequence_;
223   int num_general_registers_;
224   int num_double_registers_;
225
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_;
233   bool block_returns_;
234 };
235
236 }  // namespace compiler
237 }  // namespace internal
238 }  // namespace v8
239
240 #endif  // V8_UNITTESTS_COMPILER_INSTRUCTION_SEQUENCE_UNITTEST_H_