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 = 8; 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 kExplicit, 40 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 61 static TestOperand ExplicitReg(int index) { 62 TestOperandType type = kExplicit; 63 return TestOperand(type, VReg(), index); 64 } 65 66 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(); 135 void StartBlock(bool deferred = false); 136 Instruction* EndBlock(BlockCompletion completion = FallThrough()); 137 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 142 Instruction* Return(TestOperand input_op_0); 143 Instruction* Return(VReg vreg) { return Return(Reg(vreg, 0)); } 144 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()); 149 PhiInstruction* Phi(VReg incoming_vreg_0, size_t input_count); 150 void SetInput(PhiInstruction* phi, size_t input, VReg vreg); 151 152 VReg DefineConstant(int32_t imm = 0); 153 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()); 159 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()); 164 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()); 171 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 177 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()); } 186 187 static TestOperand Invalid() { return TestOperand(kInvalid, VReg()); } 188 189 Instruction* EmitBranch(TestOperand input_op); 190 Instruction* EmitFallThrough(); 191 Instruction* EmitJump(); 192 Instruction* NewInstruction(InstructionCode code, size_t outputs_size, 193 InstructionOperand* outputs, 194 size_t inputs_size = 0, 195 InstructionOperand* inputs = nullptr, 196 size_t temps_size = 0, 197 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); 213 void WireBlock(size_t block_offset, int jump_offset); 214 215 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); 220 221 Instruction* AddInstruction(Instruction* instruction); 222 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 232 base::SmartPointer<RegisterConfiguration> config_; 233 InstructionSequence* sequence_; 234 int num_general_registers_; 235 int num_double_registers_; 236 237 // Block building state. 238 InstructionBlocks instruction_blocks_; 239 Instructions instructions_; 240 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_ 251