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