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