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