MLIR 24.0.0git
MLIRGen.cpp
Go to the documentation of this file.
1//===- MLIRGen.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
14#include "mlir/IR/Builders.h"
15#include "mlir/IR/BuiltinOps.h"
16#include "mlir/IR/Verifier.h"
22#include "llvm/ADT/ScopedHashTable.h"
23#include "llvm/ADT/StringExtras.h"
24#include "llvm/ADT/TypeSwitch.h"
25#include <cstdint>
26#include <optional>
27
28using namespace mlir;
29using namespace mlir::pdll;
30
31//===----------------------------------------------------------------------===//
32// CodeGen
33//===----------------------------------------------------------------------===//
34
35namespace {
36class CodeGen {
37public:
38 CodeGen(MLIRContext *mlirContext, const ast::Context &context,
39 const llvm::SourceMgr &sourceMgr)
40 : builder(mlirContext), odsContext(context.getODSContext()),
41 sourceMgr(sourceMgr) {
42 // Make sure that the PDL dialect is loaded.
43 mlirContext->loadDialect<pdl::PDLDialect>();
44 }
45
46 OwningOpRef<ModuleOp> generate(const ast::Module &module);
47
48private:
49 /// Generate an MLIR location from the given source location.
50 Location genLoc(llvm::SMLoc loc);
51 Location genLoc(llvm::SMRange loc) { return genLoc(loc.Start); }
52
53 /// Generate an MLIR type from the given source type.
54 Type genType(ast::Type type);
55
56 /// Generate MLIR for the given AST node.
57 void gen(const ast::Node *node);
58
59 //===--------------------------------------------------------------------===//
60 // Statements
61 //===--------------------------------------------------------------------===//
62
63 void genImpl(const ast::CompoundStmt *stmt);
64 void genImpl(const ast::EraseStmt *stmt);
65 void genImpl(const ast::LetStmt *stmt);
66 void genImpl(const ast::ReplaceStmt *stmt);
67 void genImpl(const ast::RewriteStmt *stmt);
68 void genImpl(const ast::ReturnStmt *stmt);
69
70 //===--------------------------------------------------------------------===//
71 // Decls
72 //===--------------------------------------------------------------------===//
73
74 void genImpl(const ast::UserConstraintDecl *decl);
75 void genImpl(const ast::UserRewriteDecl *decl);
76 void genImpl(const ast::PatternDecl *decl);
77
78 /// Generate the set of MLIR values defined for the given variable decl, and
79 /// apply any attached constraints.
80 SmallVector<Value> genVar(const ast::VariableDecl *varDecl);
81
82 /// Generate the value for a variable that does not have an initializer
83 /// expression, i.e. create the PDL value based on the type/constraints of the
84 /// variable.
85 Value genNonInitializerVar(const ast::VariableDecl *varDecl, Location loc);
86
87 /// Apply the constraints of the given variable to `values`, which correspond
88 /// to the MLIR values of the variable.
89 void applyVarConstraints(const ast::VariableDecl *varDecl, ValueRange values);
90
91 //===--------------------------------------------------------------------===//
92 // Expressions
93 //===--------------------------------------------------------------------===//
94
95 Value genSingleExpr(const ast::Expr *expr);
96 SmallVector<Value> genExpr(const ast::Expr *expr);
97 Value genExprImpl(const ast::AttributeExpr *expr);
98 SmallVector<Value> genExprImpl(const ast::CallExpr *expr);
99 SmallVector<Value> genExprImpl(const ast::DeclRefExpr *expr);
100 Value genExprImpl(const ast::MemberAccessExpr *expr);
101 Value genExprImpl(const ast::OperationExpr *expr);
102 Value genExprImpl(const ast::RangeExpr *expr);
103 SmallVector<Value> genExprImpl(const ast::TupleExpr *expr);
104 Value genExprImpl(const ast::TypeExpr *expr);
105
106 SmallVector<Value> genConstraintCall(const ast::UserConstraintDecl *decl,
107 Location loc, ValueRange inputs,
108 bool isNegated = false);
109 SmallVector<Value> genRewriteCall(const ast::UserRewriteDecl *decl,
110 Location loc, ValueRange inputs);
111 template <typename PDLOpT, typename T>
112 SmallVector<Value> genConstraintOrRewriteCall(const T *decl, Location loc,
113 ValueRange inputs,
114 bool isNegated = false);
115
116 //===--------------------------------------------------------------------===//
117 // Fields
118 //===--------------------------------------------------------------------===//
119
120 /// The MLIR builder used for building the resultant IR.
121 OpBuilder builder;
122
123 /// A map from variable declarations to the MLIR equivalent.
124 using VariableMapTy =
125 llvm::ScopedHashTable<const ast::VariableDecl *, SmallVector<Value>>;
126 VariableMapTy variables;
127
128 /// A reference to the ODS context.
129 const ods::Context &odsContext;
130
131 /// The source manager of the PDLL ast.
132 const llvm::SourceMgr &sourceMgr;
133};
134} // namespace
135
136OwningOpRef<ModuleOp> CodeGen::generate(const ast::Module &module) {
137 OwningOpRef<ModuleOp> mlirModule =
138 ModuleOp::create(builder, genLoc(module.getLoc()));
139 builder.setInsertionPointToStart(mlirModule->getBody());
140
141 // Generate code for each of the decls within the module.
142 for (const ast::Decl *decl : module.getChildren())
143 gen(decl);
144
145 return mlirModule;
146}
147
148Location CodeGen::genLoc(llvm::SMLoc loc) {
149 unsigned fileID = sourceMgr.FindBufferContainingLoc(loc);
150
151 auto [lineNo, column] = sourceMgr.getLineAndColumn(loc);
152 auto *buffer = sourceMgr.getMemoryBuffer(fileID);
153
154 return FileLineColLoc::get(builder.getContext(),
155 buffer->getBufferIdentifier(), lineNo, column);
156}
157
158Type CodeGen::genType(ast::Type type) {
159 return TypeSwitch<ast::Type, Type>(type)
160 .Case([&](ast::AttributeType astType) -> Type {
161 return builder.getType<pdl::AttributeType>();
162 })
163 .Case([&](ast::OperationType astType) -> Type {
164 return builder.getType<pdl::OperationType>();
165 })
166 .Case([&](ast::TypeType astType) -> Type {
167 return builder.getType<pdl::TypeType>();
168 })
169 .Case([&](ast::ValueType astType) -> Type {
170 return builder.getType<pdl::ValueType>();
171 })
172 .Case([&](ast::RangeType astType) -> Type {
173 return pdl::RangeType::get(genType(astType.getElementType()));
174 });
175}
176
177void CodeGen::gen(const ast::Node *node) {
179 .Case<const ast::CompoundStmt, const ast::EraseStmt, const ast::LetStmt,
180 const ast::ReplaceStmt, const ast::RewriteStmt,
181 const ast::ReturnStmt, const ast::UserConstraintDecl,
182 const ast::UserRewriteDecl, const ast::PatternDecl>(
183 [&](auto derivedNode) { this->genImpl(derivedNode); })
184 .Case([&](const ast::Expr *expr) { genExpr(expr); });
185}
186
187//===----------------------------------------------------------------------===//
188// CodeGen: Statements
189//===----------------------------------------------------------------------===//
190
191void CodeGen::genImpl(const ast::CompoundStmt *stmt) {
192 VariableMapTy::ScopeTy varScope(variables);
193 for (const ast::Stmt *childStmt : stmt->getChildren())
194 gen(childStmt);
195}
196
197/// If the given builder is nested under a PDL PatternOp, build a rewrite
198/// operation and update the builder to nest under it. This is necessary for
199/// PDLL operation rewrite statements that are directly nested within a Pattern.
200static void checkAndNestUnderRewriteOp(OpBuilder &builder, Value rootExpr,
201 Location loc) {
202 if (isa<pdl::PatternOp>(builder.getInsertionBlock()->getParentOp())) {
203 pdl::RewriteOp rewrite =
204 pdl::RewriteOp::create(builder, loc, rootExpr, /*name=*/StringAttr(),
205 /*externalArgs=*/ValueRange());
206 builder.createBlock(&rewrite.getBodyRegion());
207 }
208}
209
210void CodeGen::genImpl(const ast::EraseStmt *stmt) {
211 OpBuilder::InsertionGuard insertGuard(builder);
212 Value rootExpr = genSingleExpr(stmt->getRootOpExpr());
213 Location loc = genLoc(stmt->getLoc());
214
215 // Make sure we are nested in a RewriteOp.
216 OpBuilder::InsertionGuard guard(builder);
217 checkAndNestUnderRewriteOp(builder, rootExpr, loc);
218 pdl::EraseOp::create(builder, loc, rootExpr);
219}
220
221void CodeGen::genImpl(const ast::LetStmt *stmt) { genVar(stmt->getVarDecl()); }
222
223void CodeGen::genImpl(const ast::ReplaceStmt *stmt) {
224 OpBuilder::InsertionGuard insertGuard(builder);
225 Value rootExpr = genSingleExpr(stmt->getRootOpExpr());
226 Location loc = genLoc(stmt->getLoc());
227
228 // Make sure we are nested in a RewriteOp.
229 OpBuilder::InsertionGuard guard(builder);
230 checkAndNestUnderRewriteOp(builder, rootExpr, loc);
231
232 SmallVector<Value> replValues;
233 for (ast::Expr *replExpr : stmt->getReplExprs())
234 replValues.push_back(genSingleExpr(replExpr));
235
236 // Check to see if the statement has a replacement operation, or a range of
237 // replacement values.
238 bool usesReplOperation =
239 replValues.size() == 1 &&
240 isa<pdl::OperationType>(replValues.front().getType());
241 pdl::ReplaceOp::create(
242 builder, loc, rootExpr, usesReplOperation ? replValues[0] : Value(),
243 usesReplOperation ? ValueRange() : ValueRange(replValues));
244}
245
246void CodeGen::genImpl(const ast::RewriteStmt *stmt) {
247 OpBuilder::InsertionGuard insertGuard(builder);
248 Value rootExpr = genSingleExpr(stmt->getRootOpExpr());
249
250 // Make sure we are nested in a RewriteOp.
251 OpBuilder::InsertionGuard guard(builder);
252 checkAndNestUnderRewriteOp(builder, rootExpr, genLoc(stmt->getLoc()));
253 gen(stmt->getRewriteBody());
254}
255
256void CodeGen::genImpl(const ast::ReturnStmt *stmt) {
257 // ReturnStmt generation is handled by the respective constraint or rewrite
258 // parent node.
259}
260
261//===----------------------------------------------------------------------===//
262// CodeGen: Decls
263//===----------------------------------------------------------------------===//
264
265void CodeGen::genImpl(const ast::UserConstraintDecl *decl) {
266 // All PDLL constraints get inlined when called, and the main native
267 // constraint declarations doesn't require any MLIR to be generated, only uses
268 // of it do.
269}
270
271void CodeGen::genImpl(const ast::UserRewriteDecl *decl) {
272 // All PDLL rewrites get inlined when called, and the main native
273 // rewrite declarations doesn't require any MLIR to be generated, only uses
274 // of it do.
275}
276
277void CodeGen::genImpl(const ast::PatternDecl *decl) {
278 const ast::Name *name = decl->getName();
279
280 // FIXME: Properly model HasBoundedRecursion in PDL so that we don't drop it
281 // here.
282 pdl::PatternOp pattern = pdl::PatternOp::create(
283 builder, genLoc(decl->getLoc()), decl->getBenefit(),
284 name ? std::optional<StringRef>(name->getName())
285 : std::optional<StringRef>());
286
287 OpBuilder::InsertionGuard savedInsertPoint(builder);
288 builder.setInsertionPointToStart(pattern.getBody());
289 gen(decl->getBody());
290}
291
292SmallVector<Value> CodeGen::genVar(const ast::VariableDecl *varDecl) {
293 auto it = variables.begin(varDecl);
294 if (it != variables.end())
295 return *it;
296
297 // If the variable has an initial value, use that as the base value.
298 // Otherwise, generate a value using the constraint list.
299 SmallVector<Value> values;
300 if (const ast::Expr *initExpr = varDecl->getInitExpr())
301 values = genExpr(initExpr);
302 else
303 values.push_back(genNonInitializerVar(varDecl, genLoc(varDecl->getLoc())));
304
305 // Apply the constraints of the values of the variable.
306 applyVarConstraints(varDecl, values);
307
308 variables.insert(varDecl, values);
309 return values;
310}
311
312Value CodeGen::genNonInitializerVar(const ast::VariableDecl *varDecl,
313 Location loc) {
314 // A functor used to generate expressions nested
315 auto getTypeConstraint = [&]() -> Value {
316 for (const ast::ConstraintRef &constraint : varDecl->getConstraints()) {
317 Value typeValue =
318 TypeSwitch<const ast::Node *, Value>(constraint.constraint)
319 .Case<ast::AttrConstraintDecl, ast::ValueConstraintDecl,
320 ast::ValueRangeConstraintDecl>(
321 [&, this](auto *cst) -> Value {
322 if (auto *typeConstraintExpr = cst->getTypeExpr())
323 return this->genSingleExpr(typeConstraintExpr);
324 return Value();
325 })
326 .Default(Value());
327 if (typeValue)
328 return typeValue;
329 }
330 return Value();
331 };
332
333 // Generate a value based on the type of the variable.
334 ast::Type type = varDecl->getType();
335 Type mlirType = genType(type);
336 if (isa<ast::ValueType>(type))
337 return pdl::OperandOp::create(builder, loc, mlirType, getTypeConstraint());
338 if (isa<ast::TypeType>(type))
339 return pdl::TypeOp::create(builder, loc, mlirType, /*type=*/TypeAttr());
340 if (isa<ast::AttributeType>(type))
341 return pdl::AttributeOp::create(builder, loc, getTypeConstraint());
342 if (ast::OperationType opType = dyn_cast<ast::OperationType>(type)) {
343 Value operands = pdl::OperandsOp::create(
344 builder, loc, pdl::RangeType::get(builder.getType<pdl::ValueType>()),
345 /*type=*/Value());
346 Value results = pdl::TypesOp::create(
347 builder, loc, pdl::RangeType::get(builder.getType<pdl::TypeType>()),
348 /*types=*/ArrayAttr());
349 return pdl::OperationOp::create(builder, loc, opType.getName(), operands,
350 ArrayRef<StringRef>(), ValueRange(),
351 results);
352 }
353
354 if (ast::RangeType rangeTy = dyn_cast<ast::RangeType>(type)) {
355 ast::Type eleTy = rangeTy.getElementType();
356 if (isa<ast::ValueType>(eleTy))
357 return pdl::OperandsOp::create(builder, loc, mlirType,
358 getTypeConstraint());
359 if (isa<ast::TypeType>(eleTy))
360 return pdl::TypesOp::create(builder, loc, mlirType,
361 /*types=*/ArrayAttr());
362 }
363
364 llvm_unreachable("invalid non-initialized variable type");
365}
366
367void CodeGen::applyVarConstraints(const ast::VariableDecl *varDecl,
368 ValueRange values) {
369 // Generate calls to any user constraints that were attached via the
370 // constraint list.
371 for (const ast::ConstraintRef &ref : varDecl->getConstraints())
372 if (const auto *userCst = dyn_cast<ast::UserConstraintDecl>(ref.constraint))
373 genConstraintCall(userCst, genLoc(ref.referenceLoc), values);
374}
375
376//===----------------------------------------------------------------------===//
377// CodeGen: Expressions
378//===----------------------------------------------------------------------===//
379
380Value CodeGen::genSingleExpr(const ast::Expr *expr) {
382 .Case<const ast::AttributeExpr, const ast::MemberAccessExpr,
383 const ast::OperationExpr, const ast::RangeExpr,
384 const ast::TypeExpr>(
385 [&](auto derivedNode) { return this->genExprImpl(derivedNode); })
386 .Case<const ast::CallExpr, const ast::DeclRefExpr, const ast::TupleExpr>(
387 [&](auto derivedNode) {
388 return llvm::getSingleElement(this->genExprImpl(derivedNode));
389 });
390}
391
392SmallVector<Value> CodeGen::genExpr(const ast::Expr *expr) {
394 .Case<const ast::CallExpr, const ast::DeclRefExpr, const ast::TupleExpr>(
395 [&](auto derivedNode) { return this->genExprImpl(derivedNode); })
396 .Default([&](const ast::Expr *expr) -> SmallVector<Value> {
397 return {genSingleExpr(expr)};
398 });
399}
400
401Value CodeGen::genExprImpl(const ast::AttributeExpr *expr) {
402 Attribute attr = parseAttribute(expr->getValue(), builder.getContext());
403 assert(attr && "invalid MLIR attribute data");
404 return pdl::AttributeOp::create(builder, genLoc(expr->getLoc()), attr);
405}
406
407SmallVector<Value> CodeGen::genExprImpl(const ast::CallExpr *expr) {
408 Location loc = genLoc(expr->getLoc());
409 SmallVector<Value> arguments;
410 for (const ast::Expr *arg : expr->getArguments())
411 arguments.push_back(genSingleExpr(arg));
412
413 // Resolve the callable expression of this call.
414 auto *callableExpr = dyn_cast<ast::DeclRefExpr>(expr->getCallableExpr());
415 assert(callableExpr && "unhandled CallExpr callable");
416
417 // Generate the PDL based on the type of callable.
418 const ast::Decl *callable = callableExpr->getDecl();
419 if (const auto *decl = dyn_cast<ast::UserConstraintDecl>(callable))
420 return genConstraintCall(decl, loc, arguments, expr->getIsNegated());
421 if (const auto *decl = dyn_cast<ast::UserRewriteDecl>(callable))
422 return genRewriteCall(decl, loc, arguments);
423 llvm_unreachable("unhandled CallExpr callable");
424}
425
426SmallVector<Value> CodeGen::genExprImpl(const ast::DeclRefExpr *expr) {
427 if (const auto *varDecl = dyn_cast<ast::VariableDecl>(expr->getDecl()))
428 return genVar(varDecl);
429 llvm_unreachable("unknown decl reference expression");
430}
431
432Value CodeGen::genExprImpl(const ast::MemberAccessExpr *expr) {
433 Location loc = genLoc(expr->getLoc());
434 StringRef name = expr->getMemberName();
435 SmallVector<Value> parentExprs = genExpr(expr->getParentExpr());
436 ast::Type parentType = expr->getParentExpr()->getType();
437
438 // Handle operation based member access.
439 if (ast::OperationType opType = dyn_cast<ast::OperationType>(parentType)) {
440 if (isa<ast::AllResultsMemberAccessExpr>(expr)) {
441 Type mlirType = genType(expr->getType());
442 if (isa<pdl::ValueType>(mlirType))
443 return pdl::ResultOp::create(builder, loc, mlirType, parentExprs[0],
444 builder.getI32IntegerAttr(0));
445 return pdl::ResultsOp::create(builder, loc, mlirType, parentExprs[0],
446 /*index=*/nullptr);
447 }
448
449 const ods::Operation *odsOp = opType.getODSOperation();
450 if (!odsOp) {
451 assert(llvm::isDigit(name[0]) &&
452 "unregistered op only allows numeric indexing");
453 int32_t resultIndex = 0;
454 if (name.getAsInteger(/*Radix=*/10, resultIndex))
455 llvm_unreachable("result index should have been validated");
456 IntegerAttr index = builder.getI32IntegerAttr(resultIndex);
457 return pdl::ResultOp::create(builder, loc, genType(expr->getType()),
458 parentExprs[0], index);
459 }
460
461 // Find the result with the member name or by index.
462 ArrayRef<ods::OperandOrResult> results = odsOp->getResults();
463 unsigned resultIndex = results.size();
464 if (llvm::isDigit(name[0])) {
465 name.getAsInteger(/*Radix=*/10, resultIndex);
466 } else {
467 auto findFn = [&](const ods::OperandOrResult &result) {
468 return result.getName() == name;
469 };
470 resultIndex = llvm::find_if(results, findFn) - results.begin();
471 }
472 assert(resultIndex < results.size() && "invalid result index");
473
474 // Generate the result access.
475 IntegerAttr index = builder.getI32IntegerAttr(resultIndex);
476 return pdl::ResultsOp::create(builder, loc, genType(expr->getType()),
477 parentExprs[0], index);
478 }
479
480 // Handle tuple based member access.
481 if (auto tupleType = dyn_cast<ast::TupleType>(parentType)) {
482 auto elementNames = tupleType.getElementNames();
483
484 // The index is either a numeric index, or a name.
485 unsigned index = 0;
486 if (llvm::isDigit(name[0]))
487 name.getAsInteger(/*Radix=*/10, index);
488 else
489 index = llvm::find(elementNames, name) - elementNames.begin();
490
491 assert(index < parentExprs.size() && "invalid result index");
492 return parentExprs[index];
493 }
494
495 llvm_unreachable("unhandled member access expression");
496}
497
498Value CodeGen::genExprImpl(const ast::OperationExpr *expr) {
499 Location loc = genLoc(expr->getLoc());
500 std::optional<StringRef> opName = expr->getName();
501
502 // Operands.
503 SmallVector<Value> operands;
504 for (const ast::Expr *operand : expr->getOperands())
505 operands.push_back(genSingleExpr(operand));
506
507 // Attributes.
508 SmallVector<StringRef> attrNames;
509 SmallVector<Value> attrValues;
510 for (const ast::NamedAttributeDecl *attr : expr->getAttributes()) {
511 attrNames.push_back(attr->getName().getName());
512 attrValues.push_back(genSingleExpr(attr->getValue()));
513 }
514
515 // Results.
516 SmallVector<Value> results;
517 for (const ast::Expr *result : expr->getResultTypes())
518 results.push_back(genSingleExpr(result));
519
520 return pdl::OperationOp::create(builder, loc, opName, operands, attrNames,
521 attrValues, results);
522}
523
524Value CodeGen::genExprImpl(const ast::RangeExpr *expr) {
525 SmallVector<Value> elements;
526 for (const ast::Expr *element : expr->getElements())
527 llvm::append_range(elements, genExpr(element));
528
529 return pdl::RangeOp::create(builder, genLoc(expr->getLoc()),
530 genType(expr->getType()), elements);
531}
532
533SmallVector<Value> CodeGen::genExprImpl(const ast::TupleExpr *expr) {
534 SmallVector<Value> elements;
535 for (const ast::Expr *element : expr->getElements())
536 elements.push_back(genSingleExpr(element));
537 return elements;
538}
539
540Value CodeGen::genExprImpl(const ast::TypeExpr *expr) {
541 Type type = parseType(expr->getValue(), builder.getContext());
542 assert(type && "invalid MLIR type data");
543 return pdl::TypeOp::create(builder, genLoc(expr->getLoc()),
544 builder.getType<pdl::TypeType>(),
545 TypeAttr::get(type));
546}
547
548SmallVector<Value>
549CodeGen::genConstraintCall(const ast::UserConstraintDecl *decl, Location loc,
550 ValueRange inputs, bool isNegated) {
551 // Apply any constraints defined on the arguments to the input values.
552 for (auto it : llvm::zip(decl->getInputs(), inputs))
553 applyVarConstraints(std::get<0>(it), std::get<1>(it));
554
555 // Generate the constraint call.
556 SmallVector<Value> results =
557 genConstraintOrRewriteCall<pdl::ApplyNativeConstraintOp>(
558 decl, loc, inputs, isNegated);
559
560 // Apply any constraints defined on the results of the constraint.
561 for (auto it : llvm::zip(decl->getResults(), results))
562 applyVarConstraints(std::get<0>(it), std::get<1>(it));
563 return results;
564}
565
566SmallVector<Value> CodeGen::genRewriteCall(const ast::UserRewriteDecl *decl,
567 Location loc, ValueRange inputs) {
568 return genConstraintOrRewriteCall<pdl::ApplyNativeRewriteOp>(decl, loc,
569 inputs);
570}
571
572template <typename PDLOpT, typename T>
573SmallVector<Value>
574CodeGen::genConstraintOrRewriteCall(const T *decl, Location loc,
575 ValueRange inputs, bool isNegated) {
576 const ast::CompoundStmt *cstBody = decl->getBody();
577
578 // If the decl doesn't have a statement body, it is a native decl.
579 if (!cstBody) {
580 ast::Type declResultType = decl->getResultType();
581 SmallVector<Type> resultTypes;
582 if (ast::TupleType tupleType = dyn_cast<ast::TupleType>(declResultType)) {
583 for (ast::Type type : tupleType.getElementTypes())
584 resultTypes.push_back(genType(type));
585 } else {
586 resultTypes.push_back(genType(declResultType));
587 }
588 PDLOpT pdlOp = PDLOpT::create(builder, loc, resultTypes,
589 decl->getName().getName(), inputs);
590 if (isNegated && std::is_same_v<PDLOpT, pdl::ApplyNativeConstraintOp>)
591 cast<pdl::ApplyNativeConstraintOp>(pdlOp).setIsNegated(true);
592 return pdlOp->getResults();
593 }
594
595 // Otherwise, this is a PDLL decl.
596 VariableMapTy::ScopeTy varScope(variables);
597
598 // Map the inputs of the call to the decl arguments.
599 // Note: This is only valid because we do not support recursion, meaning
600 // we don't need to worry about conflicting mappings here.
601 for (auto it : llvm::zip(inputs, decl->getInputs()))
602 variables.insert(std::get<1>(it), {std::get<0>(it)});
603
604 // Visit the body of the call as normal.
605 gen(cstBody);
606
607 // If the decl has no results, there is nothing to do.
608 if (cstBody->getChildren().empty())
609 return SmallVector<Value>();
610 auto *returnStmt = dyn_cast<ast::ReturnStmt>(cstBody->getChildren().back());
611 if (!returnStmt)
612 return SmallVector<Value>();
613
614 // Otherwise, grab the results from the return statement.
615 return genExpr(returnStmt->getResultExpr());
616}
617
618//===----------------------------------------------------------------------===//
619// MLIRGen
620//===----------------------------------------------------------------------===//
621
623 MLIRContext *mlirContext, const ast::Context &context,
624 const llvm::SourceMgr &sourceMgr, const ast::Module &module) {
625 CodeGen codegen(mlirContext, context, sourceMgr);
626 OwningOpRef<ModuleOp> mlirModule = codegen.generate(module);
627 if (failed(verify(*mlirModule)))
628 return nullptr;
629 return mlirModule;
630}
ArrayAttr()
static void checkAndNestUnderRewriteOp(OpBuilder &builder, Value rootExpr, Location loc)
If the given builder is nested under a PDL PatternOp, build a rewrite operation and update the builde...
Definition MLIRGen.cpp:200
static void rewrite(DataFlowSolver &solver, MLIRContext *context, MutableArrayRef< Region > initialRegions)
Rewrite the given regions using the computing analysis.
Definition SCCP.cpp:67
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
Definition Block.cpp:31
static FileLineColLoc get(StringAttr filename, unsigned line, unsigned column)
Definition Location.cpp:157
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:63
void loadDialect()
Load a dialect in the context.
This class helps build Operations.
Definition Builders.h:210
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes={}, ArrayRef< Location > locs={})
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
Definition Builders.cpp:439
Block * getInsertionBlock() const
Return the block the current insertion point belongs to.
Definition Builders.h:445
This class acts as an owning reference to an op, and will automatically destroy the held op on destru...
Definition OwningOpRef.h:29
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
StringRef getValue() const
Get the raw value of this expression.
Definition Nodes.h:376
Expr * getCallableExpr() const
Return the callable of this call.
Definition Nodes.h:400
MutableArrayRef< Expr * > getArguments()
Return the arguments of this call.
Definition Nodes.h:403
bool getIsNegated() const
Returns whether the result of this call is to be negated.
Definition Nodes.h:407
MutableArrayRef< Stmt * > getChildren()
Return the children of this compound statement.
Definition Nodes.h:185
This class represents the main context of the PDLL AST.
Definition Context.h:25
Decl * getDecl() const
Get the decl referenced by this expression.
Definition Nodes.h:438
const Name * getName() const
Return the name of the decl, or nullptr if it doesn't have one.
Definition Nodes.h:672
Type getType() const
Return the type of this expression.
Definition Nodes.h:351
VariableDecl * getVarDecl() const
Return the variable defined by this statement.
Definition Nodes.h:216
const Expr * getParentExpr() const
Get the parent expression of this access.
Definition Nodes.h:461
StringRef getMemberName() const
Return the name of the member being accessed.
Definition Nodes.h:464
This class represents a top-level AST module.
Definition Nodes.h:1297
MutableArrayRef< Decl * > getChildren()
Return the children of this module.
Definition Nodes.h:1302
SMRange getLoc() const
Return the location of this node.
Definition Nodes.h:131
Expr * getRootOpExpr() const
Return the root operation of this rewrite.
Definition Nodes.h:237
MutableArrayRef< Expr * > getOperands()
Return the operands of this operation.
Definition Nodes.h:532
MutableArrayRef< NamedAttributeDecl * > getAttributes()
Return the attributes of this operation.
Definition Nodes.h:548
MutableArrayRef< Expr * > getResultTypes()
Return the result types of this operation.
Definition Nodes.h:540
std::optional< StringRef > getName() const
Return the name of the operation, or std::nullopt if there isn't one.
Definition Nodes.cpp:327
const CompoundStmt * getBody() const
Return the body of this pattern.
Definition Nodes.h:1057
std::optional< uint16_t > getBenefit() const
Return the benefit of this pattern if specified, or std::nullopt.
Definition Nodes.h:1051
RangeType getType() const
Return the range result type of this expression.
Definition Nodes.h:600
MutableArrayRef< Expr * > getElements()
Return the element expressions of this range.
Definition Nodes.h:592
Type getElementType() const
Return the element type of this range.
Definition Types.cpp:99
MutableArrayRef< Expr * > getReplExprs()
Return the replacement values of this statement.
Definition Nodes.h:277
CompoundStmt * getRewriteBody() const
Return the compound rewrite body.
Definition Nodes.h:308
MutableArrayRef< Expr * > getElements()
Return the element expressions of this tuple.
Definition Nodes.h:625
StringRef getValue() const
Get the raw value of this expression.
Definition Nodes.h:654
MutableArrayRef< VariableDecl * > getResults()
Return the explicit results of the constraint declaration.
Definition Nodes.h:927
MutableArrayRef< VariableDecl * > getInputs()
Return the input arguments of this constraint.
Definition Nodes.h:914
MutableArrayRef< ConstraintRef > getConstraints()
Return the constraints of this variable.
Definition Nodes.h:1255
Expr * getInitExpr() const
Return the initializer expression of this statement, or nullptr if there was no initializer.
Definition Nodes.h:1264
Type getType() const
Return the type of the decl.
Definition Nodes.h:1270
ArrayRef< OperandOrResult > getResults() const
Returns the results of this operation.
Definition Operation.h:168
OwningOpRef< ModuleOp > codegenPDLLToMLIR(MLIRContext *mlirContext, const ast::Context &context, const llvm::SourceMgr &sourceMgr, const ast::Module &module)
Given a PDLL module, generate an MLIR PDL pattern module within the given MLIR context.
Definition MLIRGen.cpp:622
Include the generated interface declarations.
Attribute parseAttribute(llvm::StringRef attrStr, MLIRContext *context, Type type={}, size_t *numRead=nullptr, bool isKnownNullTerminated=false)
This parses a single MLIR attribute to an MLIR context if it was valid.
llvm::TypeSwitch< T, ResultT > TypeSwitch
Definition LLVM.h:139
Type parseType(llvm::StringRef typeStr, MLIRContext *context, size_t *numRead=nullptr, bool isKnownNullTerminated=false)
This parses a single MLIR type to an MLIR context if it was valid.
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
Definition Verifier.cpp:566
StringRef getName() const
Return the raw string name.
Definition Nodes.h:41