Line data Source code
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_GRAPH_BUILDER_TESTER_H_
6 : #define V8_CCTEST_COMPILER_GRAPH_BUILDER_TESTER_H_
7 :
8 : #include "src/compilation-info.h"
9 : #include "src/compiler/common-operator.h"
10 : #include "src/compiler/instruction-selector.h"
11 : #include "src/compiler/linkage.h"
12 : #include "src/compiler/machine-operator.h"
13 : #include "src/compiler/operator-properties.h"
14 : #include "src/compiler/pipeline.h"
15 : #include "src/compiler/simplified-operator.h"
16 : #include "test/cctest/cctest.h"
17 : #include "test/cctest/compiler/call-tester.h"
18 :
19 : namespace v8 {
20 : namespace internal {
21 : namespace compiler {
22 :
23 : class GraphAndBuilders {
24 : public:
25 97100 : explicit GraphAndBuilders(Zone* zone)
26 97100 : : main_graph_(new (zone) Graph(zone)),
27 : main_common_(zone),
28 : main_machine_(zone, MachineType::PointerRepresentation(),
29 : InstructionSelector::SupportedMachineOperatorFlags(),
30 : InstructionSelector::AlignmentRequirements()),
31 97100 : main_simplified_(zone) {}
32 :
33 : Graph* graph() const { return main_graph_; }
34 95579 : Zone* zone() const { return graph()->zone(); }
35 : CommonOperatorBuilder* common() { return &main_common_; }
36 : MachineOperatorBuilder* machine() { return &main_machine_; }
37 : SimplifiedOperatorBuilder* simplified() { return &main_simplified_; }
38 :
39 : protected:
40 : // Prefixed with main_ to avoid naming conflicts.
41 : Graph* main_graph_;
42 : CommonOperatorBuilder main_common_;
43 : MachineOperatorBuilder main_machine_;
44 : SimplifiedOperatorBuilder main_simplified_;
45 : };
46 :
47 :
48 : template <typename ReturnType>
49 : class GraphBuilderTester : public HandleAndZoneScope,
50 : public GraphAndBuilders,
51 : public CallHelper<ReturnType> {
52 : public:
53 10 : explicit GraphBuilderTester(MachineType p0 = MachineType::None(),
54 : MachineType p1 = MachineType::None(),
55 : MachineType p2 = MachineType::None(),
56 : MachineType p3 = MachineType::None(),
57 10 : MachineType p4 = MachineType::None())
58 : : GraphAndBuilders(main_zone()),
59 : CallHelper<ReturnType>(
60 : main_isolate(),
61 : CSignature::New(main_zone(), MachineTypeForC<ReturnType>(), p0, p1,
62 10 : p2, p3, p4)),
63 : effect_(nullptr),
64 : return_(nullptr),
65 50 : parameters_(main_zone()->template NewArray<Node*>(parameter_count())) {
66 10 : Begin(static_cast<int>(parameter_count()));
67 10 : InitParameters();
68 10 : }
69 15 : virtual ~GraphBuilderTester() {}
70 :
71 : void GenerateCode() { Generate(); }
72 : Node* Parameter(size_t index) {
73 : CHECK_LT(index, parameter_count());
74 : return parameters_[index];
75 : }
76 :
77 : Isolate* isolate() { return main_isolate(); }
78 : Factory* factory() { return isolate()->factory(); }
79 :
80 : // Initialize graph and builder.
81 10 : void Begin(int num_parameters) {
82 30 : CHECK_NULL(graph()->start());
83 10 : Node* start = graph()->NewNode(common()->Start(num_parameters + 3));
84 : graph()->SetStart(start);
85 10 : effect_ = start;
86 10 : }
87 :
88 10 : void Return(Node* value) {
89 30 : Node* zero = graph()->NewNode(common()->Int32Constant(0));
90 20 : return_ = graph()->NewNode(common()->Return(), zero, value, effect_,
91 : graph()->start());
92 10 : effect_ = nullptr;
93 10 : }
94 :
95 : // Close the graph.
96 10 : void End() {
97 20 : Node* end = graph()->NewNode(common()->End(1), return_);
98 : graph()->SetEnd(end);
99 10 : }
100 :
101 : Node* PointerConstant(void* value) {
102 : intptr_t intptr_value = reinterpret_cast<intptr_t>(value);
103 : return kPointerSize == 8 ? NewNode(common()->Int64Constant(intptr_value))
104 : : Int32Constant(static_cast<int>(intptr_value));
105 : }
106 10 : Node* Int32Constant(int32_t value) {
107 20 : return NewNode(common()->Int32Constant(value));
108 : }
109 : Node* HeapConstant(Handle<HeapObject> object) {
110 : return NewNode(common()->HeapConstant(object));
111 : }
112 :
113 : Node* BooleanNot(Node* a) { return NewNode(simplified()->BooleanNot(), a); }
114 :
115 : Node* NumberEqual(Node* a, Node* b) {
116 : return NewNode(simplified()->NumberEqual(), a, b);
117 : }
118 : Node* NumberLessThan(Node* a, Node* b) {
119 : return NewNode(simplified()->NumberLessThan(), a, b);
120 : }
121 : Node* NumberLessThanOrEqual(Node* a, Node* b) {
122 : return NewNode(simplified()->NumberLessThanOrEqual(), a, b);
123 : }
124 : Node* NumberAdd(Node* a, Node* b) {
125 : return NewNode(simplified()->NumberAdd(), a, b);
126 : }
127 : Node* NumberSubtract(Node* a, Node* b) {
128 : return NewNode(simplified()->NumberSubtract(), a, b);
129 : }
130 : Node* NumberMultiply(Node* a, Node* b) {
131 : return NewNode(simplified()->NumberMultiply(), a, b);
132 : }
133 : Node* NumberDivide(Node* a, Node* b) {
134 : return NewNode(simplified()->NumberDivide(), a, b);
135 : }
136 : Node* NumberModulus(Node* a, Node* b) {
137 : return NewNode(simplified()->NumberModulus(), a, b);
138 : }
139 : Node* NumberToInt32(Node* a) {
140 : return NewNode(simplified()->NumberToInt32(), a);
141 : }
142 : Node* NumberToUint32(Node* a) {
143 : return NewNode(simplified()->NumberToUint32(), a);
144 : }
145 :
146 : Node* StringEqual(Node* a, Node* b) {
147 : return NewNode(simplified()->StringEqual(), a, b);
148 : }
149 : Node* StringLessThan(Node* a, Node* b) {
150 : return NewNode(simplified()->StringLessThan(), a, b);
151 : }
152 : Node* StringLessThanOrEqual(Node* a, Node* b) {
153 : return NewNode(simplified()->StringLessThanOrEqual(), a, b);
154 : }
155 :
156 : Node* ChangeTaggedToInt32(Node* a) {
157 : return NewNode(simplified()->ChangeTaggedToInt32(), a);
158 : }
159 : Node* ChangeTaggedToUint32(Node* a) {
160 : return NewNode(simplified()->ChangeTaggedToUint32(), a);
161 : }
162 : Node* ChangeTaggedToFloat64(Node* a) {
163 : return NewNode(simplified()->ChangeTaggedToFloat64(), a);
164 : }
165 : Node* ChangeInt32ToTagged(Node* a) {
166 : return NewNode(simplified()->ChangeInt32ToTagged(), a);
167 : }
168 : Node* ChangeUint32ToTagged(Node* a) {
169 : return NewNode(simplified()->ChangeUint32ToTagged(), a);
170 : }
171 : Node* ChangeFloat64ToTagged(Node* a) {
172 : return NewNode(simplified()->ChangeFloat64ToTagged(), a);
173 : }
174 : Node* ChangeTaggedToBit(Node* a) {
175 : return NewNode(simplified()->ChangeTaggedToBit(), a);
176 : }
177 : Node* ChangeBitToTagged(Node* a) {
178 : return NewNode(simplified()->ChangeBitToTagged(), a);
179 : }
180 :
181 : Node* LoadField(const FieldAccess& access, Node* object) {
182 : return NewNode(simplified()->LoadField(access), object);
183 : }
184 : Node* StoreField(const FieldAccess& access, Node* object, Node* value) {
185 : return NewNode(simplified()->StoreField(access), object, value);
186 : }
187 : Node* LoadElement(const ElementAccess& access, Node* object, Node* index) {
188 : return NewNode(simplified()->LoadElement(access), object, index);
189 : }
190 : Node* StoreElement(const ElementAccess& access, Node* object, Node* index,
191 : Node* value) {
192 : return NewNode(simplified()->StoreElement(access), object, index, value);
193 : }
194 :
195 : Node* NewNode(const Operator* op) {
196 10 : return MakeNode(op, 0, static_cast<Node**>(nullptr));
197 : }
198 :
199 0 : Node* NewNode(const Operator* op, Node* n1) { return MakeNode(op, 1, &n1); }
200 :
201 : Node* NewNode(const Operator* op, Node* n1, Node* n2) {
202 : Node* buffer[] = {n1, n2};
203 : return MakeNode(op, arraysize(buffer), buffer);
204 : }
205 :
206 : Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3) {
207 : Node* buffer[] = {n1, n2, n3};
208 : return MakeNode(op, arraysize(buffer), buffer);
209 : }
210 :
211 : Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4) {
212 : Node* buffer[] = {n1, n2, n3, n4};
213 : return MakeNode(op, arraysize(buffer), buffer);
214 : }
215 :
216 : Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
217 : Node* n5) {
218 : Node* buffer[] = {n1, n2, n3, n4, n5};
219 : return MakeNode(op, arraysize(buffer), buffer);
220 : }
221 :
222 : Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
223 : Node* n5, Node* n6) {
224 : Node* nodes[] = {n1, n2, n3, n4, n5, n6};
225 : return MakeNode(op, arraysize(nodes), nodes);
226 : }
227 :
228 : Node* NewNode(const Operator* op, int value_input_count,
229 : Node** value_inputs) {
230 : return MakeNode(op, value_input_count, value_inputs);
231 : }
232 :
233 10 : Handle<Code> GetCode() {
234 10 : Generate();
235 10 : return code_.ToHandleChecked();
236 : }
237 :
238 : protected:
239 30 : Node* MakeNode(const Operator* op, int value_input_count,
240 : Node** value_inputs) {
241 10 : CHECK_EQ(op->ValueInputCount(), value_input_count);
242 :
243 10 : CHECK(!OperatorProperties::HasContextInput(op));
244 10 : CHECK(!OperatorProperties::HasFrameStateInput(op));
245 10 : bool has_control = op->ControlInputCount() == 1;
246 10 : bool has_effect = op->EffectInputCount() == 1;
247 :
248 10 : CHECK_LT(op->ControlInputCount(), 2);
249 10 : CHECK_LT(op->EffectInputCount(), 2);
250 :
251 : Node* result = nullptr;
252 10 : if (!has_control && !has_effect) {
253 10 : result = graph()->NewNode(op, value_input_count, value_inputs);
254 : } else {
255 : int input_count_with_deps = value_input_count;
256 0 : if (has_control) ++input_count_with_deps;
257 0 : if (has_effect) ++input_count_with_deps;
258 0 : Node** buffer = zone()->template NewArray<Node*>(input_count_with_deps);
259 0 : memcpy(buffer, value_inputs, kPointerSize * value_input_count);
260 0 : Node** current_input = buffer + value_input_count;
261 0 : if (has_effect) {
262 0 : *current_input++ = effect_;
263 : }
264 0 : if (has_control) {
265 0 : *current_input++ = graph()->start();
266 : }
267 0 : result = graph()->NewNode(op, input_count_with_deps, buffer);
268 0 : if (has_effect) {
269 0 : effect_ = result;
270 : }
271 : // This graph builder does not support control flow.
272 0 : CHECK_EQ(0, op->ControlOutputCount());
273 : }
274 :
275 10 : return result;
276 : }
277 :
278 10 : virtual byte* Generate() {
279 10 : if (code_.is_null()) {
280 20 : Zone* zone = graph()->zone();
281 : CallDescriptor* desc =
282 10 : Linkage::GetSimplifiedCDescriptor(zone, this->csig_);
283 : CompilationInfo info(ArrayVector("testing"), main_isolate(), main_zone(),
284 10 : Code::STUB);
285 10 : code_ = Pipeline::GenerateCodeForTesting(&info, desc, graph());
286 : #ifdef ENABLE_DISASSEMBLER
287 : if (!code_.is_null() && FLAG_print_opt_code) {
288 : OFStream os(stdout);
289 : code_.ToHandleChecked()->Disassemble("test code", os);
290 : }
291 : #endif
292 : }
293 10 : return code_.ToHandleChecked()->entry();
294 : }
295 :
296 10 : void InitParameters() {
297 10 : int param_count = static_cast<int>(parameter_count());
298 10 : for (int i = 0; i < param_count; ++i) {
299 0 : parameters_[i] = this->NewNode(common()->Parameter(i), graph()->start());
300 : }
301 10 : }
302 :
303 30 : size_t parameter_count() const { return this->csig_->parameter_count(); }
304 :
305 : private:
306 : Node* effect_;
307 : Node* return_;
308 : Node** parameters_;
309 : MaybeHandle<Code> code_;
310 : };
311 :
312 : } // namespace compiler
313 : } // namespace internal
314 : } // namespace v8
315 :
316 : #endif // V8_CCTEST_COMPILER_GRAPH_BUILDER_TESTER_H_
|