153 {
154 public:
155 MatchCode(MatchOpCode opcode)
156 : opcode_(opcode), capture_(nullptr) {}
157
158 MatchCode(MatchOpCode opcode, Instruction** capture)
159 : opcode_(opcode), capture_(capture) {}
160
161#define DEFINE_TYPED_CONSTRUCTOR(Type, ignored) \
162 MatchCode(MatchOpCode opcode, Type##Instr** capture) \
163 : opcode_(opcode), capture_(reinterpret_cast<Instruction**>(capture)) { \
164 RELEASE_ASSERT(opcode == kMatch##Type || opcode == kMatchAndMove##Type); \
165 }
168#undef DEFINE_TYPED_CONSTRUCTOR
169
171
172 private:
173 friend class ILMatcher;
174
176 Instruction** capture_;
177};
178
180
182
183
184
185
187};
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207class ILMatcher : public ValueObject {
208 public:
209 ILMatcher(FlowGraph* flow_graph,
210 Instruction* cursor,
211 bool trace = true,
212 ParallelMovesHandling parallel_moves_handling =
213 ParallelMovesHandling::kDefault)
214 : flow_graph_(flow_graph),
215 cursor_(cursor),
216 parallel_moves_handling_(parallel_moves_handling),
217
219 trace_(trace) {}
220#else
221 trace_(false) {}
222#endif
223
224
225 Instruction*
value() {
return cursor_; }
226
227
228
229
230
231
232
233
234 bool TryMatch(std::initializer_list<MatchCode> match_codes,
235 MatchOpCode insert_before = kInvalidMatchOpCode);
236
237 private:
238 Instruction* MatchInternal(std::vector<MatchCode> match_codes,
239 size_t i,
240 Instruction* cursor);
241
242 const char* MatchOpCodeToCString(MatchOpCode code);
243
244 FlowGraph* flow_graph_;
245 Instruction* cursor_;
247 bool trace_;
248};
249
250#if !defined(PRODUCT)
251#define ENTITY_TOCSTRING(v) ((v)->ToCString())
252#else
253#define ENTITY_TOCSTRING(v) "<?>"
254#endif
255
256
257
258
259
260
261#define EXPECT_PROPERTY(entity, property) \
262 do { \
263 auto& it = *entity; \
264 if (!(property)) { \
265 dart::Expect(__FILE__, __LINE__) \
266 .Fail("expected " #property " for " #entity " which is %s.\n", \
267 ENTITY_TOCSTRING(entity)); \
268 } \
269 } while (0)
270
271class FlowGraphBuilderHelper {
272 public:
273 explicit FlowGraphBuilderHelper(intptr_t num_parameters = 0)
274 : state_(CompilerState::Current()),
275 flow_graph_(MakeDummyGraph(Thread::Current(),
276 num_parameters,
277 state_.is_optimizing())) {
278 flow_graph_.CreateCommonConstants();
279 }
280
281 TargetEntryInstr* TargetEntry(intptr_t try_index = kInvalidTryIndex) const {
282 return new TargetEntryInstr(flow_graph_.allocate_block_id(), try_index,
283 state_.GetNextDeoptId());
284 }
285
286 JoinEntryInstr* JoinEntry(intptr_t try_index = kInvalidTryIndex) const {
287 return new JoinEntryInstr(flow_graph_.allocate_block_id(), try_index,
288 state_.GetNextDeoptId());
289 }
290
291 ConstantInstr* IntConstant(int64_t value) const {
292 return flow_graph_.GetConstant(
293 Integer::Handle(Integer::NewCanonical(value)));
294 }
295
296 ConstantInstr* DoubleConstant(double value) {
297 return flow_graph_.GetConstant(Double::Handle(Double::NewCanonical(value)));
298 }
299
300
301
302 void AddVariable(
const char*
name,
303 const AbstractType& static_type,
304 CompileType* inferred_arg_type = nullptr) {
305 LocalVariable* v =
306 new LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
307 String::Handle(Symbols::New(Thread::Current(),
name)),
308 static_type, LocalVariable::kNoKernelOffset,
309 new CompileType(CompileType::FromAbstractType(
310 static_type, CompileType::kCanBeNull,
311 CompileType::kCannotBeSentinel)),
312 inferred_arg_type);
313 v->set_type_check_mode(LocalVariable::kTypeCheckedByCaller);
314 flow_graph()->parsed_function().scope()->AddVariable(v);
315 }
316
317 enum class IncomingDefKind {
318 kImmediate,
319 kDelayed,
320 };
321
322 class IncomingDef {
323 public:
324 IncomingDef(BlockEntryInstr* from, Definition* defn)
325 : kind_(IncomingDefKind::kImmediate), from_(from), defn_(defn) {}
326
327 template <
typename T,
328 typename = typename std::enable_if<
329 std::is_base_of<Definition, T>::value>
::type>
330 IncomingDef(BlockEntryInstr* from,
T** defn_source)
331 : kind_(IncomingDefKind::kDelayed),
332 from_(from),
333 defn_source_(reinterpret_cast<Definition**>(defn_source)) {}
334
335 BlockEntryInstr* from() const { return from_; }
336 Definition* defn() const {
337 return kind_ == IncomingDefKind::kImmediate ? defn_ : *defn_source_;
338 }
339
340 private:
341 IncomingDefKind kind_;
342 BlockEntryInstr* from_;
343 union {
344 Definition* defn_;
345 Definition** defn_source_;
346 };
347 };
348
349 PhiInstr* Phi(JoinEntryInstr* join,
350 std::initializer_list<IncomingDef> incoming) {
351 auto phi = new PhiInstr(join, incoming.size());
352 for (size_t i = 0; i < incoming.size(); i++) {
353 auto input =
new Value(flow_graph_.constant_dead());
354 phi->SetInputAt(i, input);
355 input->definition()->AddInputUse(input);
356 }
357 for (auto def : incoming) {
358 pending_phis_.Add({phi, def});
359 }
360 return phi;
361 }
362
363 void FinishGraph() {
364 flow_graph_.DiscoverBlocks();
365 GrowableArray<BitVector*> dominance_frontier;
366 flow_graph_.ComputeDominators(&dominance_frontier);
367
368 for (auto& pending : pending_phis_) {
369 auto join = pending.phi->block();
370 EXPECT(pending.phi->InputCount() ==
join->PredecessorCount());
371 auto pred_index =
join->IndexOfPredecessor(pending.incoming.from());
373 pending.phi->InputAt(pred_index)->BindTo(pending.incoming.defn());
374 }
375 }
376
377 FlowGraph* flow_graph() { return &flow_graph_; }
378
379 private:
380 static FlowGraph& MakeDummyGraph(Thread* thread,
381 intptr_t num_parameters,
382 bool is_optimizing) {
383 const FunctionType& signature =
384 FunctionType::ZoneHandle(FunctionType::New());
385 signature.set_num_fixed_parameters(num_parameters);
386 const Function& func = Function::ZoneHandle(Function::New(
387 signature, String::Handle(Symbols::New(thread, "dummy")),
388 UntaggedFunction::kRegularFunction,
389 true,
390 false,
391 false,
392 false,
393 true,
394 Class::Handle(thread->isolate_group()->object_store()->object_class()),
395 TokenPosition::kNoSource));
396
397 Zone* zone = thread->zone();
398 ParsedFunction* parsed_function = new (zone) ParsedFunction(thread, func);
399
400 parsed_function->set_scope(new LocalScope(nullptr, 0, 0));
401
402 auto graph_entry =
403 new GraphEntryInstr(*parsed_function, Compiler::kNoOSRDeoptId);
404
405 const intptr_t block_id = 1;
406 graph_entry->set_normal_entry(
407 new FunctionEntryInstr(graph_entry, block_id, kInvalidTryIndex,
408 CompilerState::Current().GetNextDeoptId()));
409 return *new FlowGraph(*parsed_function, graph_entry, block_id,
410 PrologueInfo{-1, -1},
411 FlowGraph::CompilationModeFrom(is_optimizing));
412 }
413
414 CompilerState& state_;
415 FlowGraph& flow_graph_;
416
417 struct PendingPhiInput {
418 PhiInstr* phi;
419 IncomingDef incoming;
420 };
421 GrowableArray<PendingPhiInput> pending_phis_;
422};
423
424}
425
426#endif
#define FOR_EACH_INSTRUCTION(M)
#define FOR_EACH_ABSTRACT_INSTRUCTION(M)
#define DEFINE_TYPED_CONSTRUCTOR(Type, ignored)
SINT Vec< 2 *N, T > join(const Vec< N, T > &lo, const Vec< N, T > &hi)