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_CCTEST_COMPILER_INSTRUCTION_SELECTOR_TEST_H_ 6#define V8_CCTEST_COMPILER_INSTRUCTION_SELECTOR_TEST_H_ 7 8#include <deque> 9#include <set> 10 11#include "src/compiler/instruction-selector.h" 12#include "src/compiler/raw-machine-assembler.h" 13#include "src/ostreams.h" 14#include "test/cctest/cctest.h" 15 16namespace v8 { 17namespace internal { 18namespace compiler { 19 20typedef std::set<int> VirtualRegisterSet; 21 22enum InstructionSelectorTesterMode { kTargetMode, kInternalMode }; 23 24class InstructionSelectorTester : public HandleAndZoneScope, 25 public RawMachineAssembler { 26 public: 27 enum Mode { kTargetMode, kInternalMode }; 28 29 static const int kParameterCount = 3; 30 static MachineType* BuildParameterArray(Zone* zone) { 31 MachineType* array = zone->NewArray<MachineType>(kParameterCount); 32 for (int i = 0; i < kParameterCount; ++i) { 33 array[i] = kMachInt32; 34 } 35 return array; 36 } 37 38 InstructionSelectorTester() 39 : RawMachineAssembler( 40 new (main_zone()) Graph(main_zone()), 41 new (main_zone()) MachineCallDescriptorBuilder( 42 kMachInt32, kParameterCount, BuildParameterArray(main_zone())), 43 kMachPtr) {} 44 45 void SelectInstructions(CpuFeature feature) { 46 SelectInstructions(InstructionSelector::Features(feature)); 47 } 48 49 void SelectInstructions(CpuFeature feature1, CpuFeature feature2) { 50 SelectInstructions(InstructionSelector::Features(feature1, feature2)); 51 } 52 53 void SelectInstructions(Mode mode = kTargetMode) { 54 SelectInstructions(InstructionSelector::Features(), mode); 55 } 56 57 void SelectInstructions(InstructionSelector::Features features, 58 Mode mode = kTargetMode) { 59 OFStream out(stdout); 60 Schedule* schedule = Export(); 61 CHECK_NE(0, graph()->NodeCount()); 62 CompilationInfo info(main_isolate(), main_zone()); 63 Linkage linkage(&info, call_descriptor()); 64 InstructionSequence sequence(&linkage, graph(), schedule); 65 SourcePositionTable source_positions(graph()); 66 InstructionSelector selector(&sequence, &source_positions, features); 67 selector.SelectInstructions(); 68 out << "--- Code sequence after instruction selection --- " << endl 69 << sequence; 70 for (InstructionSequence::const_iterator i = sequence.begin(); 71 i != sequence.end(); ++i) { 72 Instruction* instr = *i; 73 if (instr->opcode() < 0) continue; 74 if (mode == kTargetMode) { 75 switch (ArchOpcodeField::decode(instr->opcode())) { 76#define CASE(Name) \ 77 case k##Name: \ 78 break; 79 TARGET_ARCH_OPCODE_LIST(CASE) 80#undef CASE 81 default: 82 continue; 83 } 84 } 85 code.push_back(instr); 86 } 87 for (int vreg = 0; vreg < sequence.VirtualRegisterCount(); ++vreg) { 88 if (sequence.IsDouble(vreg)) { 89 CHECK(!sequence.IsReference(vreg)); 90 doubles.insert(vreg); 91 } 92 if (sequence.IsReference(vreg)) { 93 CHECK(!sequence.IsDouble(vreg)); 94 references.insert(vreg); 95 } 96 } 97 immediates.assign(sequence.immediates().begin(), 98 sequence.immediates().end()); 99 } 100 101 int32_t ToInt32(const InstructionOperand* operand) const { 102 size_t i = operand->index(); 103 CHECK(i < immediates.size()); 104 CHECK_EQ(InstructionOperand::IMMEDIATE, operand->kind()); 105 return immediates[i].ToInt32(); 106 } 107 108 std::deque<Instruction*> code; 109 VirtualRegisterSet doubles; 110 VirtualRegisterSet references; 111 std::deque<Constant> immediates; 112}; 113 114 115static inline void CheckSameVreg(InstructionOperand* exp, 116 InstructionOperand* val) { 117 CHECK_EQ(InstructionOperand::UNALLOCATED, exp->kind()); 118 CHECK_EQ(InstructionOperand::UNALLOCATED, val->kind()); 119 CHECK_EQ(UnallocatedOperand::cast(exp)->virtual_register(), 120 UnallocatedOperand::cast(val)->virtual_register()); 121} 122 123} // namespace compiler 124} // namespace internal 125} // namespace v8 126 127#endif // V8_CCTEST_COMPILER_INSTRUCTION_SELECTOR_TEST_H_ 128