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