blob: eff6d4a931697894ea6cac5c26b0f7a23b2d2bd7 [file] [log] [blame]
Ben Murdoch097c5b22016-05-18 11:27:45 +01001// Copyright 2016 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#include "src/compiler/int64-lowering.h"
6#include "src/compiler/common-operator.h"
7#include "src/compiler/linkage.h"
8#include "src/compiler/machine-operator.h"
9#include "src/compiler/node.h"
10
11#include "src/compiler/node-properties.h"
12
13#include "src/signature.h"
14
15#include "src/wasm/wasm-module.h"
16
17#include "test/unittests/compiler/graph-unittest.h"
18#include "test/unittests/compiler/node-test-utils.h"
19#include "testing/gmock-support.h"
20
21using testing::AllOf;
22using testing::Capture;
23using testing::CaptureEq;
24
25namespace v8 {
26namespace internal {
27namespace compiler {
28
29class Int64LoweringTest : public GraphTest {
30 public:
31 Int64LoweringTest() : GraphTest(), machine_(zone()) {
32 value_[0] = 0x1234567890abcdef;
33 value_[1] = 0x1edcba098765432f;
34 value_[2] = 0x1133557799886644;
35 }
36
37 MachineOperatorBuilder* machine() { return &machine_; }
38
39 void LowerGraph(Node* node, Signature<MachineRepresentation>* signature) {
40 Node* ret = graph()->NewNode(common()->Return(), node, graph()->start(),
41 graph()->start());
42 NodeProperties::MergeControlToEnd(graph(), common(), ret);
43
44 Int64Lowering lowering(graph(), machine(), common(), zone(), signature);
45 lowering.LowerGraph();
46 }
47
48 void LowerGraph(Node* node, MachineRepresentation return_type,
49 MachineRepresentation rep = MachineRepresentation::kWord32,
50 int num_params = 0) {
51 Signature<MachineRepresentation>::Builder sig_builder(zone(), 1,
52 num_params);
53 sig_builder.AddReturn(return_type);
54 for (int i = 0; i < num_params; i++) {
55 sig_builder.AddParam(rep);
56 }
57 LowerGraph(node, sig_builder.Build());
58 }
59
60 void CompareCallDescriptors(const CallDescriptor* lhs,
61 const CallDescriptor* rhs) {
62 EXPECT_THAT(lhs->CalleeSavedFPRegisters(), rhs->CalleeSavedFPRegisters());
63 EXPECT_THAT(lhs->CalleeSavedRegisters(), rhs->CalleeSavedRegisters());
64 EXPECT_THAT(lhs->FrameStateCount(), rhs->FrameStateCount());
65 EXPECT_THAT(lhs->InputCount(), rhs->InputCount());
66 for (size_t i = 0; i < lhs->InputCount(); i++) {
67 EXPECT_THAT(lhs->GetInputLocation(i), rhs->GetInputLocation(i));
68 EXPECT_THAT(lhs->GetInputType(i), rhs->GetInputType(i));
69 }
70 EXPECT_THAT(lhs->ReturnCount(), rhs->ReturnCount());
71 for (size_t i = 0; i < lhs->ReturnCount(); i++) {
72 EXPECT_THAT(lhs->GetReturnLocation(i), rhs->GetReturnLocation(i));
73 EXPECT_THAT(lhs->GetReturnType(i), rhs->GetReturnType(i));
74 }
75 EXPECT_THAT(lhs->flags(), rhs->flags());
76 EXPECT_THAT(lhs->kind(), rhs->kind());
77 }
78
79 int64_t value(int i) { return value_[i]; }
80
81 int32_t low_word_value(int i) {
82 return static_cast<int32_t>(value_[i] & 0xffffffff);
83 }
84
85 int32_t high_word_value(int i) {
86 return static_cast<int32_t>(value_[i] >> 32);
87 }
88
89 private:
90 MachineOperatorBuilder machine_;
91 int64_t value_[3];
92};
93
94TEST_F(Int64LoweringTest, Int64Constant) {
95 if (4 != kPointerSize) return;
96
97 LowerGraph(Int64Constant(value(0)), MachineRepresentation::kWord64);
98 EXPECT_THAT(graph()->end()->InputAt(1),
99 IsReturn2(IsInt32Constant(low_word_value(0)),
100 IsInt32Constant(high_word_value(0)), start(), start()));
101}
102
103TEST_F(Int64LoweringTest, Int64Load) {
104 if (4 != kPointerSize) return;
105
106 int32_t base = 0x1234;
107 int32_t index = 0x5678;
108
109 LowerGraph(graph()->NewNode(machine()->Load(MachineType::Int64()),
110 Int32Constant(base), Int32Constant(index),
111 start(), start()),
112 MachineRepresentation::kWord64);
113
114 Capture<Node*> high_word_load;
115 Matcher<Node*> high_word_load_matcher =
116 IsLoad(MachineType::Int32(), IsInt32Constant(base),
117 IsInt32Add(IsInt32Constant(index), IsInt32Constant(0x4)), start(),
118 start());
119
120 EXPECT_THAT(
121 graph()->end()->InputAt(1),
122 IsReturn2(IsLoad(MachineType::Int32(), IsInt32Constant(base),
123 IsInt32Constant(index), AllOf(CaptureEq(&high_word_load),
124 high_word_load_matcher),
125 start()),
126 AllOf(CaptureEq(&high_word_load), high_word_load_matcher),
127 start(), start()));
128}
129
130TEST_F(Int64LoweringTest, Int64Store) {
131 if (4 != kPointerSize) return;
132
133 // We have to build the TF graph explicitly here because Store does not return
134 // a value.
135
136 int32_t base = 1111;
137 int32_t index = 2222;
138 int32_t return_value = 0x5555;
139
140 Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 0);
141 sig_builder.AddReturn(MachineRepresentation::kWord32);
142
143 Node* store = graph()->NewNode(
144 machine()->Store(StoreRepresentation(MachineRepresentation::kWord64,
145 WriteBarrierKind::kNoWriteBarrier)),
146 Int32Constant(base), Int32Constant(index), Int64Constant(value(0)),
147 start(), start());
148
149 Node* ret = graph()->NewNode(common()->Return(), Int32Constant(return_value),
150 store, start());
151
152 NodeProperties::MergeControlToEnd(graph(), common(), ret);
153
154 Int64Lowering lowering(graph(), machine(), common(), zone(),
155 sig_builder.Build());
156 lowering.LowerGraph();
157
158 const StoreRepresentation rep(MachineRepresentation::kWord32,
159 kNoWriteBarrier);
160
161 EXPECT_THAT(
162 graph()->end()->InputAt(1),
163 IsReturn(
164 IsInt32Constant(return_value),
165 IsStore(
166 rep, IsInt32Constant(base), IsInt32Constant(index),
167 IsInt32Constant(low_word_value(0)),
168 IsStore(rep, IsInt32Constant(base),
169 IsInt32Add(IsInt32Constant(index), IsInt32Constant(4)),
170 IsInt32Constant(high_word_value(0)), start(), start()),
171 start()),
172 start()));
173}
174
175TEST_F(Int64LoweringTest, Int64And) {
176 if (4 != kPointerSize) return;
177
178 LowerGraph(graph()->NewNode(machine()->Word64And(), Int64Constant(value(0)),
179 Int64Constant(value(1))),
180 MachineRepresentation::kWord64);
181 EXPECT_THAT(graph()->end()->InputAt(1),
182 IsReturn2(IsWord32And(IsInt32Constant(low_word_value(0)),
183 IsInt32Constant(low_word_value(1))),
184 IsWord32And(IsInt32Constant(high_word_value(0)),
185 IsInt32Constant(high_word_value(1))),
186 start(), start()));
187}
188
189TEST_F(Int64LoweringTest, TruncateInt64ToInt32) {
190 if (4 != kPointerSize) return;
191
192 LowerGraph(graph()->NewNode(machine()->TruncateInt64ToInt32(),
193 Int64Constant(value(0))),
194 MachineRepresentation::kWord32);
195 EXPECT_THAT(graph()->end()->InputAt(1),
196 IsReturn(IsInt32Constant(low_word_value(0)), start(), start()));
197}
198
199TEST_F(Int64LoweringTest, Parameter) {
200 if (4 != kPointerSize) return;
201
202 LowerGraph(Parameter(0), MachineRepresentation::kWord64,
203 MachineRepresentation::kWord64, 1);
204
205 EXPECT_THAT(graph()->end()->InputAt(1),
206 IsReturn2(IsParameter(0), IsParameter(1), start(), start()));
207}
208
209TEST_F(Int64LoweringTest, Parameter2) {
210 if (4 != kPointerSize) return;
211
212 Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 5);
213 sig_builder.AddReturn(MachineRepresentation::kWord32);
214
215 sig_builder.AddParam(MachineRepresentation::kWord32);
216 sig_builder.AddParam(MachineRepresentation::kWord64);
217 sig_builder.AddParam(MachineRepresentation::kFloat64);
218 sig_builder.AddParam(MachineRepresentation::kWord64);
219 sig_builder.AddParam(MachineRepresentation::kWord32);
220
221 int start_parameter = start()->op()->ValueOutputCount();
222 LowerGraph(Parameter(4), sig_builder.Build());
223
224 EXPECT_THAT(graph()->end()->InputAt(1),
225 IsReturn(IsParameter(6), start(), start()));
226 // The parameter of the start node should increase by 2, because we lowered
227 // two parameter nodes.
228 EXPECT_THAT(start()->op()->ValueOutputCount(), start_parameter + 2);
229}
230
231TEST_F(Int64LoweringTest, CallI64Return) {
232 if (4 != kPointerSize) return;
233
234 int32_t function = 0x9999;
235
236 Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 0);
237 sig_builder.AddReturn(MachineRepresentation::kWord64);
238
239 compiler::CallDescriptor* desc =
240 wasm::ModuleEnv::GetWasmCallDescriptor(zone(), sig_builder.Build());
241
242 LowerGraph(graph()->NewNode(common()->Call(desc), Int32Constant(function),
243 start(), start()),
244 MachineRepresentation::kWord64);
245
246 Capture<Node*> call;
247 Matcher<Node*> call_matcher =
248 IsCall(testing::_, IsInt32Constant(function), start(), start());
249
250 EXPECT_THAT(graph()->end()->InputAt(1),
251 IsReturn2(IsProjection(0, AllOf(CaptureEq(&call), call_matcher)),
252 IsProjection(1, AllOf(CaptureEq(&call), call_matcher)),
253 start(), start()));
254
255 CompareCallDescriptors(
256 OpParameter<const CallDescriptor*>(
257 graph()->end()->InputAt(1)->InputAt(0)->InputAt(0)),
258 wasm::ModuleEnv::GetI32WasmCallDescriptor(zone(), desc));
259}
260
261TEST_F(Int64LoweringTest, CallI64Parameter) {
262 if (4 != kPointerSize) return;
263
264 int32_t function = 0x9999;
265
266 Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 3);
267 sig_builder.AddReturn(MachineRepresentation::kWord32);
268 sig_builder.AddParam(MachineRepresentation::kWord64);
269 sig_builder.AddParam(MachineRepresentation::kWord32);
270 sig_builder.AddParam(MachineRepresentation::kWord64);
271
272 compiler::CallDescriptor* desc =
273 wasm::ModuleEnv::GetWasmCallDescriptor(zone(), sig_builder.Build());
274
275 LowerGraph(graph()->NewNode(common()->Call(desc), Int32Constant(function),
276 Int64Constant(value(0)),
277 Int32Constant(low_word_value(1)),
278 Int64Constant(value(2)), start(), start()),
279 MachineRepresentation::kWord32);
280
281 EXPECT_THAT(
282 graph()->end()->InputAt(1),
283 IsReturn(IsCall(testing::_, IsInt32Constant(function),
284 IsInt32Constant(low_word_value(0)),
285 IsInt32Constant(high_word_value(0)),
286 IsInt32Constant(low_word_value(1)),
287 IsInt32Constant(low_word_value(2)),
288 IsInt32Constant(high_word_value(2)), start(), start()),
289 start(), start()));
290
291 CompareCallDescriptors(
292 OpParameter<const CallDescriptor*>(
293 graph()->end()->InputAt(1)->InputAt(0)),
294 wasm::ModuleEnv::GetI32WasmCallDescriptor(zone(), desc));
295}
296
297} // namespace compiler
298} // namespace internal
299} // namespace v8