1//===- Nodes.cpp ----------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "mlir/Tools/PDLL/AST/Nodes.h"
10#include "mlir/Tools/PDLL/AST/Context.h"
11#include "llvm/ADT/SmallPtrSet.h"
12#include "llvm/ADT/TypeSwitch.h"
13#include <optional>
14
15using namespace mlir;
16using namespace mlir::pdll::ast;
17
18/// Copy a string reference into the context with a null terminator.
19static StringRef copyStringWithNull(Context &ctx, StringRef str) {
20 if (str.empty())
21 return str;
22
23 char *data = ctx.getAllocator().Allocate<char>(Num: str.size() + 1);
24 std::copy(first: str.begin(), last: str.end(), result: data);
25 data[str.size()] = 0;
26 return StringRef(data, str.size());
27}
28
29//===----------------------------------------------------------------------===//
30// Name
31//===----------------------------------------------------------------------===//
32
33const Name &Name::create(Context &ctx, StringRef name, SMRange location) {
34 return *new (ctx.getAllocator().Allocate<Name>())
35 Name(copyStringWithNull(ctx, str: name), location);
36}
37
38//===----------------------------------------------------------------------===//
39// Node
40//===----------------------------------------------------------------------===//
41
42namespace {
43class NodeVisitor {
44public:
45 explicit NodeVisitor(function_ref<void(const Node *)> visitFn)
46 : visitFn(visitFn) {}
47
48 void visit(const Node *node) {
49 if (!node || !alreadyVisited.insert(Ptr: node).second)
50 return;
51
52 visitFn(node);
53 TypeSwitch<const Node *>(node)
54 .Case<
55 // Statements.
56 const CompoundStmt, const EraseStmt, const LetStmt,
57 const ReplaceStmt, const ReturnStmt, const RewriteStmt,
58
59 // Expressions.
60 const AttributeExpr, const CallExpr, const DeclRefExpr,
61 const MemberAccessExpr, const OperationExpr, const RangeExpr,
62 const TupleExpr, const TypeExpr,
63
64 // Core Constraint Decls.
65 const AttrConstraintDecl, const OpConstraintDecl,
66 const TypeConstraintDecl, const TypeRangeConstraintDecl,
67 const ValueConstraintDecl, const ValueRangeConstraintDecl,
68
69 // Decls.
70 const NamedAttributeDecl, const OpNameDecl, const PatternDecl,
71 const UserConstraintDecl, const UserRewriteDecl, const VariableDecl,
72
73 const Module>(
74 caseFn: [&](auto derivedNode) { this->visitImpl(derivedNode); })
75 .Default(defaultFn: [](const Node *) { llvm_unreachable("unknown AST node"); });
76 }
77
78private:
79 void visitImpl(const CompoundStmt *stmt) {
80 for (const Node *child : stmt->getChildren())
81 visit(node: child);
82 }
83 void visitImpl(const EraseStmt *stmt) { visit(node: stmt->getRootOpExpr()); }
84 void visitImpl(const LetStmt *stmt) { visit(node: stmt->getVarDecl()); }
85 void visitImpl(const ReplaceStmt *stmt) {
86 visit(node: stmt->getRootOpExpr());
87 for (const Node *child : stmt->getReplExprs())
88 visit(node: child);
89 }
90 void visitImpl(const ReturnStmt *stmt) { visit(node: stmt->getResultExpr()); }
91 void visitImpl(const RewriteStmt *stmt) {
92 visit(node: stmt->getRootOpExpr());
93 visit(node: stmt->getRewriteBody());
94 }
95
96 void visitImpl(const AttributeExpr *expr) {}
97 void visitImpl(const CallExpr *expr) {
98 visit(node: expr->getCallableExpr());
99 for (const Node *child : expr->getArguments())
100 visit(node: child);
101 }
102 void visitImpl(const DeclRefExpr *expr) { visit(node: expr->getDecl()); }
103 void visitImpl(const MemberAccessExpr *expr) { visit(node: expr->getParentExpr()); }
104 void visitImpl(const OperationExpr *expr) {
105 visit(node: expr->getNameDecl());
106 for (const Node *child : expr->getOperands())
107 visit(node: child);
108 for (const Node *child : expr->getResultTypes())
109 visit(node: child);
110 for (const Node *child : expr->getAttributes())
111 visit(node: child);
112 }
113 void visitImpl(const RangeExpr *expr) {
114 for (const Node *child : expr->getElements())
115 visit(node: child);
116 }
117 void visitImpl(const TupleExpr *expr) {
118 for (const Node *child : expr->getElements())
119 visit(node: child);
120 }
121 void visitImpl(const TypeExpr *expr) {}
122
123 void visitImpl(const AttrConstraintDecl *decl) { visit(node: decl->getTypeExpr()); }
124 void visitImpl(const OpConstraintDecl *decl) { visit(node: decl->getNameDecl()); }
125 void visitImpl(const TypeConstraintDecl *decl) {}
126 void visitImpl(const TypeRangeConstraintDecl *decl) {}
127 void visitImpl(const ValueConstraintDecl *decl) {
128 visit(node: decl->getTypeExpr());
129 }
130 void visitImpl(const ValueRangeConstraintDecl *decl) {
131 visit(node: decl->getTypeExpr());
132 }
133
134 void visitImpl(const NamedAttributeDecl *decl) { visit(node: decl->getValue()); }
135 void visitImpl(const OpNameDecl *decl) {}
136 void visitImpl(const PatternDecl *decl) { visit(node: decl->getBody()); }
137 void visitImpl(const UserConstraintDecl *decl) {
138 for (const Node *child : decl->getInputs())
139 visit(node: child);
140 for (const Node *child : decl->getResults())
141 visit(node: child);
142 visit(node: decl->getBody());
143 }
144 void visitImpl(const UserRewriteDecl *decl) {
145 for (const Node *child : decl->getInputs())
146 visit(node: child);
147 for (const Node *child : decl->getResults())
148 visit(node: child);
149 visit(node: decl->getBody());
150 }
151 void visitImpl(const VariableDecl *decl) {
152 visit(node: decl->getInitExpr());
153 for (const ConstraintRef &child : decl->getConstraints())
154 visit(node: child.constraint);
155 }
156
157 void visitImpl(const Module *module) {
158 for (const Node *child : module->getChildren())
159 visit(node: child);
160 }
161
162 function_ref<void(const Node *)> visitFn;
163 SmallPtrSet<const Node *, 16> alreadyVisited;
164};
165} // namespace
166
167void Node::walk(function_ref<void(const Node *)> walkFn) const {
168 return NodeVisitor(walkFn).visit(node: this);
169}
170
171//===----------------------------------------------------------------------===//
172// DeclScope
173//===----------------------------------------------------------------------===//
174
175void DeclScope::add(Decl *decl) {
176 const Name *name = decl->getName();
177 assert(name && "expected a named decl");
178 assert(!decls.count(name->getName()) && "decl with this name already exists");
179 decls.try_emplace(Key: name->getName(), Args&: decl);
180}
181
182Decl *DeclScope::lookup(StringRef name) {
183 if (Decl *decl = decls.lookup(Key: name))
184 return decl;
185 return parent ? parent->lookup(name) : nullptr;
186}
187
188//===----------------------------------------------------------------------===//
189// CompoundStmt
190//===----------------------------------------------------------------------===//
191
192CompoundStmt *CompoundStmt::create(Context &ctx, SMRange loc,
193 ArrayRef<Stmt *> children) {
194 unsigned allocSize = CompoundStmt::totalSizeToAlloc<Stmt *>(Counts: children.size());
195 void *rawData = ctx.getAllocator().Allocate(Size: allocSize, Alignment: alignof(CompoundStmt));
196
197 CompoundStmt *stmt = new (rawData) CompoundStmt(loc, children.size());
198 std::uninitialized_copy(first: children.begin(), last: children.end(),
199 result: stmt->getChildren().begin());
200 return stmt;
201}
202
203//===----------------------------------------------------------------------===//
204// LetStmt
205//===----------------------------------------------------------------------===//
206
207LetStmt *LetStmt::create(Context &ctx, SMRange loc, VariableDecl *varDecl) {
208 return new (ctx.getAllocator().Allocate<LetStmt>()) LetStmt(loc, varDecl);
209}
210
211//===----------------------------------------------------------------------===//
212// OpRewriteStmt
213//===----------------------------------------------------------------------===//
214
215//===----------------------------------------------------------------------===//
216// EraseStmt
217
218EraseStmt *EraseStmt::create(Context &ctx, SMRange loc, Expr *rootOp) {
219 return new (ctx.getAllocator().Allocate<EraseStmt>()) EraseStmt(loc, rootOp);
220}
221
222//===----------------------------------------------------------------------===//
223// ReplaceStmt
224
225ReplaceStmt *ReplaceStmt::create(Context &ctx, SMRange loc, Expr *rootOp,
226 ArrayRef<Expr *> replExprs) {
227 unsigned allocSize = ReplaceStmt::totalSizeToAlloc<Expr *>(Counts: replExprs.size());
228 void *rawData = ctx.getAllocator().Allocate(Size: allocSize, Alignment: alignof(ReplaceStmt));
229
230 ReplaceStmt *stmt = new (rawData) ReplaceStmt(loc, rootOp, replExprs.size());
231 std::uninitialized_copy(first: replExprs.begin(), last: replExprs.end(),
232 result: stmt->getReplExprs().begin());
233 return stmt;
234}
235
236//===----------------------------------------------------------------------===//
237// RewriteStmt
238
239RewriteStmt *RewriteStmt::create(Context &ctx, SMRange loc, Expr *rootOp,
240 CompoundStmt *rewriteBody) {
241 return new (ctx.getAllocator().Allocate<RewriteStmt>())
242 RewriteStmt(loc, rootOp, rewriteBody);
243}
244
245//===----------------------------------------------------------------------===//
246// ReturnStmt
247//===----------------------------------------------------------------------===//
248
249ReturnStmt *ReturnStmt::create(Context &ctx, SMRange loc, Expr *resultExpr) {
250 return new (ctx.getAllocator().Allocate<ReturnStmt>())
251 ReturnStmt(loc, resultExpr);
252}
253
254//===----------------------------------------------------------------------===//
255// AttributeExpr
256//===----------------------------------------------------------------------===//
257
258AttributeExpr *AttributeExpr::create(Context &ctx, SMRange loc,
259 StringRef value) {
260 return new (ctx.getAllocator().Allocate<AttributeExpr>())
261 AttributeExpr(ctx, loc, copyStringWithNull(ctx, str: value));
262}
263
264//===----------------------------------------------------------------------===//
265// CallExpr
266//===----------------------------------------------------------------------===//
267
268CallExpr *CallExpr::create(Context &ctx, SMRange loc, Expr *callable,
269 ArrayRef<Expr *> arguments, Type resultType,
270 bool isNegated) {
271 unsigned allocSize = CallExpr::totalSizeToAlloc<Expr *>(Counts: arguments.size());
272 void *rawData = ctx.getAllocator().Allocate(Size: allocSize, Alignment: alignof(CallExpr));
273
274 CallExpr *expr = new (rawData)
275 CallExpr(loc, resultType, callable, arguments.size(), isNegated);
276 std::uninitialized_copy(first: arguments.begin(), last: arguments.end(),
277 result: expr->getArguments().begin());
278 return expr;
279}
280
281//===----------------------------------------------------------------------===//
282// DeclRefExpr
283//===----------------------------------------------------------------------===//
284
285DeclRefExpr *DeclRefExpr::create(Context &ctx, SMRange loc, Decl *decl,
286 Type type) {
287 return new (ctx.getAllocator().Allocate<DeclRefExpr>())
288 DeclRefExpr(loc, decl, type);
289}
290
291//===----------------------------------------------------------------------===//
292// MemberAccessExpr
293//===----------------------------------------------------------------------===//
294
295MemberAccessExpr *MemberAccessExpr::create(Context &ctx, SMRange loc,
296 const Expr *parentExpr,
297 StringRef memberName, Type type) {
298 return new (ctx.getAllocator().Allocate<MemberAccessExpr>()) MemberAccessExpr(
299 loc, parentExpr, memberName.copy(A&: ctx.getAllocator()), type);
300}
301
302//===----------------------------------------------------------------------===//
303// OperationExpr
304//===----------------------------------------------------------------------===//
305
306OperationExpr *
307OperationExpr::create(Context &ctx, SMRange loc, const ods::Operation *odsOp,
308 const OpNameDecl *name, ArrayRef<Expr *> operands,
309 ArrayRef<Expr *> resultTypes,
310 ArrayRef<NamedAttributeDecl *> attributes) {
311 unsigned allocSize =
312 OperationExpr::totalSizeToAlloc<Expr *, NamedAttributeDecl *>(
313 Counts: operands.size() + resultTypes.size(), Counts: attributes.size());
314 void *rawData =
315 ctx.getAllocator().Allocate(Size: allocSize, Alignment: alignof(OperationExpr));
316
317 Type resultType = OperationType::get(context&: ctx, name: name->getName(), odsOp);
318 OperationExpr *opExpr = new (rawData)
319 OperationExpr(loc, resultType, name, operands.size(), resultTypes.size(),
320 attributes.size(), name->getLoc());
321 std::uninitialized_copy(first: operands.begin(), last: operands.end(),
322 result: opExpr->getOperands().begin());
323 std::uninitialized_copy(first: resultTypes.begin(), last: resultTypes.end(),
324 result: opExpr->getResultTypes().begin());
325 std::uninitialized_copy(first: attributes.begin(), last: attributes.end(),
326 result: opExpr->getAttributes().begin());
327 return opExpr;
328}
329
330std::optional<StringRef> OperationExpr::getName() const {
331 return getNameDecl()->getName();
332}
333
334//===----------------------------------------------------------------------===//
335// RangeExpr
336//===----------------------------------------------------------------------===//
337
338RangeExpr *RangeExpr::create(Context &ctx, SMRange loc,
339 ArrayRef<Expr *> elements, RangeType type) {
340 unsigned allocSize = RangeExpr::totalSizeToAlloc<Expr *>(Counts: elements.size());
341 void *rawData = ctx.getAllocator().Allocate(Size: allocSize, Alignment: alignof(TupleExpr));
342
343 RangeExpr *expr = new (rawData) RangeExpr(loc, type, elements.size());
344 std::uninitialized_copy(first: elements.begin(), last: elements.end(),
345 result: expr->getElements().begin());
346 return expr;
347}
348
349//===----------------------------------------------------------------------===//
350// TupleExpr
351//===----------------------------------------------------------------------===//
352
353TupleExpr *TupleExpr::create(Context &ctx, SMRange loc,
354 ArrayRef<Expr *> elements,
355 ArrayRef<StringRef> names) {
356 unsigned allocSize = TupleExpr::totalSizeToAlloc<Expr *>(Counts: elements.size());
357 void *rawData = ctx.getAllocator().Allocate(Size: allocSize, Alignment: alignof(TupleExpr));
358
359 auto elementTypes = llvm::map_range(
360 C&: elements, F: [](const Expr *expr) { return expr->getType(); });
361 TupleType type = TupleType::get(context&: ctx, elementTypes: llvm::to_vector(Range&: elementTypes), elementNames: names);
362
363 TupleExpr *expr = new (rawData) TupleExpr(loc, type);
364 std::uninitialized_copy(first: elements.begin(), last: elements.end(),
365 result: expr->getElements().begin());
366 return expr;
367}
368
369//===----------------------------------------------------------------------===//
370// TypeExpr
371//===----------------------------------------------------------------------===//
372
373TypeExpr *TypeExpr::create(Context &ctx, SMRange loc, StringRef value) {
374 return new (ctx.getAllocator().Allocate<TypeExpr>())
375 TypeExpr(ctx, loc, copyStringWithNull(ctx, str: value));
376}
377
378//===----------------------------------------------------------------------===//
379// Decl
380//===----------------------------------------------------------------------===//
381
382void Decl::setDocComment(Context &ctx, StringRef comment) {
383 docComment = comment.copy(A&: ctx.getAllocator());
384}
385
386//===----------------------------------------------------------------------===//
387// AttrConstraintDecl
388//===----------------------------------------------------------------------===//
389
390AttrConstraintDecl *AttrConstraintDecl::create(Context &ctx, SMRange loc,
391 Expr *typeExpr) {
392 return new (ctx.getAllocator().Allocate<AttrConstraintDecl>())
393 AttrConstraintDecl(loc, typeExpr);
394}
395
396//===----------------------------------------------------------------------===//
397// OpConstraintDecl
398//===----------------------------------------------------------------------===//
399
400OpConstraintDecl *OpConstraintDecl::create(Context &ctx, SMRange loc,
401 const OpNameDecl *nameDecl) {
402 if (!nameDecl)
403 nameDecl = OpNameDecl::create(ctx, loc: SMRange());
404
405 return new (ctx.getAllocator().Allocate<OpConstraintDecl>())
406 OpConstraintDecl(loc, nameDecl);
407}
408
409std::optional<StringRef> OpConstraintDecl::getName() const {
410 return getNameDecl()->getName();
411}
412
413//===----------------------------------------------------------------------===//
414// TypeConstraintDecl
415//===----------------------------------------------------------------------===//
416
417TypeConstraintDecl *TypeConstraintDecl::create(Context &ctx, SMRange loc) {
418 return new (ctx.getAllocator().Allocate<TypeConstraintDecl>())
419 TypeConstraintDecl(loc);
420}
421
422//===----------------------------------------------------------------------===//
423// TypeRangeConstraintDecl
424//===----------------------------------------------------------------------===//
425
426TypeRangeConstraintDecl *TypeRangeConstraintDecl::create(Context &ctx,
427 SMRange loc) {
428 return new (ctx.getAllocator().Allocate<TypeRangeConstraintDecl>())
429 TypeRangeConstraintDecl(loc);
430}
431
432//===----------------------------------------------------------------------===//
433// ValueConstraintDecl
434//===----------------------------------------------------------------------===//
435
436ValueConstraintDecl *ValueConstraintDecl::create(Context &ctx, SMRange loc,
437 Expr *typeExpr) {
438 return new (ctx.getAllocator().Allocate<ValueConstraintDecl>())
439 ValueConstraintDecl(loc, typeExpr);
440}
441
442//===----------------------------------------------------------------------===//
443// ValueRangeConstraintDecl
444//===----------------------------------------------------------------------===//
445
446ValueRangeConstraintDecl *
447ValueRangeConstraintDecl::create(Context &ctx, SMRange loc, Expr *typeExpr) {
448 return new (ctx.getAllocator().Allocate<ValueRangeConstraintDecl>())
449 ValueRangeConstraintDecl(loc, typeExpr);
450}
451
452//===----------------------------------------------------------------------===//
453// UserConstraintDecl
454//===----------------------------------------------------------------------===//
455
456std::optional<StringRef>
457UserConstraintDecl::getNativeInputType(unsigned index) const {
458 return hasNativeInputTypes ? getTrailingObjects<StringRef>()[index]
459 : std::optional<StringRef>();
460}
461
462UserConstraintDecl *UserConstraintDecl::createImpl(
463 Context &ctx, const Name &name, ArrayRef<VariableDecl *> inputs,
464 ArrayRef<StringRef> nativeInputTypes, ArrayRef<VariableDecl *> results,
465 std::optional<StringRef> codeBlock, const CompoundStmt *body,
466 Type resultType) {
467 bool hasNativeInputTypes = !nativeInputTypes.empty();
468 assert(!hasNativeInputTypes || nativeInputTypes.size() == inputs.size());
469
470 unsigned allocSize =
471 UserConstraintDecl::totalSizeToAlloc<VariableDecl *, StringRef>(
472 Counts: inputs.size() + results.size(),
473 Counts: hasNativeInputTypes ? inputs.size() : 0);
474 void *rawData =
475 ctx.getAllocator().Allocate(Size: allocSize, Alignment: alignof(UserConstraintDecl));
476 if (codeBlock)
477 codeBlock = codeBlock->copy(A&: ctx.getAllocator());
478
479 UserConstraintDecl *decl = new (rawData)
480 UserConstraintDecl(name, inputs.size(), hasNativeInputTypes,
481 results.size(), codeBlock, body, resultType);
482 std::uninitialized_copy(first: inputs.begin(), last: inputs.end(),
483 result: decl->getInputs().begin());
484 std::uninitialized_copy(first: results.begin(), last: results.end(),
485 result: decl->getResults().begin());
486 if (hasNativeInputTypes) {
487 StringRef *nativeInputTypesPtr = decl->getTrailingObjects<StringRef>();
488 for (unsigned i = 0, e = inputs.size(); i < e; ++i)
489 nativeInputTypesPtr[i] = nativeInputTypes[i].copy(A&: ctx.getAllocator());
490 }
491
492 return decl;
493}
494
495//===----------------------------------------------------------------------===//
496// NamedAttributeDecl
497//===----------------------------------------------------------------------===//
498
499NamedAttributeDecl *NamedAttributeDecl::create(Context &ctx, const Name &name,
500 Expr *value) {
501 return new (ctx.getAllocator().Allocate<NamedAttributeDecl>())
502 NamedAttributeDecl(name, value);
503}
504
505//===----------------------------------------------------------------------===//
506// OpNameDecl
507//===----------------------------------------------------------------------===//
508
509OpNameDecl *OpNameDecl::create(Context &ctx, const Name &name) {
510 return new (ctx.getAllocator().Allocate<OpNameDecl>()) OpNameDecl(name);
511}
512OpNameDecl *OpNameDecl::create(Context &ctx, SMRange loc) {
513 return new (ctx.getAllocator().Allocate<OpNameDecl>()) OpNameDecl(loc);
514}
515
516//===----------------------------------------------------------------------===//
517// PatternDecl
518//===----------------------------------------------------------------------===//
519
520PatternDecl *PatternDecl::create(Context &ctx, SMRange loc, const Name *name,
521 std::optional<uint16_t> benefit,
522 bool hasBoundedRecursion,
523 const CompoundStmt *body) {
524 return new (ctx.getAllocator().Allocate<PatternDecl>())
525 PatternDecl(loc, name, benefit, hasBoundedRecursion, body);
526}
527
528//===----------------------------------------------------------------------===//
529// UserRewriteDecl
530//===----------------------------------------------------------------------===//
531
532UserRewriteDecl *UserRewriteDecl::createImpl(Context &ctx, const Name &name,
533 ArrayRef<VariableDecl *> inputs,
534 ArrayRef<VariableDecl *> results,
535 std::optional<StringRef> codeBlock,
536 const CompoundStmt *body,
537 Type resultType) {
538 unsigned allocSize = UserRewriteDecl::totalSizeToAlloc<VariableDecl *>(
539 Counts: inputs.size() + results.size());
540 void *rawData =
541 ctx.getAllocator().Allocate(Size: allocSize, Alignment: alignof(UserRewriteDecl));
542 if (codeBlock)
543 codeBlock = codeBlock->copy(A&: ctx.getAllocator());
544
545 UserRewriteDecl *decl = new (rawData) UserRewriteDecl(
546 name, inputs.size(), results.size(), codeBlock, body, resultType);
547 std::uninitialized_copy(first: inputs.begin(), last: inputs.end(),
548 result: decl->getInputs().begin());
549 std::uninitialized_copy(first: results.begin(), last: results.end(),
550 result: decl->getResults().begin());
551 return decl;
552}
553
554//===----------------------------------------------------------------------===//
555// VariableDecl
556//===----------------------------------------------------------------------===//
557
558VariableDecl *VariableDecl::create(Context &ctx, const Name &name, Type type,
559 Expr *initExpr,
560 ArrayRef<ConstraintRef> constraints) {
561 unsigned allocSize =
562 VariableDecl::totalSizeToAlloc<ConstraintRef>(Counts: constraints.size());
563 void *rawData = ctx.getAllocator().Allocate(Size: allocSize, Alignment: alignof(VariableDecl));
564
565 VariableDecl *varDecl =
566 new (rawData) VariableDecl(name, type, initExpr, constraints.size());
567 std::uninitialized_copy(first: constraints.begin(), last: constraints.end(),
568 result: varDecl->getConstraints().begin());
569 return varDecl;
570}
571
572//===----------------------------------------------------------------------===//
573// Module
574//===----------------------------------------------------------------------===//
575
576Module *Module::create(Context &ctx, SMLoc loc, ArrayRef<Decl *> children) {
577 unsigned allocSize = Module::totalSizeToAlloc<Decl *>(Counts: children.size());
578 void *rawData = ctx.getAllocator().Allocate(Size: allocSize, Alignment: alignof(Module));
579
580 Module *module = new (rawData) Module(loc, children.size());
581 std::uninitialized_copy(first: children.begin(), last: children.end(),
582 result: module->getChildren().begin());
583 return module;
584}
585

source code of mlir/lib/Tools/PDLL/AST/Nodes.cpp