1// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/compiler/backend/locations_helpers.h"
6#include "vm/dart_api_impl.h"
7#include "vm/dart_entry.h"
8#include "vm/unit_test.h"
9
10namespace dart {
11
12#define Reg(index) (static_cast<Register>(index))
13#define Fpu(index) (static_cast<FpuRegister>(index))
14
15#define ReqReg Location::RequiresRegister()
16#define ReqFpu Location::RequiresFpuRegister()
17#define RegLoc(index) Location::RegisterLocation(Reg(index))
18#define FpuLoc(index) Location::FpuRegisterLocation(Fpu(index))
19
20typedef ZoneGrowableArray<Location> LocationArray;
21
22static LocationArray* MakeLocationArray() {
23 LocationArray* arr = new LocationArray();
24 return arr;
25}
26
27static LocationArray* MakeLocationArray(Location loc0) {
28 LocationArray* arr = new LocationArray();
29 arr->Add(loc0);
30 return arr;
31}
32
33static LocationArray* MakeLocationArray(Location loc0, Location loc1) {
34 LocationArray* arr = new LocationArray();
35 arr->Add(loc0);
36 arr->Add(loc1);
37 return arr;
38}
39
40static void ValidateSummary(LocationSummary* locs,
41 Location expected_output,
42 const LocationArray* expected_inputs,
43 const LocationArray* expected_temps) {
44 EXPECT(locs->out(0).Equals(expected_output));
45 EXPECT_EQ(expected_inputs->length(), locs->input_count());
46 for (intptr_t i = 0; i < expected_inputs->length(); i++) {
47 EXPECT(locs->in(i).Equals(expected_inputs->At(i)));
48 }
49 EXPECT_EQ(expected_temps->length(), locs->temp_count());
50 for (intptr_t i = 0; i < expected_temps->length(); i++) {
51 EXPECT(locs->temp(i).Equals(expected_temps->At(i)));
52 }
53}
54
55static void FillSummary(LocationSummary* locs,
56 Location expected_output,
57 const LocationArray* expected_inputs,
58 const LocationArray* expected_temps) {
59 locs->set_out(0, expected_output);
60 for (intptr_t i = 0; i < expected_inputs->length(); i++) {
61 locs->set_in(i, expected_inputs->At(i));
62 }
63 for (intptr_t i = 0; i < expected_temps->length(); i++) {
64 locs->set_temp(i, expected_temps->At(i));
65 }
66}
67
68class MockInstruction : public ZoneAllocated {
69 public:
70 virtual ~MockInstruction() {}
71
72 LocationSummary* locs() {
73 if (locs_ == NULL) {
74 locs_ = MakeLocationSummary(Thread::Current()->zone(), false);
75 }
76 return locs_;
77 }
78
79 virtual LocationSummary* MakeLocationSummary(Zone* zone, bool opt) const = 0;
80 virtual void EmitNativeCode(FlowGraphCompiler* compiler) = 0;
81
82 private:
83 LocationSummary* locs_;
84};
85
86#define INSTRUCTION_TEST(Name, Arity, Signature, ExpectedOut, ExpectedIn, \
87 ExpectedTemp, AllocatedOut, AllocatedIn, \
88 AllocatedTemp) \
89 class Name##Instr : public MockInstruction { \
90 public: \
91 LocationSummary* MakeLocationSummary(Zone* zone, bool opt) const; \
92 void EmitNativeCode(FlowGraphCompiler* compiler); \
93 virtual intptr_t InputCount() const { return Arity; } \
94 }; \
95 TEST_CASE(LocationsHelpers_##Name) { \
96 const Location expected_out = ExpectedOut; \
97 const LocationArray* expected_inputs = MakeLocationArray ExpectedIn; \
98 const LocationArray* expected_temps = MakeLocationArray ExpectedTemp; \
99 \
100 const Location allocated_out = AllocatedOut; \
101 const LocationArray* allocated_inputs = MakeLocationArray AllocatedIn; \
102 const LocationArray* allocated_temps = MakeLocationArray AllocatedTemp; \
103 \
104 Name##Instr* instr = new Name##Instr(); \
105 LocationSummary* locs = instr->locs(); \
106 \
107 ValidateSummary(locs, expected_out, expected_inputs, expected_temps); \
108 FillSummary(locs, allocated_out, allocated_inputs, allocated_temps); \
109 \
110 instr->EmitNativeCode(NULL); \
111 } \
112 DEFINE_BACKEND(Name, Signature)
113
114// Reg -> Reg
115INSTRUCTION_TEST(Unary,
116 1,
117 (Register out, Register in),
118 ReqReg,
119 (ReqReg),
120 (),
121 RegLoc(0),
122 (RegLoc(1)),
123 ()) {
124 EXPECT_EQ(Reg(0), out);
125 EXPECT_EQ(Reg(1), in);
126}
127
128// (Reg, Fpu) -> Reg
129INSTRUCTION_TEST(Binary1,
130 2,
131 (Register out, Register in0, FpuRegister in1),
132 ReqReg,
133 (ReqReg, Location::RequiresFpuRegister()),
134 (),
135 RegLoc(0),
136 (RegLoc(1), FpuLoc(2)),
137 ()) {
138 EXPECT_EQ(Reg(0), out);
139 EXPECT_EQ(Reg(1), in0);
140 EXPECT_EQ(Fpu(2), in1);
141}
142
143// (Fpu, Reg) -> Reg
144INSTRUCTION_TEST(Binary2,
145 2,
146 (Register out, FpuRegister in0, Register in1),
147 ReqReg,
148 (ReqFpu, ReqReg),
149 (),
150 RegLoc(0),
151 (FpuLoc(1), RegLoc(2)),
152 ()) {
153 EXPECT_EQ(Reg(0), out);
154 EXPECT_EQ(Fpu(1), in0);
155 EXPECT_EQ(Reg(2), in1);
156}
157
158// -> Reg(3)
159INSTRUCTION_TEST(FixedOutput,
160 0,
161 (Fixed<Register, Reg(3)> out),
162 RegLoc(3),
163 (),
164 (),
165 RegLoc(3),
166 (),
167 ()) {
168 EXPECT_EQ(Reg(3), Reg(out));
169}
170
171// Fpu(3) -> Fpu
172INSTRUCTION_TEST(FixedInput,
173 1,
174 (FpuRegister out, Fixed<FpuRegister, Fpu(3)> in),
175 ReqFpu,
176 (FpuLoc(3)),
177 (),
178 FpuLoc(0),
179 (FpuLoc(3)),
180 ()) {
181 EXPECT_EQ(Fpu(0), out);
182 EXPECT_EQ(Fpu(3), Fpu(in));
183}
184
185// Reg -> SameAsFirstInput
186INSTRUCTION_TEST(SameAsFirstInput,
187 2,
188 (SameAsFirstInput, Register in0, Register in1),
189 Location::SameAsFirstInput(),
190 (ReqReg, ReqReg),
191 (),
192 RegLoc(0),
193 (RegLoc(0), RegLoc(1)),
194 ()) {
195 EXPECT_EQ(Reg(0), in0);
196 EXPECT_EQ(Reg(1), in1);
197}
198
199// {Temps: Fpu, Reg} (Reg, Fpu) -> Reg
200INSTRUCTION_TEST(Temps,
201 2,
202 (Register out,
203 Register in0,
204 FpuRegister in1,
205 Temp<FpuRegister> temp0,
206 Temp<Register> temp1),
207 ReqReg,
208 (ReqReg, ReqFpu),
209 (ReqFpu, ReqReg),
210 RegLoc(0),
211 (RegLoc(1), FpuLoc(2)),
212 (FpuLoc(3), RegLoc(4))) {
213 EXPECT_EQ(Reg(0), out);
214 EXPECT_EQ(Reg(1), in0);
215 EXPECT_EQ(Fpu(2), in1);
216 EXPECT_EQ(Fpu(3), Fpu(temp0));
217 EXPECT_EQ(Reg(4), Reg(temp1));
218}
219
220// {Temps: Fpu(3)} -> Fpu
221INSTRUCTION_TEST(FixedTemp,
222 0,
223 (FpuRegister out, Temp<Fixed<FpuRegister, Fpu(3)> > temp),
224 ReqFpu,
225 (),
226 (FpuLoc(3)),
227 FpuLoc(4),
228 (),
229 (FpuLoc(3))) {
230 EXPECT_EQ(Fpu(4), out);
231 EXPECT_EQ(Fpu(3), Fpu(temp));
232}
233
234} // namespace dart
235