deps: update v8 to 4.3.61.21
[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 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   typedef std::pair<VReg, VReg> VRegPair;
31
32   enum TestOperandType {
33     kInvalid,
34     kSameAsFirst,
35     kRegister,
36     kFixedRegister,
37     kSlot,
38     kFixedSlot,
39     kImmediate,
40     kNone,
41     kConstant,
42     kUnique,
43     kUniqueRegister
44   };
45
46   struct TestOperand {
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) {}
52
53     TestOperandType type_;
54     VReg vreg_;
55     int value_;
56   };
57
58   static TestOperand Same() { return TestOperand(kSameAsFirst, VReg()); }
59
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);
64   }
65
66   static TestOperand Reg(int index = kNoValue) { return Reg(VReg(), index); }
67
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);
72   }
73
74   static TestOperand Slot(int index = kNoValue) { return Slot(VReg(), index); }
75
76   static TestOperand Const(int index) {
77     CHECK_NE(kNoValue, index);
78     return TestOperand(kConstant, VReg(), index);
79   }
80
81   static TestOperand Use(VReg vreg) { return TestOperand(kNone, vreg); }
82
83   static TestOperand Use() { return Use(VReg()); }
84
85   static TestOperand Unique(VReg vreg) { return TestOperand(kUnique, vreg); }
86
87   static TestOperand UniqueReg(VReg vreg) {
88     return TestOperand(kUniqueRegister, vreg);
89   }
90
91   enum BlockCompletionType { kBlockEnd, kFallThrough, kBranch, kJump };
92
93   struct BlockCompletion {
94     BlockCompletionType type_;
95     TestOperand op_;
96     int offset_0_;
97     int offset_1_;
98   };
99
100   static BlockCompletion FallThrough() {
101     BlockCompletion completion = {kFallThrough, TestOperand(), 1, kNoValue};
102     return completion;
103   }
104
105   static BlockCompletion Jump(int offset) {
106     BlockCompletion completion = {kJump, TestOperand(), offset, kNoValue};
107     return completion;
108   }
109
110   static BlockCompletion Branch(TestOperand op, int left_offset,
111                                 int right_offset) {
112     BlockCompletion completion = {kBranch, op, left_offset, right_offset};
113     return completion;
114   }
115
116   static BlockCompletion Last() {
117     BlockCompletion completion = {kBlockEnd, TestOperand(), kNoValue, kNoValue};
118     return completion;
119   }
120
121   InstructionSequenceTest();
122
123   void SetNumRegs(int num_general_registers, int num_double_registers);
124   RegisterConfiguration* config();
125   InstructionSequence* sequence();
126
127   void StartLoop(int loop_blocks);
128   void EndLoop();
129   void StartBlock();
130   Instruction* EndBlock(BlockCompletion completion = FallThrough());
131
132   TestOperand Imm(int32_t imm = 0);
133   VReg Define(TestOperand output_op);
134   VReg Parameter(TestOperand output_op = Reg()) { return Define(output_op); }
135
136   Instruction* Return(TestOperand input_op_0);
137   Instruction* Return(VReg vreg) { return Return(Reg(vreg, 0)); }
138
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);
145
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());
170
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_; }
174
175   // Called after all instructions have been inserted.
176   void WireBlocks();
177
178  private:
179   VReg NewReg() { return VReg(sequence()->NextVirtualRegister()); }
180
181   static TestOperand Invalid() { return TestOperand(kInvalid, VReg()); }
182
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,
199                                  int index);
200   InstructionOperand Unallocated(TestOperand op,
201                                  UnallocatedOperand::BasicPolicy policy,
202                                  int index);
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);
208
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);
214
215   Instruction* AddInstruction(Instruction* instruction);
216
217   struct LoopData {
218     Rpo loop_header_;
219     int expected_blocks_;
220   };
221
222   typedef std::vector<LoopData> LoopBlocks;
223   typedef std::map<int, const Instruction*> Instructions;
224   typedef std::vector<BlockCompletion> Completions;
225
226   SmartPointer<RegisterConfiguration> config_;
227   InstructionSequence* sequence_;
228   int num_general_registers_;
229   int num_double_registers_;
230
231   // Block building state.
232   InstructionBlocks instruction_blocks_;
233   Instructions instructions_;
234   Completions completions_;
235   LoopBlocks loop_blocks_;
236   InstructionBlock* current_block_;
237   bool block_returns_;
238 };
239
240 }  // namespace compiler
241 }  // namespace internal
242 }  // namespace v8
243
244 #endif  // V8_UNITTESTS_COMPILER_INSTRUCTION_SEQUENCE_UNITTEST_H_